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
» 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.
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.