place a resource on a destination — and a state file that can say which (#21) #28
No reviewers
Labels
No labels
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-triage
ready
release
scope:apply
scope:capture
scope:coolify-api
scope:fleet
scope:manifest
scope:secrets
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/cast#28
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/destination-placement"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #21.
A destination is the Docker network a resource is created on. cast never sent one, so everything landed on the server's default. Invisible and harmless while each server hosts one project — and neither the moment a server hosts two.
The state shape
A destination is scoped project × environment, and
environments.<env>is scoped by environment alone. Adestination:key there would mean one network shared by every project in the environment — the isolation it is meant to provide, inverted. So the issue's proposal, adopted:Keyed by repo, full
<org>/<repo>slug first with a bare-<repo>fallback — thegithub_appsprecedent, for the same reason. Both fields optional; an environment whose server hosts one project declares neither.smoke_targetmoves here. It was state-file-scoped (not even per-environment): it named one project's app from a key that could not tell two projects apart, or prod's app from staging's. The old key is still read, with a warning, so an unmigrated state file keeps smoking;cast smokenow takes an optional<org>/<repo>.applysendsdestination_uuidon create — applications, databases and services alike, since Coolify runs identical destination logic in all three controllers.What the API actually does — and why ask #4 changes shape
Verified against
coollabsio/coolifyv4.1.2 (routes/api.php+ the three Api controllers), written up inreference/README.md:s3_destination. Hence the key isdestination_uuid:, notdestination:: a key calleddestinationsits right underserver:, which is a name, and would invite one that cast can never resolve.destination_uuidon write and returnsdestination_id(an integer PK) on read, with nothing mapping between them.A declared UUID therefore cannot be verified against the resource it was sent for, by cast or by anything else. Diffing it as a field would compare a UUID against an int and report drift that never clears — a phantom
updateon every run. So it is reported rather than compared, and the limit is stated out loud rather than left to be inferred:Silence here would make an unverified setting read as a verified one — the failure shape #12/#14/#17/#18 are all about, and the one this issue explicitly warns the fix must not reproduce.
What is comparable is the live side to itself.
diffgroups live resources by thedestination_idCoolify does report, and a project whose resources don't all share one network is drift — non-clean, both sides named, never repaired (apply moves nothing between networks):That catches the failure the issue is actually about, including on a box whose destinations were made by hand and cast was never told about. On an undeclared, unsplit box — every box today — placement prints nothing at all.
Not on the migration's path
Nothing here changes what a single-project server does: undeclared means "the server's only destination", which is what Coolify picks anyway.
prod-migrationis unaffected.Tests
196 pass (27 new). Unit coverage for the binding resolvers, the placement computation and its rendering, and
destination_uuidreaching all three create payloads (and being absent, not empty-string, when undeclared — Coolify branches on$request->has()). Plustest/placement-cli.test.ts, an end-to-end run of the realdist/cli.jsagainst a stub Coolify, which is what provesenvironments.yamlis actually wired to the report.Follow-up, not fixed here
smokeresolves its target against the instance-wide application list, so two projects with an app of the same name are a coin flip. Pre-existing, out of scope, worth its own issue.🤖 Generated with Claude Code