Releasing
This document describes how Choo Choo is versioned and published.
Tooling
- Changesets drives versioning and publishing. Every workspace package that should ship to npm is scoped under
@choo-choo/*. - GitHub Actions runs the release automation. There are two workflows:
ci.yml— Biome, typecheck, tests, and build on every push and pull request.release.yml— opens a “Version Packages” PR whenever changesets land onmain, and publishes to npm when that PR is merged.
Versioning policy
- Independent versions per package. Bumping
@choo-choo/coredoes not force a bump on every binding. - Pre-1.0 semver. While any package is on
0.y.z:- Breaking changes bump the minor.
- Feature additions and bug fixes bump the patch.
- Any package that imports
@choo-choo/coreat runtime declares it as a regular dependency and pins it to a^range. Whencoreships a breaking change, dependents open a follow-up changeset to match.
Once a package reaches 1.0.0, standard semver applies.
The release loop
-
Open a PR with a changeset.
Terminal window pnpm changesetPick the packages the change touches, the bump type (patch / minor / major), and write a short user-facing summary. The CLI writes a file under
.changeset/— commit it as part of the PR.A PR that is not user-facing (internal refactor, CI tweak, docs-only) does not need a changeset. In that case, add an empty changeset (
pnpm changeset --empty) so the release bot does not block the merge. -
Merge to
main. CI runs, and on success therelease.ymlworkflow either:- opens or updates a “Version Packages” PR that applies every pending changeset to package versions and to
CHANGELOG.mdfiles; or - if that PR is already merged, runs
pnpm releasewhich builds every package and callspnpm changeset publishagainst npm.
- opens or updates a “Version Packages” PR that applies every pending changeset to package versions and to
-
Review the Version Packages PR. It is machine-generated — skim the version bumps and the changelog entries and merge when they look right. Merging it is what triggers the actual publish.
Publish requirements
- All packages under
@choo-choo/*publish withpublishConfig.access = "public"(they are scoped and would otherwise be private by default). - npm authentication uses Trusted Publishers (OIDC). No long-lived
NPM_TOKENis stored in the repository. Each@choo-choo/*package is registered on npm with GitHub Actions as its trusted publisher, pinned to this repo and torelease.yml. The workflow declarespermissions: id-token: writeso npm can exchange the GitHub OIDC token for a short-lived publish token. Adding a new package means registering it as a trusted publisher on npm before the first release. - GitHub write access uses a GitHub App token, not the default
GITHUB_TOKEN. The App is installed on the repository and its credentials live in theRELEASE_BOT_APP_IDandRELEASE_BOT_PRIVATE_KEYsecrets.release.ymlmints a short-lived token from these and uses it to open the Version Packages PR and push git tags. The App token (rather than the defaultGITHUB_TOKEN) is required so that PRs opened by the release workflow triggerci.yml— GitHub suppresses downstream workflow events from actions performed with the default token.
Package metadata
Every publishable package.json carries:
name,version,description,license: "MIT",author.repositorywithtype: "git", the repo URL, and adirectorypointer (packages/<name>).homepagepointing at the docs site.bugspointing at GitHub issues.keywordsthat make the package discoverable on npm.sideEffects: falsewhere the package is pure JS (everything except the bindings that ship a CSS file — those setsideEffects: ["./styles.css"]).publishConfig.access: "public"and thedist-orientedmain/module/types/exportsoverrides so consumers load the built output, notsrc/.
packages/astro is published source-only (no build step) and therefore omits the publishConfig dist overrides. It still sets publishConfig.access: "public".
Docs site
apps/docs (Astro + Starlight) is deployed to GitHub Pages on every push to main by the docs.yml workflow. Its sources are the canonical files under docs/** — the Starlight site pulls them in via symlinks, so updating a spec automatically updates the published docs on the next deploy.
Checklist before cutting a version
-
pnpm biome check .,pnpm -r typecheck,pnpm -r test,pnpm -r buildall green. - Every user-facing change in the release has a changeset.
- The roadmap file for the version (
docs/roadmap/<version>.md) reflects what actually shipped. - The Version Packages PR diff looks right.
- Merge the Version Packages PR — the release workflow takes it from there.