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

チュートリアル: 複雑なパイプラインを作成する

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

このチュートリアルでは、小さな手順を繰り返しながら進めて、段階的に複雑になっていくCI/CDパイプラインの設定方法を解説します。パイプラインは常に完全に機能しますが、手順ごとに機能が増えていきます。目標は、ドキュメントサイトをビルド、テスト、デプロイすることです。

このチュートリアルを完了すると、GitLab.comに新しいプロジェクトが作成され、Docusaurusを使用した機能するドキュメントサイトが完成します。

このチュートリアルを完了する手順は、次のとおりです:

  1. Docusaurusファイルを保持するプロジェクトを作成する
  2. 初期パイプライン設定ファイルを作成する
  3. サイトをビルドするジョブを追加する
  4. サイトをデプロイするジョブを追加する
  5. テストジョブを追加する
  6. マージリクエストパイプラインの使用を開始する
  7. 重複する設定を減らす

前提要件

  • GitLab.comのアカウントが必要です。
  • Gitに精通している必要があります。
  • Node.jsがローカルマシンにインストールされている必要があります。たとえば、macOSでは、brew install nodeを実行してNode.jsをインストールできます。

Docusaurusファイルを保持するプロジェクトを作成する

パイプライン設定を追加する前に、まずGitLab.comでDocusaurusプロジェクトを設定する必要があります:

  1. (グループではなく)自分のユーザー名で新しいプロジェクトを作成します:

    1. 左側のサイドバーの上部で、新規作成 plus )を選択し、新規プロジェクト/リポジトリを選択します。新しいナビゲーションをオンにしている場合、このボタンは右上隅にあります。
    2. 空のプロジェクトの作成を選択します。
    3. プロジェクトの詳細を入力します:
      • プロジェクト名フィールドに、プロジェクトの名前を入力します(例: My Pipeline Tutorial Project)。
      • リポジトリを初期化しREADMEファイルを生成するを選択します。
    4. プロジェクトを作成を選択します。
  2. プロジェクトの概要ページの右上隅でコードを選択し、プロジェクトのクローンパスを見つけます。SSHパスまたはHTTPパスをコピーし、そのパスを使用してプロジェクトのクローンをローカルに作成します。

    たとえば、SSHを使用してコンピュータ上のpipeline-tutorialディレクトリにクローンを作成するには、次のコマンドを実行します:

    git clone git@gitlab.com:my-username/my-pipeline-tutorial-project.git pipeline-tutorial
  3. プロジェクトのディレクトリに変更してから、新しいDocusaurusサイトを生成します:

    cd pipeline-tutorial
    npm init docusaurus

    Docusaurusの初期化ウィザードが、サイトに関する質問を表示します。デフォルトオプションをすべて使用します。

  4. 初期化ウィザードは、website/にサイトを設定しますが、サイトはプロジェクトのルートに配置する必要があります。ファイルをルートに移動し、古いディレクトリを削除します:

    mv website/* .
    rm -r website
  5. GitLabプロジェクトの詳細でDocusaurus設定ファイルを更新します。docusaurus.config.jsで次のように設定します:

    • url:https://<my-username>.gitlab.io/という形式のパスに設定します。
    • baseUrl:/my-pipeline-tutorial-project/のようなプロジェクト名に設定します。
  6. 変更をコミットし、GitLabにプッシュします:

    git add .
    git commit -m "Add simple generated Docusaurus site"
    git push origin

初期CI/CD設定ファイルを作成する

可能な限り単純なパイプライン設定ファイルから始めて、プロジェクトでCI/CDを有効にし、ジョブの実行にRunnerを使用できるようにします。

この手順では、次の項目について説明します:

  • ジョブ: ジョブは、パイプラインの自己完結型の要素で、コマンドを実行します。ジョブはRunner上で実行され、GitLabインスタンスから独立しています。
  • script: ジョブの設定のこのセクションでは、ジョブのコマンドを定義します。(配列内に)複数のコマンドがある場合は順番に実行されます。各コマンドは、コマンドラインインターフェース(CLI)のコマンドと同様に実行されます。デフォルトでは、コマンドが失敗するかエラーを返した場合、ジョブには失敗のフラグが立てられ、それ以降のコマンドは実行されません。

この手順では、.gitlab-ci.ymlファイルをプロジェクトのルートに作成し、次の設定を記述します:

test-job:
  script:
    - echo "This is my first job!"
    - date

この変更をコミットしてGitLabにプッシュしてから、次の手順を実行します:

  1. ビルド > パイプラインに移動し、この1つのジョブで構成されるパイプラインがGitLabで実行されることを確認してください。
  2. パイプラインを選択し、ジョブを選択してジョブのログを表示し、This is my first job!メッセージの後に日付が表示されることを確認します。

これで、プロジェクトに.gitlab-ci.ymlファイルが作成されました。以降のパイプライン設定の変更はすべて、パイプラインエディタを使用して行えます。

サイトをビルドするジョブを追加する

CI/CDパイプラインの一般的なタスクは、プロジェクト内のコードをビルドし、デプロイすることです。まず、サイトをビルドするジョブを追加します。

この手順では、次の項目について説明します:

  • image: ジョブの実行に使用するDockerコンテナをRunnerに指示します。Runnerは次の処理を行います:
    1. コンテナイメージをダウンロードして起動します。
    2. 実行中のコンテナにGitLabプロジェクトのクローンを作成します。
    3. script内のコマンドを1つずつ実行します。
  • artifacts: ジョブは自己完結型で、互いにリソースを共有しません。あるジョブで生成されたファイルを別のジョブで使用する場合は、まずそれらをアーティファクトとして保存する必要があります。そうすると、後のジョブでアーティファクトを取得し、生成されたファイルを使用できます。

この手順では、test-jobbuild-jobに置き換えます:

  • imageを使用して、最新のnodeイメージで実行するようにジョブを設定します。DocusaurusはNode.jsプロジェクトであり、必要なnpmコマンドがnodeイメージに組み込まれています。
  • npm installを実行してDocusaurusを実行中のnodeコンテナにインストールし、npm run buildを実行してサイトをビルドします。
  • Docusaurusはビルドされたサイトをbuild/に保存するため、artifactsを指定してこれらのファイルを保存します。
build-job:
  image: node
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

パイプラインエディタを使用して、このパイプライン設定をデフォルトブランチにコミットし、ジョブログを確認します。次のことが可能です:

  • npmコマンドが実行され、サイトがビルドされるのを確認します。
  • 最後にアーティファクトが保存されていることを確認します。
  • ジョブの完了後、ジョブログの右側にある閲覧を選択し、アーティファクトファイルの内容を参照します。

サイトをデプロイするジョブを追加する

build-jobでDocusaurusサイトがビルドされることを確認したら、そのサイトをデプロイするジョブを追加できます。

この手順では、次の項目について説明します:

  • stagestages: 最も一般的なパイプライン設定では、ジョブをステージにグループ化します。同じステージ内のジョブは並行して実行できますが、後のステージのジョブは前のステージのジョブが完了するまで待機します。ジョブが失敗した場合、ステージ全体が失敗と見なされ、後のステージのジョブは実行されません。
  • GitLab Pages: 静的サイトをホストするには、GitLab Pagesを使用します。

この手順では、以下を実行します:

  • ビルドされたサイトをフェッチしてデプロイするジョブを追加します。GitLab Pagesを使用する場合、ジョブは常にpagesという名前になります。build-jobからのアーティファクトは自動的にフェッチされ、ジョブで使用できるように展開されます。ただし、Pagesはpublic/ディレクトリ内でサイトを探すため、サイトをそのディレクトリに移動するscriptコマンドを追加します。
  • stagesセクションを追加し、各ジョブのステージを定義します。build-jobbuildステージで最初に実行され、pagesはその後のdeployステージで実行されます。
stages:          # List of stages for jobs and their order of execution
  - build
  - deploy

build-job:
  stage: build   # Set this job to run in the `build` stage
  image: node
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

pages:
  stage: deploy  # Set this new job to run in the `deploy` stage
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"

パイプラインエディタを使用して、このパイプライン設定をデフォルトブランチにコミットし、パイプラインリストでパイプラインの詳細を表示します。以下を確認します:

  • 2つのジョブがbuilddeployの異なるステージで実行されること。
  • pagesジョブが完了した後に、pages:deployジョブが表示されること。このジョブは、PagesサイトをデプロイするGitLabプロセスです。そのジョブが完了すると、新しいDocusaurusサイトにアクセスできます。

サイトを表示するには、次の手順に従います:

  • 左側のサイドバーで、デプロイ > Pagesを選択します。
  • 一意のドメインを使用がオフになっていることを確認します。
  • ページへアクセスで、リンクを選択します。URLの形式は、https://<my-username>.gitlab.io/<project-name>のようになります。詳細については、GitLab Pagesのデフォルトドメイン名を参照してください。

一意のドメインを使用する必要がある場合は、docusaurus.config.jsbaseUrl: を/に設定します。

テストジョブを追加する

サイトが期待どおりにビルドおよびデプロイされるようになったので、テストとLintを追加できます。たとえば、RubyプロジェクトではRSpecテストジョブを実行する可能性があります。DocusaurusはMarkdownおよび生成されたHTMLを使用する静的サイトであるため、このチュートリアルではMarkdownとHTMLをテストするジョブを追加します。

この手順では、次の項目について説明します:

  • allow_failure: 断続的に失敗するジョブや、失敗が予想されるジョブは、生産性を低下させたり、問題の解決を難しくしたりする可能性があります。allow_failureを使用すると、ジョブが失敗してもパイプラインの実行は停止しません。
  • dependencies: dependenciesを使用して、アーティファクトをフェッチするジョブを指定することで、個々のジョブにおけるアーティファクトのダウンロードを制御します。

この手順では、以下を実行します:

  • builddeployの間で実行する新しいtestステージを追加します。これらの3つのステージは、設定でstagesが定義されていない場合のデフォルトステージです。
  • markdownlintを実行してプロジェクト内のMarkdownを確認するためのlint-markdownジョブを追加します。markdownlintは、Markdownファイルが書式設定の標準に準拠していることを確認する静的解析ツールです。
    • Docusaurusが生成するサンプルMarkdownファイルは、blog/docs/にあります。
    • このツールは元のMarkdownファイルのみをスキャンするため、build-jobアーティファクトに保存されている生成されたHTMLは必要ありません。そのためdependencies: []を指定して、ジョブがアーティファクトをフェッチしないようにして実行時間を短縮します。
    • いくつかのサンプルMarkdownファイルは、デフォルトのmarkdownlintルールに違反しているため、allow_failure: trueを追加して、ルール違反があってもパイプラインを続行できるようにします。
  • test-htmlジョブを追加してHTMLHintを実行し、生成されたHTMLを確認します。HTMLHintは、生成されたHTMLに既知の問題がないかをスキャンする静的解析ツールです。
  • test-htmlpagesのどちらも、build-jobアーティファクトに保存されている生成されたHTMLを必要とします。ジョブはデフォルトで前のステージのすべてのジョブからアーティファクトをフェッチしますが、今後のパイプラインの変更後にジョブが誤って他のアーティファクトをダウンロードしないように、dependencies:を追加します。
stages:
  - build
  - test               # Add a `test` stage for the test jobs
  - deploy

build-job:
  stage: build
  image: node
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

lint-markdown:
  stage: test
  image: node
  dependencies: []     # Don't fetch any artifacts
  script:
    - npm install markdownlint-cli2 --global           # Install markdownlint into the container
    - markdownlint-cli2 -v                             # Verify the version, useful for troubleshooting
    - markdownlint-cli2 "blog/**/*.md" "docs/**/*.md"  # Lint all markdown files in blog/ and docs/
  allow_failure: true  # This job fails right now, but don't let it stop the pipeline.

