Skip to content
Nuits ReceiptsDocs
HomeSearch the docs, Ctrl KGitHubDark mode

Cut a release

Write Conventional Commits, let the release workflow tag the version, or run the same steps locally.

Updated

Use this guide to publish a new version of Nuits Receipts. Nobody edits the version by hand: scripts/version.mjs reads the Conventional Commits since the last v* tag and decides the bump. Releasing only tags the code. Each deployment owner decides when to deploy it (see Upgrade your deployment).

Prerequisites

  • Push access to main on GitHub.
  • For a local release: Bun 1.4 or later, an up-to-date main with tags fetched (git fetch --tags), and the GitHub CLI (gh) signed in.

Choose the commit type

Pull requests are squash-merged, so the pull request title becomes the commit subject. Give it a Conventional Commits type:

Commit Bump Changelog section
fix(...), hotfix(...) patch Hotfixes
perf(...), revert(...) patch Hotfixes, or UI enhancements for a UI scope
style(...) patch UI enhancements
feat(...) minor Features, or UI enhancements for a UI scope
type! or a BREAKING CHANGE: footer major Breaking changes
docs, test, chore, ci, build, refactor, copy, update none not listed

UI scopes are a11y, design, footer, style and ui. The highest bump in the range wins. Subjects that are not Conventional Commits are ignored and reported under unclassified, and merge commits are skipped.

Release from GitHub

  1. Check the code

    Before merging, run the full check and a deploy dry run:

    bun run check
    bun run deploy:dry-run

    See Run the tests for what check covers.

  2. Merge to main

    Merging does not release. .github/workflows/release.yml runs only when you start it by hand on main: Actions, Release, Run workflow. It never runs on a push or a schedule, and a run started from another branch does nothing. One run releases every commit merged since the last tag.

    The workflow runs bun scripts/version.mjs apply, which rewrites package.json and prepends an entry to CHANGELOG.md, then acts on the plan:

    • release: commits chore(release): vX.Y.Z, tags vX.Y.Z, pushes main and the tag, and creates a GitHub Release from that version’s changelog entry.
    • baseline: first run only, when no tag exists. Tags the current package.json version and creates a GitHub Release for it.
    • skip: no feat, fix, perf, style or breaking commits since the last tag. Nothing changes.

    If main is protected, add a RELEASE_TOKEN repository secret with a token that may push to it. Without it the workflow uses the default GITHUB_TOKEN.

  3. Override the bump if needed

    To force a bump, run the workflow by hand: Actions, Release, Run workflow, then choose patch, minor or major under bump. auto follows the commits.

Release from your machine

The same steps run locally on an up-to-date main.

  1. Preview the plan

    bun run version:next

    This is read-only. It prints the plan as JSON: action, currentVersion, bump, nextVersion, tag, the grouped changelog lines and any unclassified subjects. To preview a forced bump:

    bun run version:next -- --force minor
  2. Apply the plan

    bun run version:apply > plan.json

    This rewrites package.json and prepends CHANGELOG.md. It does not touch git or the network. Read action and nextVersion in plan.json.

  3. Commit, tag and publish

    For "action": "release", with X.Y.Z from nextVersion:

    git add package.json CHANGELOG.md
    git commit -m "chore(release): vX.Y.Z"
    git tag -a vX.Y.Z -m "Release vX.Y.Z"
    git push origin main
    git push origin vX.Y.Z
    bun scripts/version.mjs notes X.Y.Z > notes.md
    gh release create vX.Y.Z --title vX.Y.Z --notes-file notes.md

    For "action": "baseline", tag the current version with git tag -a vX.Y.Z -m "Release baseline vX.Y.Z", push the tag and create a GitHub Release for it. For "action": "skip", there is nothing to do.

Nothing is published to npm.

Check it worked

  • The new tag shows under Releases on GitHub with the grouped notes.
  • CHANGELOG.md on main starts with the new version.
  • After a deployment, the footer of every app page shows the new version. src/ui.ts reads it from package.json at build time, and if SOURCE_REPOSITORY is set the version links to <SOURCE_REPOSITORY>/releases/tag/vX.Y.Z.

If something goes wrong

  • Push rejected: no tag or release was created. Fix the cause and run it again; the plan is computed from scratch.
  • Tag exists, release does not: run bun scripts/version.mjs notes X.Y.Z > notes.md, then gh release create vX.Y.Z --notes-file notes.md.
  • Wrong commit type: land a correcting commit. Never move or delete a published tag.

Docs

The docs site in docs-site/ is not versioned by this process: a docs(...) commit does not bump the version. Build it before you merge a docs change, so broken internal links and copy rule hits fail locally rather than later. See the end of Run the tests for the commands.

Type to search…

↑↓ navigate↵ selectEsc close