Skip to content

A GitHub Action that adds opinionated comments to a PR from Terraform fmt/init/plan output

License

Notifications You must be signed in to change notification settings

k1rk/terraform-pr-commenter

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Terraform PR Commenter

This project was forked from https://github.com/robburger/terraform-pr-commenter project, originally created by Rob Burger.

Summary

This Docker-based GitHub Action is designed to work in tandem with hashicorp/setup-terraform and terraform-linters/setup-tflint with the wrapper enabled, taking the output from a fmt, init, plan, validate or tflint, formatting it and adding it to a pull request. Any previous comments from this Action are removed to keep the PR timeline clean.

The terraform_wrapper needs to be set to true for the hashicorp/setup-terraform step if using stdout, stderr and the exitcode step outputs like the below examples.

The tflint_wrapper needs to be set to true for the terraform-linters/setup-tflint step if using stdout, stderr and the exitcode step outputs like the below examples.

Support (for now) is limited to Linux as Docker-based GitHub Actions can only be used on Linux runners.

Usage

This action can only be run after a Terraform fmt, init, plan, validate or tflint has completed, and the output has been captured. Terraform rarely writes to stdout and stderr in the same action, so the commenter_input needs to be concatenated. For the plan commenter type we recommend saving the output to a file instead of using stdout/stderr as this allows us to bypass size limits for variables so large terraform plans don't need to be truncated.

Example Workflow:

name: Terraform

on:
  pull_request:

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  TF_WORKSPACE: "example"
  TF_VERSION: "1.4.6"

jobs:
  terraform:
    name: Run Terraform and Comment
    runs-on: ubuntu-latest
  steps:
    - name: HashiCorp - Setup Terraform
      uses: hashicorp/setup-terraform@v2
      with:
        terraform_version: ${{ env.TF_VERSION }}
    - name: Terraform Format
      id: fmt
      run: |
        terraform fmt -check -recursive -diff
      continue-on-error: true
    - name: Post Format Comment
      if: ${{ always() && (steps.fmt.outcome == 'success' || steps.fmt.outcome == 'failure') }}
      uses: GetTerminus/terraform-pr-commenter@v3
      with:
        commenter_type: fmt
        commenter_input: ${{ format('{0}{1}', steps.fmt.outputs.stdout, steps.fmt.outputs.stderr) }}
        commenter_exitcode: ${{ steps.fmt.outputs.exitcode }}
    - name: Terraform Init
      id: init
      run: terraform init -lock=false -input=false
    - name: Post Init Comment
      if: ${{ always() && (steps.init.outcome == 'success' || steps.init.outcome == 'failure') }}
      uses: GetTerminus/terraform-pr-commenter@v3
      with:
        commenter_type: init
        commenter_input: ${{ format('{0}{1}', steps.init.outputs.stdout, steps.init.outputs.stderr) }}
        commenter_exitcode: ${{ steps.init.outputs.exitcode }}
    - name: Terraform Validate
      id: validate
      run: terraform validate
    - name: Post TF Validate Comment
      if: ${{ always() && (steps.validate.outcome == 'success' || steps.validate.outcome == 'failure') }}
      uses: GetTerminus/terraform-pr-commenter@v3
      with:
        commenter_type: validate
        commenter_input: ${{ format('{0}{1}', steps.validate.outputs.stdout, steps.validate.outputs.stderr) }}
        commenter_exitcode: ${{ steps.validate.outputs.exitcode }}
    - name: TFLint - Setup
      id: tflint
      uses: terraform-linters/setup-tflint@v3
      with:
        tflint_wrapper_enabled: true
    - name: TFLint - Run
      run: |
        tflint --version
        tflint --init
        tflint
    - name: Post TFLint Comment
      if: ${{ always() && (steps.tflint.outcome == 'success' || steps.tflint.outcome == 'failure') }}
      uses: GetTerminus/terraform-pr-commenter@dpr-update-commenter
      with:
        commenter_type: tflint
        commenter_input: ${{ format('{0}{1}', steps.tflint.outputs.stdout, steps.tflint.outputs.stderr) }}
        commenter_exitcode: ${{ steps.tflint.outputs.exitcode }}
    - name: Terraform Plan
      id: plan
      run: terraform plan -lock=false -input=false |& tee tf_plan.txt
    - uses: GetTerminus/terraform-pr-commenter@v3
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        TF_WORKSPACE: ${{ inputs.terraform_workspace }}
      with:
        commenter_type: plan
        commenter_plan_path: tf_plan.txt
        commenter_exitcode: ${{ steps.plan.outputs.exit }}

