On this page
1. Know the two places settings can live2. Know the reserved keys3. Worked example: add a team-wide default4. Worked example: a one-off override for your own branch5. Worked example: reference a shared secret without pasting its value🧪 Sandbox6. Where to check your workFor Training
How to teach an engineer to use layered sandbox settings, step by step.
1. Know the two places settings can live
- The
sandboxGitHub Environment (repo → Settings → Environments →
sandbox): variables and secrets here apply to every sandbox unless a more specific layer overrides them. Use SANDBOX_ALL_<NAME> to apply to every branch, or SANDBOX_<BRANCH>_<NAME> to apply to one branch only.
- The PR description's
## 🧪 Sandboxblock: a fenced YAML block under
a heading that contains the word "sandbox" (case-insensitive) — this is per-PR and always wins over the environment.
2. Know the reserved keys
After stripping the SANDBOX_ALL_/SANDBOX_<BRANCH>_ prefix (or, in a PR block, as a bare top-level key), five names are special:
| Key | Meaning | Values |
|---|---|---|
WHATSAPP / whatsapp | Run the WhatsApp integration profile | truthy: 1, true, yes, on (case-insensitive) |
TWO_REGIONS / two_regions | Run the two-region (EU-1/ME-1) stack | truthy, as above |
CRON / cron | Run the cron/scheduled-jobs profile | truthy, as above |
QUEUE / queue | Run the queue-worker profile | truthy, as above |
SEED / seed | Seed mode, e.g. basic or rich | passed through as a string |
Anything else becomes an environment-variable override handed to the sandbox's compose stack.
3. Worked example: add a team-wide default
Say the team wants every sandbox to run with the queue worker on by default, without every PR having to say so. In the sandbox GitHub Environment, add a variable: SANDBOX_ALL_QUEUE = true. Done — every new sandbox deploy picks it up on the next run of the deploy job, no workflow edit, no PR-body edit needed.
4. Worked example: a one-off override for your own branch
Say your branch is feature/patient-portal-v2 and you want this sandbox, and only this one, to run with whatsapp on. Two ways:
- Branch-scoped GitHub variable: sanitize the branch name yourself —
uppercase, non-alphanumeric runs become a single underscore, no leading/trailing underscore. feature/patient-portal-v2 becomes FEATURE_PATIENT_PORTAL_V2. Add variable SANDBOX_FEATURE_PATIENT_PORTAL_V2_WHATSAPP = true.
- PR-body block (simpler for a truly one-off case):
~~~ ## 🧪 Sandbox ``yaml whatsapp: true `` ~~~
Either works; the PR-body version is easier to review in the PR itself and disappears when the PR closes, so prefer it for anything that's specific to one PR rather than the whole branch's lifetime.
5. Worked example: reference a shared secret without pasting its value
~~~
🧪 Sandbox
env:
SOME_API_KEY: secret:SANDBOX_SHARED_TEST_KEY
~~~
SANDBOX_SHARED_TEST_KEY must already exist as a secret visible to the sandbox environment (repo/org secret, or the environment's own). The literal string secret:SANDBOX_SHARED_TEST_KEY is what appears in your PR description — the real value never does. Two things will make this fail loudly instead of silently: naming a secret that doesn't exist, or naming github_token (which is rejected unconditionally, whatever its case).
6. Where to check your work
Open the deploy job's run for your PR and expand the 🧪 sandbox settings (layered: env vars → secrets → PR inline) log group — it prints the resolved toggles and the resolved env variable names (never values). If your setting isn't reflected there, work backwards through The precedence chain to find which layer is actually winning.