Repository navigation
fix(scripts): read compose's guards from the parsed YAML, not the text (#107) - #289
Merged
Merged
Conversation
#107) `${VAR:?message}` in compose.yaml is the declaration that a service cannot start without VAR, so two scripts derive what a stack requires from it: seed-validation-env.sh must satisfy every guard to get `docker compose config` past them, and render-config.sh must ask SOPS for every guarded secret. Both grepped the raw file, which reads comments as well as YAML — so a comment that *mentioned* the guard syntax became a guard, and validation demanded a value for a variable that does not exist: compose.yaml guards VAR, which the validation .env does not set. That was hit while writing #62, and the fix then was to reword the comment, which is the wrong way round: documentation should not have to avoid describing the thing it documents. Read the parsed document instead, where a comment cannot appear. `docker compose config` is not the authority to ask — it resolves the guards rather than reporting them, and it is the thing being satisfied — so this walks every scalar of the PyYAML parse, which check_compose_health.py already depends on. One script, not two copies of the fix. render-config.sh's comment already described its derivation as "the same one seed-validation-env.sh uses"; now it literally is, in scripts/compose-guards.sh, so the two cannot drift and the comment bug is not left standing in the caller the issue did not name — where it is worse, because there it sends a render to SOPS for a key no stack has. PyYAML is asked for and worked around if absent, rather than required: renders happen on deploy hosts, and making one depend on a Python library to read a list of variable names is a worse trade than the fallback, which strips what YAML would treat as a comment and greps what is left. That is right about the case this exists for and can only ever miss a guard hidden behind a `#` inside a quoted string — the old failure mode, not a new false demand. Both callers read the list through command substitution, because a process substitution's exit status is not the loop's: a failure in the helper would otherwise arrive as an empty guard list, and read as "this stack requires nothing". The guard convention is now documented in the header of stacks/observability/ compose.yaml — the documentation the old grep forbade, and a live regression test for this fix: it names `${VAR:?message}`, so a return to grepping the raw file fails `make validate` with the exact error from the issue. Verified: guards for both stacks unchanged (parsed and fallback paths agree with the old grep on both files), a guard added to a compose.yaml is still caught by name, `make validate` passes, and the old grep sees VAR in the new comment while neither new path does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… talk around (#107) `5625c52` (#62) explains why GRAFANA_RENDERER_TOKEN is required rather than optional, then describes the mechanism as "the required-variable guard below" — a paraphrase, written three days after the raw-grep check landed in `595f0e2` and made naming the syntax fatal. Writing what it means would have demanded a throwaway value for a variable that does not exist before `make validate` would pass. That is the rewording #107 was filed about, and the previous commit is what removes the need for it. There is no earlier text to restore: the rewording happened while the comment was being written, so no commit ever carried the version this puts in its place. Nothing else in either compose.yaml is talking around a guard — the alertmanager note names `${RENDER_UID:-65534}`, and the `:-` form was never matched by the grep. Verified: the stack's guards are unchanged on both extraction paths, seed + `docker compose config` pass, yamllint clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Gerrrt
force-pushed
the
gerrrt/compose-guards-107
branch
from
September 4, 2026 22:09
3bec684 to
4fe7ab8
Compare
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.
Closes #107.
${VAR:?message}in compose.yaml is the declaration that a service cannot start without VAR, and two scripts derive what a stack requires from it:seed-validation-env.shmust satisfy every guard to getdocker compose configpast them, andrender-config.shmust ask SOPS for every guarded secret. Both grepped the raw file, which reads comments as well as YAML — so a comment that mentioned the guard syntax became a guard, and validation demanded a value for a variable that does not exist:That was hit while writing #62, and the fix then was to reword the comment. Documentation should not have to avoid describing the thing it documents.
What changed
5625c52described the mechanism as "the required-variable guard below" — a paraphrase written three days after the raw grep landed. There is no earlier text to restore; the rewording happened before the comment was ever committed.