Versioning and Release
This doc explains how we version and publish artifacts. Platform version (root package.json, apps, npm packages, and semver image tags) is managed together via Changesets.
Version source (for contributors)
| Artifact | Version source | Published tags / registry |
|---|---|---|
Platform (grant) | Changesets fixed group | Root package.json version |
Apps (grant-api, grant-web, grant-docs) | Same fixed group | Not published to npm (private) |
npm (@grantjs/schema, client, server, cli) | Same fixed group | registry.npmjs.org |
| Docker images | apps/api/package.json after version PR | :demo, :sha-<commit>, :<version>, :latest |
example-nextjs image | Same as platform apps (image tags, not npm) | Same GHCR tags as other images |
| Demo environment | :demo on main | Latest main commit |
Web header / GET /api/config appVersion | apps/api/package.json at API startup | No env vars; matches running API image semver |
OpenAPI info.version | Same as config.app.version | — |
Do not set APP_VERSION or NEXT_PUBLIC_APP_VERSION — they were removed. The API reads semver from apps/api/package.json via readPlatformVersion() so the UI and OpenAPI stay aligned with the Docker tag CI publishes.
Fixed versioning group
All of these bump together when you add a changeset for any member of the fixed group (for example @grantjs/schema or grant-api):
grant-api,grant-web,grant-docs@grantjs/schema,@grantjs/client,@grantjs/server,@grantjs/cli
The root grant package is private and not in the pnpm workspace, so changesets cannot target it by name.
Internal packages (@grantjs/core, @grantjs/database, etc.) and examples remain in the changeset ignore list.
How Changesets work
Add a changeset when you change platform or publishable package behavior:
bashpnpm changesetChoose bump type (patch/minor/major) for any fixed-group member (not the root
grantpackage). This creates a file under.changeset/.Open a PR (or push to an existing PR). The release workflow runs on every push to
main. If there are unversioned changesets, it creates or updates a PR titled "chore: version packages" by runningpnpm version(changeset versionplus scripts/update-root-changelog.mjs). That updates package versions, package changelogs, root CHANGELOG.md, and the rootpackage.jsonversion. Nothing is published yet.Merge the "chore: version packages" PR. The workflow then:
- Runs
pnpm release(builds and publishes to npm) - Tags Docker images with
:<version>and:latest - Creates git tag
v*and a platform GitHub Release (notes from changeset summaries / root changelog) .changeset/*files from that PR are removed in the version commit
- Runs
Every push to
mainstill builds and pushes app images with:demoand:sha-<commit>when relevant paths change.
Docker image tags
| Tag | When | Use |
|---|---|---|
:demo | Every qualifying push to main | Demo / rolling main |
:sha-<full-sha> | Same build as :demo | Traceability |
:1.0.0, :1.1.0, … | After version PR merge (or release-baseline) | Pin production / Helm |
:latest | Same as newest semver release | Local compose default |
Baseline semver tags (one-time)
To tag existing :demo images as 1.0.0 without a version bump:
gh workflow run release-baseline.yml -f version=1.0.0 -f source_tag=demoThen tag the repo and publish notes:
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0Pushing a v* tag manually also triggers github-release.yml when a release for that tag does not already exist.
When to add a changeset
- Platform or publishable package API/behavior changes (use the fixed group).
- No changeset for: docs-only (unless releasing platform), internal ignored packages, or example apps.
- The changeset summary is the release note. Write it for humans; it appears in package changelogs and the platform GitHub Release.
GitHub Releases
- Platform release (
vX.Y.Z) — created by release.yml after npm publish. Notes come fromscripts/extract-release-notes.sh: root CHANGELOG.md when present, otherwise aggregated changeset entries from the fixed-group package changelogs. - Not created: per-package GitHub Releases (
@grantjs/client@…, etc.). Those tags may still exist for npm; the public release page is the platformv*release only. - CHANGELOG.md — platform-wide notes (kept in sync by
pnpm versionviascripts/update-root-changelog.mjs; preferred source for GitHub Release notes when present) docs/releases/vX.Y.Z.md— optional long-form detail for a release- Package histories:
apps/*/CHANGELOG.md,packages/@grantjs/*/CHANGELOG.md