cast/test
claude-hdb d083f74bec fix(diff): ignore preview env rows so they cannot shadow production (#85)
`GET /applications/{uuid}/envs` does not return one row per key: it merges
the production vars with the PREVIEW ones into one flat array
(`environment_variables->merge(environment_variables_preview)`,
ApplicationsController@envs v4.1.2). The two relations are complements split
on `is_preview`, with a unique index per (key, resource, is_preview) — so the
same key legitimately arrives twice. `fetchEnv` keyed by `key` alone, and
`Object.fromEntries` keeps the LAST, so cast diffed the manifest against
whichever row Coolify happened to serialize last.

Confirmed on prod: REPORTING_ENABLED came back as {value:"true",
is_preview:false} AND {value:"false", is_preview:true}; cast read the "false"
twin and re-proposed a `change` that could never clear.

That is also why #78 looked like a stale read. Both rows are born equal
(Coolify seeds a preview twin), and syncEnv only ever PATCHes the PRODUCTION
row — so the two diverge for exactly the vars updated in place. Five prod
flags flipped false->true re-proposed on every diff forever, while
created-once vars stayed clean because their twins still agreed. Nothing was
stale: cast was reading the other deployment's value. `real_value` tracked
`value` on every row, exactly as the accessor predicts.

cast declares PRODUCTION env and already says so on every write — syncEnv
sends `is_preview: false` on each bulk upsert. This is the read finally
saying the same thing; the asymmetry was the whole bug. Services and
databases map a single set, so this is a no-op for them.

Tests pin the exact prod shape, both serialization orders (the fix is "drop
preview", not "take the first"), a preview-only key, and rows with no
is_preview field at all.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 16:37:32 +00:00
..
fixtures feat(service): set and diff per-container service hostnames via urls (#72) 2026-07-16 15:14:29 +00:00
apply.test.ts fix(diff): compare non-secret env vars against fresh value, not stale real_value (#78) 2026-07-16 14:53:00 +00:00
backup-cli.test.ts feat: diff and apply a database's backup schedule (#51) 2026-07-14 23:07:54 +00:00
bindings.test.ts fix: smoke resolves its target inside the project it was declared under (#29) 2026-07-13 20:08:35 +00:00
capture-cli.test.ts feat(capture): --generated-only, the bootstrap's missing pass 2 2026-07-14 22:32:07 +00:00
capture.test.ts Merge pull request #58 from claude-hdb/feat/capture-generated-only 2026-07-14 23:49:49 +01:00
cli.test.ts fix: smoke resolves its target inside the project it was declared under (#29) 2026-07-13 20:08:35 +00:00
config.test.ts feat: select the Coolify instance by name instead of editing .coolify.env (#14) 2026-07-13 16:42:45 +00:00
coolify.test.ts feat: diff and apply a database's backup schedule (#51) 2026-07-14 23:07:54 +00:00
destroy.test.ts feat(destroy): a scoped teardown verb, gated in state (#43) 2026-07-14 22:52:17 +00:00
diff.test.ts fix(diff): compare non-secret env vars against fresh value, not stale real_value (#78) 2026-07-16 14:53:00 +00:00
domain-preflight.test.ts feat(service): set and diff per-container service hostnames via urls (#72) 2026-07-16 15:14:29 +00:00
draft-cli.test.ts Merge pull request #82 from claude-hdb/feat/github-app-binding 2026-07-16 17:44:01 +02:00
draft.test.ts feat(draft): resolve a repo's GitHub App by source_id, not the only-App guess (#72) 2026-07-16 15:22:40 +00:00
envtemplate.test.ts feat(resolve): derive base-URL env vars from manifest domains via ${domain:...} (#66) 2026-07-15 12:02:33 +00:00
fleet-cli.test.ts feat: --all — every project in an environment, and a report that says so (#26) 2026-07-13 20:23:23 +00:00
fleet.test.ts feat: --all — every project in an environment, and a report that says so (#26) 2026-07-13 20:23:23 +00:00
inventory.test.ts feat: read-side coordinates (#17, #18) + cast inventory (#19) 2026-07-13 18:20:53 +00:00
live-lookup.test.ts fix(diff): ignore preview env rows so they cannot shadow production (#85) 2026-07-16 16:37:32 +00:00
manifest.test.ts fix(apply): express static-site build settings so a monorepo app is served, not run (#63) 2026-07-14 23:46:14 +00:00
placement-cli.test.ts fix: the first apply against a fresh multi-destination box (#40, #41) 2026-07-14 17:25:29 +00:00
read-side-cli.test.ts feat: --resource, the third name a hand-built box does not share with you 2026-07-13 18:50:06 +00:00
reserved.test.ts fix(diff): compare non-secret env vars against fresh value, not stale real_value (#78) 2026-07-16 14:53:00 +00:00
resolve.test.ts feat(service): set and diff per-container service hostnames via urls (#72) 2026-07-16 15:14:29 +00:00
secrets.test.ts fix: hand the age identity to age on stdin — fd paths resolve only in cast's process 2026-07-13 22:43:00 +00:00
smoke-cli.test.ts fix: smoke resolves its target inside the project it was declared under (#29) 2026-07-13 20:08:35 +00:00
smoke.test.ts feat: cast — the Coolify executor, extracted from the infra state repo 2026-07-11 12:25:44 +00:00
sweep-cli.test.ts feat: inventory sweeps the instance — a discovery verb that needed you to have discovered 2026-07-13 19:07:17 +00:00
team.test.ts feat: assert the token's team before touching Coolify (fail-closed) 2026-07-12 20:55:04 +00:00
wire.test.ts feat(service): set and diff per-container service hostnames via urls (#72) 2026-07-16 15:14:29 +00:00