test-html:
  stage: test
  image: node
  dependencies:
    - build-job        # Only fetch artifacts from `build-job`
  script:
    - npm install --save-dev htmlhint                  # Install HTMLHint into the container
    - npx htmlhint --version                           # Verify the version, useful for troubleshooting
    - npx htmlhint build/                              # Lint all markdown files in blog/ and docs/

pages:
  stage: deploy
  dependencies:
    - build-job        # Only fetch artifacts from `build-job`
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"

このパイプライン設定をデフォルトブランチにコミットし、パイプラインの詳細を表示します。

  • サンプルMarkdownがデフォルトのmarkdownlintルールに違反しているためlint-markdownジョブは失敗しますが、失敗が許可されています。次のことが可能です:
    • 今回は違反を無視します。チュートリアルの一部として修正する必要はありません。
    • Markdownファイルの違反を修正します。次に、allow_failurefalseに変更するか、allow_failureを完全に削除できます。allow_failure: falseは、定義されていない場合のデフォルトの動作です。
    • markdownlint設定ファイルを追加して、アラート対象のルール違反を制限します。
  • Markdownファイルの内容を変更し、次のデプロイ後にサイトでその変更を確認することもできます。

マージリクエストパイプラインの使用を開始する

前述のパイプライン設定では、パイプラインが正常に完了するたびにサイトがデプロイされますが、これは理想的な開発ワークフローではありません。フィーチャーブランチとマージリクエストから作業し、変更をデフォルトブランチにマージする場合にのみサイトをデプロイすることをおすすめします。

