GitHub Actions で terraform plan を実行して Claude Code にレビューさせてみた
Claude Code GitHub Actions で terraform plan の結果をレビューする仕組みを作ってみました。
以前コードレビュー(HCL)について記事を書きました。
今回は GitHub Actions 上で terraform plan を実行し、その plan の出力(JSON)をレビュー対象にします。
今回使用したサンプルコード(スキル・ワークフロー・Terraformコード)はGitHubリポジトリ msato0731/terraform-sample に格納しました。
- ワークフロー: https://github.com/msato0731/terraform-sample/blob/main/.github/workflows/terraform-plan-review.yml
- スキル: https://github.com/msato0731/terraform-sample/blob/main/.claude/skills/terraform-plan-review/SKILL.md
- Terraformコード: https://github.com/msato0731/terraform-sample/tree/main/claude-code-terraform-plan-review
plan レビュー用スキルを作る
検証用にplanレビュー用のスキルを作成しました。
planファイルを読み込んで、リソース変更を確認します。
重大度の目安は以下にしました。
- 状態を持つリソース(RDS / EBS / S3 / DynamoDB など)の delete・replace → HIGH(データ消失)
- 想定外の delete(PR の意図にないリソースが消える)→ HIGH
- ステートレスなリソースの replace(ダウンタイムのみ)→ MEDIUM
- 1つの変更が多数リソースへ波及する場合 → 件数を明示して注意喚起
出力形式は、先頭に1行サマリ(create / update / delete / replace の件数)を置き、replace と delete を上から列挙します。
各指摘には「対象リソースアドレス・アクション・なぜ危険か・確認すべきこと」を書かせるようにしました。
GitHub Actions で plan を実行する
plan を実行するので、AWS 認証と Terraform のセットアップが要ります。
name: terraform-plan-review
on:
pull_request:
types: [opened, synchronize]
paths:
- "claude-code-terraform-plan-review/**" # このディレクトリの変更でだけ起動する
permissions:
contents: read
pull-requests: write
id-token: write
jobs:
plan-review:
runs-on: ubuntu-latest
defaults:
run:
working-directory: claude-code-terraform-plan-review
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ap-northeast-1
- uses: hashicorp/setup-terraform@v4
- run: terraform init
- run: terraform plan -out=tfplan
- run: terraform show -json tfplan > plan.json
サンプルコードを実際に動かす場合は、backend.tfの<STATE_BUCKET>の値を環境に合わせて修正してください。
terraform {
backend "s3" {
bucket = "<STATE_BUCKET>"
key = "claude-code-terraform-plan-review/terraform.tfstate"
region = "ap-northeast-1"
use_lockfile = true
}
}
plan は -out=tfplan で保存し、レビューにはその保存ファイルを terraform show -json で render した plan.json を渡します。
plan の出力を Claude にレビューさせる
prompt を指定するとコメントは自動作成されないので、投稿に使うツールを claude_args で明示許可します。
- id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ secrets.GITHUB_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
/terraform-plan-review claude-code-terraform-plan-review/plan.json をレビューしてください。
replace / delete を中心に、適用時のリスクを指摘してください。
結果は gh pr comment でトップレベルコメントとして投稿してください。
claude_args: |
--allowedTools "Read,Bash(jq:*),Bash(gh pr comment:*),Bash(gh pr view:*)"
動作確認
実際に PR を作って動かしてみます。
まずベースライン(Ubuntu AMI)を main に置き、ローカルで一度 terraform init && apply して state を S3 に保存します。
VPC と EC2 がを作成します。
次に EC2の ami_id を変更するPRを作成します。
variable "ami_id" {
type = string
- default = "ami-0d52744d6551d851e"
+ default = "ami-0a371542ad09d2434"
}
ami は変更すると再作成が必要な属性なので、plan は replace になります。
Planファイルを見ると # forces replacement 付きで確認できます。
# aws_instance.web must be replaced
-/+ resource "aws_instance" "web" {
~ ami = "ami-0d52744d6551d851e" -> "ami-0a371542ad09d2434" # forces replacement
~ arn = "<ARN>" -> (known after apply)
~ private_ip = "<PRIVATE_IP>" -> (known after apply)
~ public_ip = "<PUBLIC_IP>" -> (known after apply)
~ id = "<INSTANCE_ID>" -> (known after apply)
# ...省略...
}
Plan: 1 to add, 0 to change, 1 to destroy.
ワークフローは pull_request で起動し、1分半程度で完了しました。
OIDC 認証 → terraform init(S3 上の既存 state を読む)→ terraform plan -out=tfplan → terraform show -json → claude-code-action まで、全ステップの成功を確認できました。

投稿された PR コメントがこちらです。
## Terraform plan レビュー結果
create: 0 / update: 0 / delete: 0 / **replace: 1**
---
### [HIGH] `aws_instance.web` が replace(破棄→再作成)される
- **アクション**: replace(delete → create)
- **要因**: `ami` 属性の変更(ForceNew フィールドのため、変更すると必ず再作成)
- **リスク**: インスタンスが一度破棄されてからの再作成となる。ルート EBS ボリュームのデータが失われ、再作成完了までダウンタイムが発生する。またプライベート IP アドレスが変わる可能性がある(Elastic IP を使っていない場合)
- **確認事項**:
- AL2023 への AMI 更新は意図した変更か
- ルート EBS に保持すべきデータ(アプリケーションデータ・ログ等)がないか。あれば事前スナップショットを取得すること
- ダウンタイム許容が取れているか(Blue/Green や ASG によるローリング更新が必要でないか)
- Elastic IP を使っていない場合、IP アドレス変更による影響(DNS・セキュリティグループ・接続先設定)を確認すること

おわりに
GitHub Actions で terraform plan を実行し、その出力を Claude にレビューさせる仕組みを試してみました。
AMI 変更の PR では replace を HIGH として拾い、データ消失とダウンタイムのリスクを PR コメントに出せました。
コードのレビューだと「この書き方で何が起きるか」までしか見えませんが、plan を渡すと「実際に何が消えて何が作り直されるか」を判断材料にできます。
replace や delete の見落としを PR の段階で気づける点が便利でした。
今回作成したスキルは最小限の叩き台です。
drift や output の変更まで広げたり、重大度の基準を調整したりは運用しながら足していけます。






