正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

CI/CDコンポーネントの例

  • プラン: Free、Premium、Ultimate
  • 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated

コンポーネントをテストする

コンポーネントの機能によっては、コンポーネントをテストするために、リポジトリに追加ファイルが必要になる場合があります。たとえば、特定のプログラミング言語でソフトウェアをlint、ビルド、テストするコンポーネントには、実際のソースコードのサンプルが必要です。ソースコードの例、設定ファイルなどを同じリポジトリに配置できます。

たとえば、コード品質CI/CDコンポーネントには、テスト用のコードサンプルがいくつかあります。

例: Rust言語のCI/CDコンポーネントをテストする

コンポーネントの機能によっては、コンポーネントをテストするために、リポジトリに追加ファイルが必要になる場合があります。

次に示すRustプログラミング言語の「hello world」の例では、簡略化のためにcargoツールチェーンを使用しています:

  1. CI/CDコンポーネントのルートディレクトリに移動します。

  2. cargo initコマンドを使用して、新しいRustプロジェクトを初期化します。

    cargo init

    このコマンドは、src/main.rsの「hello world」サンプルを含む、必要なすべてのプロジェクトファイルを作成します。コンポーネントジョブ内でcargo buildを使用してRustソースコードをビルドするには、このステップだけで十分です。

    tree
    .
    ├── Cargo.toml
    ├── LICENSE.md
    ├── README.md
    ├── src
    │   └── main.rs
    └── templates
        └── build.yml
  3. Rustソースコードをビルドするジョブがコンポーネントに含まれていることを確認します。その例として、以下にtemplates/build.ymlを示します:

    spec:
      inputs:
        stage:
          default: build
          description: 'Defines the build stage'
        rust_version:
          default: latest
          description: 'Specify the Rust version, use values from https://hub.docker.com/_/rust/tags Defaults to latest'
    ---
    
    "build-$[[ inputs.rust_version ]]":
      stage: $[[ inputs.stage ]]
      image: rust:$[[ inputs.rust_version ]]
      script:
        - cargo build --verbose

    この例では、次のように設定します:

    • 入力パラメータstagerust_versionはデフォルト値から変更できます。CI/CDジョブは、build-プレフィックスで始まり、入力パラメータrust_versionに基づいて名前を動的に作成します。コマンドcargo build --verboseでRustソースコードをコンパイルします。
  4. プロジェクトの.gitlab-ci.yml設定ファイルで、コンポーネントのbuildテンプレートをテストします:

    include:
      # include the component located in the current project from the current SHA
      - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/build@$CI_COMMIT_SHA
        inputs:
          stage: build
    
    stages: [build, test, release]
  5. テストやその他の処理を実行するには、Rustコードに関数とテストを追加し、cargo testを実行するコンポーネントテンプレートとジョブをtemplates/test.ymlに追加します。

    spec:
      inputs:
        stage:
          default: test
          description: 'Defines the test stage'
        rust_version:
          default: latest
          description: 'Specify the Rust version, use values from https://hub.docker.com/_/rust/tags Defaults to latest'
    ---
    
    "test-$[[ inputs.rust_version ]]":
      stage: $[[ inputs.stage ]]
      image: rust:$[[ inputs.rust_version ]]
      script:
        - cargo test --verbose
  6. testコンポーネントテンプレートを含めることで、パイプラインで追加のジョブをテストします:

    include:
      # include the component located in the current project from the current SHA
      - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/build@$CI_COMMIT_SHA
        inputs:
          stage: build
      - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/test@$CI_COMMIT_SHA
        inputs:
          stage: test
    
    stages: [build, test, release]

CI/CDコンポーネントのパターン

このセクションでは、CI/CDコンポーネントで一般的なパターンを実装するための実践的な例を示します。

ブール値の入力を使用してジョブを条件付きで設定する

boolean型の入力とextends機能を組み合わせることで、2つの条件分岐を持つジョブを構成できます。

たとえば、boolean入力を使用して複雑なキャッシュ動作を設定するには、次のようにします:

spec:
  inputs:
    enable_special_caching:
      description: 'If set to `true` configures a complex caching behavior'
      type: boolean
