Skip to content

ci: consolidate PR workflows into single ci.yml + add act support (#34) #19

ci: consolidate PR workflows into single ci.yml + add act support (#34)

ci: consolidate PR workflows into single ci.yml + add act support (#34) #19

Workflow file for this run

name: CI
on:
pull_request:
paths:
- "**.tf"
- "modules/**"
- "tests/**"
- "schemas/**"
- "scripts/**"
- "validate/**"
- "docs/**"
- "mkdocs.yml"
- ".terraform-docs.yml"
- ".terraform.lock.hcl"
- ".github/workflows/ci.yml"
- "!topologies/**"
push:
branches: [main]
paths:
- "**.tf"
- "modules/**"
- "tests/**"
- "schemas/**"
- "scripts/**"
- "validate/**"
- "docs/**"
- "mkdocs.yml"
- ".terraform-docs.yml"
- ".terraform.lock.hcl"
- ".github/workflows/ci.yml"
- "!topologies/**"
schedule:
- cron: "0 8 * * 1"
permissions:
contents: read
jobs:
validate:
name: Validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3
with:
terraform_version_file: .terraform-version
- name: Cache Terraform providers
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: .terraform
key: terraform-${{ hashFiles('.terraform.lock.hcl') }}
restore-keys: terraform-
- name: Format check
run: terraform fmt -check -recursive
- name: Init
run: terraform init -backend=false
- name: Set up tflint
uses: terraform-linters/setup-tflint@90f302c255ef959cbfb4bd10581afecdb7ece3e6 # v4
with:
tflint_version: latest
- name: Lint
run: |
tflint --init
tflint --recursive
- name: Test (mock providers)
run: terraform test
module-tests:
name: Module Tests (${{ matrix.module }})
runs-on: ubuntu-latest
strategy:
matrix:
module:
- project
- environments
- jobs
- credentials
- repository
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3
with:
terraform_version_file: .terraform-version
- name: Cache Terraform providers
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: .terraform
key: terraform-${{ hashFiles('.terraform.lock.hcl') }}
restore-keys: terraform-
- name: Terraform Init
working-directory: modules/${{ matrix.module }}
run: terraform init -backend=false
- name: Terraform Test
working-directory: modules/${{ matrix.module }}
run: terraform test -verbose
docs:
name: Docs up to date
runs-on: ubuntu-latest
env:
TERRAFORM_DOCS_VERSION: v0.20.0
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install terraform-docs
run: |
wget -q -O /tmp/terraform-docs.tar.gz \
https://github.com/terraform-docs/terraform-docs/releases/download/${TERRAFORM_DOCS_VERSION}/terraform-docs-${TERRAFORM_DOCS_VERSION}-linux-amd64.tar.gz
tar -xzf /tmp/terraform-docs.tar.gz -C /tmp
sudo mv /tmp/terraform-docs /usr/local/bin/
chmod +x /usr/local/bin/terraform-docs
- name: Regenerate docs
run: bash scripts/gen-docs.sh
- name: Check for drift
run: |
if ! git diff --exit-code docs/reference/; then
echo ""
echo "Docs are out of date. Run 'bash scripts/gen-docs.sh' locally and commit the result."
exit 1
fi
schema-drift:
name: Schema Drift Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3
with:
terraform_version_file: .terraform-version
- name: Cache Terraform providers
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: .terraform
key: terraform-${{ hashFiles('.terraform.lock.hcl') }}
restore-keys: terraform-
- name: Init
run: terraform init -backend=false
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Check schema drift
run: |
uv run --with PyYAML scripts/check_schema_drift.py \
--mapping scripts/resource_mapping.yml \
--schema schemas/v1.json \
--terraform-dir .
- name: Annotate PR on failure
if: failure() && github.event_name == 'pull_request'
run: |
echo "::error::Schema drift detected. Run 'uv run --with PyYAML scripts/check_schema_drift.py --mapping scripts/resource_mapping.yml --schema schemas/v1.json --terraform-dir .' locally and classify any UNMAPPED fields in scripts/resource_mapping.yml. Add MISSING_FROM_SCHEMA fields to schemas/v1.json."
yaml-validate:
name: YAML Validate Action
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Valid YAML passes
uses: ./validate
with:
file: validate/tests/valid.yml
- name: Invalid YAML is rejected
id: validate-invalid
uses: ./validate
with:
file: validate/tests/invalid.yml
continue-on-error: true
- name: Assert validation failed
run: |
if [ "${{ steps.validate-invalid.outcome }}" != "failure" ]; then
echo "Expected validation to fail for invalid.yml, but it did not."
exit 1
fi
echo "Validation correctly rejected invalid.yml."
mkdocs-build:
name: MkDocs Build
runs-on: ubuntu-latest
env:
TERRAFORM_DOCS_VERSION: v0.20.0
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"
cache: "pip"
cache-dependency-path: "docs/requirements.txt"
- name: Install MkDocs and dependencies
run: pip install -r docs/requirements.txt
- name: Install terraform-docs
run: |
wget -O /tmp/terraform-docs.tar.gz \
https://github.com/terraform-docs/terraform-docs/releases/download/${TERRAFORM_DOCS_VERSION}/terraform-docs-${TERRAFORM_DOCS_VERSION}-linux-amd64.tar.gz
tar -xzf /tmp/terraform-docs.tar.gz -C /tmp
sudo mv /tmp/terraform-docs /usr/local/bin/
chmod +x /usr/local/bin/terraform-docs
- name: Generate Terraform documentation
run: bash scripts/gen-docs.sh
- name: Setup Pages
id: pages
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
- name: Set MkDocs site_url for GitHub Pages
run: |
SITE_URL="https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/"
python3 -c "
import re, pathlib, sys
site_url = sys.argv[1]
path = pathlib.Path('mkdocs.yml')
text = path.read_text()
text, n = re.subn(r'(?m)^site_url:.*$', f'site_url: {site_url}', text, count=1)
if n != 1:
sys.exit('Expected exactly one site_url line in mkdocs.yml')
path.write_text(text)
print(f'site_url -> {site_url}')
" "$SITE_URL"
- name: Build with MkDocs
run: mkdocs build --strict --site-dir ./site