Making a release
Use when cutting a new fused-render release, bumping the version, or creating a release tag — bumps __version__, lands it on protected main via a bump PR, then tags vX.Y.Z and pushes the tag to trigger the DMG build/release workflow.From its SKILL.md
npx -y skills add fusedio/fused-render --skill making-a-releaseAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 9 stars9 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.1 KB, as published. Nobody here has run it
Making a Release
Overview
A release is: bump __version__, land that bump on main through a PR, then tag the merged commit vX.Y.Z and push the tag. Pushing the tag is what triggers .github/workflows/release.yml (build → sign → notarize → publish DMG + GitHub Release).
main is a protected branch. Direct pushes are rejected (GH006: Changes must be made through a pull request), so the bump PR is not optional — it is the only path. Do not try git push origin main first.
Single source of truth: the version lives ONLY in fused_render/__init__.py. pyproject.toml derives it dynamically ([tool.hatch.version]) — never edit a version into pyproject.toml.
The invariant that matters: the git tag name must equal __version__. Tag v0.3.5 ⟺ __version__ = "0.3.5". A mismatch ships the wrong version silently.
Steps
-
Start clean and on the latest
main. Always pull first — tagging a stale commit ships an old build. Use--ff-onlyso a diverged local branch errors out loudly instead of creating a merge commit:git switch main git pull --ff-only origin main # REQUIRED: get the latest before releasing git status --porcelainIf
git pull --ff-onlyfails, your localmainhas diverged — reconcile it before continuing. Ifgit status --porcelainprints anything, stop and resolve it first. -
Pick the new version. Read the current value and the latest tag; choose the next semver:
grep __version__ fused_render/__init__.py git tag --sort=-creatordate | head -1 -
Branch, then bump. Work on a branch from the start —
mainis protected:git switch -c bump-X.Y.ZBump
__version__infused_render/__init__.py(Edit tool). This is the only file to change. -
Commit (message matches the repo's history convention exactly):
git commit -am "Bump version to X.Y.Z" -
Open the bump PR and let it merge. Push the branch and open the PR with the
creating-pull-requestsskill (titleBump version to X.Y.Z), then enable auto-merge so it lands as soon as checks go green:git push -u origin HEAD gh pr create --title "Bump version to X.Y.Z" --body-file <body.md> gh pr merge <N> --squash --autoPoll until it actually reports
MERGED— do NOT tag before then:gh pr view <N> --json state,mergeStateStatus,mergeCommit -
Return to
mainand pull the merged bump. The squash merge creates a NEW commit, so the tag must point at that commit, not your local branch commit:git switch main git pull --ff-only origin main grep __version__ fused_render/__init__.py # confirm it reads X.Y.Z -
Tag — annotated, name is
v+ the exact version:git tag -a vX.Y.Z -m "vX.Y.Z" -
Push the tag. This is the release trigger:
git push origin vX.Y.Z -
Verify the release workflow started, then clean up the branch:
gh run list --workflow=release.yml --limit 3 git branch -d bump-X.Y.Z && git push origin --delete bump-X.Y.Z
Quick Reference
| Thing | Value |
|---|---|
| Version source | fused_render/__init__.py → __version__ |
| Tag format | vX.Y.Z (must match __version__) |
| Release trigger | pushing a v* tag → .github/workflows/release.yml |
| Commit message | Bump version to X.Y.Z |
| How the bump lands | bump PR into protected main, squash-merged (never a direct push) |
| What gets tagged | the squash-merge commit on main, after git pull |
| Do NOT edit | pyproject.toml version (dynamic via hatchling) |
Common Mistakes
- Editing the version in
pyproject.toml. It's dynamic; the value there is ignored/derived. Edit__init__.pyonly. - Tag name ≠
__version__. e.g. taggingv0.3.5while__version__is still0.3.4. Bump and commit before tagging. - Committing the bump straight onto local
main. The push will be rejected by branch protection and you'll have to move the commit to a branch anyway (git branch bump-X.Y.Z && git reset --hard origin/main). Branch first (step 3). - Tagging your local bump commit instead of the merged one. The squash merge
produces a different SHA; tagging the pre-merge commit points the release at a
commit that is not on
main. Pullmainfirst (step 6), then tag. - Tagging before the PR is actually merged. "Auto-merge enabled" is not merged —
wait for
state: MERGED. - Forgetting the tag push. No tag push = no release, even once the bump is on
main. - Reusing an existing tag. Tags are immutable releases; pick an unused version. Check
git tagfirst. - Skipping
git pull. Tagging a stale localmainbuilds and ships an old commit. Always pull (steps 1 and 6) so the tag points at the true latest.