The release model
kuda releases itself — there is no hosted CI and no release tool in the loop. Two deliberate phases:
Phase 1 — the explicit seed
kuda deploy release runs once, by hand: it reads cargo metadata, topologically orders the workspace's path-dependency graph, cargo publishes every member, tags {repo}-v{version}, and pushes the tag.
Why explicit? Publishing is the only irreversible step in the whole system. Queues, runs, and statuses are all idempotent and local; a crate version on crates.io is forever. Everything else in kuda fires on push — the seed doesn't. (--dry-run prints the order and tag without touching anything.)
Phase 2 — push-driven forever after
From then on a release is just another kuda job: a push to main hits the webhook, queues latest-wins, and runs scripts/release.sh in a detached worktree under the shell runner.
The script:
- diffs crate paths since the last
kuda-v*tag cargo set-version --bump patchon touched crates only (the cli republishes on any change — it's the install artifact)cargo publishes them in dep order- tags
kuda-vX.Y.Z, builds host-arch binaries withcargo dist, uploads to a GitHub Release viagh
The 5-minute sleep at the top isn't a hack — it's the debounce window. Combined with queue = "latest" + cancel_running, rapid push bursts collapse to one release of the newest sha; killed runs get an honest "cancelled" status.
Why this shape
- No release-plz / GHA: the point of the project is that CI is a local loop — depending on hosted CI to ship it would be self-defeating.
scripts/release.shis deliberately boring bash so it can run as a plaincmdunderrunner.kind = "shell". - Latest-wins, not
all: a release that misses an intermediate push loses nothing — the tag lands on HEAD, which contains everything.queue = "all"is for pipelines where each sha's run is individually meaningful. - Explicit over automatic: a wrong tag or half-published workspace is far worse than a delayed release; the boundary sits exactly at irreversibility.
Host prerequisites: cargo-edit, cargo-dist, gh, and CARGO_REGISTRY_TOKEN (env → keyring → env file). Multi-arch binaries arrive when the remote-runner pair lands — see TODO.