Skip to content

chore: working on the terraform tests creations #1

chore: working on the terraform tests creations

chore: working on the terraform tests creations #1

---
name: Terraform Module Validation
on:
workflow_call:
secrets:
infracost-api-key:
description: "The API key for infracost"
required: false
inputs:
cicd-repository:
default: "appvia/appvia-cicd-workflows"
description: "The repository to pull the CI/CD workflows from"
required: false
type: string
cicd-branch:
default: "main"
description: "The branch to pull the CI/CD workflows from"
required: false
type: string
enable-infracost:
default: false
description: "Whether to run infracost on the Terraform Plan (secrets.infracost-api-key must be set if enabled)"
required: false
type: boolean
enable-commitlint:
default: true
description: "Whether to run commitlint on the commit message"
required: false
type: boolean
enable-terraform-tests:
default: true
description: "Whether to run terraform test"
required: false
type: boolean
enable-terraform-tests-credentials:
default: false
description: "Whether to run terraform test with AWS credentials"
required: false
type: boolean
terraform-dir:
default: "."
description: "The directory to validate"
required: false
type: string
terraform-tests-aws-region:
default: "eu-west-1"
description: "The AWS region to use for the terraform tests"
required: false
type: string
terraform-tests-aws-role:
description: "The AWS role to assume for the terraform tests"
required: false
type: string
terraform-version:
default: "1.7.1"
description: "The version of terraform to use"
required: false
type: string
working-directory:
default: "."
description: "Working directory"
required: false
type: string
env:
AWS_ROLE: ${{ inputs.aws-role }}
AWS_WEB_IDENTITY_TOKEN_FILE: /tmp/web_identity_token_file
TF_LOG: ${{ inputs.terraform-log-level }}
permissions:
contents: read
pull-requests: write
jobs:
commitlint:
name: "Commitlint"
if: github.event_name == 'pull_request' && inputs.enable-commitlint
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
outputs:
result: ${{ steps.commitlint.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 16
- name: Install Dependencies
run: npm install @commitlint/config-conventional @commitlint/cli
- name: Retrieve Commit Configuration
run: |
wget https://raw.githubusercontent.com/${{ inputs.cicd-repository }}/${{ inputs.cicd-branch }}/config/commitlint.config.js -O commitlint.config.js
- name: Run Commitlint
id: commitlint
run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }}
terraform-format:
name: "Terraform Format"
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
outputs:
result: ${{ steps.format.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ inputs.terraform-version }}
- name: Terraform Format
id: format
run: terraform -chdir=${{ inputs.terraform-dir }} fmt -check -recursive
terraform-lint:
name: "Terraform Lint"
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
outputs:
result: ${{ steps.lint.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Linter
uses: terraform-linters/setup-tflint@v4
- name: Terraform Init
run: terraform -chdir=${{ inputs.terraform-dir }} init -backend=false
- name: Setup Linter
uses: terraform-linters/setup-tflint@v4
- name: Linter Initialize
run: tflint --init
- name: Linting Code
id: lint
run: tflint -f compact
terraform-tests:
name: "Terraform Unit Tests"
runs-on: ubuntu-latest
if: inputs.enable-terraform-tests
defaults:
run:
working-directory: ${{ inputs.working-directory }}
outputs:
result: ${{ steps.tests.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ inputs.terraform-version }}
- name: Retrieve Web Identity Token for AWS Authentication
if: inputs.enable-terraform-tests-credentials
run: |
curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sts.amazonaws.com" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE
- name: Authenticate with AWS
if: inputs.enable-terraform-tests-credentials
id: auth
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ inputs.terraform-tests-aws-region }}
role-session-name: ${{ github.event.repository.name }}
role-to-assume: ${{ inputs.terraform-tests-aws-role }}
mask-aws-account-id: "no"
- name: Terraform Init
run: terraform -chdir=${{ inputs.terraform-dir }} init -backend=false
- name:
- name: Run Tests
id: tests
run: terraform -chdir=${{ inputs.terraform-dir }} test
terraform-init:
name: "Terraform Init"
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
outputs:
result: ${{ steps.init.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 16
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ inputs.terraform-version }}
- name: Terraform Init
id: init
run: terraform -chdir=${{ inputs.terraform-dir }} init
terraform-validate:
name: "Terraform Validate"
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
outputs:
result: ${{ steps.validate.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 16
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ inputs.terraform-version }}
- name: Terraform Init
id: init
run: terraform -chdir=${{ inputs.terraform-dir }} init
- name: Terraform Validate
id: validate
run: terraform -chdir=${{ inputs.terraform-dir }} validate -no-color
terraform-validate-examples:
name: "Terraform Validate Examples"
runs-on: ubuntu-latest
outputs:
result: ${{ steps.validate-examples.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 16
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ inputs.terraform-version }}
- name: Validate Examples
id: validate-examples
run: |
for dir in examples/*; do
if [ -d "$dir" ]; then
echo "--> Validating $dir"
terraform -chdir=${dir} init -backend=false
terraform -chdir=${dir} validate -no-color
fi
done
terraform-docs:
name: "Terraform Docs"
runs-on: ubuntu-latest
if: ${{ github.actor != 'dependabot[bot]' }}
defaults:
run:
working-directory: ${{ inputs.working-directory }}
outputs:
result: ${{ steps.docs.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Terraform Docs
id: docs
uses: terraform-docs/[email protected]
with:
fail-on-diff: true
working-dir: ${{ inputs.terraform-dir }}
terraform-security:
name: "Terraform Security"
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
outputs:
result: ${{ steps.security.outcome }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Terraform security
id: security
uses: aquasecurity/[email protected]
with:
working_directory: ${{ inputs.working-directory }}
terraform-infracost:
name: "Get Cost Estimate"
if: github.event_name == 'pull_request' && inputs.enable-infracost
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
steps:
- name: Setup Infracost
uses: infracost/actions/setup@v2
with:
api-key: ${{ secrets.infracost-api-key }}
currency: GBP
- name: Checkout PR Base Branch
uses: actions/checkout@v4
with:
ref: "${{ github.event.pull_request.base.ref }}"
- name: Check For TF Files
id: baseline
run: |
if ls *.tf 2>/dev/null; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi
- name: Generate Cost Estimate Baseline
if: steps.baseline.outputs.exists == 'true'
run: |
infracost breakdown --path=${TF_ROOT} \
--format=json \
--out-file=/tmp/infracost-base.json
- name: Checkout PR branch
uses: actions/checkout@v4
- name: Generate Cost Estimate Difference
if: steps.baseline.outputs.exists == 'true'
run: |
infracost diff --path=${TF_ROOT} \
--format=json \
--compare-to=/tmp/infracost-base.json \
--out-file=/tmp/infracost.json
- name: Generate Infracost Cost Estimate
if: steps.baseline.outputs.exists == 'false'
run: |
infracost breakdown --path=${TF_ROOT} \
--format=json \
--out-file=/tmp/infracost.json
- name: Post Infracost comment
run: |
infracost comment github --path=/tmp/infracost.json \
--repo=$GITHUB_REPOSITORY \
--github-token=${{github.token}} \
--pull-request=${{github.event.pull_request.number}} \
--behavior=update
update-pr:
name: "Update PR"
if: github.event_name == 'pull_request' && (success() || failure())
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
needs:
- commitlint
- terraform-docs
- terraform-format
- terraform-init
- terraform-lint
- terraform-tests
- terraform-security
- terraform-validate
- terraform-validate-examples
steps:
- name: Add PR Comment
uses: actions/github-script@v6
with:
script: |
// 1. Retrieve existing bot comments for the PR
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
})
const botComment = comments.find(comment => {
return comment.user.type === 'Bot' && comment.body.includes('Pull Request Review Status') && comment.body.includes('<b>Working Directory:</b> \`${{ inputs.working-directory }}\`')
})
// 2. Prepare format of the comment
const output = `### Pull Request Review Status
* ๐Ÿ–Œ <b>Terraform Format and Style:</b> \`${{ needs.terraform-format.outputs.result }}\`
* ๐Ÿ” <b>Terraform Linting:</b> \`${{ needs.terraform-lint.outputs.result }}\`
* ๐Ÿ‘ฎ <b>Terraform Security Check:</b> \`${{ needs.terraform-security.outputs.result }}\`
* ๐Ÿ”˜ <b>Terraform Tests:</b> \`${{ needs.terraform-tests.outputs.result }}\`
* ๐Ÿ”ง <b>Terraform Initialisation:</b> \`${{ needs.terraform-init.outputs.result }}\`
* ๐Ÿค– <b>Terraform Validation:</b> \`${{ needs.terraform-validate.outputs.result }}\`
* ๐Ÿค– <b>Terraform Example Validation:</b> \`${{ needs.terraform-validate-examples.outputs.result }}\`
* ๐Ÿ“– <b>Terraform Documentation:</b> \`${{ needs.terraform-docs.outputs.result }}\`
* ๐Ÿ”– <b>Commitlint:</b> \`${{ needs.commitlint.outputs.result }}\`
*<b>Working Directory:</b> \`${{ inputs.working-directory }}\`*
*<b>Pusher:</b> @${{ github.actor }}, <b>Action:</b> \`${{ github.event_name }}\`*
*<b>Workflow Run Link:</b> ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}*`;
// 3. If we have a comment, update it, otherwise create a new one
if (botComment) {
github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: output
})
} else {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
}