🙆‍♀️

【GitHub Actions】ブランチ名をもとに環境(Environments)を切り替える

2022/10/06に公開

GitHubには環境(Environments)という機能があり、productionstagingといった環境ごとにシークレットを設定することができます。

https://docs.github.com/ja/actions/deployment/targeting-different-environments/using-environments-for-deployment

よくある例だとAPP_ENVDATABASE_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はABCdevブランチの場合は123、といった具合です。

jobs:
  deploy: # デプロイを行うジョブは一つだけ
    runs-on: ubuntu-latest
    environment: ??? <- ここの値(環境)をブランチによって切り替えたい!
    steps:
      - name: deploy
        # ...デプロイ処理

environmentのところで${{ github.ref_name }}で取得したブランチ名と条件式を使って設定すればいいじゃん!と思うかもしれませんが、この段階ではリポジトリをチェックアウトしていないのでブランチ名は取得できません。

プロジェクトの規模が大きくなるほど環境によってデプロイ処理の内容も異なってくるでしょうから、ジョブを分ける形でもよいのかもしれませんが、ちょっとこれは不便ですよね...。

ということで色々調べた結果、以下のように再利用可能なワークフローを作成すれば解決できることがわかりました。


main.ymlがデプロイ処理などを行うメインのワークフローで、shared-get-gh-env.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