bashでGitLabCIの再利用可能なパイプラインを作成する

過去数年間で、私はGitLabCIがとても好きになりました主にそのシンプルさと機能性のため。リポジトリのルートにファイルを作成し、そこに数行のコードを.gitlab-ci.yml



追加するだけで十分です次のコミットにより、指定されたコマンドを実行する一連のジョブでパイプラインが開始されます。





また、これにインクルード機能拡張機能を追加すると、非常に興味深いことができます。テンプレートジョブとパイプラインを作成し、それらを別々のリポジトリに移動して、コードをコピーせずに別のプロジェクトで再利用できます。





しかし残念ながら、すべてが私たちが望むほどバラ色であるわけではありません。script



GitLabCIの命令は非常に低レベルです。文字列の形式で与えられたコマンドを実行するだけです。YAML内で大きなスクリプトを書くのはあまり便利ではありません。ロジックがより複雑になると、スクリプトの数が増え、YAMLと混ざり合って構成が読み取れなくなり、メンテナンスが複雑になります。





大きなスクリプトの開発を簡素化するメカニズムを本当に見逃しました。その結果、GitLab CIを開発するためのマイクロフレームワークが誕生しました。これについては、この記事で説明します(Dockerイメージを構築するための単純なパイプラインの例を使用)。





例:GitLabでDockerイメージを構築する

さまざまなチームとよく会う簡単なタスクの例を使用してパイプラインを作成するプロセスを検討したいと思います。GitLabで再利用するための基本的なDockerイメージを作成することです。





たとえば、チームがマイクロサービスを作成し、プリインストールされたデバッグユーティリティのセットを使用して、すべてのマイクロサービスに独自のベースイメージを使用したいとします。





または、別の例として、チームがテストを作成し、GitLabで直接サービスを使用して、独自のイメージを使用して一時データベース(またはキューなど)を作成したいと考えています





, docker- GitLab . .gitlab-ci.yml



:





services:
  - docker:dind

Build:
  image: docker
  script:
    - |
      docker login "$CI_REGISTRY" \
        --username "$CI_REGISTRY_USER" \
        --password "$CI_REGISTRY_PASSWORD"

      docker build \
        --file "Dockerfile" \
        --tag "$CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG" .

      docker push "$CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG"
      
      



Build



, GitLab Container Registry, . , ( , ).





, , :





  • , dockerfiles



    .





  • :





    • Build All



      - dockerfiles



      . ( ).





    • Build Changed



      - dockerfiles



      , . ( ) .





. . , .





:









, .NET.





:









docker-, Container Registry :





, .





1: " "

. .gitlab-ci.yml



. :





services:
  - docker:dind

stages:
  - Build

Build All:
  stage: Build
  image: docker
  when: manual
  script:
    - |
      dockerfiles=$(find "dockerfiles" -name "*.Dockerfile" -type f)

      docker login "$CI_REGISTRY" \
        --username "$CI_REGISTRY_USER" \
        --password "$CI_REGISTRY_PASSWORD"

      for dockerfile in $dockerfiles; do
        path=$(echo "$dockerfile" | sed 's/^dockerfiles\///' | sed 's/\.Dockerfile$//')
        tag="$CI_REGISTRY/$CI_PROJECT_PATH/$path:$CI_COMMIT_REF_SLUG"

        echo "Building $dockerfile..."
        docker build --file "$dockerfile" --tag "$tag" .

        echo "Pushing $tag..."
        docker push "$tag"
      done

Build Changed:
  stage: Build
  image: docker
  only:
    changes:
      - 'dockerfiles/*.Dockerfile'
      - 'dockerfiles/**/*.Dockerfile'
  script:
    - |
      apk update
      apk add git #  ,     ,    ...

      dockerfiles=$(git diff --name-only HEAD HEAD~1 -- 'dockerfiles/***.Dockerfile')

      docker login "$CI_REGISTRY" \
        --username "$CI_REGISTRY_USER" \
        --password "$CI_REGISTRY_PASSWORD"

      for dockerfile in $dockerfiles; do
        path=$(echo "$dockerfile" | sed 's/^dockerfiles\///' | sed 's/\.Dockerfile$//')
        tag="$CI_REGISTRY/$CI_PROJECT_PATH/$path:$CI_COMMIT_REF_SLUG"

        echo "Building $dockerfile..."
        docker build --file "$dockerfile" --tag "$tag" .

        echo "Pushing $tag..."
        docker push "$tag"
      done
      
      



