概要
普段CI/CD何使ってますか?
私はgithub actionsを使うことが多いのですが、その機能の中でreusable workflowという読んで字の如く、ワークフローを再利用できるものがあります。
よく使っているシーンとしては、開発環境と本番環境へそれぞれデプロイするのに、ワークフローは同じだけど環境変数が違うような場合です。
共通の部分(ワークフローの骨組み)だけをテンプレート化しておいて、必要な部分(環境変数)は呼び出し元で与える形になります。
ちょうどプログラムの関数と引数のようなイメージですね。
使い方の例
.env
の内容が開発環境と本番環境で違うのはよくあることだと思います。
開発環境用と本番環境用に次のようにenvファイルを用意します。
秘匿情報であるDB_PASSWORD
の値はgithub actionsのRepository secretsで指定するため、ファイル内には記載していません。
# 開発環境用
DB_MS=mysql
DB_HOST=192.168.10.11
DB_NAME=test_dev
DB_USER=dev
DB_PASSWORD=
# 本番環境用
DB_MS=mysql
DB_HOST=192.168.10.11
DB_NAME=test_prd
DB_USER=prd
DB_PASSWORD=
開発環境にデプロイする時は.env.dev
を、
本番環境にデプロイする時は.env.prd
を使います。
呼び出される側
で、早速テンプレート(呼び出される側)です。
name: Deploy Template
on:
workflow_call:
inputs:
ENV_FILE:
type: string
required: true
secrets:
DB_PASSWORD:
required: true
jobs:
test-job:
runs-on: ubuntu-latest
steps:
- name: Setup .env
run: |
cp ./${{ inputs.ENV_FILE }} ./.env
sed -i -e 's/DB_PASSWORD=.*/DB_PASSWORD=${{ secrets.DB_PASSWORD }}' ./.env
まぁデプロイテンプレートと書きつつ、デプロイに関する内容は一切書いてないんですが、大事なのは再利用できるワークフローなのでそこは目を瞑ってもらって。
やっている内容は単純で、呼び出し元から指定されたenvファイルを.env
という名前でコピーして、
.env
内のDB_PASSWORD=
を、呼び出し元から指定されたsecretsの値が含まれた形に置換します。
最初のこの部分が関数でいうところの言わば仮引数にあたります。
ワークフローの呼び出し元から、これらの値が渡されてjobs
の中で使用されます。
on:
workflow_call:
inputs:
ENV_FILE:
type: string
required: true
secrets:
DB_PASSWORD:
required: true
呼び出す側
呼び出す側は開発環境と本番環境で2つあります。
name: Dev Deploy
on:
push:
branches:
- dev
jobs:
CD:
uses: ./.github/workflows/_cd_template.yaml
with:
ENV_FILE: .env.dev
secrets:
DB_PASSWORD: ${{ $secrets.DB_PASSWORD_DEV }}
name: Prd Deploy
on:
push:
branches:
- main
jobs:
CD:
uses: ./.github/workflows/_cd_template.yaml
with:
ENV_FILE: .env.prd
secrets:
DB_PASSWORD: ${{ $secrets.DB_PASSWORD_PRD }}
両者の内容は実行するブランチとテンプレートに渡す値が違うだけです。
下記の部分が関数でいうところの言わば実引数にあたります。
with:
ENV_FILE: .env.dev
secrets:
DB_PASSWORD: ${{ $secrets.DB_PASSWORD_DEV }}
ここでDB_PASSWORD
はgithub actionsのsecretsから読み込んだ値になるため、今回の場合はRepository secretsにDB_PASSWORD_DEV
とDB_PASSWORD_PRD
を設定しておけば、それらを読み込んで、テンプレート上では同名のDB_PASSWORD
という変数名で統一できます。
まとめ
ワークフローに追加や削除などの修正をしたい時、テンプレートにまとめておくことで、そのファイルのみの修正で済みます。
またAWSやGCPにデプロイするとなると、途端に環境別の変数が増えます。
CloudRunへのデプロイで言えば、プロジェクト名、リージョン、サービスアカウント、dockerイメージ名、CloudRun名などなど。
呼び出し元では「テンプレートを呼び出す」「引数を渡す」だけにしておけばそれらの見通しも良くなります。
補足
今回はRepository secrets前提でDB_PASSWORD_DEV
とDB_PASSWORD_PRD
を設定するような形にしていますが、Environment secretsを使うことで、命名を分けずともDB_PASSWORD
という同名にすることもできます(サンプル)。
またCIもテンプレート化しておいて、CD前に必ずCIを実行するというようなCI/CDパイプラインも見通しが良くなります。
jobs:
CI:
uses: ./.github/workflows/_ci_template.yaml
CD:
needs: [CI]
uses: ./.github/workflows/_cd_template.yaml
with:
ENV_FILE: .env.prd
secrets:
DB_PASSWORD: ${{ $secrets.DB_PASSWORD }}
お試しあれ。