Terraformのコードをチームで開発する際、Pull Request (PR) を作成すると、レビュワーは terraform plan
の実行結果を基に修正の要否を判断します。なぜなら、この結果を確認することで、実際に適用される変更内容に基づいてレビューできるからです。しかし、PR内で新しい変更が加わるたびに、ローカル環境にコードをpullして terraform plan
を実行し、変更内容を確認するのは手間がかかります。また、そのような運用では、リソースに問題が発生した際に、どの変更が原因かを特定するのにも多くの時間と労力を要します。
そこで今回は、 tfcmt というツールを使用して、PRに変更内容を可視化し、レビュープロセスを効率化するとともに、変更履歴を記録することで将来的なトラブルシューティングの負担軽減を目指します。
tfcmtの概要と特徴
tfcmt は、Terraformの terraform plan
や terraform apply
の結果をGitHubのPRコメントとして自動的に投稿するツールです。このツールを活用することで、レビュワーがわざわざローカルで terraform plan
を実行する手間を省き、PR画面上で直接変更内容を確認できるようになります。主な特徴として以下の点が挙げられます:
- 変更の可視化:
terraform plan
やterraform apply
の結果を整形し、見やすい形式でPRにコメントします。 - ログの記録: PRに対して変更内容が記録されるため、将来のトラブルシューティングに役立ちます。
- チームの生産性向上: レビューの効率化により、開発サイクルの短縮が期待できます。
最低限のCI/CDパイプラインを構築する
ここでは、GitHub Actions を用いて tfcmt を組み込んだ具体的なCI/CDパイプラインの例を示します。なお、以下のパイプラインでは、 Google Cloud の Workload Identity を使用して認証を通しています。Google Cloud, AWS, Azureにおいて、OIDCを設定する際は、以下のドキュメントを参考に認証を通してください。
- Google Cloud Platform:Configuring OpenID Connect in Google Cloud Platform
- AWS:Configuring OpenID Connect in Amazon Web Services
- Azure:Configuring OpenID Connect in Azure
※Google Cloudでの設定方法の記事を書いているので、よろしければご参照ください。
Workload Identityを使ってGitHub ActionsからGoogle Cloudにアクセスする
CIの構築
ではまずはCIの部分から。.github/workflows/terraform-ci.yml
に下記コードを記述してください。
name: "Terraform-ci"
on:
pull_request:
types:
- opened
- reopened
- synchronize
paths:
- '**.tf'
- '**.tfvars'
permissions:
id-token: write
contents: read
pull-requests: write
jobs:
terraform-ci:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Authenticate to GCP
uses: google-github-actions/auth@v1
with:
workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ secrets.SERVICE_ACCOUNT }}
- name: Setup tfcmt
env:
TFCMT_VERSION: v4.0.0
run: |
wget "https://github.com/suzuki-shunsuke/tfcmt/releases/download/${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: Terraform Format
run: terraform fmt -check
- name: Terraform Init
run: terraform init
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: tfcmt plan -patch -- terraform plan -no-color -input=false
このパイプラインでは、プルリクエストに含まれる変更において、拡張子が .tf
または .tfvars
のファイルであるときのみトリガーされ、 terraform plan
の結果をPRにコメントします。
- name: Terraform Plan
if: github.event_name == 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: tfcmt plan -patch -- terraform plan -no-color -input=false
具体的にこのステップで terraform plan
の結果をPRにコメントするようにしています。また、修正のたびに terraform plan
の結果のコメントが追加されていくことを防ぐために、 -patch
オプションを使用して terraform plan
の結果を上書きするようにしています。
参考: -patch 公式ドキュメント
CDの構築
次にCDの部分。.github/workflows/terraform-cd.yml
に下記コードを記述してください。
name: "Terraform-cd"
on:
push:
branches:
- 'main'
paths:
- '**.tf'
- '**.tfvars'
permissions:
id-token: write
contents: read
pull-requests: write
jobs:
terraform-cd:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Authenticate to GCP
uses: google-github-actions/auth@v1
with:
workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ secrets.SERVICE_ACCOUNT }}
- name: Setup tfcmt
env:
TFCMT_VERSION: v4.0.0
run: |
wget "https://github.com/suzuki-shunsuke/tfcmt/releases/download/${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: Terraform Format
run: terraform fmt -check
- name: Terraform Init
run: terraform init
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: terraform plan -input=false -out=tfplan
- name: Terraform Apply
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: tfcmt apply -- terraform apply tfplan
このパイプラインでは、main
ブランチに対する push において、拡張子が .tf
または .tfvars
のファイルの変更が含まれているときのみトリガーされ、 terraform apply
の結果をPRにコメントします。
- name: Terraform Plan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: terraform plan -input=false -out=tfplan
- name: Terraform Apply
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: tfcmt apply -- terraform apply tfplan
terraform plan
において、-out=tfplan
とし、tfplan
というバイナリ形式のファイルに計画を保存し、terraform apply
でそのファイルを基に変更を適用するようにしています。
※
ブランチへの直接 push を制限するためには、ブランチルールを作成しておくことをお勧めします。詳細は ブランチ保護ルールを管理する を参考にしてくださいmain
動作確認
CIの動作検証
任意の名前で main
からブランチを切り、プロジェクトのルートに gcs_bucket.tf
ファイルを作成し、下記コードを記述してください。
resource "google_storage_bucket" "sample_bucket" {
name = "unique-bucket-name"
location = "asia-northeast1"
}
push した後、PRを作成するとCIのWorkflowが実行され、PR内に terraform plan
の結果がコメントされます。また、 terraform plan
の結果に則したラベルが追加されていることも確認できます。
CDの動作検証
次に、このPRをマージすると、main ブランチへの push となり、CDのWorkflowが実行されます。
一連のWorkflowが成功すると、 terraform apply
の結果がコメントされます。
※ terraform apply
が失敗したらこんな表示になります。
(サービスアカウントに権限をつけ忘れていた)
まとめ
今回は、Terraformコードをチームで効率よく開発・レビューするために、tfcmt
を使用して、最低限のCI/CDの構築をしました。PR作成時に自動的に terraform plan
を実行し、その結果を可視化することで、レビュワーが変更内容を直感的に把握でき、修正の要否を迅速に判断できるようになります。これにより、レビュー作業の手間を大幅に削減でき、将来的なトラブルシューティングも容易になります。tfcmt
を活用することで、チーム全体の開発プロセスが効率化され、品質の向上が期待できるでしょう。