
IssueOps でブランチデプロイを実現できる GitHub 公式アクション Branch Deploy Action (branch-deploy) を使って,Terraform の Apply-Before-Merge デプロイ (plan / apply) を自動化してみた❗️
ちなみに Branch Deploy Action に関しては2023年7月(約2年前)にまとめたことがある😀
Terraform サンプル
Branch Deploy Action のドキュメント docs/examples.md に Terraform のサンプルが載っている📝
name: branch-deploy on: issue_comment: types: [created] # The working directory where our Terraform files are located env: WORKING_DIR: terraform/ # Permissions needed for reacting and adding comments for IssueOps commands permissions: pull-requests: write deployments: write contents: write checks: read statuses: read jobs: deploy: name: deploy runs-on: ubuntu-latest if: ${{ github.event.issue.pull_request }} # only run on pull request comments environment: production-secrets # the locked down environment we pull secrets from defaults: run: working-directory: ${{ env.WORKING_DIR }} # the directory we use where all our TF files are stored steps: # The branch-deploy Action - name: branch-deploy id: branch-deploy uses: github/branch-deploy@vX.X.X # If the branch-deploy Action was triggered, checkout our branch - name: Checkout if: steps.branch-deploy.outputs.continue == 'true' uses: actions/checkout@v4 with: ref: ${{ steps.branch-deploy.outputs.sha }} # Setup Terraform on our Actions runner - uses: hashicorp/setup-terraform@ed3a0531877aca392eb870f440d9ae7aba83a6bd # pin@v1 if: steps.branch-deploy.outputs.continue == 'true' with: terraform_version: 1.1.7 # use the version of Terraform your project uses here cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }} # Run Terraform init in our working directory - name: Terraform init if: steps.branch-deploy.outputs.continue == 'true' run: terraform init # If '.noop' was used, run a Terraform plan - name: Terraform plan if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop == 'true' }} id: plan run: terraform plan -no-color continue-on-error: true # continue on error as we will handle errors later on # If '.deploy' was used, run a Terraform apply - name: Terraform apply if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }} id: apply run: terraform apply -no-color -auto-approve continue-on-error: true # continue on error as we will handle errors later on # This step writes the TF plan/apply output to $GITHUB_ENV which the branch-deploy Action will read from and post as a comment on the pull request - name: Terraform plan output if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop == 'true' }} env: TF_STDOUT: ${{ steps.plan.outputs.stdout }} run: | TF_OUTPUT="\`\`\`terraform\n${TF_STDOUT}\n\`\`\`" echo 'DEPLOY_MESSAGE<<EOF' >> $GITHUB_ENV echo "$TF_OUTPUT" >> $GITHUB_ENV echo 'EOF' >> $GITHUB_ENV - name: Terraform apply output if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }} env: TF_STDOUT: ${{ steps.apply.outputs.stdout }} run: | TF_OUTPUT="\`\`\`terraform\n${TF_STDOUT}\n\`\`\`" echo 'DEPLOY_MESSAGE<<EOF' >> $GITHUB_ENV echo "$TF_OUTPUT" >> $GITHUB_ENV echo 'EOF' >> $GITHUB_ENV # Here we handle any errors that might have occurred during the Terraform plan/apply and exit accordingly - name: Check Terraform plan output if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop == 'true' && steps.plan.outcome == 'failure' }} run: exit 1 - name: Check Terraform apply output if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' && steps.apply.outcome == 'failure' }} run: exit 1
Terraform サンプルを拡張する
今回は Branch Deploy Action のドキュメントに載っている Terraform のサンプルを参考に以下を拡張する❗️
- plan / apply 結果の出力は
GITHUB_ENV環境変数ではなく tfcmt を使う - トリガーコメントをデフォルトの
.noopと.deployから.planと.applyに変更する
tfcmt に関しては最近まとめた📝
なお issue_comment で GitHub Actions ワークフローをトリガーする場合はデフォルトブランチが GITHUB_REF に設定されてしまう仕様になっていた.そこで tfcmt plan コマンドと tfcmt apply コマンドを実行するときに --pr ${{ github.event.issue.number }} を指定して期待通りに動くようになった👌
name: branch-deploy on: issue_comment: types: [created] permissions: id-token: write pull-requests: write deployments: write contents: write checks: read statuses: read issues: write jobs: deploy: name: deploy runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }} if: ${{ github.event.issue.pull_request }} steps: - name: branch-deploy id: branch-deploy uses: github/branch-deploy@v10.4.1 with: noop_trigger: ".plan" trigger: ".apply" - name: Checkout if: steps.branch-deploy.outputs.continue == 'true' uses: actions/checkout@v4 with: ref: ${{ steps.branch-deploy.outputs.sha }} - uses: aws-actions/configure-aws-credentials@v4 if: steps.branch-deploy.outputs.continue == 'true' with: role-to-assume: arn:aws:iam::000000000000:role/xxxxx aws-region: ap-northeast-1 - uses: hashicorp/setup-terraform@v3 if: steps.branch-deploy.outputs.continue == 'true' with: terraform_version: 1.10.3 - name: Setup tfcmt if: steps.branch-deploy.outputs.continue == 'true' run: | gh release download -R suzuki-shunsuke/tfcmt v4.14.7 -p tfcmt_linux_amd64.tar.gz tar -xzf tfcmt_linux_amd64.tar.gz sudo mv tfcmt /usr/local/bin/ tfcmt --version - name: Terraform init if: steps.branch-deploy.outputs.continue == 'true' run: terraform init - name: Terraform plan if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop == 'true' }} id: plan run: tfcmt plan --pr ${{ github.event.issue.number }} --patch -- terraform plan -no-color - name: Terraform apply if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }} id: apply run: tfcmt apply --pr ${{ github.event.issue.number }} -- terraform apply -no-color -auto-approve
動作確認
期待通りになった👌
.plan (.noop)

.apply (.deploy)

関連記事
同じように Terraform の Apply-Before-Merge デプロイができる Digger に関しては以下の記事にまとめてある📝