【GitHub Actions】ブランチ名をもとに環境(Environments)を切り替える
GitHubには環境(Environments)という機能があり、productionやstagingといった環境ごとにシークレットを設定することができます。
よくある例だとAPP_ENVやDATABASE_URL的な秘密情報をGitHub Actionsで利用する場合に環境毎に値を切り替える、といったものでしょうか。

そしてこの機能ですが、下記のように環境をベタ書きにすることを想定されているようです。
name: Deployment
on:
push:
branches:
- main
jobs:
deploy_production:
runs-on: ubuntu-latest
environment: production # ここで環境を指定
steps:
- name: deploy
# ...productionの場合のデプロイ処理
deploy_staging:
runs-on: ubuntu-latest
environment: staging # ここで環境を指定
steps:
- name: deploy
# ...stagingの場合のデプロイ処理
これはこれでよいとして、ジョブは分けずにブランチ毎に環境を良い感じに切り替えてシークレットを利用することもできるんだろうなと思っていたのですが、なんと現在そのような機能は提供されていませんでした。
例えばmainブランチの場合のDATABASE_URLはABC、devブランチの場合は123、といった具合です。
jobs:
deploy: # デプロイを行うジョブは一つだけ
runs-on: ubuntu-latest
environment: ??? <- ここの値(環境)をブランチによって切り替えたい!
steps:
- name: deploy
# ...デプロイ処理
environmentのところで${{ github.ref_name }}で取得したブランチ名と条件式を使って設定すればいいじゃん!と思うかもしれませんが、この段階ではリポジトリをチェックアウトしていないのでブランチ名は取得できません。
プロジェクトの規模が大きくなるほど環境によってデプロイ処理の内容も異なってくるでしょうから、ジョブを分ける形でもよいのかもしれませんが、ちょっとこれは不便ですよね...。
ということで色々調べた結果、以下のように再利用可能なワークフローを作成すれば解決できることがわかりました。

main.ymlがデプロイ処理などを行うメインのワークフローで、shared-get-gh-env.ymlがブランチ名をもとに環境を判断して出力する再利用可能ワークフローです。
name: GitHubの環境名を出力
on:
workflow_call:
outputs:
# env_nameという名前で環境名を出力するよう設定
env_name:
description: "GitHubの環境名"
value: ${{ jobs.get_env_name.outputs.env_name }}
jobs:
get_env_name:
name: GitHubの環境名を出力
runs-on: ubuntu-latest
outputs:
env_name: ${{ steps.get_env_name.outputs.env_name }}
steps:
- name: Check out code
uses: actions/checkout@v2
with:
fetch-depth: 2
- name: GitHubの環境名を出力
id: get_env_name
# ブランチ名をもとに環境を判断&出力
run: |
if [ "${{ github.ref_name }}" = "main" ]; then
echo "::set-output name=env_name::production"
elif [ "${{ github.ref_name }}" = "dev" ]; then
echo "::set-output name=env_name::staging"
fi
name: Main
on:
push:
branches: ["main", "dev"]
jobs:
get_env_name:
# ここで再利用可能ワークフローを呼ぶ
# その結果、再利用可能ワークフローのoutputとして環境名が出力される
uses: ./.github/workflows/shared-get-gh-env.yml
deploy:
name: Deploy
needs: ["get_env_name"] # 再利用可能ワークフローが先に呼ばれるよう設定
runs-on: ubuntu-latest
environment:
# ここがキモで、先に実行した再利用可能ワークフローのoutputを環境として設定する
# (依存しているワークフローのoutputをneedsで取得できる)
name: ${{ needs.get_env_name.outputs.env_name }}
steps:
# ...省略
これ、最初は再利用可能ワークフローではなくアクションを作成してそれをちまちま呼ぶとか色々やっていたのですが、最終的にかなりシンプルな方法で実現できて良かったです。
では以上です。
何か不明点あればコメントください😘
Discussion