Automating Terraform Deployment to Google Cloud with GitHub Actions

CI/CD using GitHub Actions.

Vikram Shinde
interleap
5 min readNov 13, 2020

--

Introduction

Terraform is an infrastructure as a code tool that makes it easy to provision infrastructure on any cloud or on-premise. Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently.
It is preferred by a lot of people over Cloud Deployment Manager, AWS Cloud Formation and Azure ARM templates for its simplicity to read and understand. It’s popularity is growing day by day.

GitHub Actions add continuous integration to GitHub repositories to automate your software builds, tests, and deployments. Automating Terraform with CI/CD enforces configuration best practices, promotes collaboration and automates the Terraform workflow.

I have seen many blogs, articles, documents on Automating Terraform using GitHub Actions on AWS or Azure. But there is no documents for Google Cloud. This tutorial will help you on Google Cloud.

I’d like to share a special thank you to Kyle Ruddy at HashiCorp for publishing this Automate Infrastructure Provisioning Workflows with the GitHub Action for Terraform blog post.

Workflow

The workflow will:

  1. Check whether the configuration is formatted properly to demonstrate how you can enforce best practices.
  2. Generate a plan for every pull requests.
  3. Apply the configuration when you update the master branch.

Sample code is available at

https://github.com/vikramshinde12/terraform-gcp-github-actions.git

Prerequisites

This tutorial assumes that you are familiar with the Terraform, Git and Google Cloud Platform.

In order to complete this guide, you’ll need to install the following tools

Google Cloud Platform

Create a GCP project for this tutorial.

Create Service Account

  • Create Service Account.
  • Assign the roles: Editor (and required permission based on TF config)
  • Download the service account key.

Enable API

In order to operate with the Service Account you must activate the following APIs on the project where the Service account was created.

  • Cloud Resource Manager API

GitHub Action

GitHub Actions make use of YAML-formatted workflow file. This file establishes the configuration for things such as what event should include action processes, the type of runner to use and the configuration of the job with required steps to reach completion.
In order for the GitHub actions process to pick up the YAML file, there’s specific location for it to live. Each repository using actions requires a directory structure called /.github/workflows

The directory structure should resemble something like this following:

A typical workflow for a Terraform includes terraform init , terraform validate , terraform fmt , terraform plan and terraform apply

In my scenario, I want two things to happen:

  1. Plan: When a pull request is received, a GitHub Workflow is triggered to perform a security audit, construct Google Cloud credentials, load the Terraform CLI, and perform an init , fmt and plan using the proposed files in the pull request. Finally, I want a comment on the pull request to show the results of the plan step.
  2. Apply: When a push is received in the master branch, I can assume that the proposal was accepted and the new code should be applied. I again wish to construct Google Cloud credentials and load the Terraform CLI. However, the final steps will be to apply the configuration.

Now let’s take a look at how to construct this workflow with a GitHub Actions workflow file.

Create a new workflow file at /.github/workflows/workflow.yaml in the root of the GitHub repository. The content of the workflow file should be as follow:

These steps define all actions in the workflow. However, this job does not run every step when you trigger the action. Some of these steps only run from pull requests; others only run only when you merge a commit to master.

The first step should always be a checkout action. Checkout allows the overall workflow to use a copy of the repository’s code.
The second step is to set up Terraform CLI on the runner.
Terraform Init , Plan and Apply steps load GOOGLE_CREDENTIALS secret as an environment variable enabling the Terraform to authenticate Google Cloud project.
Terraform Format step checks whether the configuration is formatted properly.

Note: This code stores the Terraform state at Google Cloud Storage bucket as remote backend hence init requires GOOGLE_CREDENTAILS.

Save Google Credentials in GitHub Secrets

To add the credentials they need to be altered a bit to be stored in the variable. You need to remove all newline characters from the file.
Use following commands to convert JSON multi-line to single line

Open the file with vim

vi gcp-credential.jsonpress :

Add the following
%s;\n; ;g
Press enter.

press : again

type wq!

Save this credential in GitHub Secret (Settings → Secrets → New Secret ) Called GOOGLE_CREDENTIALS.

Pull Request

Let’s create a feature branch to create a Google Storage bucket.

resource "google_storage_bucket" "gcs_bucket" {
name = "test-bucket-random-001123"
}

Once the pull request is generated, a new check is triggered.

Checking the terraform plan

I can view the workflow process in real time by visiting the Action Menu or by clicking the details button next to the queued check.

Note here, the Terraform apply step is skipped for Pull Request job.

Merging the Pull Request into Master

Once pull request is reviewed and merged into master, the same workflow will run with additional apply step.

This is because the condition in Terraform Apply step:

if: github.ref == 'refs/heads/main' && github.event_name == 'push'
Terraform apply

You have successfully set up a complete GitHub Actions workflow to deploy an infrastructure using Terraform on Google Cloud.

Conclusion

In this post, we covered how GitHub Actions enables a flexible, native continuous integration pipeline for Terraform without the need to depend on external tooling. Github Actions enables us to validate syntax, test resources, and maintain the quality of our Terraform modules as we integrate changes to their configurations. To learn more about GitHub Actions, refer to the official documentation.

Reference

--

--