Terraform plan in Pull Requests with Google Cloud Build
Running Terraform locally just to review a pull request always was a bit of a pain in the ass. Good thing is, there are some nice people running projects like Atlantis and if you host them by yourself or use Spacelift, you’re good to go.
I just always felt like it’s a bit too much work to manage Atlantis just to run plans and applies. Instead, I deep dived into Cloud Build and tried to replicate the same idea, but in a serverless way.
PR Comments were a Problem
At the time I was trying to stitch all the components together, there was a missing component: containerized cloud builder for Github CLI. Yup, Github has a new CLI, that lets you post comments on PRs. How cool is that?
So I contributed the Github CLI builder into the cloud-builders-community in PR#469 (by the time you are reading this, it may be in master, but if not, just feel free to use the branch).
> Edit: the contribution was merged, installation steps below are updated.
git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git && cd cloud-builders-community/github
gcloud builds submit --config=cloudbuild.yaml .
The script installs the Github builder into your Google Cloud project. In case you are missing the terraform, just cd ../terraform
and submit the build in the same way.
Planning Terraform inside Cloud Build
First, we’ll want to use the terraform builder to initialize and plan the changes. Make sure your Cloud Build service account has enough rights to do whatever you require in the terraform.
steps:
- name: 'gcr.io/$PROJECT_ID/terraform'
args: [
'init'
]
- name: 'gcr.io/$PROJECT_ID/terraform'
entrypoint: 'bash'
args: [
'-c',
'terraform plan -no-color > plan.txt'
]
The second step puts its output into a file called plan.txt
. Files in the /workspace
directory are preserved between steps, making it available in the next steps.
Providing a Github Token
The next step is to provide a Github token for our CLI. We can generate one navigating into settings/Developer Settings/Personal Access Tokens. The token will need to have the following rights:
repo
so it can read from your private repositories and write commentsorg:read
in case you are using this for an organization
Once your token is created, copy it, and create a new secret inside your project's Secret Manager. You can call the secret github-personal-token
.
Posting the Plan into a Github PR
To post a comment with the plan results, we will need to Create a Trigger for Pull Request events, connected to your terraform repository. Afterward, we will add two more steps to our cloudbuild.yaml
. These steps will get the Github Token and use it in the Github builder to post the comment.
First, let’s create our trigger. Put it on the Pull Request event and connect your repository like on an example below. You can also enable the Comment Control in case you want the triggers to be manual only for collaborators or owners (to make sure you don’t execute plans on pre-approved PRs).
Second, we’ll update our build configuration. The added steps do the following:
- Get the Github Token from the Secret Manager so we can pass it as an authorization to our Github builder
- Use the Github builder to comment the plan into a foldable code in the PR
- name: gcr.io/cloud-builders/gcloud
entrypoint: 'bash'
args: [
'-c',
"gcloud secrets versions access latest --secret=github-personal-token --format='get(payload.data)' | tr '_-' '/+' | base64 -d > token.txt"
]
- name: 'gcr.io/$PROJECT_ID/github'
entrypoint: 'bash'
args:
- '-c'
- |-
read -r -d "" gh_comment_template << EOF
<details>
<summary>Terraform Plan Results</summary>
\`\`\`
%s
\`\`\`
</details>
EOF
gh_comment=$(printf "$$gh_comment_template" "$(cat plan.txt)")
/usr/bin/gh.bash pr review $_PR_NUMBER -R $_GITHUB_USER/$REPO_NAME -c -b "$$gh_comment"
The second step may seem a bit too much, however, it makes the comment folded. Running the trigger multiple times won’t create infinite scroll PRs with terraform plans.
Once set up, you’ll see full terraform plan
outputs in the PR comments.
If you have any questions, hit me up on my Twitter
Enjoy!