---

.my-component:enable_special_caching:false:
  extends: null

.my-component:enable_special_caching:true:
  cache:
    policy: pull-push
    key: $CI_COMMIT_SHA
    paths: [...]

my-job:
  extends: '.my-component:enable_special_caching:$[[ inputs.enable_special_caching ]]'
  script: ... # run some fancy tooling

このパターンは、ジョブのextendsキーワードにenable_special_caching入力を渡すことによって機能します。enable_special_cachingtruefalseかに応じて、定義済みの非表示ジョブ(.my-component:enable_special_caching:trueまたは.my-component:enable_special_caching:false)から適切な設定が選択されます。

optionsを使用してジョブを条件付きで設定する

複数のオプションを持つジョブを構成し、ifelseifの条件と同様の動作を実現できます。extendsstring型と複数のoptionsを組み合わせることで、任意の数の条件を設定できます。

たとえば、3つの異なるオプションを使用して複雑なキャッシュ動作を設定するには、次のようにします:

spec:
  inputs:
    cache_mode:
      description: Defines the caching mode to use for this component
      type: string
      options:
        - default
        - aggressive
        - relaxed
---

.my-component:cache_mode:default:
  extends: null

.my-component:cache_mode:aggressive:
  cache:
    policy: push
    key: $CI_COMMIT_SHA
    paths: ['*/**']

.my-component:cache_mode:relaxed:
  cache:
    policy: pull-push
    key: $CI_COMMIT_BRANCH
    paths: ['bin/*']

my-job:
  extends: '.my-component:cache_mode:$[[ inputs.cache_mode ]]'
  script: ... # run some fancy tooling

この例では、cache_mode入力はdefaultaggressiverelaxedのオプションを提供し、それぞれ異なる非表示ジョブに対応しています。extends: '.my-component:cache_mode:$[[ inputs.cache_mode ]]'でコンポーネントジョブを拡張することにより、ジョブは選択されたオプションに基づいて正しいキャッシュ設定を動的に継承します。

バージョニングされた参照リソースを参照するためにコンポーネントコンテキストを使用します

ジョブの参照、コミットSHAなどのコンポーネントメタデータを参照するには、コンポーネントコンテキストCI/CD式を使用します。1つのユースケースは、コンポーネントでバージョニングされたリソース(Dockerイメージなど)をビルドおよび公開し、コンポーネントが一致するバージョンを使用するようにすることです。

たとえば、次のことができます:

  • コンポーネントのバージョンに一致するタグを使用して、コンポーネントのリリースパイプラインでDockerイメージをビルドします。
  • コンポーネントに、同じDockerイメージのバージョンを参照させます。

コンポーネントプロジェクトのリリースパイプライン(.gitlab-ci.yml)内:

build-image:
  stage: build
  image: docker:latest
  script:
    - docker build -t $CI_REGISTRY_IMAGE/my-tool:$CI_COMMIT_TAG .
    - docker push $CI_REGISTRY_IMAGE/my-tool:$CI_COMMIT_TAG

create-release:
  stage: release
  image: registry.gitlab.com/gitlab-org/cli:latest
  script: echo "Creating release $CI_COMMIT_TAG"
  rules:
    - if: $CI_COMMIT_TAG
  release:
    tag_name: $CI_COMMIT_TAG
    description: "Release $CI_COMMIT_TAG"

コンポーネントテンプレート(templates/my-component/template.yml)内:

spec:
  component: [version, reference]
  inputs:
    stage:
      default: test
---

run-tool:
  stage: $[[ inputs.stage ]]
  image: $CI_REGISTRY_IMAGE/my-tool:$[[ component.version ]]
  script:
    - echo "Running tool version $[[ component.version ]]"
    - echo "Component was included using reference: $[[ component.reference ]]"
    - my-tool --version

