Automating Terraform Deployments with GitHub Actions: A Step-by-Step Guide

Tech Community • 4 min read

GitHub Actions is a potent automation tool that elevates your software development processes by responding to events and executing predefined workflows.

In this article, you’ll learn how to use GitHub Actions to deploy your Terraform code to production in Google Cloud.

The Scenario

You've been working on your infrastructure as code (IaC) using Terraform. Now, you're preparing to implement your changes in a production environment. You need these deployments to be error-free, follow best practices, and have appropriate approval procedures. GitHub Actions can be effective for this by using a manual step before deploying to production.

The Setup

Setting up your Terraform deployment workflow with GitHub Actions involves several important steps. In this section, we'll walk you through each step in detail.

1) Configure GitHub Actions trigger and permissions

The first step in automating your Terraform deployments is to configure the GitHub Actions workflow trigger and permissions. This configuration determines when and how the workflow will be initiated.

Here's the YAML code to configure GitHub Actions:

#.github/workflows/deploy-to-prod.yaml
name: Terraform PROD Deployment

on:
  push:
    branches:
      - main
  workflow_dispatch:
    branches:
      - main

permissions:
  contents: read
  issues: write

This configuration accomplishes two key things:

- Trigger Events: It specifies that the workflow should be triggered when changes are pushed to the "main" branch and when manually initiated using the "workflow_dispatch" event.

- Permissions: It defines the necessary permissions for the workflow, ensuring that it can read repository contents and write issues.

2) Add initial Setup

Let's examine the workflow steps:

- Checkout Git Repository: This step involves checking out your Git repository.

- Authenticate with your cloud provider: This is crucial if you need to deploy resources, like a Terraform deployment, on your cloud provider. In this example, we are using Google Cloud for the deployment.

jobs:
  gcp-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Git Repository
        uses: actions/checkout@v3.0.0
        with:
          fetch-depth: 0

      - id: "auth"
        name: "Authenticate to Google Cloud"
        uses: "google-github-actions/auth@v1"
        with:
          credentials_json: "${{ secrets.GOOGLE_CREDENTIALS }}"
          create_credentials_file: true
          export_environment_variables: true

3) Check the Terraform code

Ensure Terraform code works in your local setup: Do this before using it directly in your workflow  to avoid errors related to your Terraform code itself rather than GitHub Actions errors.

You can try your terraform commands such as ``init``, ``plan`` and ``apply``:

terraform init

terraform plan

terraform apply # Review your plan before applying

4) Add Terraform steps

In this step, we'll use ``terraform init`` to get your Terraform environment ready by setting up what it needs. Then, we'll run 'terraform plan' to see a preview of the changes that will be made.

- name: Setup Terraform
  uses: hashicorp/setup-terraform@v1
  with:
      terraform_version: 1.5.7
- name: Terraform init and validate
  run: |
	  terraform init

- name: Terraform plan
	run: |
		terraform plan
```

5) Create Issue for approval

You can use GitHub Actions, for example, to deploy your Terraform code, but before applying the changes, you need a mechanism to review your Terraform code. This helps ensure that your infrastructure changes are safe and minimizes the risks of deployment in production

For the manual approval in the workflow, we will use the [`trstringer/manual-approval`](https://github.com/trstringer/manual-approval) .

This GitHub Actions workflow enables you to create an approval process within your automation pipeline. It's particularly useful when you want to add a layer of human review and approval, especially for actions such as deploying to production. 👀

- uses: trstringer/manual-approval@v1
  with:
    secret: ${{ github.TOKEN }}
    approvers: laysauchoa
    minimum-approvals: 1
    issue-title: "Deploying v1.0.0 to prod"
    issue-body: "Review the terraform plan, then approve or deny the deployment of v1.0.0 to prod."
    exclude-workflow-initiator-as-approver: false

Once the Terraform plan step is completed, a corresponding issue is automatically generated for your review. Below, you can see an example of what this issue might look like:

In this issue, you have the opportunity to thoroughly examine the proposed changes in your Terraform deployment. If you agree with the plan and are ready to proceed with the deployment, you can simply approve the issue.

Upon approval, the workflow will automatically advance to the next step, applying your Terraform changes.

Deploying changes to production can be risky. Using a manual approval process allows us to review and confirm the deployment plan before proceeding, especially when deploying to production.

And you’ve built it

That's it! You've successfully built a CI/CD pipeline using Terraform and GitHub Actions. Just think about how much time and hassle this can save you as your website or system grows. Terraform and GitHub Actions make things easier and faster.

See you next time! 👋

👋 Hello, I'm Laysa, a developer and cloud engineer, a public speaker, and a knowledge sharer as I go along.

♻️ If you like this article, why not give it a share?

💜 And you can follow me or reach out here | Laysa Uchoa on X | Laysa Uchoa on LinkedIn 

--

#.github/workflows/deploy-to-prod.yaml
name: Terraform PROD Deployment

on:
    push:
      branches:
        - develop
    workflow_dispatch:
      branches:
        - develop

permissions:
    contents: read
    issues: write

jobs:
  gcp-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Git Repository
        uses: actions/checkout@v3.0.0
        with:
          fetch-depth: 0

      - id: "auth"
        name: "Authenticate to Google Cloud"
        uses: "google-github-actions/auth@v1"
        with:
          credentials_json: "${{ secrets.GOOGLE_CREDENTIALS }}"
          create_credentials_file: true
          export_environment_variables: true
          
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v1
        with:
            terraform_version: 1.5.7

      - name: Terraform init and validate
        run: |
          terraform init

      - name: Terraform plan
        run: |
          terraform plan

      - uses: trstringer/manual-approval@v1
        with:
          secret: ${{ github.TOKEN }}
          approvers: laysauchoa
          minimum-approvals: 1
          issue-title: "Deploying v1.0.0 to prod"
          issue-body: "Review the terraform plan, then approve or deny the deployment of v1.0.0 to prod."
          exclude-workflow-initiator-as-approver: false

      - name: Terraform apply
        run: |
          terraform apply

Get in Touch.

Let’s discuss how we can help with your cloud journey. Our experts are standing by to talk about your migration, modernisation, development and skills challenges.

Ilja Summala
Ilja Summala LinkedIn
CTO
Ilja’s passion and tech knowledge help customers transform how they manage infrastructure and develop apps in cloud.