:





  • ( step1)









:





  • Build All



    , :





    • , .. when: manual



      .





    • :





      • find "dockerfiles" -name "*.Dockerfile" -type f







  • Build Changed



    , :





    • , .. only:changes



      .





    • , :





      • git diff --name-only HEAD HEAD~1 -- 'dockerfiles/***.Dockerfile'







  • , , , dockerfiles/



    .Dockerfile



    , GitLab Container Registry.





:





  • ( )





  • , .





GitLab CI .





GitLab CI Bootstrap

GitLab CI Bootstrap - GitLab CI. :





  • ( .gitlab-ci.yml



    ) (bash shell), YAML .





  • , .





  • ( ) , .





GitLab CI Bootstrap bootstrap.gitlab-ci.yml, .gitlab-ci.yml



include. . include:local:





include:
  - local: 'bootstrap.gitlab-ci.yml'
      
      



.bootstrap



, :





.bootstrap:
  before_script:
    - |
     	...
      
      



.bootstrap



, extends:





example:
  extends: '.bootstrap'
  script:
    - '...'
      
      



( ), GitLab.





. . , , .





bash shell. git, . .bootstrap



docker- .





, , docker-.





2:

, .bootstrap



.gitlab-ci.sh



. , .





, , .gitlab-ci.yml



:





.gitlab-ci.yml



:





include:
  - project: '$CI_PROJECT_NAMESPACE/bootstrap'
    ref: 'master'
    file: 'bootstrap.gitlab-ci.yml'

services:
  - docker:dind

stages:
  - Build

Build All:
  stage: Build
  image: docker
  extends: .bootstrap
  when: manual
  script:
    - search_all_dockerfiles_task
    - build_and_push_dockerfiles_task

Build Changed:
  stage: Build
  image: docker
  extends: .bootstrap
  only:
    changes:
      - 'dockerfiles/*.Dockerfile'
      - 'dockerfiles/**/*.Dockerfile'
  script:
    - install_git_task
    - search_changed_dockerfiles_task
    - build_and_push_dockerfiles_task
      
      



.gitlab-ci.sh



:





DOCKERFILES=""

function search_all_dockerfiles_task() {
    DOCKERFILES=$(find "dockerfiles" -name "*.Dockerfile" -type f)
}

function search_changed_dockerfiles_task() {
    DOCKERFILES=$(git diff --name-only HEAD HEAD~1 -- 'dockerfiles/***.Dockerfile')
}

function install_git_task() {
    #  ,     ,    ...
    apk update
    apk add git
}

function build_and_push_dockerfiles_task() {
    docker login "$CI_REGISTRY" \
        --username "$CI_REGISTRY_USER" \
        --password "$CI_REGISTRY_PASSWORD"

    for dockerfile in $DOCKERFILES; do
        path=$(echo "$dockerfile" | sed 's/^dockerfiles\///' | sed 's/\.Dockerfile$//')
        tag="$CI_REGISTRY/$CI_PROJECT_PATH/$path:$CI_COMMIT_REF_SLUG"

        echo "Building $dockerfile..."
        docker build --file "$dockerfile" --tag "$tag" .

        echo "Pushing $tag..."
        docker push "$tag"
    done
}
      
      



:





gitlab-ci.sh



, .gitlab-ci.yml



. search_all_dockerfiles_task



search_changed_dockerfiles_task



DOCKERFILES



, build_and_push_dockerfiles_task



.





3:

, , . , , . , - , , .





include.





. , , , - , . , .





, .bootstrap



CI_IMPORT



, : CI_{module}_PROJECT



, CI_{module}_REF



CI_{module}_FILE



, {module}



- CI_IMPORT



( ).





, .gitlab-ci.sh



, .





:





.gitlab-ci.yml



:





include:
  - project: '$CI_PROJECT_NAMESPACE/dockerfiles-example-ci'
    ref: 'step3'
    file: 'dockerfiles.gitlab-ci.yml'
      
      



:





dockerfiles.gitlab-ci.yml



( .gitlab-ci.yml



):





