6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GitHub ActionsでTerragruntとtfcmtを組み合わせてplan結果を見やすくする方法

Last updated at Posted at 2023-01-28

やりたいこと

GitHub ActionsでTerragruntを使う際に、plan結果をプルリクエストにコメントする方法を調べていました。
plan結果をそのままコメントすることはできたのですが、もっと見やすくできないかと思い、気になっていたtfcmtと組み合わせてみることにしました。

Terragruntとは?

Terragruntは、Terraformをより便利にしてくれる薄いラッパーツールです。
設定をDRYに保ち、複数のTerraformモジュールの管理や、リモートステートの管理をやりやすくしてくれます。

Terraformのステートが複数ディレクトリに分かれていて、かつ依存関係があるような場合だと、必須レベルで便利なツールだと思います。
色々と便利な機能があるので、使ったことがない方はぜひ一度試してみてほしいです。

tfcmtとは?

tfcmt は terraform plan, apply の結果を GitHub の Pull Request (以下 PR) にコメントとして通知する CLI ツールです。
態々 CI のログを見にいかなくても PR のページで結果を確認でき、
なおかつ素のログに比べて非常に分かりやすいのが特徴です。

tfcmtの使い方

terraform plan, terraform applyを以下のように置き換えます。

$ tfcmt plan -- terraform plan [terraform plan の引数...]
$ tfcmt apply -- terraform apply [terraform apply の引数...]

terraformコマンドをそのままterragruntコマンドに置き換えた場合、run-allを使うことができないので、少し工夫する必要があります。

Terragruntとtfcmtを組み合わせて使う方法

terragruntコマンドのオプションで--terragrunt-tfpathを指定します。
このオプションによって、Terragrunt内部で実行されるterraformコマンドの代わりに実行されるバイナリを指定することができます。
以下のようなシェルスクリプトへのパスを指定することで、terraformコマンドの動作をカスタマイズすることができます。

terragrunt run-all plan --terragrunt-tfpath $GITHUB_WORKSPACE/.github/scripts/tfwrapper.sh

tfwrapper.sh
#!/bin/bash

set -euo pipefail

# コマンドの種類を取得(例: apply, plan, fmt...)
type=$(echo "$@" |  awk '{print $1}')

# 実行しているディレクトリ名を取得
current_dir=$(pwd | sed 's/.*\///g')

if [ "$type" == "plan" ]; then
    # planのときは-patchオプションを付ける
    # 実行ディレクトリ名をターゲットとして指定
    tfcmt -var "target:${current_dir}" plan -patch -- terraform "$@"
elif [ "$type" == "apply" ]; then
    tfcmt -var "target:${current_dir}" apply -- terraform "$@"
else
    terraform "$@"
fi

terraformコマンドの種類で条件分岐させています。
planとapplyの時はtfcmtを実行しますが、planのときは-patchオプションを付けてコメントの数を抑えています。
それ以外のコマンドはそのまま実行します。

また、tfcmtでは-var "target:foo"のようにすることで、それぞれの結果をラベルのprefixなどで区別できるようになります。
これを利用して実行ディレクトリ名をターゲットとして指定しています。

サンプルコード

ディレクトリ構成
.
├── .github
│   ├── scripts
│   │   └── tfwrapper.sh
│   └── workflows
│       └── plan.yml
└── app
    ├── envs
    │   ├── dev
    │   │   ├── app
    │   │   │   ├── 〇〇.tf
    │   │   │   └── terragrunt.hcl
    │   │   ├── cicd
    │   │   │   ├── 〇〇.tf
    │   │   │   └── terragrunt.hcl
    │   │   ├── db
    │   │   │   ├── 〇〇.tf
    │   │   │   └── terragrunt.hcl
    │   │   └── ...
    │   └── prod
    ├── modules
    │   ├── acm
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   ├── cloudfront
    │   ├── cognito
    │   └── ...
    └── shared
        ├── provider.tf
        ├── variables.tf
        └── version.tf

.github/workflows/plan.yml
name: Terraform plan
on:
  pull_request:
    branches:
      - main
      - develop
    types:
      - opened
      - synchronize

env:
  AWS_REGION: ap-northeast-1
  PROJECT: sample
  TF_VERSION: 1.3.7
  TG_VERSION: 0.43.0
  TFCMT_VERSION: 4.0.1

permissions:
  id-token: write
  contents: read
  pull-requests: write

jobs:
  plan:
    name: Terraform plan
    runs-on: ubuntu-latest

    steps:
      - name: Set env vars for dev
        if: github.base_ref == 'develop'
        run: |
          echo "ENVIRONMENT=dev" >> $GITHUB_ENV
          echo "AWS_ACCOUNT_ID=123456789012" >> $GITHUB_ENV
          echo "WORK_DIR=app/envs/dev" >> $GITHUB_ENV

      - name: Set env vars for prod
        if: github.base_ref == 'main'
        run: |
          echo "ENVIRONMENT=dev" >> $GITHUB_ENV
          echo "AWS_ACCOUNT_ID=123456789012" >> $GITHUB_ENV
          echo "WORK_DIR=app/envs/prod" >> $GITHUB_ENV

      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Terraform
        uses: hashicorp/setup-Terraform@v1
        with:
          terraform_version: ${{ env.TF_VERSION }}
          terraform_wrapper: false

      - name: Setup Terragrunt
        run: |
          sudo wget -q -O /bin/terragrunt "https://github.com/gruntwork-io/terragrunt/releases/download/v${TG_VERSION}/terragrunt_linux_amd64"
          sudo chmod +x /bin/terragrunt
          terragrunt --version

      - name: Setup tfcmt
        run: |
          wget "https://github.com/suzuki-shunsuke/tfcmt/releases/download/v${TFCMT_VERSION}/tfcmt_linux_amd64.tar.gz" -O /tmp/tfcmt.tar.gz
          tar xzf /tmp/tfcmt.tar.gz -C /tmp
          mv /tmp/tfcmt /usr/local/bin
          tfcmt --version

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@master
        with:
          role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/${{ env.PROJECT }}-${{ env.ENVIRONMENT }}-github-actions-terraform-role
          role-session-name: ${{ env.PROJECT }}-${{ env.ENVIRONMENT }}-github-actions-terraform-session
          aws-region: ${{ env.AWS_REGION }}

      - name: Terragrunt init
        working-directory: ${{ env.WORK_DIR }}
        run: terragrunt run-all init

      - name: Check terraform fmt
        working-directory: ${{ env.WORK_DIR }}
        run: terraform fmt -check -recursive

      - name: Terragrunt validate
        working-directory: ${{ env.WORK_DIR }}
        run: terragrunt run-all validate

      - name: Terragrunt plan
        working-directory: ${{ env.WORK_DIR }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          terragrunt run-all plan --terragrunt-tfpath $GITHUB_WORKSPACE/.github/scripts/tfwrapper.sh

参考

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?