release flow: tagged releases with a prebuilt dist asset #96
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#96
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
The problem
cast has a version (
package.jsonsays0.1.0) but no tags, no GitHub releases, and noCHANGELOG.md.install.shdownloadsarchive/refs/heads/mainand builds on the operator's machine —npm ci,tsc, then prune — so every install pulls devDependencies and compiles, and "what cast is this?" means "whatever main was when you last curl'd". For the tool that holds the keys to the fleet's secrets and reconciles production Coolify, installs should be reproducible and named.This is the cast half of the flow designed in heavy-duty/box#83 — same release shape, plus the piece unique to cast: a prebuilt dist asset, because cast is the one repo where the source tarball is not the package.
The flow
1. Grow the release surface.
CHANGELOG.mdwith an## Unreleasedsection; feature PRs land their entry as part of the PR.cast --versionreadspackage.json— the version's single source of truth (no separateVERSIONfile; the ecosystem already has one).2. A release is a PR, then a tag.
release: X.Y.Z— bumpspackage.jsonand stamps the Unreleased section with version + date. CI green on it.X.Y.Z(matching box's and rig's tag scheme), push the tag.3.
release.yml, on tag push — this is where cast differs:package.jsonversion — fail loudly on mismatch, create nothing.npm ci && npm run build && npm prune --omit=dev, then tar the runnable tree (bin/,dist/, productionnode_modules/,package.json) intocast-X.Y.Z.tgz.gh release createwith the version'sCHANGELOG.mdsection as the body and the tarball attached as the asset.4. The installer defaults to the latest release asset, not a source build.
CAST_REFunset → resolve the latest tag via thereleases/latestredirect (Locationheader — no API, no token), downloadcast-$TAG.tgz, extract into$DEST. Nonpm ci, notsc, no devDependencies on the operator's machine — the build happened once, in CI. Node >= 22.12 andageremain runtime prerequisites exactly as today.CAST_REFset (a branch or tag with no asset) → fall back to today's build-from-source path. That keepsCAST_REF=mainas the dev channel.CAST_REF=X.Y.Z= pinned,CAST_REF=main= dev build-from-source.Order
CHANGELOG.md+cast --version.release.ymlwith the dist-asset build + asset-aware installer.