Project yaml, env yaml, .env, an exported variable and a flag all set the same thing — which one wins?
Asked 24,980 views4 answers
71votes
We have base URLs in envs/staging.yaml, an old SDODS_UI_BASE_URL exported in the build image, and someone has started passing flags on the command line. Nobody can predict what a run will actually hit any more.
Is there a documented order, or is it whatever merges last?
.env and .env.<env> (repo root, then the project folder)
process.env, including the SDODS_* variables
flags on sdods run and friends
So your exported SDODS_UI_BASE_URL beats the env yaml, and a flag beats the exported variable. Merging is per key, not per file: objects merge recursively, arrays replace wholesale.
You do not have to reason about it in the abstract — ask:
bash
sdods config show -p demo-shop -e staging --explain
The bit that trips people is that layers 4 and 5 do two jobs.
They are the merge layers above, and they are also the only scope ${VAR} is resolved against. Layer 5 does a third thing on top: a fixed set of SDODS_* names is mapped onto configuration paths, so SDODS_UI_BASE_URL is not just a variable, it writes env.ui.baseUrl.
Practical footnote from our build: CI counts too. When it is set, retries.ci applies instead of retries.local, so the same command retries twice on the agent and zero times on your laptop. An environment file can force it with ci: true if you want that locally.
And the thing that is deliberately absent from the order: an environment file cannot override arbitrary project keys. It may only patch screenshots, heal, timeouts and perf on top of the project section. Everything else in envs/<env>.yaml describes the target, not the project.