A GitHub Action that runs terraform plan and posts a formatted comment to your pull request.
Subsequent pushes to the PR's branch will update the existing comment with the latest plan.
This makes it easy for reviewers (who won't have access to run terraform plan) to quickly and easily see what infrastructure changes would be applied by the PR.
- Updates existing comments instead of creating duplicates
- Collapsible sections for plan output and state refresh output
- handles large plans gracefully-ish with truncation
- Shows plan summary, count of import/create/update/destroy
- Multi-directory support via
working-directoryinput (for mono repos) - Terraform workspace support - works with multiple workspaces (dev/staging/prod)
- Accessibility themes - colorblind-friendly emoji options
name: Terraform Plan
on:
pull_request:
branches: [main]
jobs:
plan:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
id-token: write # If using OIDC
steps:
- uses: actions/checkout@v6
# Configure your cloud credentials (example: AWS OIDC)
- uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::123456789:role/my-role
aws-region: us-east-2
# Run the plan
# There are semantic versions (`v1.1.15`), `v1` will _always_ point to the latest `1.x.x`.
- uses: thekbb/terraform-plan-commenter-action@v1| Input | Description | Required | Default |
|---|---|---|---|
github-token |
GitHub token for posting PR comments | No | ${{ github.token }} |
working-directory |
Directory containing Terraform configuration | No | . |
terraform-version |
Terraform version to use | No | latest |
setup-terraform |
Whether to setup Terraform (set false if already configured) |
No | true |
init-args |
Additional arguments for terraform init |
No | '' |
plan-args |
Additional arguments for terraform plan |
No | '' |
summary-theme |
Emoji theme: default, colorblind, or minimal |
No | default |
| Output | Description |
|---|---|
plan-exit-code |
Exit code from terraform plan (0=no changes, 1=error, 2=changes) |
has-changes |
Whether the plan has changes (true/false) |
plan-stdout |
Standard output from terraform plan |
Though Terraform state locking will keep you safe from concurrent runs, It's possible that Multiple commits in the same PR, or multiple PRs may collide with each other or a Terraform apply in a different GitHub action - which may require manually unlocking terraform state.
You should use GitHub actions concurrency to queue up jobs. You'll need to get fancier if you have multiple workspaces, or a matrix setup - action inputs and matrix values will help make the group name.
concurrency:
group: terraform
cancel-in-progress: false- uses: thekbb/terraform-plan-commenter-action@v1
with:
terraform-version: '1.14.3'- uses: thekbb/terraform-plan-commenter-action@v1
with:
working-directory: 'infrastructure/'- uses: thekbb/terraform-plan-commenter-action@v1
with:
plan-args: '-var-file=prod.tfvars'If you're using a matrix or already have Terraform configured:
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: '1.14.3'
terraform_wrapper: false # Important if capturing output
- uses: thekbb/terraform-plan-commenter-action@v1
with:
setup-terraform: 'false'- uses: thekbb/terraform-plan-commenter-action@v1
with:
summary-theme: 'colorblind'Available themes:
| Theme | Import | Create | Update | Destroy |
|---|---|---|---|---|
default |
π΅ | π’ | π‘ | π΄ |
colorblind |
π₯ | β | βοΈ | β |
minimal |
[import] | [create] | [update] | [destroy] |
The action automatically detects your Terraform workspace:
- Workspaces: Detects the current workspace (via
terraform workspace show) and creates separate comments for each workspace (dev/staging/prod) - Monorepos: Each
working-directorygets its own independent comment - Matrix builds: Jobs running different workspace/directory combinations maintain separate comments
Select the workspace before running the action:
- name: Select Terraform workspace
run: terraform workspace select staging || terraform workspace new staging
working-directory: ./infrastructure
- uses: thekbb/terraform-plan-commenter-action@v1
with:
working-directory: ./infrastructurestrategy:
matrix:
workspace: [dev, staging, prod]
steps:
- uses: actions/checkout@v6
- name: Configure AWS
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::123456789:role/terraform-${{ matrix.workspace }}
aws-region: us-east-1
- name: Select workspace
run: terraform workspace select ${{ matrix.workspace }} || terraform workspace new ${{ matrix.workspace }}
- uses: thekbb/terraform-plan-commenter-action@v1Each workspace gets its own independent PR comment that updates separately!
The action posts a comment like this:
π΅ import
2Β· π’ create3Β· π‘ update1Β· π΄ destroy0Terraform used the selected providers to generate the following execution plan:Pusher: @username, Action:
pull_request
For strict environments, pin to a full semantic version or full SHA:
uses: thekbb/terraform-plan-commenter-action@v1.1.15or
uses: thekbb/terraform-plan-commenter-action@<full-commit-sha>See CONTRIBUTING.md for development setup.
