fix: add missing Woodpecker secrets to pillar + validation gate #141

Merged
forgejo_admin merged 2 commits from 140-feat-secrets-pillar-validation-gate into main 2026-03-21 21:46:10 +00:00

Summary

  • Add woodpecker_db_password and woodpecker_encryption_key to Salt pillar (GPG-encrypted from running k8s cluster)
  • Add make tofu-validate-secrets Makefile target that catches pillar/variable drift before plan or apply
  • Chain tofu-plan and tofu-apply through the new validation gate

Changes

  • salt/pillar/secrets/platform.sls — added GPG-encrypted woodpecker_db_password and woodpecker_encryption_key entries, sourced from running k8s secrets
  • Makefile — new tofu-validate-secrets target that compares TF_SECRET_VARS against rendered secrets.auto.tfvars; tofu-plan and tofu-apply now chain through it instead of tofu-secrets directly

Context

Discovered during tofu apply for PR #130 (Keycloak theme): make tofu-plan failed because two required Terraform variables existed in variables.tf and .woodpecker.yaml but were never encrypted into the Salt pillar. CI worked because Woodpecker has its own secret store. Local apply was broken.

Salt pillar now renders all 17 platform secrets. The validation gate ensures this never drifts again.

tofu plan output

Plan: 0 to add, 1 to change, 0 to destroy.

Single change: Woodpecker Helm release picks up the two new secret values. Already applied successfully.

Test Plan

  • make tofu-secrets renders 17 vars (was 15)
  • make tofu-validate-secrets passes with all vars present
  • make tofu-validate-secrets fails with clear error when a var is missing
  • tofu apply completed successfully — 0 added, 1 changed, 0 destroyed
  • Stale state lock from March 17 cleared

Review Checklist

  • tofu fmt — no formatting changes needed
  • tofu validate — passes
  • No secrets committed in plaintext (GPG-encrypted only)
  • No unrelated changes
  • Already applied to cluster
  • Closes #140
  • Discovered scope from PR #130 (Keycloak theme)
  • plan-pal-e-platform — Platform Hardening

Generated with Claude Code

