Test Stage
We start the pipeline with a rigourous testing stage consisting of multiple steps. These steps ensure that the Terraform code pushed to the feature branch is formatted correctly, validated, and tested using the Terraform Test Framework and Checkov.
Input variables
name: 'Terraform setup and test'
description: 'Sets up Terraform and tests the code'
inputs:
terraform_directory:
description: 'Directory that holds Terraform code'
required: true
root_directory:
description: 'Root directory for fmt check'
required: true
terraform_version:
description: 'Terraform version'
required: true
default: 1.9.2
github_token:
description: 'GitHub token for auth'
required: true
pr_id:
description: 'Pull request ID'
required: true
aws_role_to_assume:
description: 'AWS Role to assume'
required: true
default: <aws-role-arn>
aws_role_session_name:
description: 'AWS Role session name'
required: true
default: <aws-role-session-name>
aws_region:
description: 'AWS Region'
required: true
default: '<aws-region>'
These are the input variables we use for the test stage. Fill in the previously created AWS Role ARN, AWS Role Session Name and AWS Region.
Composite
runs:
using: "composite"
steps:
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ inputs.terraform_version }}
terraform_wrapper: false
The next code block defines a composite. The use of a composite is to reuse these defined steps in different pipelines. The composite is also using the terraform_version
input variable defined earlier.
Configure AWS Credentials
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ inputs.aws_role_to_assume }}
role-session-name: ${{ inputs.aws_role_session_name }}
aws-region: ${{ inputs.aws_region }}
With this code block, we are authenticating the GitHub Actions runner with our AWS account using the previously created AWS Role which are defined in the input variables.
Testing Terraform
- name: Terraform Init
id: init
working-directory: ${{ inputs.terraform_directory }}
shell: bash
run: |
terraform init
- name: Terraform fmt check
id: fmt
working-directory: ${{ inputs.root_directory }}
shell: bash
run: |
terraform fmt -check -diff -recursive ${{ inputs.root_directory }}
- name: Terraform Validate
id: validate
working-directory: ${{ inputs.terraform_directory }}
shell: bash
run: |
terraform validate
- name: Terraform Test (Terraform Test Framework)
id: tftest
working-directory: ${{ inputs.terraform_directory }}
shell: bash
run: |
terraform test -no-color 2>&1 | tee terraform_test.txt
- name: Terraform Test (Checkov)
id: checkov
uses: bridgecrewio/checkov-action@master
with:
directory: ${{ inputs.terraform_directory }}
framework: terraform
quiet: true
output_format: cli
output_file_path: checkov_results.sarif
After defining the input variables and authenticating with our AWS account, we are now ready to test Terraform. We first initialise the directory to install the Terraform providers. Afterwards, we run a format check to make sure the pushed Terraform code conforms to the formatting guidelines. Next up is the validation step. Terraform aims to validate the configuration files and whether it is syntactically valid and internally consistent.
Terraform testing comes afterwards using the Terraform Test Framework and Checkov. The Terraform Test Framework is used to perform integration or unit testing and Checkov is used to scan Terraform configuration files to find misconfigurations before deploying.
Comment Test Results to PR
- name: Concatenate Test Results Files
id: concatenate-files
shell: bash
run: |
echo "###################################" >> test_results.txt
echo "------ Terraform Test Framework Results -----" >> test_results.txt
cat ${{ inputs.terraform_directory }}/terraform_test.txt >> test_results.txt
echo "###################################" >> test_results.txt
echo "----- Checkov Results -----" >> test_results.txt
cat checkov_results.sarif/results_cli.txt >> test_results.txt
- name: Comment Test Results
id: comment-test-results
uses: thollander/actions-comment-pull-request@v2
with:
filePath: test_results.txt
Finally, we concatenate test results into one text file that is then posted on the open PR. An example would look like this: