Releases are tag-driven. Pushing a v*.*.* tag triggers
.github/workflows/release.yml, which validates, tests, builds, publishes
to npm with provenance, and creates a GitHub Release from the matching
CHANGELOG.md section.
You should never run npm publish manually for routine releases.
NPM_TOKENmust exist inSettings → Secrets and variables → Actions. Use an automation token withpublishscope (not a user token), and keep npm 2FA onauth-and-writesso token-based CI publish keeps working.- The
id-token: writeandcontents: writepermissions are already set in the workflow — these enable npm--provenanceand GitHub Release creation.
-
Make sure
mainis green. All work for the release is merged and the regularci.ymlis passing. -
Add a CHANGELOG entry for the new version. Heading must be exactly
## [X.Y.Z] — YYYY-MM-DDso the workflow can extract release notes. -
Bump the version:
npm run release:patch # 0.2.1 → 0.2.2 npm run release:minor # 0.2.x → 0.3.0 npm run release:major # 0.x.y → 1.0.0
Each script runs
npm version <bump>(which updatespackage.json, creates a commit, and creates the matchingvX.Y.Ztag) then pushes the commit and tag together with--follow-tags. -
Watch the run in the Actions tab. The pipeline runs four jobs:
verify— fails fast if the tag doesn't matchpackage.json.version.unit— matrix Node 18/20/22, typecheck + build + tests.integration— Postgres 17 + Redis 7 services, three retry attempts.publish—npm publish --provenance --access publicthen creates the GitHub Release with the CHANGELOG section as body.
-
Verify the published artifact:
npm view kompensa@<version> npm install kompensa@<version> --dry-run
Check the GitHub Release page and the
Provenancebadge on the npm page.
The most common failures and their fixes:
-
Tag/version mismatch (
verifyjob): the tag was pushed but thepackage.jsonchange was forgotten. Delete the tag locally and remotely, fixpackage.json, retry:git tag -d vX.Y.Z git push --delete origin vX.Y.Z # fix package.json, commit, then re-run the bump -
Tests fail on a Node version not in
ci.yml: bump matrix inci.ymlto keep parity withrelease.yml. Don't lower coverage to ship. -
Integration retry exhausted: usually flaky service startup. Re-run the failed
integrationjob from the Actions page; nothing else needs to change. The downstreampublishjob re-runs automatically. -
npm publish403 / OTP: token expired or scope wrong. Generate a new automation token, updateNPM_TOKENsecret, re-run the failed job. -
Pre-publish blocked locally:
prepublishOnlyruns typecheck + tests + build. If you're trying to publish manually, fix the underlying error rather than bypassing the script.
- Patch (
0.2.x): fixes, docs, dep bumps, additive type-only changes. - Minor (
0.x.0): new features that are additive. Backwards-compatible with prior0.xconsumers — no removal, rename, or behavior change of existing public API. - Major (
1.0.0): API freeze. Until then, treat any breaking change as reason to delay the release rather than ship it.
The current public surface is fixed in llms.txt and AGENTS.md. Adding
to it is allowed; removing or renaming requires a major bump.
Only the files listed under package.json#files:
dist/
README.md
LICENSE
CHANGELOG.md
Anything else (src/, test/, .github/, docs/, node_modules/, etc.)
stays out of the tarball. Run npm pack --dry-run locally to inspect what
would be published.