Files
Toru Makabe 1b9ff37cf9 Add terraform-azurerm-set-diff-analyzer skill
Add a new skill that analyzes Terraform plan JSON output for AzureRM Provider
to distinguish between false-positive diffs (order-only changes in Set-type
attributes) and actual resource changes.

This skill helps users identify 'noise' in terraform plan output caused by
Azure API returning Set elements in different order, making plan reviews
easier and reducing confusion in CI/CD pipelines.

Bundled assets:
- references/azurerm_set_attributes.json
- references/azurerm_set_attributes.md
- scripts/analyze_plan.py
2026-01-29 19:33:19 +09:00

5.2 KiB

Terraform AzureRM Set Diff Analyzer Script

A Python script that analyzes Terraform plan JSON and identifies "false-positive diffs" in AzureRM Set-type attributes.

Overview

AzureRM Provider's Set-type attributes (such as backend_address_pool, security_rule, etc.) don't guarantee order, so when adding or removing elements, all elements appear as "changed". This script distinguishes such "false-positive diffs" from actual changes.

Use Cases

  • As an Agent Skill (recommended)
  • As a CLI tool for manual execution
  • For automated analysis in CI/CD pipelines

Prerequisites

  • Python 3.8 or higher
  • No additional packages required (uses only standard library)

Usage

Basic Usage

# Read from file
python analyze_plan.py plan.json

# Read from stdin
terraform show -json plan.tfplan | python analyze_plan.py

Options

Option Short Description Default
--format -f Output format (markdown/json/summary) markdown
--exit-code -e Return exit code based on changes false
--quiet -q Suppress warnings false
--verbose -v Show detailed warnings false
--ignore-case - Compare values case-insensitively false
--attributes - Path to custom attribute definition file (built-in)
--include - Filter resources to analyze (can specify multiple) (all)
--exclude - Filter resources to exclude (can specify multiple) (none)

Exit Codes (with --exit-code)

Code Meaning
0 No changes, or order-only changes
1 Actual Set attribute changes
2 Resource replacement (delete + create)
3 Error

Output Formats

Markdown (default)

Human-readable format for PR comments and reports.

python analyze_plan.py plan.json --format markdown

JSON

Structured data for programmatic processing.

python analyze_plan.py plan.json --format json

Example output:

{
  "summary": {
    "order_only_count": 3,
    "actual_set_changes_count": 1,
    "replace_count": 0
  },
  "has_real_changes": true,
  "resources": [...],
  "warnings": []
}

Summary

One-line summary for CI/CD logs.

python analyze_plan.py plan.json --format summary

Example output:

🟢 3 order-only | 🟡 1 set changes

CI/CD Pipeline Usage

GitHub Actions

name: Terraform Plan Analysis

on:
  pull_request:
    paths:
      - '**.tf'

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        
      - name: Terraform Init & Plan
        run: |
          terraform init
          terraform plan -out=plan.tfplan
          terraform show -json plan.tfplan > plan.json
          
      - name: Analyze Set Diff
        run: |
          python path/to/analyze_plan.py plan.json --format markdown > analysis.md
          
      - name: Comment PR
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          path: analysis.md

GitHub Actions (Gate with Exit Code)

      - name: Analyze and Gate
        run: |
          python path/to/analyze_plan.py plan.json --exit-code --format summary
        # Fail on exit code 2 (resource replacement)
        continue-on-error: false

Azure Pipelines

- task: TerraformCLI@0
  inputs:
    command: 'plan'
    commandOptions: '-out=plan.tfplan'

- script: |
    terraform show -json plan.tfplan > plan.json
    python scripts/analyze_plan.py plan.json --format markdown > $(Build.ArtifactStagingDirectory)/analysis.md
  displayName: 'Analyze Plan'

- task: PublishBuildArtifacts@1
  inputs:
    pathToPublish: '$(Build.ArtifactStagingDirectory)/analysis.md'
    artifactName: 'plan-analysis'

Filtering Examples

Analyze only specific resources:

python analyze_plan.py plan.json --include application_gateway --include load_balancer

Exclude specific resources:

python analyze_plan.py plan.json --exclude virtual_network

Interpreting Results

Category Meaning Recommended Action
🟢 Order-only False-positive diff, no actual change Safe to ignore
🟡 Actual change Set element added/removed/modified Review the content, usually in-place update
🔴 Resource replacement delete + create Check for downtime impact

Custom Attribute Definitions

By default, uses references/azurerm_set_attributes.json, but you can specify a custom definition file:

python analyze_plan.py plan.json --attributes /path/to/custom_attributes.json

See references/azurerm_set_attributes.md for the definition file format.

Limitations

  • Only AzureRM resources (azurerm_*) are supported
  • Some resources/attributes may not be supported
  • Comparisons may be incomplete for attributes containing after_unknown (values determined after apply)
  • Comparisons may be incomplete for sensitive attributes (they are masked)