chore: working on the terraform tests creations #1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
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 | |
}) | |
} |