.gitlab-ci.ymlをincludeキーワードでモジュール化する

gitlabのciを構築するyaml構文にはincludeキーワードで、ほかのyamlを利用することができる

docs.gitlab.com

挙動としてはCのincludeとほぼ同じで、指定したyamlの内容テキストを指定元のyamlにコピーする形。そのため変数の値は展開されず変数定義がコピーされてコピー後に評価される。include参照先のプロジェクト変数を参照してるyamlをincludeしてもプロジェクト変数は持ってこられないんじゃないかな。調べる。

これ使ったら.gitlab-ci.ymlの記述を共通化するためのユーティリティプロジェクト作って、それで省力・共通化できんじゃね?って思ったので調べる

ユーザー名jump24dでプロジェクト名がgitlab-ci-utilityだからそこは適宜自分のに置き換えて読むこと

目的

テスト実行など、よく使うyamlパターンを自作テンプレートプロジェクトに保存して、それを複数プロジェクトでincludeすることでテスト機能を実現する

今回のテスト実行は以下の機能を備える。include先で各機能が実現できたらOK

  • npm testを行えること
    • 行う内容は各プロジェクト依存
  • テスト結果をgitlabのtestタブに表示すること

できればAllure Reportもやる

  • テスト結果をAllure ReportとしてGitlab Pagesに出力する
  • テスト結果を保存して、次回以降履歴として保存できる
    • 履歴を保存するブランチをinclude先で指定できるかしらべる
  • 履歴を持つAllure Reportを出力する

とりあえず簡単に試す

ユーティリティプロジェクトyaml

ファイル名はplaywright.test.ymlとした。一応gitlabのtemplateプロジェクトの命名が参考元 プロジェクト名はjump24d/gitlab-ci-utility

stages:
  - test
  - allure
  - deploy

.download_history:
  after_script:
    - apt-get update
    - apt-get upgrade -y
    - apt-get install -y unzip
    - mkdir backup && cd backup || true
    - "curl --location --output report.zip --request GET \"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/artifacts/main/download?job=pages\" --header \"Authorization: Bearer ${CI_DEPLOY_TOKEN}\" || true"
    - (unzip report.zip) || true
    - cd ../
    - (cp -r backup/public/history/ allure-results/history) || true

.test_template:
  allow_failure: true
  stage: test
  image: mcr.microsoft.com/playwright:v1.41.2-jammy
  script:
    - npm install @playwright/test
    - npx playwright test
  artifacts:
    when: always
    paths:
      - allure-results/
    reports:
      junit: results.xml

smoke:
  extends: 
    - .download_history
    - .test_template

allure_report:
  stage: allure
  when: always
  image: timbru31/java-node
  dependencies: 
    - smoke
  script:
    - npm install
    - npx allure generate #change allure command specific to your framework
  artifacts:
    when: always
    paths:
      - allure-report/
      - allure-results/
  only:
    - main
  
pages:
  stage: deploy
  when: always
  dependencies:
    - allure_report
  script:
    - mv allure-report/ public/
  artifacts:
    paths:
      - public
    expire_in: 30 days
  only:
    - main

includeする側yaml

include:
  - project: 'jump24d/gitlab-ci-utility'
    file: 'playwright.test.yml'

は?ってなるくらいincludeする側yamlが少ないけど、実際こんなことできちゃった

完全な設定yaml

includeする側yamlのプロジェクトのパイプラインエディタに「完全な設定」ってタブがあって、そこでマージ後のプレビューがみられる様子。上二つからは以下ができる。

---
stages:
- ".pre"
- test
- allure
- deploy
- ".post"
".download_history":
  after_script:
  - apt-get update
  - apt-get upgrade -y
  - apt-get install -y unzip
  - mkdir backup && cd backup || true
  - 'curl --location --output report.zip --request GET "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/artifacts/main/download?job=pages"
    --header "Authorization: Bearer ${CI_DEPLOY_TOKEN}" || true'
  - "(unzip report.zip) || true"
  - cd ../
  - "(cp -r backup/public/history/ allure-results/history) || true"
".test_template":
  allow_failure: true
  stage: test
  image: mcr.microsoft.com/playwright:v1.41.2-jammy
  script:
  - npm install @playwright/test
  - npx playwright test
  artifacts:
    when: always
    paths:
    - allure-results/
    reports:
      junit: results.xml
smoke:
  after_script:
  - apt-get update
  - apt-get upgrade -y
  - apt-get install -y unzip
  - mkdir backup && cd backup || true
  - 'curl --location --output report.zip --request GET "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/artifacts/main/download?job=pages"
    --header "Authorization: Bearer ${CI_DEPLOY_TOKEN}" || true'
  - "(unzip report.zip) || true"
  - cd ../
  - "(cp -r backup/public/history/ allure-results/history) || true"
  allow_failure: true
  stage: test
  image: mcr.microsoft.com/playwright:v1.41.2-jammy
  script:
  - npm install @playwright/test
  - npx playwright test
  artifacts:
    when: always
    paths:
    - allure-results/
    reports:
      junit:
      - results.xml
  extends:
  - ".download_history"
  - ".test_template"
allure_report:
  stage: allure
  when: always
  image: timbru31/java-node
  dependencies:
  - smoke
  script:
  - npm install
  - npx allure generate
  artifacts:
    when: always
    paths:
    - allure-report/
    - allure-results/
  only:
  - main
