okaryo.log

GitHubActionsで環境ごとに異なるシークレットを使用するジョブを一つのワークフローファイルで構築する | okaryo.log

GitHubActionsで環境ごとに異なるシークレットを使用するジョブを一つのワークフローファイルで構築する

    #GitHubActions#GitHub#CI/CD

はじめに

GitHubActionsでワークフローを組んでいるときに、本番環境とStaging環境に対するワークフローを組みたいがワークフロー自体は同一の内容で違うのはシークレットの値だけ、という場面があった。

ワークフローを共通化させて良い感じにするには、今まで使ったことのなかったReusable workflowというものが必要だったので残しておく。

方法

例として、本番環境とStaging環境へデプロイするためのワークフローがあり、デプロイ処理自体は同一だがシークレットの値によってデプロイ先を制御できるとする。それぞれのシークレットのキーは以下とする。

  • 本番環境: secrets.DEPLOY_KEY_PRODUCTION
  • Staging環境: secrets.DEPLOY_KEY_STAGING

このワークフローを素直に構築してしまうと以下のパターンが考えられる。

  • 同一のワークフローファイル内でifを使いながらシークレットを使い分ける
  • deploy-production.ymldeploy-staging.ymlと環境ごとにワークフローファイルを作成する

どちらの方法でも実現できるが、前者は行数が長くなるし制御が複雑で可読性に欠ける。後者は環境ごとに処理内容が重複するファイルが増えてしまい変更時などの管理が煩雑になってしまう。

これらの問題に対応するには、同一のワークフローを利用しながら異なるシークレットを同じキーとして利用できるようにしたい。これを実現できるのがReusable workflowで、共通の処理を複数のワークフローで共有することができる仕組みだ。

まずはいつものようにワークフローを作成する。mainブランチまたはdevelopブランチへのプッシュをトリガーとしている。

name: Deploy

on:
  push:
    branches:
      - main
      - develop

jobs:
  staging:
    if: github.ref == 'refs/heads/develop'
    uses: ./.github/workflows/_deploy.yml
    with:
      environment: staging
    secrets:
      DEPLOY_KEY: ${{ secrets.DEPLOY_KEY_STAGING }}

  production:
    if: github.ref == 'refs/heads/main'
    uses: ./.github/workflows/_deploy.yml
    with:
      environment: production
    secrets:
      DEPLOY_KEY: ${{ secrets.DEPLOY_KEY_PRODUCTION }}

stagingproductionという環境ごとのジョブを呼び出し、それぞれをifで制御している。stagingのジョブはdevelopブランチへのプッシュがあったとき、productionのジョブはmainブランチへのプッシュがあったときに実行されるようにしている。そして、uses: ./.github/workflows/_deploy.ymlでReusable workflowを呼び出す。このときにそれぞれの環境ごとに利用する変数とシークレットをwithsecretsでワークフローに渡す。

_deploy.ymlは以下のように設定する。

name: _Deploy

on:
  workflow_call:
    inputs:
      environment:
        type: string
        description: Name of target environment
        required: true
    secrets:
      DEPLOY_KEY:
        description: Deploy key
        required: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      run: |
        echo ${{ inputs.environment }}
        echo ${{ secrets.DEPLOY_KEY }}

workflow_callで別のワークフローから呼び出せるようにトリガーを設定する。また、inputssecretsでワークフローから渡される変数とシークレットの定義を記述する。

これで別々のシークレットであるDEPLOY_KEY_PRODUCTIONDEPLOY_KEY_STAGINGを同じワークフロー内でDEPLOY_KEYとして利用することができるようになった。

おわり

最初はoutputsを使って環境ごとのシークレットの差異を吸収してワークフローの共通化を図ったが、ワークフローにシークレットを渡せなかったり、やるとしても暗号化して復号化してと処理が煩雑になったりと試行錯誤することになってしまった。

まだまだGitHubActionsの経験値が足りないことを実感した。


関連記事
最新記事
プロモーション

This site uses Google Analytics.