Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 114 additions & 31 deletions .github/workflows/terraform-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,24 @@ on:
paths:
- 'infra/**'
- '.github/workflows/terraform_validate.yml'
workflow_dispatch:
inputs:
debug:
description: 'Enable debug mode with verbose output'
required: false
default: 'false'
type: choice
options:
- 'true'
- 'false'

permissions:
actions: read # Needed for uploading SARIF reports
contents: read
security-events: write
pull-requests: write # Allow workflow to comment on PRs
id-token: write # Needed for OIDC Authentication

# Global environment variables
env:
ERROR_HANDLING: true # Enable enhanced error handling
Expand Down Expand Up @@ -43,7 +53,7 @@ jobs:
timeout-minutes: 60
needs: check-dependabot
# Run for all PRs but handle Dependabot PRs specially

steps:
- name: Checkout code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
Expand All @@ -54,7 +64,7 @@ jobs:
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: '18.x'

- name: Setup Terraform
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
with:
Expand All @@ -75,23 +85,58 @@ jobs:
id: tf-fmt
run: |
echo "Checking Terraform formatting..."
terraform fmt -check -recursive
if [ $? -ne 0 ]; then

# Capture files that need formatting
FMT_OUTPUT=$(terraform fmt -check -recursive -diff 2>&1) || FMT_EXIT=$?

if [ "${FMT_EXIT:-0}" -ne 0 ]; then
echo "::error::Terraform format check failed! Run 'terraform fmt -recursive' locally to fix formatting issues."

# Always show which files need formatting
echo ""
echo "Files that need formatting:"
terraform fmt -check -recursive 2>&1 | grep -v "^$" || true

# Show diff in debug mode or if requested
if [ "${{ github.event.inputs.debug }}" == "true" ] || [ "${{ env.ERROR_HANDLING }}" == "true" ]; then
echo ""
echo "Formatting differences:"
echo "$FMT_OUTPUT"
fi

exit 1
fi

echo "All Terraform files are properly formatted."
working-directory: ./infra

- name: Terraform Validate
id: tf-validate
run: |
echo "Validating Terraform configuration..."
terraform validate -json | tee validation_result.json
if [ $? -ne 0 ]; then

# Run validation and capture both JSON and exit code
terraform validate -json > validation_result.json 2>&1 || VALIDATE_EXIT=$?

if [ "${VALIDATE_EXIT:-0}" -ne 0 ]; then
echo "::error::Terraform validation failed! Check your Terraform files for errors."
cat validation_result.json

# Always show validation errors in a readable format
echo ""
echo "Validation errors:"
cat validation_result.json | jq -r '.diagnostics[]? | "- [\(.severity | ascii_upcase)] \(.summary): \(.detail)"' 2>/dev/null || cat validation_result.json

# Show full JSON output in debug mode
if [ "${{ github.event.inputs.debug }}" == "true" ]; then
echo ""
echo "Full validation output:"
cat validation_result.json | jq '.' 2>/dev/null || cat validation_result.json
fi

exit 1
fi

echo "Terraform configuration is valid."
working-directory: ./infra

- name: Setup TFLint
Expand All @@ -115,15 +160,33 @@ jobs:
id: tflint-run
run: |
echo "Running TFLint..."
tflint --format=json --force | tee tflint_result.json
if [ $? -ne 0 ]; then

# Run TFLint and capture output
tflint --format=json --force > tflint_result.json 2>&1 || TFLINT_EXIT=$?

if [ "${TFLINT_EXIT:-0}" -ne 0 ]; then
echo "::error::TFLint found issues in your Terraform configuration!"
cat tflint_result.json | jq '.issues[] | "::error file=\(.range.filename),line=\(.range.start.line),col=\(.range.start.column)::\(.message)"'

# Always show formatted errors
echo ""
echo "TFLint issues found:"
cat tflint_result.json | jq -r '.issues[]? | "- [\(.severity | ascii_upcase)] \(.rule.name) in \(.range.filename):\(.range.start.line): \(.message)"' 2>/dev/null || echo "Failed to parse TFLint output"

# Show full JSON output in debug mode
if [ "${{ github.event.inputs.debug }}" == "true" ]; then
echo ""
echo "Full TFLint output:"
cat tflint_result.json | jq '.' 2>/dev/null || cat tflint_result.json
fi

