Skip to content

Usage

Quick start

- task: TerraformInstaller@0
  inputs:
    terraformVersion: 'latest'

- task: Bash@3
  displayName: 'Terraform Plan'
  inputs:
    targetType: 'inline'
    script: |
      terraform init
      terraform plan -out=tfplan

- task: TerraformPlanViewer@1
  displayName: 'Publish Terraform Plan'
  inputs:
    planPath: '$(System.DefaultWorkingDirectory)/tfplan'

After the pipeline runs, open the build and click the Plan Review tab.

The task accepts either form of plan:

  • The binary plan from terraform plan -out=tfplan — the task converts it via terraform show -json automatically.
  • The JSON form from terraform show -json tfplan > tfplan.json — useful if terraform isn't on the publishing agent.

OpenTofu

OpenTofu plans work the same way. With the default cliTool: 'auto', the task converts binary plans with terraform if it's on the agent, otherwise tofu. If both are installed, set cliTool: 'tofu' so the plan is read by the CLI that produced it:

- task: Bash@3
  displayName: 'OpenTofu Plan'
  inputs:
    targetType: 'inline'
    script: |
      tofu init
      tofu plan -out=tfplan

- task: TerraformPlanViewer@1
  displayName: 'Publish OpenTofu Plan'
  inputs:
    planPath: '$(System.DefaultWorkingDirectory)/tfplan'
    cliTool: 'tofu'

tofu must be on the PATH of the account running the agent. Passing a JSON plan (tofu show -json tfplan > tfplan.json) needs no CLI at all.

Pinning a version

TerraformPlanViewer@1 tracks the latest 1.x automatically. If your security policy requires a complete version number, see Version pinning.

Multi-stage example

Call the task once per stage with distinct attachmentName values:

- task: TerraformPlanViewer@1
  displayName: 'Publish dev plan'
  inputs:
    planPath: '$(System.DefaultWorkingDirectory)/dev/tfplan'
    attachmentName: 'dev'

- task: TerraformPlanViewer@1
  displayName: 'Publish prod plan'
  inputs:
    planPath: '$(System.DefaultWorkingDirectory)/prod/tfplan'
    attachmentName: 'prod'

Each attachmentName becomes a label in the dropdown. Sorted alphabetically, the first is selected by default.

Agent runtime

The task runs on the agent's Node.js 24 handler, with Node.js 20 kept as a fallback for older agents.

How it works

The task uploads the plan JSON as a build attachment under the type terraform-plan-viewer.plan. The tab fetches the attachment via Azure DevOps's Build REST API, parses it client-side, and renders the diff entirely in the browser. No server, no database, no third-party endpoint — plan data sits in your Azure DevOps organization the same way build logs do. See Privacy & security for the full picture.