Inputs

Name Requirement Description
commenter_type required The type of comment. Options: [fmt, init, plan, validate, tflint]
commenter_input optional The comment to post from a previous step output. For plan commenter type either commenter_input or commenter_plan_path must be set. This is limited to 128KiB
commenter_plan_path optional The plan file path including the filename. Only available for plan commenter types.
commenter_exitcode required The exit code from a previous step output.
terraform_version optional The version of terraform from the workflow. Defaults to 1.4.6.
use_beta_version optional Whether or not to use the beta version of the commenter.
project optional Project name to use in comments header. usefull for monorepos

Environment Variables

Name Requirement Description
GITHUB_TOKEN required Used to execute API calls. The ${{ secrets.GITHUB_TOKEN }} already has permissions, but if you're using your own token, ensure it has the repo scope.
TF_WORKSPACE optional Default: default. This is used to separate multiple comments on a pull request in a matrix run.
EXPAND_SUMMARY_DETAILS optional Default: false. This controls whether the comment output is collapsed or not.
HIGHLIGHT_CHANGES optional Default: true. This switches ~ to ! in plan diffs to highlight Terraform changes in orange. Set to false to disable.
COMMENTER_DEBUG optional Default: false. This switches the commenter into debug mode.

Outputs

Name Description
comment_id ID of comment created by step. Can be used for further manipulations with comment
comment_url URL pointing to comment created by step. Can be used to create a link from summary or to send a notification

Notes

  • The commenter requires a pull request to run so the github event must contain a .pull_request.number.
  • For large terraform plans using stdout/stder, there is aproximately 128KiB limit to the size of the commenter_input. If your output is larger than that you will need to either truncate or switch the output to a text file as shown in the workflow example above. An example of how to truncate the plan output is shown below.

Example TF Plan Truncate:

- name: TF Plan - Truncate
  id: plan
  # have to use /bin/bash because GHA runs by default with `set -e` to end execution on any error.
  # we want to capture the error instead.
  shell: '/bin/bash {0}'
  run: |
    # copy the stdout file handle to fd5.
    exec 5>&1

    # merge stderr into stdout and print it to fd5 (parent shell's stdout); exit with the code from terraform plan
    OUTPUT=$(terraform plan -lock=false -input=false 2>&1 | tee /dev/fd/5; exit ${PIPESTATUS[0]})

    # store the exit code here
    EXITCODE=$?

    # github actions doesn't allow us to set a multiline output so we export it to the environment
    EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
    echo "PLAN_OUTPUT<<$EOF" >> $GITHUB_OUTPUT
    echo "${OUTPUT::128000}" >> $GITHUB_OUTPUT
    echo "$EOF" >> $GITHUB_OUTPUT

    # set exit code for pickup later, and make sure we exit with same code
    echo "exitcode=$EXITCODE" >> $GITHUB_OUTPUT
    exit $EXITCODE

Screenshots

plan

fmt

fmt

fmt

fmt

fmt

init

fmt

validate

fmt

tflint

fmt

Troubleshooting & Contributing

Feel free to head over to the Issues tab to see if the issue you're having has already been reported. If not, open a new one and be sure to include as much relevant information as possible, including code-samples, and a description of what you expect to be happening.

License

MIT

About

A GitHub Action that adds opinionated comments to a PR from Terraform fmt/init/plan output

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Shell 95.6%
  • Dockerfile 4.4%