include:
  - project: '$CI_PROJECT_NAMESPACE/bootstrap'
    ref: 'master'
    file: 'bootstrap.gitlab-ci.yml'

services:
  - docker:dind

stages:
  - Build

variables:
  CI_DOCKERFILES_PROJECT: '$CI_PROJECT_NAMESPACE/dockerfiles-example-ci'
  CI_DOCKERFILES_REF: 'step3'
  CI_DOCKERFILES_FILE: 'dockerfiles.gitlab-ci.sh'

Build All:
  stage: Build
  image: docker
  extends: .bootstrap
  variables:
    CI_IMPORT: dockerfiles
  when: manual
  script:
    - search_all_dockerfiles_task
    - build_and_push_dockerfiles_task

Build Changed:
  stage: Build
  image: docker
  extends: .bootstrap
  variables:
    CI_IMPORT: dockerfiles
  only:
    changes:
      - 'dockerfiles/*.Dockerfile'
      - 'dockerfiles/**/*.Dockerfile'
  script:
    - search_changed_dockerfiles_task
    - build_and_push_dockerfiles_task
      
      



dockerfiles.gitlab-ci.sh



( .gitlab-ci.sh



):





DOCKERFILES=""

function search_all_dockerfiles_task() {
    DOCKERFILES=$(find "dockerfiles" -name "*.Dockerfile" -type f)
}

function search_changed_dockerfiles_task() {
    DOCKERFILES=$(git diff --name-only HEAD HEAD~1 -- 'dockerfiles/***.Dockerfile')
}

function build_and_push_dockerfiles_task() {
    docker login "$CI_REGISTRY" \
        --username "$CI_REGISTRY_USER" \
        --password "$CI_REGISTRY_PASSWORD"

    for dockerfile in $DOCKERFILES; do
        path=$(echo "$dockerfile" | sed 's/^dockerfiles\///' | sed 's/\.Dockerfile$//')
        tag="$CI_REGISTRY/$CI_PROJECT_PATH/$path:$CI_COMMIT_REF_SLUG"

        echo "Building $dockerfile..."
        docker build --file "$dockerfile" --tag "$tag" .

        echo "Pushing $tag..."
        docker push "$tag"
    done
}
      
      



:





Build All



Build Changed



CI_IMPORT



dockerfiles



. : CI_DOCKERFILES_PROJECT



, CI_DOCKERFILES_REF



CI_DOCKERFILES_FILE



, .





, dockerfiles.gitlab-ci.sh



, $CI_PROJECT_NAMESPACE/dockerfiles-example-ci



, step3



.





, install_git_task



. git , .. git git .





4:

. , .





dockerfiles.gitlab-ci.sh



. , .





, include



, , . , . include



, .





, , include



.





dockerfiles.gitlab-ci.sh



:





dockerfiles.gitlab-ci.sh



:





include "tasks/search.sh"
include "tasks/docker.sh"
      
      



tasks/search.sh



:





DOCKERFILES=""

function search_all_dockerfiles_task() {
    DOCKERFILES=$(find "dockerfiles" -name "*.Dockerfile" -type f)
}

function search_changed_dockerfiles_task() {
    DOCKERFILES=$(git diff --name-only HEAD HEAD~1 -- 'dockerfiles/***.Dockerfile')
}
      
      



tasks/docker.sh



:





function build_and_push_dockerfiles_task() {
    docker login "$CI_REGISTRY" \
        --username "$CI_REGISTRY_USER" \
        --password "$CI_REGISTRY_PASSWORD"

    for dockerfile in $DOCKERFILES; do
        path=$(echo "$dockerfile" | sed 's/^dockerfiles\///' | sed 's/\.Dockerfile$//')
        tag="$CI_REGISTRY/$CI_PROJECT_PATH/$path:$CI_COMMIT_REF_SLUG"

        echo "Building $dockerfile..."
        docker build --file "$dockerfile" --tag "$tag" .

        echo "Pushing $tag..."
        docker push "$tag"
    done
}
      
      



:





GitLab CI bash GitLab CI Bootstrap.





. :





  • . .. , . GitLab CI.





  • . , Python C#.





  • . , .





, .





, 1.0. , . , .





ソース:ここで見つけることができます:https//gitlab.com/chakrygin/bootstrap





ここに例のあるリポジトリ:








All Articles