release-publish
Use when tagging versions or publishing a GitHub release. Version in every manifest, build, gates, a pathspec commit, push of main or one tag (never --tags, never --force), a draft release with checks
SKILL.mdiclone/skills/release-publish/SKILL.md
GitHubRelease — one version, everywhere, verified from outside
When to use
The owner asks to cut a version, tag it, or publish a release with downloadable files. For gh login and repo basics see the github skill (references/auth.md, and references/repo-management.md for releases); this skill is the safe order around them.
Prerequisites
git,gh(gh auth statusshows a login withreposcope) andshasum(macOS) orsha256sum(Linux). Truth: each tool's--help.- A clean tree:
git status --porcelainprints nothing you did not mean to ship. - Tag, push and release are WRITES →
~/.iclone-os/bin/acp consent request terminal --reason "Publish <vX.Y.Z> of <owner>/<repo>", state the version, the branch and the asset list, and wait for the owner's yes.
Quick reference
bump → build → gates → sterilise → commit the checked index → push main → push ONE tag → draft release + SHA256SUMS.txt → check → promote → fresh download + logged-out check.
Procedure
Bump the version in every manifest. Find them all first, then change each one:
git grep -n -I -e '"version"' -e '^version' -- '*package.json' '*pyproject.toml' '*Cargo.toml' '*.plist' '*.conf.json' # exampleNode packages:
npm version <X.Y.Z> --no-git-tag-version(also updates the lockfile). Add the entry toCHANGELOG.md. Thengit grep -n '<old-version>'must list only history notes. Stage exactly the release files:git add -- <path> <path>(# example).Build and run the project's gates (tests, lint, type check, packaging). A failing gate stops the release; never skip one to "fix later".
Sterilise. Run
sterilise-before-commiton the staged release changes (stage any file the build changed first). Zero findings or stop.Commit the scanned index, with no pathspec. A pathspec re-reads the working tree and re-adds a file step 3 untracked (
git rm --cached). List the index first: every path must be a release file; a stray one:git restore --staged <path>, then redo step 3:git diff --cached --name-only # example git commit -m "release: <vX.Y.Z>" # examplePush the branch, then one annotated tag (after the owner's yes):
git push origin main && git tag -a <vX.Y.Z> -m "<vX.Y.Z>" && git push origin refs/tags/<vX.Y.Z> # exampleA rejected push means someone else pushed:
git pull --rebase, re-run the gates, push again. Do not force.Checksums and a draft release:
cd <dist> && shasum -a 256 <asset> <asset> > SHA256SUMS.txt && cd - # examplegh release create <vX.Y.Z> <dist>/<asset> <dist>/SHA256SUMS.txt --repo <owner>/<repo> --verify-tag --draft --title "<vX.Y.Z>" --notes-file <notes.md> # example--verify-tagaborts if the tag is not on the remote. Add--prereleasefor a beta.Promote once the draft's assets and notes look right:
gh release edit <vX.Y.Z> --repo <owner>/<repo> --draft=false --latest # exampleDownload it fresh (a new empty folder on every run, no local build in the path).
ghuses your own login, so this proves the files and checksums, not anonymous access:d=$(mktemp -d) && cd "$d" && gh release download <vX.Y.Z> --repo <owner>/<repo> && shasum -a 256 -c SHA256SUMS.txt # examplePublic repo only — prove a stranger can download it with the logged-out URL:
curl -sSL -o /dev/null -w '%{http_code}\n' https://github.com/<owner>/<repo>/releases/latest/download/<asset>prints200(# example). A private repo has no anonymous download.
Pitfalls
- A version left behind in one manifest ships an app that reports the wrong version and breaks update checks.
git push --tagspublishes every local tag, including experiments and imported upstream tags.- A pushed tag is public history. If it is wrong, publish
<vX.Y.Z+1>; moving or deleting a published tag needs the owner's explicit yes and breaks anyone who already fetched it. - Bundled third-party code can trip the secret scanner; record a reviewed exception, never disable the scan.
- Signing and notarisation are project-specific: run the project's own release script, never improvise identities.
Never
- Never
git push --force,--force-with-leaseor--tagsin a release. - Never
git commit -aor a pathspec commit in a release: both ship the working tree, not the scanned index. - Never publish before the owner's yes and a passing gate run.
Verification
gh release list --repo <owner>/<repo> --json tagName,isDraft,isLatest --limit 5 (# example) shows <vX.Y.Z> with "isDraft":false and "isLatest":true, and shasum -a 256 -c SHA256SUMS.txt prints OK for every asset.