name: release description: Use whenever cutting, preparing, tagging, or publishing an onde-cli release — version bumps, release branch, merges, tagging, pushing to trigger the publish pipeline, and verifying it landed. Also use when a release went wrong (wrong tag target, failed crates.io verify, development left behind main, unsigned release commits) and the repo state needs repair. Trigger even if the user only says "release vX.Y.Z", "bump the version", "tag a release", or "publish the new version".
user-invocable: true
Release skill
End-to-end release procedure for onde-cli. Complements the git skill (merge rules)
and the distribution skill (channel details) — this skill is the concrete runbook.
Decide the version
- Look at
git tag -l 'v*' --sort=-v:refname | head -1for the latest release. - Look at the commits since (
git log v<latest>..development --oneline). Fixes and chores only → patch bump. New user-facing features → minor bump. - Check for an abandoned
release/vX.Y.Zbranch — its version is usually the intended next one. If it exists, inspect it (git log development..release/...) before deciding to reuse or delete it; do not blindlybranch -Dwithout looking, and never reuse a branch whose commits were made unsigned or by the wrong identity.
Version bump surfaces
These files pin the crate version and must all move together:
Cargo.toml—version = "X.Y.Z"in[package]pub/onde_cli/pubspec.yaml—version: X.Y.Zserver.json— three occurrences: top-levelversion, and the npm and NuGetpackages[].versionentries (search for the old version string to catch all)
docs/mcp-registry.md and .github/workflows/release-mcp-registry.yml mention
past versions only as historical examples — do not bump those.
The npm wrapper manifests are NOT bump targets: the committed package.json files
are rewritten at release time by npm/scripts/render-*.cjs from the tag.
After editing, run cargo check --locked (or let the build update Cargo.lock)
so the lockfile carries the new version, and commit it in the same bump commit.
Sequence
Follow the git skill's branch flow — release/vX.Y.Z → development → main,
--no-ff at every hop, tag on the final main merge commit. Concretely:
git checkout development
git pull <remote> development # start from the pushed tip
git checkout -b release/vX.Y.Z
# ... edit the bump surfaces ...
git commit -am "Prepare vX.Y.Z" # signed, correct identity (see below)
git checkout development
git merge --no-ff release/vX.Y.Z -m "Merge release prep for vX.Y.Z"
git checkout main
git pull <remote> main
git merge --no-ff development -m "Merge development for vX.Y.Z"
git tag vX.Y.Z
git push <remote> development main vX.Y.Z
git branch -d release/vX.Y.Z # only after the merge lands
The remote here is the one whose URL is the sigit.si or GitHub org repo —
check git remote -v; this repo is commonly cloned with per-account remotes
(gh-setoelkahfi, gh-paydii, gh-keypair34) rather than origin.
What a good result looks like
- The tag sits on the step-3 merge commit on
main(git log --graph mainshows a merge commit directly above the previous release). git log development..mainandgit log main..developmentare both empty after the merges — the two branches carry identical trees.- Never tag a release-branch tip or a bare bump commit on
main; if the work somehow already landed onmainlinearly, follow the git skill's fallback (normal commit, tag it) rather than rewriting history.
Post-push back-merge check
If anything reached main without passing through development first (hotfix,
manual push, a fast-forwarded release), bring it back immediately:
git checkout development
git merge --no-ff main -m "Merge main for vX.Y.Z"
git push <remote> development
A release is not done until the two branches contain the same tree.
Commits and signatures — read the git-commit-signing skill first
Release commits must be GPG-signed by the maintainer identity that GitHub can
verify (this repo: Seto Elkahfi <1797197+setoelkahfi@users.noreply.github.com>,
EDDSA key 2B76DF0F04014E36). The gh CLI's active account is independent of
git config — set both, and verify before pushing:
git log -1 --format='%an <%ae> sig:%G? %GK' # want sig:G and the right key
gh api repos/<owner>/<repo>/commits/<sha> --jq .commit.verification.verified
Every git commit and git merge in this flow creates a commit — configure
signing so merges are signed too, or amend unsigned ones before pushing
(git commit --amend --no-edit -S, only on unpushed commits).
Commit trailer: end release-related commit messages with
Co-Authored-By: siGit Code v1.6.7-acp <noreply@sigit.si>
The tag push is the release
Pushing vX.Y.Z triggers release-crates.yml, which verifies the tag against
Cargo.toml and pubspec.yaml, publishes the crate, then dispatches the
wrapper workflows (GitHub Releases, npm, NuGet, PyPI, then Homebrew and pub.dev
after the GitHub Release assets exist). There is no separate "publish" step.
Watch it land:
gh run list --branch vX.Y.Z
gh run watch <run-id> --exit-status
CI also runs on the tag push; both should be green. If release-crates fails,
no wrapper publishes — fix the cause, move the tag only if it has not published
anything yet (crates.io versions are immutable; a failed verify is safe to retry,
a published crate is not).
Verify
After the pipeline finishes, spot-check the fan-out (all idempotent, safe to re-check):
- crates.io:
cargo search onde-cli --limit 1 - GitHub Release:
gh release view vX.Y.Z - npm:
npm view onde-cli version - PyPI:
https://pypi.org/pypi/onde-cli/json→info.version - NuGet: flat container index for
onde-cli - Homebrew/pub.dev trail the GitHub Release; they may take a few extra minutes
Failure modes seen before
- Fast-forwarding
mainto the bump commit and tagging it — leaves no merge commit, and leavesdevelopmentbehind. Back-mergemainintodevelopmentright away and prefer merge commits next time. - Deleting a leftover
release/branch that contained unsigned bump commits and redoing the bump fresh — fine, but check it first. - Forgetting
Cargo.lockin the bump commit. - Pushing with the wrong
ghaccount active — the push works, but PR/issue actions afterwards get attributed to the wrong identity.