Terraform is an extremely powerful tool, but the out-of-the-box workflow can lead to pitfalls such as forgetting to commit and push changes to manifest and terraform.tfstate files.

Use this example CircleCI configuration for a rock-solid pull-request workflow for Terraform projects.

The Workflow

  1. A project contributor creates a pull request with changes to terraform manifests.
  2. CircleCI runs a terraform plan and posts the diff as a comment in the pull request.
  3. When the PR is merged to master, CircleCI runs terraform apply to resolve the diffs.

Additional Requirements

Add an environment variable GITHUB_TOKEN with the personal access token of a bot user (this is used to post the comment on the PR).

You will also need to add authentication environment variables for your cloud provider (in AWS this is AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY).

Ensure your state is stored in remote storage, such as S3.

Copy the .circleci/config.yml and .circleci/plan-comment.tpl from the gist below to your repo.

version: 2
jobs:
plan:
docker:
- image: hashicorp/terraform:latest
working_directory: /code
steps:
- checkout
- run:
name: Init
command: terraform init -input=false
- run:
name: Plan
command: terraform plan -input=false -out=tfplan -no-color
- run:
name: Render plan for PR comment
command: terraform show -no-color tfplan > tfplan.txt
- persist_to_workspace:
root: /code
paths:
- .
apply:
docker:
- image: hashicorp/terraform:latest
working_directory: /code
steps:
- attach_workspace:
at: /code
- run:
name: Apply
command: terraform apply tfplan
plan_comment:
docker:
- image: cloudposse/github-commenter:latest
working_directory: /code
steps:
- checkout
- attach_workspace:
at: /code
- run:
name: Post plan to PR comment
command: |-
export CIRCLE_PR_NUMBER=${CIRCLE_PR_NUMBER:-${CIRCLE_PULL_REQUEST##*/}}
if [ -z $CIRCLE_PR_NUMBER ]; then echo "Not a pull request - aborting"; exit 0; fi
cat /code/tfplan.txt | github-commenter \
-owner ${CIRCLE_PROJECT_USERNAME} \
-repo ${CIRCLE_PROJECT_REPONAME} \
-number $CIRCLE_PR_NUMBER \
-delete-comment-regex "Output from" \
-type pr \
-template_file /code/.circleci/plan-comment.tpl
workflows:
version: 2
plan_pr:
jobs:
- plan
- plan_comment:
requires:
- plan
filters:
branches:
ignore: master
- apply:
requires:
- plan
filters:
branches:
only: master
view raw config.yml hosted with ❤ by GitHub
Output from `terraform plan`
```
{{.}}
```