environment
以下のようにjobを実行する環境を指定する
[!IMPORTANT]
環境上の variables、secrets を使用する場合のみ environment を指定する
jobs:
deployment:
runs-on: ubuntu-latest
environment: dev # 環境指定
env:
account: ${{ vars.ACCOUNT_ID }} # Environment variablesの使用
role_name: ${{ secrets.ACTIONS_ASSUME_ROLE_NAME }} # Environment secretsの使用
steps:
- name: deploy
environmentは、GitHub上に作成し、environmentごとにsecretsとvariablesを登録できる
用途
よく使われるパターンとして、
以下のようにpull request のマージ先によって環境を切り替える
on:
pull_request:
jobs:
develop:
name: Deploy Develop
if: ${{ github.base_ref == 'develop' }} # pull requestのマージ先で条件分岐
uses: ./.github/workflows/reuse_deploy_develop.yml
secrets: inherit
with:
environment_name: dev # 環境指定
on:
workflow_call:
inputs:
environment_name: # 使用する環境名を引数でもらう
required: true
type: string
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment:
name: ${{ inputs.environment_name }} # 環境指定
env:
account: ${{ vars.ACCOUNT_ID }} # Environment variablesの使用
role_name: ${{ secrets.ACTIONS_ASSUME_ROLE_NAME }} # Environment secretsの使用
steps:
- name: deploy
Deployment protection rules
Deployment protection rules を環境に対して設定しておくことで、
環境を使用するjob実行時に指定したレビュアーの承認が必要になり、承認されるまでWaiting状態となる
environment指定の集約
environmentはjobに対して指定するが、
可読性向上目的や runs-on
の使い分け、matrixを使う場合等、
どうしてもworkflowが複数job構成となることが多い
Deployment protection rulesを設定したenvironmentを以下のように3つのjobで指定すると、
各jobごとに承認待ちとなり、計3回の承認操作が必要になる
jobs:
job-1:
runs-on: ubuntu-latest
environment: dev
env:
account: ${{ vars.ACCOUNT_ID }}
steps:
- name: step-1
job-2:
runs-on: ubuntu-latest
environment: dev
env:
account: ${{ vars.ACCOUNT_ID }}
steps:
- name: step-1
job-3:
runs-on: ubuntu-latest
environment: dev
env:
account: ${{ vars.ACCOUNT_ID }}
steps:
- name: step-1
variables
承認操作を何回も行うのは面倒なので、
以下のようにenvironmentを指定したjobのoutputsを使用することで、
以降のjobでは承認操作が不要になる
jobs:
output_environment:
name: Output Environment
runs-on: ubuntu-latest
environment: dev # 環境指定
outputs:
accountId: ${{ vars.ACCOUNT_ID }} # Environment variablesを出力する
steps:
- name: Checkout
uses: actions/checkout@v4
job-1: # environmentは指定しない
name: Job 1
needs: [output_environment]
runs-on: ubuntu-latest
env:
account: ${{ needs.output_environment.outputs.accountId }} # Environment variablesの代わりにjobのoutputsを使用する
steps:
- name: step-1
secrets
secretsをoutputするとマスクされた文字列***
が出力され後続jobで使用できない
これを解決するためにsecretsは暗号化してoutput、後続jobで復号化する
暗号化にはbase64とGPGを組み合わせたものを使用(base64だけでは上手くいかず)
ただしsecretsを暗号化/復号化を行うと全く別文字列扱いとなり、
ログ等にマスクされていないsecretsが出力されてしまう
そのため、復号化時に::add-mask::
を使ってマスクする
以下、暗号化/復号化の実装例
name: Encrypt secret
inputs:
secret: # 暗号化したいsecrets
required: true
type: string
outputs:
enc_secret: # 暗号化したsecrets
value: ${{ steps.encrypt_secret.outputs.enc_secret }}
runs:
using: 'composite'
steps:
- name: encrypt secret
id: encrypt_secret
shell: bash
run: |
enc_secret=$(gpg --symmetric --batch --passphrase "SECRET" --output - <(echo "${{ inputs.secret }}") | base64 -w0)
echo "enc_secret=${enc_secret}" >> $GITHUB_OUTPUT
name: Decrypt secret
inputs:
enc_secret: # 暗号化されたsecrets
required: true
type: string
outputs:
dec_secret: # 復号化したsecrets
value: ${{ steps.decrypt_secret.outputs.dec_secret }}
runs:
using: 'composite'
steps:
- name: decrypt secret
id: decrypt_secret
shell: bash
run: |
dec_secret=$(gpg --decrypt --quiet --batch --passphrase "SECRET" --output - <(echo "${{ inputs.enc_secret }}" | base64 --decode))
echo "::add-mask::$dec_secret"
echo "dec_secret=${dec_secret}" >> $GITHUB_OUTPUT
以下secretsを出力した例
jobs:
output_environment:
name: Output Environment
runs-on: ubuntu-latest
environment: dev # 環境指定
outputs:
accountId: ${{ vars.ACCOUNT_ID }}
enc_roleName: ${{ steps.encrypt_roleName.outputs.enc_secret }} # 暗号化したsecretsを出力
steps:
- name: Checkout
uses: actions/checkout@v4
- name: encrypt roleName
id: encrypt_roleName
uses: ./.github/actions/encrypt-secret
with:
secret: ${{ secrets.ACTIONS_ASSUME_ROLE_NAME }}
job-1: # environmentは指定しない
name: Job 1
needs: [output_environment]
runs-on: ubuntu-latest
env:
account: ${{ needs.output_environment.outputs.accountId }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: decrypt roleName
id: decrypt_roleName
uses: ./.github/actions/decrypt-secret
with:
enc_secret: ${{ needs.output_environment.outputs.enc_roleName }}