🐙

GitHub Actionsでワークフローは使いまわしたいけど環境別に変数切り替えしたい場合

2022/07/15に公開

要するに、staging環境とproduction環境でやることは一緒だけど環境変数だけ切り替えて利用したい ということを実現したい。
変数受け渡し周りで意外とハマったのでメモしておく。

ブランチ・デプロイ戦略

Gitlab Flow がわかりやすいのでこれベースで説明していく。
以下のデプロイフローを想定。

  • 環境毎のブランチにpushされると、GitHub Actionsでその環境にデプロイする
     - developブランチにpushすると、develop環境にデプロイ
     - stagingブランチにpushすると、staging環境にデプロイ
     - productionブランチにpushすると、production環境にデプロイ

ファイル構成設計

以下のような感じで置くイメージ

.github/
  workflows/
    deploy.yaml            > 共通で利用できる実際に実行するワークフローyaml
    deploy_develop.yaml    > develop環境の変数を定義し、共通ワークフローを実行するyaml
    deploy_staging.yaml    > staging環境の変数を定義し、共通ワークフローを実行するyaml
    deploy_production.yaml > production環境の変数を定義し、共通ワークフローを実行するyaml

共通利用したいワークフローyamlをincludeする

利用側でusesに以下のフォーマットで指定すればOK。

deploy_develop.yaml
name: Deploy to develop

on:
  push:
    branches:
      - develop

jobs:
  deploy:
    # format: [organization]/[repo_name]/.github/workflows/[common workflow file]@[branch]
    uses: toritsuyo/iikanji-app/.github/workflows/deploy.yaml@develop

共通利用したいワークフローに変数を渡す

ここで若干ハマった。
env / secrets / with などでinclude先に渡そうにもスコープの関係で
Unrecognized named-value: xxxs
的なエラーが発生してしまい四苦八苦…

今回、結果的には secrets に直接渡すことで要件を満たすことが出来た 🎉

環境別のyamlでこんな定義をしておいて…

deploy_develop.yaml
name: Deploy to develop

on:
  push:
    branches:
      - develop

jobs:
  deploy:
    uses: toritsuyo/iikanji-app/.github/workflows/deploy.yaml@develop
    secrets:
      himitsu: ${{ secrets.himitsu_dev }}
      project_id: 'iikanji-app-dev'

共通ワークフロー側ではこんな感じでsecrets経由で変数を受け渡し出来る。

deploy.yaml
name: Deploy workflow

on:
  workflow_call:
    secrets:
      himitsu:
        description: 秘密のトークン
        required: true
      project_id:
        description: プロジェクトID
        required: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Cloud SDK
        uses: google-github-actions/setup-gcloud@v0.2.0
        with:
          project_id: ${{ secrets.project_id }}
    ...

補足: 共通利用したいワークフローで条件分岐したい場合

ifを使えば簡単に条件分岐できる。

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: checkout repo
        uses: actions/checkout@v1
      - name: step 1
        if: github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop'
        run: echo "Hello develop"
      ...


余談

Github Actions Environments を利用するともう少し良い感じに環境変数を管理することができそうです。

ちなみにGithub Actions Environmentsをざっくり説明すると、以下のようなことが出来ます。

  • 環境別に保護ルールとシークレットを持つ環境を設定できます
    • 必須のレビュー担当者を割り当て
    • 環境毎のシークレット設定
    • 環境にデプロイ出来るブランチを制限

ただ、プライベートリポジトリだと Github Enterprise Cloud契約でないとEnvironmentsが利用できなかったため、今回は利用しませんでした。

最後に

割とあるあるな要件を実現してみました。もし「こうすればもっと簡単にできるよ!」という方法があればご教示いただけると助かります!

Discussion