この例では、次のように設定します:

  • コンポーネントを@1.0.0で含めると、ジョブはmy-tool:1.0.0のDockerイメージを使用します。
  • コンポーネントを@1.0で含めると、最新の1.0.xバージョン(たとえば、1.0.3)に解決されるため、my-tool:1.0.3を使用します。
  • コンポーネントを@~latestで含めると、最新のリリースされたバージョンが使用されます。
  • component.referenceフィールドには、指定した正確な参照(1.0~latest、またはSHAなど)が表示されます。この参照は、ログ記録またはデバッグに役立ちます。

CI/CDコンポーネントの移行例

このセクションでは、CI/CDテンプレートとパイプライン設定を再利用可能なCI/CDコンポーネントに移行するための実践的な例を示します。

CI/CDコンポーネントの移行例: Go

ソフトウェア開発ライフサイクル全体のパイプラインは、複数のジョブとステージで構成できます。プログラミング言語用のCI/CDテンプレートは、単一のテンプレートファイルで複数のジョブを提供する場合があります。実践として、次のGo CI/CDテンプレートを移行する必要があります。

default:
  image: golang:latest

stages:
  - test
  - build
  - deploy

format:
  stage: test
  script:
    - go fmt $(go list ./... | grep -v /vendor/)
    - go vet $(go list ./... | grep -v /vendor/)
    - go test -race $(go list ./... | grep -v /vendor/)

compile:
  stage: build
  script:
    - mkdir -p mybinaries
    - go build -o mybinaries ./...
  artifacts:
    paths:
      - mybinaries

より段階的なアプローチとして、一度に1つのジョブを移行します。まずbuildジョブから始め、その後formatジョブ、testジョブの順に同じ手順を繰り返します。

