こんにちは。jedipunkz🚀 です。

Terraform を運用しているとたまに Plan 結果がどうしても出てしまう事があります。また Terraform を GitHub で実行する環境を運用していると Plan 結果をうまく扱って自動化したいモチベーションも湧いてきます。この場合に Plan の差分をうまく処理してくれる GitHub Action があればなと思って作ってみました。

GitHub Actions

作成した GitHub Action は下記のレポジトリで公開しています。

https://github.com/jedipunkz/tf-plan-parser

入力・オプション設定

この GitHub Action では2つの入力オプションが利用可能です:

terraform-plan (必須)

パース対象となる Terraform Plan の出力結果を指定します。通常は前のステップで実行した terraform plan コマンドの標準出力を渡します。

ignore-resources (オプション)

無視したいリソースタイプや特定のリソースを配列形式で指定します。デフォルトは空の配列 [] です。

指定方法の例:

リソースタイプ全体を無視:

ignore-resources: '["null_resource", "local_file"]'

特定のリソースインスタンスを無視:

ignore-resources: '["null_resource.temporary", "local_file.cache"]'

リソースタイプとインスタンスの混在:

ignore-resources: '["null_resource", "aws_s3_bucket.temp", "local_file"]'

出力される情報

この Action は以下の出力を提供します。また下記は ignore-resources オプションの指定に沿って結果を出力してくれます。

  • diff-bool: 変更があるかどうかの真偽値(true または false
  • diff-count: 変更されるリソースの数
  • diff-resources: 変更されるリソースのアドレス一覧(カンマ区切り)
  • diff-raw: 生の差分データ

これらの出力を使って、後続のステップで条件分岐や通知の制御が可能です。

使い方の例

基本的な使い方

- name: Terraform Plan
  id: plan
  run: terraform plan -no-color

- name: Parse Plan
  id: parse
  uses: jedipunkz/tf-plan-parser@v1
  with:
    terraform-plan: ${{ steps.plan.outputs.stdout }}
    ignore-resources: '["null_resource", "random_id"]'

- name: Check results
  run: |
    echo "Changes detected: ${{ steps.parse.outputs.diff-bool }}"
    echo "Resource count: ${{ steps.parse.outputs.diff-count }}"

Pull Request への自動コメント

- name: Terraform Plan
  id: plan
  run: terraform plan -out=tfplan -no-color

- name: Parse Plan
  id: parse
  uses: jedipunkz/tf-plan-parser@v1
  with:
    terraform-plan: ${{ steps.plan.outputs.stdout }}
    ignore-resources: '["null_resource", "local_file"]'

- name: Comment on PR
  uses: actions/github-script@v7
  with:
    script: |
      const diffBool = '${{ steps.parse.outputs.diff-bool }}';
      const diffCount = '${{ steps.parse.outputs.diff-count }}';
      const resources = JSON.parse('${{ steps.parse.outputs.diff-resources }}');
      const diffRaw = `${{ steps.parse.outputs.diff-raw }}`;

      let body = '## Terraform Plan Parser\n\n';

      // Summary
      if (diffBool === 'true') {
        body += `✅ **Changes detected** affecting ${diffCount} resources:\n\n`;
        body += '### Changed Resources\n```\n';
        for (const resource of resources) {
          body += `${resource}\n`;
        }
        body += '```\n\n';
      } else {
        body += '✅ **No changes detected**\n\n';
      }

      // All outputs
      body += '### Outputs\n';
      body += `- **diff-bool**: \`${diffBool}\`\n`;
      body += `- **diff-count**: \`${diffCount}\`\n`;
      body += `- **diff-resources**: \`${JSON.stringify(resources)}\`\n\n`;

      // Raw plan
      if (diffRaw && diffRaw.trim()) {
        body += '### Raw Terraform Plan Output\n';
        body += '```\n' + diffRaw + '\n```\n\n';
      }

      body += '---\n*Generated by Terraform Plan Parser*';

      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: body
      })

条件分岐でのデプロイ制御

- name: Terraform Plan
  id: plan
  run: terraform plan -out=tfplan -no-color

- name: Parse Plan
  id: parse
  uses: jedipunkz/tf-plan-parser@v1
  with:
    terraform-plan: ${{ steps.plan.outputs.stdout }}
    ignore-resources: '["null_resource", "random_id", "local_file"]'

- name: Skip deployment if no changes
  if: steps.parseoutputs.diff-bool == 'false'
  run: echo "No infrastructure changes detected. Skipping deployment."

- name: Proceed with deployment
  if: steps.parseoutputs.diff-bool == 'true'
  run: |
    echo "Infrastructure changes detected: ${{ steps.parseoutputs.diff-count }} resources"
    terraform apply -auto-approve tfplan

- name: Notify on major changes
  if: steps.parseoutputs.diff-count > 10
  run: |
    echo "⚠️ Large number of changes detected (${{ steps.parseoutputs.diff-count }} resources)"
    echo "Manual review recommended"

まとめ・今後の機能追加について

今回作成したツールにより、Terraform Plan の差分解析が効率化されるかもしれないと思っています。特に下記の点で効果を期待しています。

  • 意図しない差分と重要な差分の区別が指定出来るようになった
  • Plan 結果差分に反応して通知する仕組み等に応用が効く
  • チーム全体で差分の判断基準を統一指定出来る

今後の機能追加として、以下を検討しています:

  • 差分の変更の種類(create/update/delete)ごとの分類
  • 入力・出力の拡張

ぜひ皆さんの Terraform 運用でも活用してみてください!