ci: seed the validation .env from one script, not two copies - #20
Merged
Conversation
The throwaway .env that gets compose.yaml's `${VAR:?}` guards past validation
was built in two places: a `run:` block in ci.yml and a heredoc in validate.sh.
Both copied .env.example and appended the same variables, and nothing tied them
together.
They drifted the first time the list changed. 2431173 added the
RENDER_UID/RENDER_GID guards and updated only validate.sh, so the change passed
locally and failed in CI:
error while interpolating services.alertmanager.user:
required variable RENDER_UID is missing a value: run make render
and needed a follow-up commit (165394c) to fix the copy that was missed.
Extract scripts/seed-validation-env.sh and have both callers invoke it, so the
list of variables exists once. The script takes an output path and writes;
lifetime stays with the caller, which is the only thing the two genuinely
disagree about — CI wants the gitignored stacks/observability/.env, validate.sh
wants an mktemp file it removes on a trap. Hardcoding either inside the script
would have left it able to serve only one of them.
Sharing the script stops the two copies drifting from each other, but both
could still drift from compose.yaml, so the script also asserts it covers every
`${VAR:?}` it finds there. A newly guarded variable now fails at seeding time
and names itself:
compose.yaml guards NEW_VAR, which the validation .env does not set.
rather than surfacing as an interpolation error in whichever caller runs first.
validate.sh runs without `set -e`, so a failed seed had to be caught explicitly
or the compose check would have run against a half-written file and reported
its confusing error instead; the existing if/else grew a leading `if ! seed`
branch that reports through the usual fail().
Co-Authored-By: Claude Opus 5 <[email protected]>
Gerrrt
added a commit
that referenced
this pull request
Aug 19, 2026
ci: seed the validation .env from one script, not two copies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The throwaway
.envthat getscompose.yaml's${VAR:?}guards pastvalidation was built in two places: a
run:block inci.ymland a heredoc invalidate.sh. Both copied.env.exampleand appended the same variables, andnothing tied them together.
They drifted the first time the list changed.
2431173added theRENDER_UID/RENDER_GIDguards and updated onlyvalidate.sh, so it passedlocally and failed in CI:
and needed a follow-up commit (
165394c) to fix the copy that was missed.scripts/seed-validation-env.shis extracted and both callers invoke it, so thelist exists once. The script takes an output path; lifetime stays with the
caller, which is the only thing the two genuinely disagree about — CI wants the
gitignored
stacks/observability/.env,validate.shwants anmktempfile itremoves on a trap.
Sharing the script stops the two callers drifting from each other. It does not
stop both drifting from
compose.yaml, so the script also asserts it coversevery
${VAR:?}it finds there — a newly guarded variable fails at seeding timeand names itself, rather than surfacing as an opaque interpolation error in
whichever caller runs first.
History
This commit was pushed to
fix/rendered-secrets-container-uidafter #15 wasmerged, so it never had a PR of its own and was never merged. It surfaced during
a branch cleanup: its tip no longer matched the tip #15 recorded as merged, and
scripts/seed-validation-env.shdid not exist onmain.Rebased from
165394conto475126b. No conflicts, thoughmainhas sincetouched both
compose.yaml(b4da221) andvalidate.sh(c971366).Verification
Run against the rebased tree:
shellcheck scripts/*.sh— cleanGRAFANA_ADMIN_PASSWORD,RENDER_UID,RENDER_GID) plus the.env.exampledefaultsdocker compose --env-file <seeded> config -q— passes${NEWLY_GUARDED_VAR:?}tocompose.yamlmakes theseeder exit 1 with
compose.yaml guards NEWLY_GUARDED_VAR, which the validation .env does not set.(
compose.yamlrestored afterwards)./scripts/validate.sh— all checks pass exceptgitleaks (full history),which fails only because the local gitleaks is 8.30.1 against CI's pinned
8.24.0 and the
.gitleaksignorefingerprints do not match across that gap.Pre-existing on
main, unrelated to this branch.🤖 Generated with Claude Code