Open23
GitLab CIしたい
- リポジトリのルートに
.gitlab-ci.yml
を作成する -
.gitlab-ci.yml
にパイプラインを設定する - パイプラインはステージとジョブで構成する
- ステージ:
build
/test
/deploy
など - ジョブ: ステージごとの実行内容
- ステージ:
- Pythonのテンプレート
- キーワード・リファレンス
- グローバルキーワードとジョブキーワードがある
-
default
というグローバルキーワードで、デフォルトのジョブを設定する
-
poetry
を使ったバージョンを考えてみた(未テスト)
.gitlab-ci.yml
default:
image: python:latest
before_script:
- python --version
- pip --version
- pip install virtualenv
- virtualenv venv
- source venv/bin/activate
- pip install -U pip
- pip install -U poetry
- which poetry
- poetry env info --path
- poetry install
variables:
# mystmdのためにBASE_URLが必要
BASE_URL: $CI_PAGES_URL
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
cache:
paths:
- .cache/pip
- venv/
- venv/lib/python3.11/site-packages/
test:
stage: test
script:
# Run test & lint
- poetry install --with=test
- poetry run ruff check .
- poetry run ruff format --check .
- poetry run pytest --verbose
rules:
# Run test jobs in non-default branches
- if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH
build:
stage: deploy
script:
- poetry build
artifacts:
paths:
- build/*
build-python310:
image: python:3.10
stage: deploy
script:
- poetry build
rules:
# Run build jobs after test stage
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
preview:
stage: deploy
script:
- poetry install --with=docs
- cd docs; poetry run make dirhtml; cd ..;
- mkdir -p public/preview/$CI_COMMIT_REF_NAME
- mv docs/_build/dirhtml/* public/preview/$CI_COMMIT_REF_NAME/
artifacts:
paths:
- public/preview/$CI_COMMIT_REF_NAME/
expire_in: "10 days"
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
pages:
stage: deploy
scripts:
- cd docs; poetry run make dirhtml; cd ..;
- cd mystmd; poetry run myst build --html; cd ..;
- mv mystmd/_build/html/ public/
- mv docs/_build/dirhtml/ public/docs/
artifacts:
paths:
- public
expire_in: "180 days"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy:
stage: deploy
script: echo "Define your deployment script!"
environment: production
rules
rules:
- if: 条件式1
when: 実行タイミング
allow_failure: false
- if: 条件式2
when: 実行タイミング
allow_failure: false
-
12.3
で導入されたキーワード-
only
/except
の置き換えとして導入された
-
- ひとつのジョブに、複数の
rules
を設定できる - 定義できるルール
-
if
: 条件。条件にマッチしたときにパイプラインにジョブを追加する -
changes
: ファイルパス。特定のファイルに変更があったときに、パイプラインにジョブを追加する -
exists
: ファイルパスの配列。特定のファイルが存在するときに、パイプラインにジョブを追加する -
allow_failure
: ジョブが失敗しても、パイプラインを停止させないように設定できる -
variables
: 条件ごとにCI変数を設定できる -
when
:on_success
(デフォルト値) /always
/delayed
/never
/manual
。パイプラインにジョブを追加するタイミング。デフォルトはon_success
になっていて、前のステージのジョブがすべて完了したときになっている。
-
- MRしたときと、特定のブランチにプッシュしたとき
rules:
- if: $CI_MERGE_REQUEST_ID || $CI_COMMIT_REF_NAME == "main"
- デフォルトブランチにMRしたとき
rules:
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
デフォルトブランチにプッシュしたとき
rules:
- if: $CI_COMMIT_BRANCH == "main"
-
main
ブランチを直接指定してもよいが、次のように$CI_DEFAULT_BRANCH
のほうが汎用的
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-
$CI_COMMIT_BRANCH
: コミットしたブランチ名 -
$CI_DEFAULT_BRANCH
: リポジトリの設定で設定したデフォルトブランチ名
デフォルトブランチ以外にプッシュしたとき
- 機能ブランチにプッシュしたときを想定
- コードのテストなどをしたいが、GitLab Pagesには公開しなくてよい場合などに該当
rules:
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
マージリクエストしたとき
- 新規にMRしたとき or MRを更新したとき
rules:
- if: $CI_MERGE_REQUEST_ID
- MRを新規作成/更新したときはスキップしたいとき
- ブランチへのプッシュすると、プッシュ用とMR更新用で、2つのパイプラインが実行されてしまう
- パイプライン時間を節約するために、スキップ(
when: never
)してもよい
rules:
- if: $CI_MERGE_REQUEST_ID
when: never
マージしたとき
グローバル・キーワード
-
default
: ジョブのデフォルト値 -
include
: CI設定のインポート -
stages
(: ["build", "test", "deploy"]
): パイプラインの名前と順番を指定 -
variables
: パイプライン全体のCI/CD変数を設定 -
workflow
: パイプラインの実行タイプを設定
default
# .gitlab-ci.yaml
default:
image: イメージ
before_script:
- ジョブの前に実行するスクリプト
- コマンドを1つずつ記述する
build_job:
stage: build
script:
- ビルド用スクリプト
test_job:
stage: test
script:
- テスト用スクリプト
-
build_job
ジョブとtest_job
ジョブを定義する - それぞれのジョブに
default
ジョブの設定も適用される
include
-
11.4
から GitLab Free でも使えるようになったキーワード -
.gitlab-ci.yaml
を分割して作成できるようになる - インクルード対象
-
local
: 同じリポジトリ内のCI設定ファイル -
remote
: 外部URLにあるCI設定ファイル -
template
: GitLabの組み込みテンプレート -
project
: 外部のGitLabプロジェクト
-
- 読み込まれ方
- インクルードされたファイルは、ひとつの
.gitlab-ci.yml
に統合される - なので、同じ名前のジョブは上書きされてします
-
.github/workflows/アクション.yml
とはちょっと違うかも
- インクルードされたファイルは、ひとつの
include:local
# .gitlab-ci.yaml
include:
- local: "/.gitlab/workflows/build.yml"
- local: "/.gitlab/workflows/test.yml"
- local: "/.gitlab/workflows/deploy.yml"
include:template
- 組み込みテンプレート: https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates
- テンプレートの内容はそれぞれのファイルを確認する
- そのまま使えるかはわからないけど、参考になるものがたくさんある
# .gitlab-ci.yaml
include:
- template: Python.gitlab-ci.yml
- template: Workflows/Branch-Pipelines.gitlab-ci.yml
- template: Workflows/MergeRequest-Pipelines.gitlab-ci.yml
- template: Pages/Hugo.gitlab-ci.yml
- template: Pages/HTML.gitlab-ci.yml
stages
- パイプラインのステージ名と、実行する順番を設定
- 同じステージ名のジョブは並行して実行
- 前のステージ名のジョブが正常に終了したあとに、次のステージ名のジョブを実行
- デフォルト値:
[build, test, deploy]
- ステージ名(
stage
)が設定されてないジョブはtest
に割り当てられる
- ステージ名(
# .gitlab-ci.yml
stages:
- build # buildのすべてのジョブを並列実行
- test # buildのすべてのジョブが成功 -> testのすべてのジョブを並列実行
- deploy # testのすべてのジョブが成功 -> deployのすべてのジョブを並列実行
# deployのすべてのジョブが成功 -> パイプラインを passed としてマーク
workflow
-
12.5
で利用可能になったキーワード -
workflow:name
でワークフロー名を設定する -
workflow:rules
で、ワークフローを実行する条件を設定するworkflow:rules:if
workflow:rules:changes
workflow:rules:exists
-
workflow:rules:when
: ワークフローを実行するタイミング(always
/never
) workflow:rules:variables
workflow:
name: ワークフロー名
rules:
- if: 実行する条件
when: always
- if: 実行しない条件
when: never
ジョブ・キーワード
after_script
-
allow_failure
(false
) -
artifacts
(なし
) before_script
-
cache
(なし
) coverage
dast_configuration
dependencies
environment
-
except
/only
(なし
) extends
-
image
(なし
) inherit
-
interruptible
(false
) needs
pages
-
parallel
(1
) release
resource_group
-
retry
(0
) -
rules
(なし
) script
secrets
services
stage
-
tags
(なし
) -
timeout
(1 hour
) trigger
variables
-
when
(on_success
)
image
-
image: イメージ名:タグ名
- ジョブで使用するDockerイメージを設定する
- ジョブごとにイメージを変更できる
- 指定しない場合は
default
で指定したイメージに設定される
オプション
-
name
:image: イメージ名:タグ名
と同じ -
entrypoint
:- コンテナが起動するときに最初に実行されるコマンドを上書きできる
- 特定のスクリプトを必ず実行したい場合に利用する
- コマンドやオプションをリスト形式で記述する(例: `["/bin/sh", "-c"])
-
pull_policy
:if-not-present
(デフォルト) /always
/never
- イメージの取得方法を指定できる
-
services
-
services
は、image
のオプションではなく、別のキーワード - 追加のイメージを設定できる
-
script
/ before_script
/ after_script
-
script
: ジョブで実行するスクリプト -
before_script
: ジョブの前に実行するスクリプト。ツールのインストールなど -
after_script
: ジョブの後に実行するスクリプト
# .gitlab-ci.yaml
job:
stage: test
image: python:3.11
before_script:
- python --version
- pip install virtualenv
- virtualenv venv
- source venv/bin/activate
- pip install -U pip
- pip install -U poetry
- poetry install
script:
- テスト用スクリプト
cache
-
15.0
で導入されたキーワード - ジョブ間でキャッシュするファイルやディレクトリのリストを設定する
- ローカルの作業コピーにあるパスのみ設定できる
-
cache:paths
: CI設定ファイルからの相対パス-
include
キーワードで読み込んだ場合は、パス設定を確認する
-
オプション
-
paths
:[]
- キャッシュするファイルやディレクトリのパスを指定する
- 複数のパスをリスト形式で指定する
- リポジトリのルートを基準とした相対パスで指定する(要確認)
-
key
: 文字列 / ファイル名 / CI変数- キャッシュのキー(ID)を指定できる
- 同じキーのキャッシュは、ジョブ間で共有できる
- キーを持たないジョブはすべて
default
キャッシュを共有する -
${CI_COMMIT_REF_SLUG}
のようなCI変数を使って、コミットごとにキーを分けることもできる -
key: files
で特定のファイル名を指定できる
-
untracked
:false
(デフォルト) / `true- Git管理されていないファイルをすべてキャッシュするかを指定できる
-
.gitignore
で除外されているファイルなどのキャッシュされるため、キャッシュサイズが大きくなる可能性がある
-
policy
:pull-push
(デフォルト) /pull
/push
- キャッシュの利用ポリシー(=取得または保存する条件)を設定できる。
-
pull-push
: キャッシュを取得し、ジョブ終了後に新しいキャッシュを保存 -
pull
: 既存のキャッシュを取得し、新しいキャッシュは作成しない -
push
: 既存のキャッシュを取得せず、新しいキャッシュを保存
-
when
:on_success
(デフォルト)- キャッシュの保存タイミンを設定できる
-
on_success
: ジョブが成功した場合にキャッシュを保存 -
on_failure
: ジョブが失敗した場合にキャッシュを保存 -
always
: ジョブの結果に関係なく、常にキャッシュを保存
-
prefix
: 文字列- キャッシュのキーに接頭辞を設定できる
- ジョブごとにキャッシュを区別する場合に利用できる
基本的なキャッシュ設定
job_name:
cache:
paths:
- .cache/pip/
- venv/
ハッシュキーを使用したキャッシュ
job_name:
cache:
key:
files:
- poetry.lock
paths:
- .cache/pip/
- venv/
キャッシュを常に保存する
job_name:
cache:
paths:
- public/
when: always
パイプラインごとにキーを設定
default:
cache:
key: "$CI_COMMIT_REF_NAME"
paths:
- build/
stages
/ stage
- ジョブを実行するパイプライン名(=ステージ名)を設定する
- デフォルトは
build
->test
->deploy
- 同じステージ名のジョブは並列処理される
- 指定しない場合は
test
が設定される - グローバル・キーワードの
stages
で実行順をカスタマイズできる
# .gitlab-ci.yaml
stages:
- lint
- build
- test
- review
- deploy
lint_job:
stage: lint
script:
- echo "ソースコードの静的解析"
build_job:
stabe: build
script:
- echo "ビルド開始"
unit_test:
stage: test
script:
- echo "ユニットテスト開始"
review_job:
stage: review
script:
- echo "レビュー環境にデプロイ"
deploy:
stage: deploy
script:
- echo "プロダクション環境にデプロイ"
rules
と workflow
-
rules
はジョブをパイプラインに追加する条件を設定する -
workflow
はパイプラインの開始条件を設定する
マージリクエストのときだけ、パイプラインを実行したい
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
特定のブランチやタグのときのみ、パイプラインを実行したい
workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_TAG =~ /^v[0-9]+/' # v* 形式のタブ
スケジュールされたパイプラインのみ実行したい
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
workflow
とinclude
-
workflow
はルートレベルで設定できるキーワード -
stage
ごとの制御はできない(stage
ごとの条件はrules
で設定) -
include
でCI設定を分割するときにworkflow
キーワードを使える
.gitlab-ci.yml | 分割ファイル.yml |
---|---|
workflow | なし |
なし | workflow |
workflow | workflow |
- 上記の3パターンでworkflow設定ができる
- 途中で変更するのは大変だと思うので、最初にストラテジーを決めたほうがよい
- ファイルを分割したとき、ジョブ名にprefixをつけるなどして、一意にする
- 分割ファイルが読み込まれるときに、名前空間的なものはなく、ひとつの
.gitlab-ci.yml
に統合されるというイメージでよいはず - 同じ名前のジョブ名が存在した場合、あとから読み込まれたジョブ設定で上書きされる
- 設定内容に不定性が生じるので、ジョブ名は重複しないように定義することが大事
- 分割ファイルが読み込まれるときに、名前空間的なものはなく、ひとつの
設定ファイルの構造の例
.gitlab-ci.yml
.gitlab/pipelines/
|--- main.yml
|--- merge_request.yml
|--- schedule.yml
.gitlab-ci.yml
workflow:
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
include:
- local: '.gitlab/pipelines/main.yml'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
include:
- local: '.gitlab/pipelines/merge_request.yaml'
- if: '$CI_PIPELINE_SOURCE == "schedule"'
include:
- local: '.gitlab/pipelines/schedule.yml'
- when: never # 上記に該当しないときはパイプラインを開始しない
- デフォルトブランチにプッシュしたとき
- マージリクエストしたとき
- スケジュール実行したとき
- それ以外:パイプラインをスキップ