この手順では、次の項目について説明します:

  • rules: 各ジョブにルールを追加して、ジョブを実行するパイプラインを設定します。マージリクエストパイプラインスケジュールされたパイプライン、またはその他の特定の状況で実行するようにジョブを設定できます。ルールは上から順に評価され、ルールが一致した場合、そのジョブはパイプラインに追加されます。
  • CI/CD変数: これらの環境変数を使用して、設定ファイルおよびスクリプトコマンドでジョブの動作を設定します。定義済みCI/CD変数は、手動で定義する必要がない変数です。これらはパイプラインに自動的に挿入されるため、パイプラインの設定に使用できます。変数は通常$VARIABLE_NAMEの形式で設定され、定義済み変数には通常$CI_のプレフィックスが付けられます。

この手順では、以下を実行します:

  • 新しいフィーチャーブランチを作成し、デフォルトブランチではなくそのブランチで変更を行います。
  • 各ジョブにrulesを追加します:
    • サイトは、デフォルトブランチへの変更がある場合にのみデプロイされるようにします。
    • 他のジョブは、マージリクエストまたはデフォルトブランチのすべての変更に対して実行されるようにします。
  • このパイプライン設定では、ジョブを実行せずにフィーチャーブランチから作業できるため、リソースを節約できます。変更を検証する準備ができたら、マージリクエストを作成し、マージリクエストで実行するように設定されたジョブを含むパイプラインを実行します。
  • マージリクエストが承認され、変更がデフォルトブランチにマージされると、pagesデプロイメントジョブが追加された新しいパイプラインが実行されます。どのジョブも失敗しなかった場合、サイトはデプロイされます。
stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  image: node
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'  # Run for all changes to a merge request's source branch
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       # Run for all changes to the default branch

lint-markdown:
  stage: test
  image: node
  dependencies: []
  script:
    - npm install markdownlint-cli2 --global
    - markdownlint-cli2 -v
    - markdownlint-cli2 "blog/**/*.md" "docs/**/*.md"
  allow_failure: true
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'  # Run for all changes to a merge request's source branch
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       # Run for all changes to the default branch

test-html:
  stage: test
  image: node
  dependencies:
    - build-job
  script:
    - npm install --save-dev htmlhint
    - npx htmlhint --version
    - npx htmlhint build/
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'  # Run for all changes to a merge request's source branch
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       # Run for all changes to the default branch

pages:
  stage: deploy
  dependencies:
    - build-job
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH      # Run for all changes to the default branch only

マージリクエストの変更をマージします。このアクションにより、デフォルトブランチが更新されます。新しいパイプラインに、サイトをデプロイするpagesジョブが含まれていることを確認します。

今後、パイプライン設定を変更する際には、必ずフィーチャーブランチとマージリクエストを使用してください。Gitタグの作成やパイプラインスケジュールの追加といったその他のプロジェクトの変更は、それらを対象としたルールを追加しない限り、パイプラインをトリガーしません。