pages:
  stage: deploy
  when: always
  dependencies:
  - allure_report
  script:
  - mv allure-report/ public/
  artifacts:
    paths:
    - public
    expire_in: 30 days
  only:
  - main

一応スクショ

ユーティリティプロジェクトの設計事項

include:project想定 公開するのはprojectパス、ブランチ、ファイル名

ブランチじゃなくてコミットハッシュでも良いんだけど流石にブランチ

ユーティリティプロジェクトの公開範囲は基本社内、同じGitlabインスタンス内でプロジェクトを公開できる相手になると想定する。その場合 include:projectで使ってくださいね案内になると思う。

Includeする時指定するのが節の三つ。ブランチは省略可能で省略した場合はHEADらしい。GitlabのHEADってどこ?

バージョン戦略する意味あるか知らんけど、安全にためにrefはmain使ってくださいね。くらいはやっても良いんじゃないだろうか

Project、グループ名、ブランチ名、ファイル名はPublicになるから基本変えられないよ、と覚えとく

remote公開ならファイルの絶対パス公開

もし社内公開とかじゃなく自作ツールをCICDで使ってもらう時のテンプレート公開とかならinclude:remoteで使われることを想定

その場合基本的にGitlabで表示されるそのファイルのURLを公開することになる。詳細は以下

docs.gitlab.com

個別プロジェクト

各includeファイルの内容を把握しておく

複数includeとか個別側に書いたのとかで定義被ったら後勝ちになるから、どこで何が入るか全部抑えないといけない事を意識すること。includeって参照じゃなく全コピペしてるのと変わらないから

GitlabのWebパイプラインエディタ機能で完全な設定タブを何回も見るのがいいかも。ここが一番わかりやすい

基本はinclude:project

基本これで使う。参照するものはユーティリティの方参照

include:
  - project: 'jump24d/gitlab-ci-utility'
    file: 'playwright.test.yml'

変数やscriptの上書き

個別プロジェクト側でincludeしたファイルのyamlキーと同じ項目を書くことで、上書きできる

つまり

include される側

.download_history:
  after_script:
    - apt-get update
    - apt-get upgrade -y
    - apt-get install -y unzip
    - mkdir backup && cd backup || true
    - "curl --location --output report.zip --request GET \"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/artifacts/main/download?job=pages\" --header \"Authorization: Bearer ${CI_DEPLOY_TOKEN}\" || true"
    - (unzip report.zip) || true
    - cd ../
    - (cp -r backup/public/history/ allure-results/history) || true

.test_template:
  allow_failure: true
  stage: test
  image: mcr.microsoft.com/playwright:v1.41.2-jammy
  script:
    - npm install @playwright/test
    - npx playwright test
  artifacts:
    when: always
    paths:
      - allure-results/
    reports:
      junit: results.xml

smoke:
  extends: 
    - .download_history
    - .test_template

する側

smoke:
  script:
  - echo "override this!"
  - npm install @playwright/test
  - npx playwright test
  - echo "fuhahahahah!"
  - echo "Yatta!"

完全な設定yaml

smoke:
  after_script:
  - apt-get update
  - apt-get upgrade -y
  - apt-get install -y unzip
  - mkdir backup && cd backup || true
  - 'curl --location --output report.zip --request GET "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/artifacts/main/download?job=pages"
    --header "Authorization: Bearer ${CI_DEPLOY_TOKEN}" || true'
  - "(unzip report.zip) || true"
  - cd ../
  - "(cp -r backup/public/history/ allure-results/history) || true"
  allow_failure: true
  stage: test
  image: mcr.microsoft.com/playwright:v1.41.2-jammy
  script:
  - echo "override this!"
  - npm install @playwright/test
  - npx playwright test
  - echo "fuhahahahah!"
  artifacts:
    when: always
    paths:
    - allure-results/
    reports:
      junit:
      - results.xml
  extends:
  - ".download_history"
  - ".test_template"

出力

$ echo "override this!"
override this!
$ npm install @playwright/test
added 9 packages, and audited 10 packages in 2s
found 0 vulnerabilities
$ npx playwright test
Running 6 tests using 1 worker
······
  6 passed (9.8s)
$ echo "fuhahahahah!"
fuhahahahah!
$ echo "Yatta!"
Yatta!

完全な設定yamlのsmokeのscriptが見どころ。確認用のechoが足されてる

javascriptか?ってなるくらい上書きしてる。

これのおかげで実際枠組みを提供しつつ実際のテスト実行コードはプロジェクトごとに変えられるから便利な挙動。実質strategyパターン

template

include:templateは以下のプロジェクトのyamlをコピーできるらしい。使うのがありそうか調べる

gitlab.com

一応パイプライン画面とか

ちゃんとパイプライン動いてAllure Reportも履歴取れた。

ちゃんと

JUnitビューもできてる

注意点

ジョブの再実行時、include対象は再取得されない。けどパイプラインの場合はされる

ジョブとパイプラインそれぞれの実行単位で挙動が違う

要はパイプラインから実行しないとパイプラインの評価とジョブ実行しないっていうか実装優先の仕様というかほぼ挙動だと思う。

ジョブ単位の実行の場合は再生成せずその時作成されたインスタンスで再度実行されるイメージ。

「直したんで再実行してくださいね」でジョブの再実行しても無意味。新しくパイプラインから再実行でないとinclude先の変更は反映されない。