diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index a265609..7d97dda 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -20,7 +20,7 @@ jobs: - name: Install OpenTofu uses: opentofu/setup-opentofu@v2 with: - tofu_version: latest + tofu_version: 1.9.0 - name: Install SOPS run: | @@ -71,7 +71,7 @@ jobs: - name: Install OpenTofu uses: opentofu/setup-opentofu@v2 with: - tofu_version: latest + tofu_version: 1.9.0 - name: Install SOPS run: | diff --git a/.github/workflows/validate-terraform.yml b/.github/workflows/validate-terraform.yml index e101e41..28c6b1c 100644 --- a/.github/workflows/validate-terraform.yml +++ b/.github/workflows/validate-terraform.yml @@ -3,9 +3,16 @@ name: Validate Terraform on: pull_request: +permissions: + contents: read + pull-requests: write + +# Requires these repository secrets: +# AGE_SECRET_KEY — age private key for SOPS decryption + jobs: - tofu-validate: - name: tofu validate + plan: + name: tofu plan runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 @@ -13,7 +20,7 @@ jobs: - name: Install OpenTofu uses: opentofu/setup-opentofu@v2 with: - tofu_version: latest + tofu_version: 1.9.0 - name: Install SOPS run: | @@ -30,18 +37,64 @@ jobs: echo "Decrypted: $f -> $out" done - - name: Find and validate Terraform roots + - name: Set backend credentials + working-directory: terraform/ run: | - found=0 - for dir in $(find terraform/ -name '*.tf' -printf '%h\n' | sort -u); do - echo "::group::Validating $dir" - cd "$dir" - tofu init -backend=false - tofu validate - cd "$GITHUB_WORKSPACE" - echo "::endgroup::" - found=1 - done - if [ "$found" -eq 0 ]; then - echo "No .tf files found — skipping validation." - fi + echo "AWS_ACCESS_KEY_ID=$(yq '.backblaze_keyID' secrets.yaml)" >> "$GITHUB_ENV" + echo "AWS_SECRET_ACCESS_KEY=$(yq '.backblaze_applicationKey' secrets.yaml)" >> "$GITHUB_ENV" + + - name: tofu init + working-directory: terraform/ + run: tofu init + + - name: tofu validate + working-directory: terraform/ + run: tofu validate + + - name: tofu plan + id: plan + 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 + uses: actions/github-script@v7 + 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: steps.plan.outcome == 'failure' + run: exit 1 diff --git a/ansible/services/caddy/Caddyfile b/ansible/services/caddy/Caddyfile index a1c7caa..c00807d 100644 --- a/ansible/services/caddy/Caddyfile +++ b/ansible/services/caddy/Caddyfile @@ -6,7 +6,7 @@ # { - admin 100.67.6.27:2019 + admin localhost:2019 metrics { per_host }