CTO室所属の高橋と申します。皆からはニャンさんと呼ばれております。そして私は特に無茶振りはされていません。
さて、developブランチに変更が入ったらdev環境にリリース、mainブランチに変更が入ったら本番環境にリリースを行う仕組み、いわゆる継続的デリバリーを構築しているプロジェクトは多いことと思う。我々のチームではCircle CIで行なっていたが事情があってGithub Actionsに移行することになった。ところがGithub Actionsではdevリリースと本番リリースの手順をどう共通化すればいいのか分からず迷ってしまった。
近年のソフトウェア開発の現場ではCI/CDは当たり前になっているが、もはや当たり前すぎて逆にまとまった情報がネット上にないのかもしれない。であれば得られた知見は共有しておくべきだろう。
結論から言うとジョブの共通化には再利用可能なワークフロー用いるのが良さそうだ。
Github Actionsでやりたいことは以下の3点。
- featureブランチの変更時にテストを実行する
- developブランチの変更時にテストを実行し、dev環境にデプロイ
- mainブランチの変更時にテストを実行し、本番環境にデプロイ
.github/workflowsに以下5つののyamlファイルを用意した。
test.yml
: featureブランチの変更時、テストを実行release-dev.yml
: devlopブランチの変更時、テストとdev環境へのデプロイを実行release-prd.yml
:mainブランチの変更時、テストと本番環境へのデプロイを実行reusable-test.yml
: テスト手順を記述した再利用可能なワークフローreusable-release.yml
: リリース手順を記述した再利用可能なワークフロー
以下、各ファイルの詳細を見ていこう
再利用可能なワークフロー
再利用可能なワークフローのファイル名には reusable-
、shared-
、common-
など、それとわかる接頭辞をつけておくといいかもしれない。
reusable-test.yml
lintとtestのジョブ手順を定義する。onにworklflow_call
を設定すると再利用可能なワークフローとなる
name: test on: workflow_call: jobs: test: runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: 'npm' - run: npm ci - run: npm run lint - run: npm run test
reusable-deploy.yml
リリースジョブの手順を定義する。このプロジェクトではmakeで以下のタスクを実行してdockerイメージの作成とCloud runへのデプロイを行なっている。
- docker build
- docker push(artifact registryにpush)
- gcloud run deploy
以下のコマンドでdevリリース、本番リリースを実行している
make deploy TARGET=dev make deploy TARGET=prd
見ての通りTARGETによってリリース先の環境を切り替えているのだが、Github Actionsではinputsという記述で再利用可能なワークフローの呼び出し元で指定可能な変数にできる。これが共通化のポイントその1。
もう一つのポイントはGoogle Cloudのサービスアカウントキーの切り替え方法。サービスアカウントキーは機密情報なのでsecretsに登録してあり、dev用と本番用で鍵を切り替えなければならない。githubのsecretsは環境という名前空間のような機能を持っており、ワークフローのenvironmentという記述でどの環境を使用するか指定できる。ここではTARGETと同じ名前で環境(devとprd)を作成し、それぞれの環境にGCP_CREDENTIALSという名前でサービスアカウントキーを登録する。そしてinputsをenvironmentに引き渡してsecretsを実行時に切り替える方法を採った。
name: deploy on: workflow_call: inputs: target: required: true type: string description: 'リリースターゲット dev or prd' jobs: deploy: runs-on: ubuntu-latest timeout-minutes: 10 environment: name: ${{ inputs.target }} steps: - uses: actions/checkout@v4 - uses: google-github-actions/auth@v2 with: credentials_json: '${{ secrets.GCP_CREDENTIALS }}' - uses: google-github-actions/setup-gcloud@v2 - name: Configure Docker run: gcloud auth configure-docker asia-northeast1-docker.pkg.dev --quiet - name: Run make deploy run: | make deploy TARGET=${{ inputs.target }}
pushで実行するワークフロー
jobsは再利用可能なワークフローを呼び出すだけ。実行の条件指定(on)の記述が主な内容となる。
test.yml
テスト実行、mainブランチとdevelopブランチはリリースジョブ内で行うので除外する。
name: Lint and Test code on: push: branches-ignore: - main - develop jobs: test: uses: ./.github/workflows/reusable-test.yml
release-dev.yml
devリリース、ここでのポイントは
secrets: inherit
、secretsを再利用可能なワークフローに引き渡す設定。workflow_dispatch
、actionsのweb画面上から手動で実行できるようにする設定。任意のブランチをdev環境にリリースすることができる
name: Release to the development environment on: push: branches: - develop workflow_dispatch: jobs: test: uses: ./.github/workflows/resuable-test.yml deploy: needs: [test] uses: ./.github/workflows/reusable-deploy.yml with: target: dev secrets: inherit
release-prd.yml
本番リリース、devとはブランチ指定とtargetが違うだけ。本番は手動リリースしないのでworkflow_dispatchはなし
name: Release to the production environment on: push: branches: - main jobs: test: uses: ./.github/workflows/resuable-test.yml deploy: needs: [test] uses: ./.github/workflows/reusable-deploy.yml with: target: prd secrets: inherit
重複する記述を完全に削除できるわけではないが、見通しのよいyamlになったのではないかと思う。