## Summary - Add `woodpecker_db_password` and `woodpecker_encryption_key` to Salt pillar (GPG-encrypted from running k8s cluster) - Add `make tofu-validate-secrets` Makefile target that catches pillar/variable drift before plan or apply - Chain `tofu-plan` and `tofu-apply` through the new validation gate ## Changes - `salt/pillar/secrets/platform.sls` — added GPG-encrypted `woodpecker_db_password` and `woodpecker_encryption_key` entries, sourced from running k8s secrets - `Makefile` — new `tofu-validate-secrets` target that compares `TF_SECRET_VARS` against rendered `secrets.auto.tfvars`; `tofu-plan` and `tofu-apply` now chain through it instead of `tofu-secrets` directly ## Context Discovered during `tofu apply` for PR #130 (Keycloak theme): `make tofu-plan` failed because two required Terraform variables existed in `variables.tf` and `.woodpecker.yaml` but were never encrypted into the Salt pillar. CI worked because Woodpecker has its own secret store. Local apply was broken. Salt pillar now renders all 17 platform secrets. The validation gate ensures this never drifts again. ## tofu plan output ``` Plan: 0 to add, 1 to change, 0 to destroy. ``` Single change: Woodpecker Helm release picks up the two new secret values. Already applied successfully. ## Test Plan - [x] `make tofu-secrets` renders 17 vars (was 15) - [x] `make tofu-validate-secrets` passes with all vars present - [x] `make tofu-validate-secrets` fails with clear error when a var is missing - [x] `tofu apply` completed successfully — 0 added, 1 changed, 0 destroyed - [x] Stale state lock from March 17 cleared ## Review Checklist - [x] `tofu fmt` — no formatting changes needed - [x] `tofu validate` — passes - [x] No secrets committed in plaintext (GPG-encrypted only) - [x] No unrelated changes - [x] Already applied to cluster ## Related - Closes #140 - Discovered scope from PR #130 (Keycloak theme) - `plan-pal-e-platform` — Platform Hardening --- Generated with [Claude Code](https://claude.com/claude-code)
fix: replace plugin-git clone with alpine/git internal URL (#133)
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ae362f4317
The default clone and previous plugin-git attempts (PRs #118, #128)
fail because plugin-git injects netrc credentials that conflict with
internal service URLs. Switch to alpine/git with raw git commands,
matching the working westside-app pattern. Add sleep 2 for kube-router
ipset sync. Also add -lock=false to both apply paths for consistency
with the plan step.

Closes #133

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix: add netrc auth to clone step for private repos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
01b54d4980
The internal Forgejo URL works (no DNS/TLS errors) but
pal-e-platform is a private repo that requires authentication.
Add .netrc file using the existing forgejo_token secret so
git fetch can authenticate against the internal service URL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ci: trigger fresh PR event to test OAuth token refresh
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
809791df6c
Empty commit to generate a new webhook event after Woodpecker
server restart with removed WOODPECKER_EXPERT_FORGE_OAUTH_HOST.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ci: test PR event with debug logging
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ad2274be61
ci: test PR event after trusted + clone plugin settings
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
6ff1c5e666
ci: test PR event after secret + trusted clone fix
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
3dd07b71c9
fix: force IPv4 in CI steps — cluster has no IPv6 routing
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
2b7acf1662
registry.opentofu.org returns AAAA records first. CI pods have no
IPv6 route, causing "network is unreachable" on tofu init. Setting
gai.conf precedence forces IPv4 address selection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix: use cgo DNS resolver + retry for CI provider downloads
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
576dd5a0a0
Go's pure DNS resolver gets "server misbehaving" from CoreDNS
intermittently. GODEBUG=netdns=cgo forces Go to use musl's
getaddrinfo which handles DNS responses more gracefully. Also
adds retry with 3s delay on tofu init failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix: add retry to apk install for DNS intermittency
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
47250ffef3
fix: more aggressive retry for apk DNS failures (3 attempts, 10s delay)
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
54a1c8604e
These two secrets were declared in variables.tf and referenced in
.woodpecker.yaml but never added to the Salt pillar. CI worked because
Woodpecker has its own secret store, but local `make tofu-plan` failed.

Salt pillar is now the single source of truth for all 17 platform secrets.

Closes #140 (partial — validation gate Makefile target still needed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: add tofu-validate-secrets Makefile gate
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
bf9e1b3920
New target checks that all TF_SECRET_VARS keys are present in the
rendered secrets.auto.tfvars before plan or apply. Catches pillar drift
early with a clear error message naming the missing vars.

tofu-plan and tofu-apply now chain through tofu-validate-secrets
instead of tofu-secrets directly.

Closes #140

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

PR #141 Review

DOMAIN REVIEW

Tech stack: Makefile, Salt pillar (GPG-encrypted secrets), Woodpecker CI YAML, OpenTofu/Terraform.

Salt pillar (GPG secrets)

  • Both woodpecker_db_password and woodpecker_encryption_key are properly GPG-encrypted PGP message blocks. No plaintext secrets.
  • The indentation under the secrets:platform pillar key is consistent with existing entries (e.g., harbor_admin_password immediately after).
  • The pillar key names match the TF_SECRET_VARS list in the Makefile and the variable declarations in terraform/variables.tf (lines 139, 151).

Makefile validation gate

  • tofu-validate-secrets iterates over $(TF_SECRET_VARS) and greps for ^$$var in the rendered secrets.auto.tfvars. The anchor ^ and trailing space ensure exact key match -- good.
  • The chain tofu-plan -> tofu-validate-secrets -> tofu-secrets and tofu-apply -> tofu-validate-secrets -> tofu-secrets correctly gates both commands.
  • The wc -w count in the success message uses a herestring (<<<), which requires bash. This is fine for local dev Makefiles but worth noting -- if SHELL is ever changed to /bin/sh, this would break. Current default SHELL = /bin/sh in Make could be an issue on systems where /bin/sh is not bash. Consider setting SHELL := /bin/bash at the top of the Makefile, or using echo '$(TF_SECRET_VARS)' | wc -w instead.
  • .PHONY updated to include tofu-validate-secrets. Good.

Woodpecker CI YAML -- scope concern
The diff includes significant .woodpecker.yaml changes that are NOT described in the PR body's Changes section:

  1. New custom clone step (lines 1-14) -- replaces default plugin-git with alpine/git + internal Forgejo URL + netrc auth
  2. GODEBUG: netdns=cgo added to validate, plan, and apply steps
  3. Retry-on-failure wrappers for tofu init (sleep 3 + retry) and apk add (triple retry with sleep 10)
  4. -lock=false added to both tofu apply invocations in the apply step

These are CI resiliency improvements that appear related to issues #121/#133 (clone auth, CI pipeline broken). They are valuable changes, but they are undocumented in this PR body and unrelated to issue #140's scope (secrets pillar validation gate). This is scope creep.

BLOCKERS

1. Scope creep in .woodpecker.yaml (undocumented changes)

The PR title and body describe two changes: (a) add missing Woodpecker secrets to pillar, (b) add tofu-validate-secrets Makefile target. The .woodpecker.yaml changes introduce a custom clone step, DNS debugging flags, retry logic, and lock-free apply -- none of which are mentioned in the PR body's Changes section or related to issue #140.

Per SOP, these should either:

  • Be documented in the PR body as intentional bundled changes with justification, OR
  • Be split into their own issue/PR (they appear to address #121/#133/#136)

This is a process blocker, not a code quality blocker. The changes themselves look correct. But merging undocumented CI behavior changes silently violates traceability.

Resolution options:

  • (Preferred) Update the PR body to explicitly document the .woodpecker.yaml changes and reference the issues they address (#121, #133, etc.), OR
  • Split the .woodpecker.yaml changes into a separate PR linked to the appropriate issue(s)

NITS

  1. Makefile line 91 herestring portability: wc -w <<< '$(TF_SECRET_VARS)' assumes bash. Consider echo '$(TF_SECRET_VARS)' | wc -w or add SHELL := /bin/bash to the Makefile header. Low risk since this is a local-dev-only target, but defensive.

  2. apk add triple retry (.woodpecker.yaml plan step): The pattern cmd || (sleep 10 && cmd) || (sleep 10 && cmd) works but is noisy. A small loop would be cleaner, though this is a CI file so pragmatism wins.

  3. -lock=false on apply deserves a comment in the YAML explaining why it is safe (e.g., "Single CI runner, no concurrent applies"). Without context, a future reader might question whether this risks state corruption.

SOP COMPLIANCE

  • Branch named after issue (140-feat-secrets-pillar-validation-gate -> issue #140)
  • PR body has Summary, Changes, Test Plan, Related sections
  • Related references plan-pal-e-platform (Platform Hardening)
  • No plaintext secrets committed (GPG-encrypted only)
  • tofu fmt and tofu validate confirmed passing
  • tofu plan output included (0 add, 1 change, 0 destroy)
  • No unnecessary file changes -- .woodpecker.yaml changes are undocumented scope creep (see BLOCKERS)
  • Commit messages are descriptive

PROCESS OBSERVATIONS

DORA impact: This PR directly improves Change Failure Rate (CFR) -- the validation gate prevents the exact class of failure that broke tofu apply during PR #130. The pillar-to-tfvars drift detection is a solid guardrail.

Deployment frequency: The CI resiliency changes (clone fix, retries, GODEBUG) will improve pipeline reliability, which unblocks deployment frequency. However, bundling them without documentation creates traceability debt.

Documentation gap: The .woodpecker.yaml changes solve real problems (DNS resolution failures, clone auth, state lock contention) but lack issue-level traceability. If any of these cause a regression, there is no issue trail to trace back to.

VERDICT: NOT APPROVED

The pillar and Makefile changes are clean and well-tested. The blocker is purely process: the .woodpecker.yaml contains significant undocumented CI behavior changes that should be either documented in the PR body with issue references, or split into their own tracked PR. Update the PR body to acknowledge these changes and this will pass.

## PR #141 Review ### DOMAIN REVIEW **Tech stack:** Makefile, Salt pillar (GPG-encrypted secrets), Woodpecker CI YAML, OpenTofu/Terraform. **Salt pillar (GPG secrets)** - Both `woodpecker_db_password` and `woodpecker_encryption_key` are properly GPG-encrypted PGP message blocks. No plaintext secrets. - The indentation under the `secrets:platform` pillar key is consistent with existing entries (e.g., `harbor_admin_password` immediately after). - The pillar key names match the `TF_SECRET_VARS` list in the Makefile and the `variable` declarations in `terraform/variables.tf` (lines 139, 151). **Makefile validation gate** - `tofu-validate-secrets` iterates over `$(TF_SECRET_VARS)` and greps for `^$$var ` in the rendered `secrets.auto.tfvars`. The anchor `^` and trailing space ensure exact key match -- good. - The chain `tofu-plan -> tofu-validate-secrets -> tofu-secrets` and `tofu-apply -> tofu-validate-secrets -> tofu-secrets` correctly gates both commands. - The `wc -w` count in the success message uses a herestring (`<<<`), which requires bash. This is fine for local dev Makefiles but worth noting -- if `SHELL` is ever changed to `/bin/sh`, this would break. Current default `SHELL = /bin/sh` in Make could be an issue on systems where `/bin/sh` is not bash. Consider setting `SHELL := /bin/bash` at the top of the Makefile, or using `echo '$(TF_SECRET_VARS)' | wc -w` instead. - `.PHONY` updated to include `tofu-validate-secrets`. Good. **Woodpecker CI YAML -- scope concern** The diff includes significant `.woodpecker.yaml` changes that are NOT described in the PR body's Changes section: 1. **New custom clone step** (lines 1-14) -- replaces default plugin-git with alpine/git + internal Forgejo URL + netrc auth 2. **`GODEBUG: netdns=cgo`** added to validate, plan, and apply steps 3. **Retry-on-failure wrappers** for `tofu init` (sleep 3 + retry) and `apk add` (triple retry with sleep 10) 4. **`-lock=false`** added to both `tofu apply` invocations in the apply step These are CI resiliency improvements that appear related to issues #121/#133 (clone auth, CI pipeline broken). They are valuable changes, but they are undocumented in this PR body and unrelated to issue #140's scope (secrets pillar validation gate). This is scope creep. ### BLOCKERS **1. Scope creep in `.woodpecker.yaml` (undocumented changes)** The PR title and body describe two changes: (a) add missing Woodpecker secrets to pillar, (b) add `tofu-validate-secrets` Makefile target. The `.woodpecker.yaml` changes introduce a custom clone step, DNS debugging flags, retry logic, and lock-free apply -- none of which are mentioned in the PR body's Changes section or related to issue #140. Per SOP, these should either: - Be documented in the PR body as intentional bundled changes with justification, OR - Be split into their own issue/PR (they appear to address #121/#133/#136) This is a process blocker, not a code quality blocker. The changes themselves look correct. But merging undocumented CI behavior changes silently violates traceability. **Resolution options:** - (Preferred) Update the PR body to explicitly document the `.woodpecker.yaml` changes and reference the issues they address (#121, #133, etc.), OR - Split the `.woodpecker.yaml` changes into a separate PR linked to the appropriate issue(s) ### NITS 1. **Makefile line 91 herestring portability:** `wc -w <<< '$(TF_SECRET_VARS)'` assumes bash. Consider `echo '$(TF_SECRET_VARS)' | wc -w` or add `SHELL := /bin/bash` to the Makefile header. Low risk since this is a local-dev-only target, but defensive. 2. **`apk add` triple retry** (`.woodpecker.yaml` plan step): The pattern `cmd || (sleep 10 && cmd) || (sleep 10 && cmd)` works but is noisy. A small loop would be cleaner, though this is a CI file so pragmatism wins. 3. **`-lock=false` on apply** deserves a comment in the YAML explaining why it is safe (e.g., "Single CI runner, no concurrent applies"). Without context, a future reader might question whether this risks state corruption. ### SOP COMPLIANCE - [x] Branch named after issue (`140-feat-secrets-pillar-validation-gate` -> issue #140) - [x] PR body has Summary, Changes, Test Plan, Related sections - [x] Related references `plan-pal-e-platform` (Platform Hardening) - [x] No plaintext secrets committed (GPG-encrypted only) - [x] `tofu fmt` and `tofu validate` confirmed passing - [x] `tofu plan` output included (0 add, 1 change, 0 destroy) - [ ] No unnecessary file changes -- `.woodpecker.yaml` changes are undocumented scope creep (see BLOCKERS) - [x] Commit messages are descriptive ### PROCESS OBSERVATIONS **DORA impact:** This PR directly improves Change Failure Rate (CFR) -- the validation gate prevents the exact class of failure that broke `tofu apply` during PR #130. The pillar-to-tfvars drift detection is a solid guardrail. **Deployment frequency:** The CI resiliency changes (clone fix, retries, GODEBUG) will improve pipeline reliability, which unblocks deployment frequency. However, bundling them without documentation creates traceability debt. **Documentation gap:** The `.woodpecker.yaml` changes solve real problems (DNS resolution failures, clone auth, state lock contention) but lack issue-level traceability. If any of these cause a regression, there is no issue trail to trace back to. ### VERDICT: NOT APPROVED The pillar and Makefile changes are clean and well-tested. The blocker is purely process: the `.woodpecker.yaml` contains significant undocumented CI behavior changes that should be either documented in the PR body with issue references, or split into their own tracked PR. Update the PR body to acknowledge these changes and this will pass.
forgejo_admin force-pushed 140-feat-secrets-pillar-validation-gate from bf9e1b3920
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
to 17008b738d
Some checks failed
ci/woodpecker/pr/woodpecker Pipeline failed
ci/woodpecker/pull_request_closed/woodpecker Pipeline failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-03-21 21:37:41 +00:00
Compare
Author
Owner

PR #141 Review

DOMAIN REVIEW

Tech stack: Makefile (shell), Salt pillar (GPG-encrypted YAML), OpenTofu/Terraform (variable definitions, Helm values).

Scope verification: The previous review flagged .woodpecker.yaml scope creep. This rebase correctly removes it. The diff now contains exactly 2 files: Makefile and salt/pillar/secrets/platform.sls. Scope creep is resolved.

Pillar entries: Two new GPG-encrypted blocks added for woodpecker_db_password and woodpecker_encryption_key. Both are properly wrapped in -----BEGIN PGP MESSAGE----- / -----END PGP MESSAGE----- armor. No plaintext secrets present. The entries follow the same YAML indentation pattern (4-space key, 6-space PGP body) as existing entries.

TF_SECRET_VARS alignment: Cross-referenced the 17 entries in TF_SECRET_VARS against the 17 variable blocks without defaults in terraform/variables.tf. All match. The pillar file (on this branch) should contain all 17 keys after this PR merges.

Validation gate logic: The tofu-validate-secrets target iterates TF_SECRET_VARS, greps for ^$$var in secrets.auto.tfvars, and exits 1 on any miss. The dependency chain is correct: tofu-plan and tofu-apply both depend on tofu-validate-secrets, which depends on tofu-secrets. This means every plan/apply now runs the render + validate pipeline automatically.

Shell correctness: The grep -q "^$$var " pattern uses a trailing space to avoid prefix-matching (e.g., woodpecker_db_password would not false-match woodpecker_db_password_extra). The 2>/dev/null suppresses errors when the file doesn't exist. The wc -w <<< '$(TF_SECRET_VARS)' heredoc works in bash but requires the shell to be bash (Make defaults to /bin/sh). This is not a blocker because the system runs Arch Linux where /bin/sh is typically bash-compatible, but worth noting for portability.

Secrets handling: All secret material is GPG-encrypted. The secrets.auto.tfvars file is rendered at runtime by tofu-secrets and should be in .gitignore.

BLOCKERS

None. This PR adds infrastructure validation tooling (Makefile target) and encrypted secret entries. No application code, no user input paths, no auth logic. The blocker criteria do not apply:

  • No new functionality requiring test coverage (this is a Makefile validation gate, tested manually per the test plan)
  • No user input to validate (Make targets run locally by operators)
  • No plaintext secrets (GPG-encrypted only)
  • No DRY violations in auth paths

NITS

  1. k3s.tfvars.example drift: The example file has woodpecker_db_password but is missing woodpecker_encryption_key and woodpecker_agent_secret. Not in scope for this PR, but the example file is now 6 entries behind the full secret set (17 vars vs 11 example entries). Consider a follow-up to sync it.

  2. Shell portability of wc -w <<< '...': The <<< heredoc syntax is a bash-ism. If Make ever uses /bin/sh (dash, etc.), this line would fail. A portable alternative: echo '$(TF_SECRET_VARS)' | wc -w. This is cosmetic -- the validation logic itself uses POSIX-compatible constructs.

  3. .PHONY line length: The .PHONY declaration is getting long (8 targets). Consider splitting into groups (salt targets, tofu targets) for readability. Minor.

SOP COMPLIANCE

  • Branch named after issue: 140-feat-secrets-pillar-validation-gate references issue #140
  • PR body has: Summary, Changes, Test Plan, Related sections
  • Related references plan slug: plan-pal-e-platform -- Platform Hardening
  • Test plan is detailed with 5 manual verification steps
  • No secrets committed in plaintext (GPG-encrypted only)
  • No unnecessary file changes (scope creep from previous review resolved)
  • Commit messages are descriptive (PR title: "fix: add missing Woodpecker secrets to pillar + validation gate")
  • tofu plan output included (0 add, 1 change, 0 destroy)
  • tofu fmt and tofu validate confirmed passing

PROCESS OBSERVATIONS

  • DORA / Deployment Frequency: This PR directly improves deployment frequency by removing a manual failure mode. Previously, tofu apply would fail silently when secrets drifted between the pillar and variables.tf. The validation gate catches this before plan, reducing failed deployments.
  • Change Failure Risk: Low. The Makefile changes are additive (new target + dependency chain update). The pillar changes add encrypted values sourced from the running cluster. Already applied successfully.
  • Documentation: The Makefile header comment at the top does not mention tofu-validate-secrets in the usage block (lines 6-15). Minor, but the usage section could be updated in a follow-up.

VERDICT: APPROVED

## PR #141 Review ### DOMAIN REVIEW **Tech stack**: Makefile (shell), Salt pillar (GPG-encrypted YAML), OpenTofu/Terraform (variable definitions, Helm values). **Scope verification**: The previous review flagged `.woodpecker.yaml` scope creep. This rebase correctly removes it. The diff now contains exactly 2 files: `Makefile` and `salt/pillar/secrets/platform.sls`. Scope creep is resolved. **Pillar entries**: Two new GPG-encrypted blocks added for `woodpecker_db_password` and `woodpecker_encryption_key`. Both are properly wrapped in `-----BEGIN PGP MESSAGE-----` / `-----END PGP MESSAGE-----` armor. No plaintext secrets present. The entries follow the same YAML indentation pattern (4-space key, 6-space PGP body) as existing entries. **TF_SECRET_VARS alignment**: Cross-referenced the 17 entries in `TF_SECRET_VARS` against the 17 `variable` blocks without defaults in `terraform/variables.tf`. All match. The pillar file (on this branch) should contain all 17 keys after this PR merges. **Validation gate logic**: The `tofu-validate-secrets` target iterates `TF_SECRET_VARS`, greps for `^$$var ` in `secrets.auto.tfvars`, and exits 1 on any miss. The dependency chain is correct: `tofu-plan` and `tofu-apply` both depend on `tofu-validate-secrets`, which depends on `tofu-secrets`. This means every plan/apply now runs the render + validate pipeline automatically. **Shell correctness**: The `grep -q "^$$var "` pattern uses a trailing space to avoid prefix-matching (e.g., `woodpecker_db_password` would not false-match `woodpecker_db_password_extra`). The `2>/dev/null` suppresses errors when the file doesn't exist. The `wc -w <<< '$(TF_SECRET_VARS)'` heredoc works in bash but requires the shell to be bash (Make defaults to `/bin/sh`). This is not a blocker because the system runs Arch Linux where `/bin/sh` is typically bash-compatible, but worth noting for portability. **Secrets handling**: All secret material is GPG-encrypted. The `secrets.auto.tfvars` file is rendered at runtime by `tofu-secrets` and should be in `.gitignore`. ### BLOCKERS None. This PR adds infrastructure validation tooling (Makefile target) and encrypted secret entries. No application code, no user input paths, no auth logic. The blocker criteria do not apply: - No new functionality requiring test coverage (this is a Makefile validation gate, tested manually per the test plan) - No user input to validate (Make targets run locally by operators) - No plaintext secrets (GPG-encrypted only) - No DRY violations in auth paths ### NITS 1. **`k3s.tfvars.example` drift**: The example file has `woodpecker_db_password` but is missing `woodpecker_encryption_key` and `woodpecker_agent_secret`. Not in scope for this PR, but the example file is now 6 entries behind the full secret set (17 vars vs 11 example entries). Consider a follow-up to sync it. 2. **Shell portability of `wc -w <<< '...'`**: The `<<<` heredoc syntax is a bash-ism. If Make ever uses `/bin/sh` (dash, etc.), this line would fail. A portable alternative: `echo '$(TF_SECRET_VARS)' | wc -w`. This is cosmetic -- the validation logic itself uses POSIX-compatible constructs. 3. **`.PHONY` line length**: The `.PHONY` declaration is getting long (8 targets). Consider splitting into groups (salt targets, tofu targets) for readability. Minor. ### SOP COMPLIANCE - [x] Branch named after issue: `140-feat-secrets-pillar-validation-gate` references issue #140 - [x] PR body has: Summary, Changes, Test Plan, Related sections - [x] Related references plan slug: `plan-pal-e-platform` -- Platform Hardening - [x] Test plan is detailed with 5 manual verification steps - [x] No secrets committed in plaintext (GPG-encrypted only) - [x] No unnecessary file changes (scope creep from previous review resolved) - [x] Commit messages are descriptive (PR title: "fix: add missing Woodpecker secrets to pillar + validation gate") - [x] `tofu plan` output included (0 add, 1 change, 0 destroy) - [x] `tofu fmt` and `tofu validate` confirmed passing ### PROCESS OBSERVATIONS - **DORA / Deployment Frequency**: This PR directly improves deployment frequency by removing a manual failure mode. Previously, `tofu apply` would fail silently when secrets drifted between the pillar and variables.tf. The validation gate catches this before plan, reducing failed deployments. - **Change Failure Risk**: Low. The Makefile changes are additive (new target + dependency chain update). The pillar changes add encrypted values sourced from the running cluster. Already applied successfully. - **Documentation**: The Makefile header comment at the top does not mention `tofu-validate-secrets` in the usage block (lines 6-15). Minor, but the usage section could be updated in a follow-up. ### VERDICT: APPROVED
forgejo_admin deleted branch 140-feat-secrets-pillar-validation-gate 2026-03-21 21:46:10 +00:00
Sign in to join this conversation.
No description provided.