pez-infra/.github/workflows/validate-terraform.yml
dependabot[bot] 352bfbe3bc
chore(deps): bump the github-actions group with 2 updates
Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [actions/cache](https://github.com/actions/cache).


Updates `actions/checkout` from 6 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

Updates `actions/cache` from 5 to 6
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-24 16:04:43 +00:00

122 lines
4.3 KiB
YAML

name: Validate Terraform
on:
pull_request:
paths:
- "terraform/**"
- ".github/workflows/validate-terraform.yml"
permissions:
contents: read
pull-requests: write
# Requires these repository secrets:
# AGE_SECRET_KEY — age private key for SOPS decryption
#
# Dependabot PRs run with no access to these secrets and a read-only token,
# so they take a lightweight, secret-free path (init + validate, no plan/
# comment). Provider-version bumps are still resolved and validated.
jobs:
plan:
name: tofu plan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-tofu
# --- Dependabot: secret-free validation -------------------------------
- name: Validate (no secrets)
if: github.actor == 'dependabot[bot]'
working-directory: terraform/
run: |
# secrets.yaml is decrypted from SOPS at plan time and can't be
# produced here, so stub the keys the config reads (kept in sync by
# deriving them from the actual secrets["..."] references).
# Stub values must satisfy provider config validators: hcloud
# requires a 64-char token, and Grafana's fleet_management_auth
# must look like `username:password`.
stub64=$(printf 'stub%.0s' {1..16})
grep -rhoE 'secrets\["[^"]+"\]' . \
| sed -E 's/.*secrets\["([^"]+)"\].*/\1/' \
| sort -u \
| while read -r key; do
case "$key" in
*_auth) echo "$key: \"stub:stub\"" ;;
*) echo "$key: \"$stub64\"" ;;
esac
done > secrets.yaml
tofu init -backend=false
tofu validate
# --- Human PRs: full plan against real backend ------------------------
- name: Decrypt secrets
if: github.actor != 'dependabot[bot]'
uses: ./.github/actions/sops-decrypt
with:
age-key: ${{ secrets.AGE_SECRET_KEY }}
- name: Set backend credentials
if: github.actor != 'dependabot[bot]'
uses: ./.github/actions/tofu-backend-creds
- name: tofu init
if: github.actor != 'dependabot[bot]'
working-directory: terraform/
run: tofu init
- name: tofu validate
if: github.actor != 'dependabot[bot]'
working-directory: terraform/
run: tofu validate
- name: tofu plan
id: plan
if: github.actor != 'dependabot[bot]'
working-directory: terraform/
continue-on-error: true
run: |
set -o pipefail
tofu plan -no-color 2>&1 | tee plan_output.txt
- name: Post plan as PR comment
if: github.actor != 'dependabot[bot]'
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');
const raw = fs.readFileSync('terraform/plan_output.txt', 'utf8');
const filtered = raw.split('\n').filter(l => !l.includes(': Refreshing state...')).join('\n');
const truncated = filtered.length > 65000
? filtered.slice(0, 65000) + '\n\n...(output truncated)'
: filtered;
const outcome = '${{ steps.plan.outcome }}';
const header = outcome === 'failure' ? '## Terraform Plan — FAILED' : '## Terraform Plan';
const body = `${header}\n\`\`\`\n${truncated}\n\`\`\``;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find(c => c.body.startsWith('## Terraform Plan'));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
}
- name: Fail if plan failed
if: github.actor != 'dependabot[bot]' && steps.plan.outcome == 'failure'
run: exit 1