kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Branch Deploy Action で複数環境に Terraform をデプロイする

Branch Deploy Action (branch-deploy) を使って Terraform をデプロイする仕組みを以下の記事にまとめた📝プルリクエストに .plan.apply とコメントするとデプロイできるという IssueOps を実現できる👌

kakakakakku.hatenablog.com

前に書いた記事では「1つの AWS 環境」にデプロイしていた.今回は「stg / prd という複数の AWS 環境」にデプロイする仕組みを試す❗️Branch Deploy Action (branch-deploy) は .plan stg.apply stg のように環境名を指定してデプロイする機能もサポートしている👌

GitHub Actions ワークフロー

前に書いた記事に載せた GitHub Actions ワークフローをベースに変更したポイントを以下にまとめる.

まず,branch-deploy のパラメータとして environment_targets: stg,prd を指定した.デフォルトは production,development,staging になっていた.さらに stgprd 以外の環境名が指定された場合はワークフローをエラーで落とすようにした.

次に aws-actions/configure-aws-credentials@v4 を使って stg 環境と prd 環境それぞれの IAM Role を紐付けた.GitHub Environments(branch-deploy の environment ではなく GitHub リポジトリ自体の機能)のシークレットから IAM Role の ARN を取得できたらもっと簡単に実装できそう...?(うまくできなかった)

最後に init / plan / apply 実行時には working-directory: ${{ steps.branch-deploy.outputs.environment }} を指定して stg ディレクトリもしくは prd ディレクトリを作業ディレクトリとして実行できるようにした.今回 Terraform プロジェクトは以下のような簡易的なディレクトリ構成にしてある😀

├── prd
│   ├── backend.tf
│   ├── sqs.tf
│   └── terraform.tf
└── stg
    ├── backend.tf
    ├── sqs.tf
    └── terraform.tf

👾 .github/workflows/branch-deploy.yml

最終的に以下のような GitHub Actions ワークフローにした.

もっと効率的に実装することもできそうだけど...🫠

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"
          environment_targets: stg,prd

      - name: Check environment
        if: steps.branch-deploy.outputs.environment != 'stg' && steps.branch-deploy.outputs.environment != 'prd'
        run: exit 1

      - 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' && steps.branch-deploy.outputs.environment == 'stg' }}
        with:
          role-to-assume: arn:aws:iam::000000000000:role/xxxxx
          aws-region: ap-northeast-1

      - uses: aws-actions/configure-aws-credentials@v4
        if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.environment == 'prd' }}
        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
        working-directory: ${{ steps.branch-deploy.outputs.environment }}

      - 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
        working-directory: ${{ steps.branch-deploy.outputs.environment }}

      - 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
        working-directory: ${{ steps.branch-deploy.outputs.environment }}

動作確認

.plan

環境名を指定していないため期待通りエラーになった👌

.plan stg

stg 環境で plan を実行できた👌(.plan prd は基本的に同じなので省略)

stg 環境で apply を実行できた👌(.apply prd は基本的に同じなので省略)

Branch Deploy Action (branch-deploy) ドキュメント修正

Branch Deploy Action (branch-deploy) のドキュメント README.md を読んでいたら Available Commands に以下のように載っていて「もしかして .noop は環境名を指定できないの!?」と感じてしまった.試しつつ他のドキュメントも読むと実際には .noop でも環境名を指定することができた💡

.deploy
.noop
.deploy to <environment>
.deploy <stable_branch>

README.md を改善するプルリクエストを送ったらすぐに merge してもらえた🎉

github.com