Repository navigation
Description
What happened
External repository review at commit c7bebd1 reproduced a scenario where setup.sh destroys the existing config.local.env when it fails partway through.
Reproduction:
- A scratch copy with a pre-existing
config.local.envwas reconfigured withbash setup.sh --defaults --env dev. - The command failed with
MYSQL_HOST: unbound variable. - The prior
config.local.envwas left at zero bytes.
The reviewer traced the write to build/setup.sh L339–398, where the file is truncated before an unconditional heredoc containing variables for every supported DB engine expands. Any unset variable (even for a deferred engine) kills the heredoc after the truncation has already committed.
Why this matters
Non-atomic write to a file holding the user's configuration. The write pattern is:
- Truncate the destination ← commits destruction immediately
- Compute content ← can fail here
- Write content ← may never run
The file is gitignored, so there is no git checkout recovery. Any custom DB paths, ports or environment-specific overrides the user had typed are gone. ADR-0001 defers non-PostgreSQL engines, so references to MYSQL_HOST and similar should not block the PostgreSQL path.
Decision taken 3 Nov 2026
Option (b) of 3 considered: switch to an atomic-write pattern. Write to config.local.env.new, verify completion, then mv -f to replace the destination. This fixes the whole class of bug.
Option (a) rejected: initialising the unset variables (MYSQL_HOST=${MYSQL_HOST:-unused}) is a 5-line patch but keeps the destructive write pattern.
Option (c) rejected for now: narrowing the heredoc to drop non-PostgreSQL engine blocks is tempting but reopens engine-scope questions (BR-02) and should stay separate.
Proposed
In build/setup.sh around L339–398:
- Write the computed config to
config.local.env.newin the same directory. - Verify the file is complete (sentinel line check, non-zero size, or similar).
mv -f config.local.env.new config.local.envonce verified.- On failure anywhere between steps 1 and 3, the
.newfile may be left on disk; the next successful run cleans it up or overwrites it. Clean up on exit viatrapis nice-to-have.
Done when
- Reproduction test added: a shell test that unsets a referenced variable, runs
setup.sh, asserts the priorconfig.local.envsurvives byte-identically. - The test fails on
mainatc7bebd1without the fix. - The test passes with the fix.
- Full matrix of
--env dev,--env test,--env staging,--env prodwith and without--defaultsruns clean against a pre-existing config file. - No change to the fresh-install path (empty
config.local.envbecomes populated as before).
Reference
Tracker row G35 (main tab). Repo review finding RV-S2. Related: G34 (RV-S1 deployer DB config), both Standards P1.
Activity
fix: address 8 open issues — security, data integrity, test reliability
amar-python commentedon Nov 9, 2026
Fixed in #202 (merged as 203c8ae).
Generated by Claude Code