CI/CDのコードを書く上で、開発(dev)と本番(prd)で似たようなワークフローファイルが2つあるのが、少し面倒に感じていました。そこで、1つのワークフローでブランチなどをトリガーにして、デプロイ先を自動で切り替える方法を書き留めておきます。
基本:ブランチで環境を分ける
ワークフローの前の方に、ブランチを見てデプロイ先を決める一手間を加えてみました。
試したコードはこんな感じです。id
を付けておき、後からこのステップの結果を使います。
- name: 環境を決める
id: env
run: |
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
# mainブランチなら本番
echo "environment=prd" >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" = "refs/heads/develop" ]; then
# developブランチなら開発
echo "environment=dev" >> $GITHUB_OUTPUT
fi
$GITHUB_OUTPUT
に判定結果を書き込むのがコツだと思います。
後のステップでif: steps.env.outputs.environment == 'prd'
のように書けば、環境に応じた処理の分岐ができて、認証情報の切り替えなどがすっきりしました。
応用1:タグで本番リリース
同じ要領で、条件を一つ追加すればv1.2.3
のようなバージョンタグが付いたときに本番環境へデプロイする、といったルールも作れそうです。
# ... スクリプトのelif部分に追加
elif [[ "${{ github.ref }}" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "environment=prd" >> $GITHUB_OUTPUT
応用2:マトリックスで複数環境へ
もう少し凝った使い方として、マトリックス戦略と組み合わせると、プルリクエスト時に複数のステージング環境へまとめてデプロイする、なんてこともできます。
これには、まずデプロイ先のリストを作るジョブを動かし、次にそのリストを使って一斉にデプロイする、という二段構えにします。
1. デプロイ先のリストを決めるJOB
jobs:
determine-environments:
runs-on: ubuntu-latest
outputs:
environments: ${{ steps.env-list.outputs.environments }}
steps:
- name: デプロイ先リストを作成
id: env-list
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
# プルリクならステージング環境を複数指定
echo 'environments=["stg-1", "stg-2"]' >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" = "refs/heads/main" ]; then
# mainなら本番のみ
echo 'environments=["prd"]' >> $GITHUB_OUTPUT
else
# それ以外は空リスト
echo 'environments=[]' >> $GITHUB_OUTPUT
fi
2. リストを元にデプロイするJOB
deploy:
needs: determine-environments
# リストが空でなければ実行
if: needs.determine-environments.outputs.environments != '[]'
runs-on: ubuntu-latest
strategy:
matrix:
# JSON形式のリストをマトリックスに渡す
environment: ${{ fromJson(needs.determine-environments.outputs.environments) }}
steps:
- name: ${{ matrix.environment }} へデプロイ
run: echo "Deploying to ${{ matrix.environment }}"
# ...
needs
でジョブの実行順を制御し、outputs
でリストを渡すのがポイントです。ここまでやると、変更があったサービスだけをデプロイする、といったテクい動きも実現できそうですね。
まとめ
run
ステップでデプロイ先を動的に決めるようにしたことで、ワークフローの見通しがずいぶん良くなったと感じています。
特にマトリックスと組み合わせれば、シンプルなものから複雑なものまで、プロジェクトに合わせた柔軟なデプロイができそうです。
どなたかの参考になれば嬉しいです。