Use tfviz in CI
The pattern is the same everywhere: create the plan, pipe its JSON into tfviz, and upload only the report.
The exported plan JSON can contain plaintext secrets. Pipe it straight into tfviz rather than saving it as an artefact. If your apply step needs the binary plan, keep it separately with restricted access. These examples assume a pinned, verified tfviz binary is already installed.
GitHub Actions
- name: Plan and report
run: |
set -euo pipefail
umask 077
mkdir -p artefacts
terraform plan -input=false -out=tfplan
terraform show -json tfplan | tfviz plan --input - --output artefacts/infra-report.html --force
- uses: actions/upload-artifact@<pinned-sha> # pin to a commit SHA
with:
name: infra-report
path: artefacts/infra-report.html
retention-days: 14
GitLab CI
infra-report:
script:
- umask 077 && mkdir -p artefacts
- terraform plan -input=false -out=tfplan
- terraform show -json tfplan | tfviz plan --input - --output artefacts/infra-report.html --force
artifacts:
paths: [artefacts/infra-report.html]
expire_in: 2 weeks
Jenkins
pipeline {
agent any
stages {
stage('Infrastructure review report') {
steps {
sh(script: '''#!/usr/bin/env bash
set -euo pipefail
set +x
umask 077
mkdir -p artefacts
plan_path=$(mktemp)
trap 'rm -f "$plan_path"' EXIT
terraform plan -input=false -out="$plan_path"
terraform show -json "$plan_path" | tfviz plan --input - --output artefacts/infra-report.html --force
''')
}
}
}
post {
success {
archiveArtifacts(artifacts: 'artefacts/infra-report.html', fingerprint: true, allowEmptyArchive: false)
}
}
}
Jenkins usually serves archived artefacts under a policy that blocks scripts. Download the report and open it locally. Don't weaken the controller's security settings just to display a diagram.
Buildkite
steps:
- label: "Infrastructure review report"
command: |
set -euo pipefail
umask 077 && mkdir -p artefacts
terraform plan -input=false -out=tfplan
terraform show -json tfplan | tfviz plan --input - --output artefacts/infra-report.html --force
artifact_paths: "artefacts/infra-report.html"
Failing the pipeline on gaps
A plan that changes infrastructure is still a success. Add --strict to fail when anything can't be fully interpreted, such as an unsupported resource type or a plan the producer reported as incomplete.
| Exit code | Meaning |
|---|---|
0 | Report written. |
1 | Processing or retrieval failed. |
2 | Invalid arguments, unsupported input, or a --strict failure. |
Sharing outside the team
Reports show approved names, IDs and network details. Apply your normal artefact access and retention controls, and use --safe-share for audiences who shouldn't see identifying details.