# Also create GitHub annotations for issues
cat tflint_result.json | jq -r '.issues[]? | "::error file=\(.range.filename),line=\(.range.start.line),col=\(.range.start.column)::\(.message)"' 2>/dev/null || true

exit 1
fi
working-directory: ./infra


echo "TFLint completed successfully with no issues."
working-directory: ./infra

- name: Install GitLeaks
run: |
Expand Down Expand Up @@ -161,7 +224,7 @@ jobs:
- name: Run Checkov action
id: checkov
uses: bridgecrewio/checkov-action@de3c276ef8118f7ce6bcb2e51d8dd3d65ac0ae36 # v12.1347.0
with:
with:
framework: terraform
download_external_modules: true
directory: ./infra
Expand All @@ -179,56 +242,76 @@ jobs:
category: checkov
wait-for-processing: true # Wait for processing to complete before proceeding



- name: Summary
if: always() # Always run this step
run: |
echo "## Terraform Validation Results :clipboard:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY


# Show debug mode status if enabled
if [ "${{ github.event.inputs.debug }}" == "true" ]; then
echo "🔍 **Debug Mode**: Enabled (verbose output shown)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi

# Check Terraform Init
if [ "${{ steps.tf-init.outcome }}" == "success" ]; then
echo "✅ **Terraform Init**: Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Terraform Init**: Failed" >> $GITHUB_STEP_SUMMARY
fi

# Check Terraform Format
if [ "${{ steps.tf-fmt.outcome }}" == "success" ]; then
echo "✅ **Terraform Format**: Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Terraform Format**: Failed - Run 'terraform fmt -recursive' locally" >> $GITHUB_STEP_SUMMARY
echo " - Check step logs for list of files that need formatting" >> $GITHUB_STEP_SUMMARY
fi

# Check Terraform Validate
if [ "${{ steps.tf-validate.outcome }}" == "success" ]; then
echo "✅ **Terraform Validate**: Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Terraform Validate**: Failed - Check configuration files" >> $GITHUB_STEP_SUMMARY
echo " - Check step logs for detailed validation errors" >> $GITHUB_STEP_SUMMARY
fi

# Check TFLint
if [ "${{ steps.tflint-run.outcome }}" == "success" ]; then
echo "✅ **TFLint**: Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **TFLint**: Failed - Review linting errors" >> $GITHUB_STEP_SUMMARY
echo " - Check step logs for detailed linting issues" >> $GITHUB_STEP_SUMMARY
fi

# Check Checkov
if [ "${{ steps.checkov.outcome }}" == "success" ]; then
echo "✅ **Checkov Security Check**: Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Checkov Security Check**: Failed - Security issues found" >> $GITHUB_STEP_SUMMARY
fi

# Check GitLeaks
if [ "${{ steps.gitleaks.outcome }}" == "success" ]; then
echo "✅ **GitLeaks Scan**: Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **GitLeaks Scan**: Failed - Sensitive information detected" >> $GITHUB_STEP_SUMMARY
fi

# Add help message if any checks failed
if [ "${{ steps.tf-fmt.outcome }}" != "success" ] || \
[ "${{ steps.tf-validate.outcome }}" != "success" ] || \
[ "${{ steps.tflint-run.outcome }}" != "success" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "💡 **Tip**: Re-run this workflow with debug mode enabled for more verbose output:" >> $GITHUB_STEP_SUMMARY
echo " - Go to Actions → Select this workflow → Run workflow → Enable 'debug mode'" >> $GITHUB_STEP_SUMMARY
fi

update-dependabot-pr:
name: Update Dependabot PR Status
needs: [check-dependabot, lint-and-check]
Expand All @@ -241,23 +324,23 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.issue.number;

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `## Terraform Validation Passed ✅

The Terraform provider update has been validated with:
- ✅ Terraform Init
- ✅ Terraform Format Check
- ✅ Terraform Validation
- ✅ TFLint Check
- ✅ Security Scanning

This PR can pass all the checks to be tested and then merged.`
});

// Add 'terraform-validated' label to the PR
await github.rest.issues.addLabels({
owner: context.repo.owner,
Expand All @@ -278,22 +361,22 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.issue.number;

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `## ❌ Terraform Validation Failed

The Terraform provider update has failed validation. Please check the workflow logs for details.

This may indicate that the provider update is not compatible with the current configuration.`
});

// Add 'terraform-validation-failed' label to the PR
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: ['terraform-validation-failed']
});
});
Loading