概要
普段GithubやGitlabを触ることが多いのですが、CI/CDパイプラインを作成するときにどうしても一度で正確なものをプッシュできず、プッシュしてからでなければ意図したものになっているかわからないという事象に悩まされています
スクリプト自体はひとまずとして、ステージやジョブの構成が歪な状態になっているなど発生してしまいます
よく見ればわかりますが、ファイルの内容が長くなると確認に時間がかかるのも事実です
なので今回は何か手段がないかということで調べてみたところ、gitlab-ci-localというものがあったので触ってみたいと思います
本題
gitlab-ci-localとは
ローカルのDocker環境でGitLab CIをエミュレートするOSSになります
筆者の環境はMacOSなのでインストールにはbrewを使ってインストールします
brew install gitlab-ci-local
またDocker環境の構築が必要なのでそちらは別途構築していることを前提に進めたいと思います
使い方
基本的な使い方は「gitlab-ci-local」を直接実行する方法とオプションをつける方法で実行ができます
今回、サンプルで用意したのは以下のyamlファイルになります
stages:
- test
- build
- deploy
default:
image: alpine:latest
# 共通テンプレート
.test-template:
stage: test
script:
- echo "共通のテスト前処理を実行します..."
# ユニットテスト(常に実行)
unit-test:
extends: .test-template
script:
- echo "ユニットテストを実行中..."
# 統合テスト(mainブランチのみ実行)
integration-test:
extends: .test-template
script:
- echo "統合テストを実行中..."
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
# ビルドジョブ
build-job:
stage: build
script:
- echo "アプリケーションをビルドしています..."
- mkdir -p build
- echo "ビルド成果物" > build/app.bin
artifacts:
paths:
- build/
# デプロイジョブ(mainブランチのみ、かつ手動実行)
deploy-job:
stage: deploy
script:
- echo "本番環境へデプロイしています..."
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
直接実行するとmanual以外が実行されました
unit-test starting alpine:latest (test)
integration-test starting alpine:latest (test)
unit-test pulled alpine:latest in 3.45 s
integration-test pulled alpine:latest in 3.46 s
unit-test pulled docker.io/firecow/gitlab-ci-local-util:latest in 7.65 s
integration-test pulled docker.io/firecow/gitlab-ci-local-util:latest in 7.65 s
integration-test copied to docker volumes in 8.48 s
unit-test copied to docker volumes in 8.56 s
integration-test $ echo "統合テストを実行中..."
integration-test > 統合テストを実行中...
unit-test $ echo "ユニットテストを実行中..."
unit-test > ユニットテストを実行中...
integration-test finished in 13 s
unit-test finished in 13 s
build-job starting alpine:latest (build)
build-job copied to docker volumes in 731 ms
build-job $ echo "アプリケーションをビルドしています..."
build-job > アプリケーションをビルドしています...
build-job $ mkdir -p build
build-job $ echo "ビルド成果物" > build/app.bin
build-job finished in 1.46 s
build-job exported artifacts in 685 ms
build-job copied artifacts to cwd in 21 ms
PASS unit-test
PASS integration-test
PASS build-job
--listオプション
現在のブランチや環境変数などのコンテキストを考慮し、実際に実行可能なジョブのみ(when: neverや、ルールにマッチせず除外されたジョブを除いたもの)を一覧表示します
name description stage when allow_failure environment needs
unit-test test on_success false
integration-test test on_success false
build-job build on_success false
deploy-job deploy manual false
サンプルのyamlに記載の通りでstageの内容や前段のジョブ成功時に実行されることや手動実行のジョブかどうかがわかるようになっております
例えば実行しているブランチがdevelopになるとサンプルのパイプラインで実行されるのは以下になります(ブランチの指定方法については後述します)
name description stage when allow_failure environment needs
unit-test test on_success false
build-job build on_success false
こちらもルール通りにmainブランチでしか実行されないものが除外されているということが確認できました
--list-allオプション
yamlファイル内に定義されているすべてのジョブを強制的に一覧表示します
こちらはサンプルのファイルだと確認がしづらいため、ルールの部分を一時的にmain→developにすると挙動がわかりやすくなると思います
ルールの部分を一時的にmain→developにすると、--listオプションではunit-testとbuild-jobしか表示されないのですが、--list-allオプションでは全てのジョブが表示されるようになります
使い方としては--listオプションと--list-allオプションの出力結果の比較で、適切にルールが適用されているかという確認に使用することができそうだと感じました
--previewオプション
extends(テンプレート)などがすべて結合されたGitLab側で解釈される最終的なフラットなYAMLファイルの内容が出力します
---
stages:
- .pre
- test
- build
- deploy
- .post
unit-test:
stage: test
script:
- echo "ユニットテストを実行中..."
image:
name: alpine:latest
<省略>
長いので一部省略しましたが、extendsが使われていたところが展開された内容が出力されました
Gitlab側がどのように解釈しているか見えるのは非常に便利です
その他
今回はgit管理していないディレクトリでコマンドを実行しましたが、管理下のディレクトリでコマンドを実行するとブランチも追跡してくれるようです
なのでmainブランチの挙動が問題ないか、開発ブランチでは問題なく動作するかなどが確認できるようになっています
また、今回のようにgit管理していないディレクトリでもブランチを指定する方法が以下の3択で存在します
- コマンド実行時にオプションで指定するか
gitlab-ci-local --variable CI_COMMIT_BRANCH=main --list - 設定ファイル(.gitlab-ci-local-variables.yml)に書き出すか
.gitlab-ci-local-variables.yml
CI_COMMIT_BRANCH: develop CI_COMMIT_REF_NAME: develop
さらに実際の運用ではCI/CDで環境変数を使用することもあると思いますが、gitlab-ci-local-variables.ymlはそちらにも対応しています
以下のような文字列変数から、File型変数についても定義することが可能となっています
API_URL: "https://local-api.example.com"
DB_USER: "local_user"
DB_PASS: "local_password"
SSH_KEY: "~/.ssh/id_rsa"
おわりに
ということでgitlab-ci-localの紹介でした
調べていないだけで世の中には自分のニーズに合ったものが1つは存在するのかと感動しました
AIの普及によって情報を収集する手段が格段に増えたので、より活用して自分のやりたいことを実現していきたいです