重複する設定を減らす

現在パイプラインに含まれている3つのジョブは、すべてrulesimageの設定が同じです。これらのルールを繰り返し記述するのではなく、extendsdefaultを使用して、信頼できる唯一の情報源を作成します。

この手順では、次の項目について説明します:

  • 非表示ジョブ: .で始まるジョブは、パイプラインに追加されません。再利用する設定を保持するために使用します。
  • extends: extendsを使用して、複数の場所で設定を繰り返し利用します。多くの場合、非表示ジョブから継承します。非表示ジョブの設定を更新すると、その非表示ジョブを拡張しているすべてのジョブが更新された設定を使用します。
  • default: 定義されていない場合に、すべてのジョブに適用されるキーワードのデフォルトを設定します。
  • YAMLのオーバーライド: extendsまたはdefaultを使用して設定を再利用する場合、ジョブ内でキーワードを明示的に定義して、extendsまたはdefaultの設定をオーバーライドできます。

この手順では、以下を実行します:

  • build-joblint-markdowntest-htmlで繰り返し使用されるルールを保持するために.standard-rules非表示ジョブを追加します。
  • extendsを使用して、3つのジョブで.standard-rulesの設定を再利用します。
  • defaultセクションを追加して、imageのデフォルトをnodeとして定義します。
  • pagesデプロイメントジョブにはデフォルトのnodeイメージは必要ないため、busybox(非常に小さく高速なイメージ)を明示的に使用します。
stages:
  - build
  - test
  - deploy

default:               # Add a default section to define the `image` keyword's default value
  image: node

.standard-rules:       # Make a hidden job to hold the common rules
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

build-job:
  extends:
    - .standard-rules  # Reuse the configuration in `.standard-rules` here
  stage: build
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

lint-markdown:
  stage: test
  extends:
    - .standard-rules  # Reuse the configuration in `.standard-rules` here
  dependencies: []
  script:
    - npm install markdownlint-cli2 --global
    - markdownlint-cli2 -v
    - markdownlint-cli2 "blog/**/*.md" "docs/**/*.md"
  allow_failure: true

test-html:
  stage: test
  extends:
    - .standard-rules  # Reuse the configuration in `.standard-rules` here
  dependencies:
    - build-job
  script:
    - npm install --save-dev htmlhint
    - npx htmlhint --version
    - npx htmlhint build/

pages:
  stage: deploy
  image: busybox       # Override the default `image` value with `busybox`
  dependencies:
    - build-job
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

マージリクエストを使用して、このパイプライン設定をデフォルトブランチにコミットします。ファイルはより単純ですが、前の手順と同じ動作をするはずです。

これでパイプライン全体が作成され、より効率的に整理されました。おつかれさまでした。この知識を活用して、CI/CD YAML構文リファレンスで残りの.gitlab-ci.ymlキーワードについて学び、独自のパイプラインを構築してみてください。