CI/CDテンプレートを移行するには、次の手順を実行します:

  1. CI/CDジョブと依存関係を分析し、移行アクションを定義します:

    • image設定はグローバルであるため、ジョブ定義に移動する必要があります
    • formatジョブは、1つのジョブで複数のgoコマンドを実行します。パイプラインの効率性を高めるために、go testコマンドは別のジョブに移動する必要があります。
    • compileジョブはgo buildを実行しているため、buildに名前を変更する必要があります。
  2. パイプラインの効率性を向上させるための最適化戦略を定義します。

    • さまざまなCI/CDパイプラインの利用者が活用できるように、stageジョブ属性は設定可能でなければなりません。
    • imageキーは、ハードコーディングされたイメージタグlatestを使用します。より柔軟で再利用可能なパイプラインにするため、latestをデフォルト値とするgolang_versionを入力として追加します。入力は、Docker Hubのイメージタグの値と一致する必要があります。
    • compileジョブは、バイナリをハードコーディングされたターゲットディレクトリmybinariesにビルドします。これは、mybinariesをデフォルト値とする動的な入力として拡張できます。
  3. ジョブごとに1つのテンプレートを基にして、新しいコンポーネントのテンプレート用ディレクトリ構造を作成します。

    • テンプレートの名前は、goコマンドに従う必要があります(例: format.ymlbuild.ymltest.yml)。
    • 新しいプロジェクトを作成し、Gitリポジトリを初期化し、すべての変更を追加/コミットし、リモートoriginを設定してプッシュします。CI/CDコンポーネントプロジェクトのパスに合わせてURLを変更します。
    • コンポーネントを作成するためのガイダンスで概説されているように、追加のファイルとしてREADME.mdLICENSE.md.gitlab-ci.yml.gitignoreを作成します。次のShellコマンドは、Goコンポーネント構造を初期化します:
    git init
    
    mkdir templates
    touch templates/{format,build,test}.yml
    
    touch README.md LICENSE.md .gitlab-ci.yml .gitignore
    
    git add -A
    git commit -avm "Initial component structure"
    
    git remote add origin https://gitlab.example.com/components/golang.git
    
    git push
  4. CI/CDジョブをテンプレートとして作成します。buildジョブから開始します。

    • specセクションで、stagegolang_versionbinary_directoryの各入力を定義します。

    • inputs.golang_versionにアクセスして、動的なジョブ名の定義を追加します。

    • inputs.golang_versionにアクセスして、Goイメージのバージョンも同様に動的に指定します。

    • inputs.stage値にステージを割り当てます。

    • inputs.binary_directoryからバイナリディレクトリを作成し、go buildのパラメータとして追加します。

    • アーティファクトのパスをinputs.binary_directoryとして定義します。

      spec:
        inputs:
          stage:
            default: 'build'
            description: 'Defines the build stage'
          golang_version:
            default: 'latest'
            description: 'Go image version tag'
          binary_directory:
            default: 'mybinaries'
            description: 'Output directory for created binary artifacts'
      ---
      
      "build-$[[ inputs.golang_version ]]":
        image: golang:$[[ inputs.golang_version ]]
        stage: $[[ inputs.stage ]]
        script:
          - mkdir -p $[[ inputs.binary_directory ]]
          - go build -o $[[ inputs.binary_directory ]] ./...
        artifacts:
          paths:
            - $[[ inputs.binary_directory ]]
    • formatジョブテンプレートは同じパターンに従いますが、必要なのはstagegolang_versionの入力のみです。

      spec:
        inputs:
          stage:
            default: 'format'
            description: 'Defines the format stage'
          golang_version:
            default: 'latest'
            description: 'Golang image version tag'
      ---
      
      "format-$[[ inputs.golang_version ]]":
        image: golang:$[[ inputs.golang_version ]]
        stage: $[[ inputs.stage ]]
        script:
          - go fmt $(go list ./... | grep -v /vendor/)
          - go vet $(go list ./... | grep -v /vendor/)
    • testジョブテンプレートは同じパターンに従いますが、必要なのはstagegolang_versionの入力のみです。

      spec:
        inputs:
          stage:
            default: 'test'
            description: 'Defines the format stage'
          golang_version:
            default: 'latest'
            description: 'Golang image version tag'
      ---
      
      "test-$[[ inputs.golang_version ]]":
        image: golang:$[[ inputs.golang_version ]]
        stage: $[[ inputs.stage ]]
        script:
          - go test -race $(go list ./... | grep -v /vendor/)
  5. コンポーネントをテストするために、.gitlab-ci.yml設定ファイルを変更し、テストを追加します。

    • buildジョブの入力として、golang_versionに別の値を指定します。

    • CI/CDコンポーネントのパスに合わせてURLを変更します。

      stages: [format, build, test]
      
      include:
        - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/format@$CI_COMMIT_SHA
        - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/build@$CI_COMMIT_SHA
        - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/build@$CI_COMMIT_SHA
          inputs:
            golang_version: "1.21"
        - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/test@$CI_COMMIT_SHA
          inputs:
            golang_version: latest
  6. CI/CDコンポーネントをテストするためのGoソースコードを追加します。goコマンドは、ルートディレクトリにgo.modmain.goを含むGo言語プロジェクトを想定しています。

    • Goモジュールを初期化します。CI/CDコンポーネントのパスに合わせてURLを変更します。

      go mod init example.gitlab.com/components/golang
    • たとえば、Hello, CI/CD componentを出力するmain関数を持つmain.goファイルを作成します。コードコメントを使用して、GitLab Duoコード提案でGoコードを生成できます。

      // Specify the package, import required packages
      // Create a main function
      // Inside the main function, print "Hello, CI/CD Component"
      
      package main
      
      import "fmt"
      
      func main() {
        fmt.Println("Hello, CI/CD Component")
      }
    • ディレクトリツリーは次のようになります:

      tree
      .
      ├── LICENSE.md
      ├── README.md
      ├── go.mod
      ├── main.go
      └── templates
          ├── build.yml
          ├── format.yml
          └── test.yml

CI/CDテンプレートをコンポーネントに変換するセクションの残りの手順に従って、移行を完了します:

  1. 変更をコミットしてプッシュし、CI/CDパイプラインの結果を検証します。
  2. コンポーネントを作成するに記載されたガイダンスに従って、README.mdLICENSE.mdファイルを更新します。
  3. コンポーネントをリリースし、CI/CDカタログで検証します。
  4. CI/CDコンポーネントをstagingステージ/本番環境に追加します。

GitLabが管理するGoコンポーネントは、Go CI/CDテンプレートからの移行の成功例を示しており、入力とコンポーネントのベストプラクティスによって強化されています。詳細については、Gitの履歴をご覧ください。