Skip to main content

Continuous Integration for Terraform Modules with GitHub Actions

Collaborating on infrastructure projects using code can introduce challenges such as testing, configuring continuous integration, and deployment pipelines. These things help to ensure that the software is stable, and enables faster releases. These challenges extend to things like Terraform modules that help you share Terraform configuration in your organization. In this post, we’ll take a look at how you can configure a continuous integration pipeline to help test and collaborate on Terraform modules using Github Actions.

»GitHub Actions

GitHub Actions gives users the ability to configure actions based on events such as pull requests and merges to their repositories. This feature can be used for Terraform modules managed in GitHub, without having to rely on external tooling.

GitHub Actions relies on a YAML workflow file to specify the steps to execute. A typical workflow for a Terraform module includes terraform init and terraform validate commands. The init command initializes the module and downloads any needed providers. The validate command helps validate the configuration files in the module and is useful for general verification.

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 follows:

name: Terraform CI

on: 
  pull_request:
    branches:
      - master

jobs:
  validate:
    name: Validate
    runs-on: ubuntu-latest
    steps:
    - name: Check out code  
      uses: actions/checkout@v1

    - name: Run a Terraform init  
      uses: docker://hashicorp/terraform:0.12.11
      with:
        entrypoint: terraform
        args: init

    - name: Run a Terraform validate    
      uses: docker://hashicorp/terraform:0.12.11
      with:
        entrypoint: terraform
        args: validate

First, we name the workflow “Terraform CI”. Next, we specify that this workflow should be triggered on a pull request event opened against the master branch.

Then, we define each step to be run during this workflow. In the example, we use the predefined checkout action to retrieve the code contained in the repository. After retrieving the contents of the repository, we specify steps to execute terraform init and terraform validate commands using the Terraform container from Docker Hub.

By using these steps, we can initialize and validate the syntax of Terraform modules in Github without setting up additional tooling. Teams can collaborate on modules and push to the repository with a continuous integration workflow.

»Continuous Testing

In addition to validating Terraform code, we can extend this workflow to incorporate automated testing of modules. This is especially important when multiple developers are collaborating on a module, and helps continuously verify that it executes as expected.

We now update our example with the addition of a step to execute unit tests implemented with Terratest, a Golang library for running tests against Terraform.

name: Terraform CI

on: 
  pull_request:
    branches:
      - master

jobs:
  validate:
    name: Validate
    runs-on: ubuntu-latest
    steps:

# Steps omitted for clarity

   - name: Set up Go 1.13
      uses: actions/setup-go@v1
      with:
        go-version: 1.13
      id: go

    - name: Get dependencies
      run: |
        if [ -f Gopkg.toml ]; then
            curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
            dep ensure
        else
          go get -v -t -d ./...  
        fi

    - name: Test
      working-directory: /home/runner/work/terratest-demo/terratest-demo/test
      run: go test

Similar to the previous section, we use the setup-go action to bootstrap a Golang environment to stage the unit tests. Next, we pull down the dependencies for the test code in order to execute go test. Before running the tests, we change to the directory containing the test files, located in /home/runner/work/{repository-name}/{repository-name}

»GitHub Status Checks

To ensure a potentially disruptive configuration does not affect a stable Terraform module, we protect the master branch from merging a pull request with failing checks. We go to the “Settings” tab on the GitHub repository and select the “Branches” section.

We select “Require status checks to pass before merging” and choose the status checks created by the GitHub actions workflow. Finally, we click “Create” to save the branch protection rule. This will ensure that pull requests can’t be completed until the checks have passed.

»Conclusion

In this post, we covered how GitHub Actions enables a flexible, native continuous integration pipeline for Terraform modules 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.


Sign up for the latest HashiCorp news

By submitting this form, you acknowledge and agree that HashiCorp will process your personal information in accordance with the Privacy Policy.