Sitelet https://github.com/cacheplane/threadplane/blob/main/docs/RELEASE.md
Skip to content

Latest commit

 

History

History
145 lines (105 loc) · 6.51 KB

File metadata and controls

145 lines (105 loc) · 6.51 KB

Release Process

The six publishable libraries (@threadplane/chat, @threadplane/langgraph, @threadplane/ag-ui, @threadplane/render, @threadplane/a2ui, @threadplane/telemetry) ship together at a synchronized version via Nx Release. Releases use minor bumps (0.1.0 → 0.2.0 → …). Never cut 1.0.0 without explicit approval from the repository owner, every time.

Nx updates internal dependency and peer ranges with the synchronized release. preserveMatchingDependencyRanges is disabled so a prior ^0.0.x peer range cannot block the next patch or leave companion packages on incompatible versions. External dependency ranges remain unchanged.

Standard release (second release onward)

First release? See First @threadplane release below — the flow is different because there's no prior package under the new npm org yet.

Warning

Do not use nx release patch. The one-shot nx release command does not work in this repo. nx.json configures git options under release.changelog.git, and Nx rejects the top-level command whenever granular git config is present:

NX The "release" top level command cannot be used with granular git configuration.

Use the subcommands below instead.

From a clean main branch:

git checkout main && git pull

# 1. Version bump. Runs preVersionCommand (builds all six projects), rewrites every
#    package.json, updates package-lock.json, and stages the result.
npx nx release version --specifier=minor

# 2. Regenerate the public agent-context files. They embed the release
#    version, and the Website unit suite fails the release commit until
#    `apps/website/public/{AGENTS,CLAUDE}.md` say the new version.
npm run generate-agent-context
git add apps/website/public/AGENTS.md apps/website/public/CLAUDE.md

# 3. Changelog + commit + tag + GitHub Release.
#    Pass the BARE version — see the warning below.
npx nx release changelog 0.0.57

# 4. Push. The Publish workflow fires on the tag and publishes to npm
#    with provenance via OIDC trusted publishing.
git push origin main --tags

Warning

Pass the bare version to changelog, not vX.Y.Z. releaseTagPattern is v{version}, so Nx prepends the v itself. Passing v0.0.57 produces a malformed vv0.0.57 tag and a GitHub Release at /releases/tag/vv0.0.57. Pass 0.0.57.

Always --dry-run step 2 first and check the printed tag URL before committing to it.

Step 4 is what actually ships. Prefer the tag-driven workflow: it rebuilds the versioned sources, runs the package gates, and publishes with provenance without local npm credentials. If publishing locally, first rebuild all six packages and Growth, then run telemetry:test-install-pack and telemetry:test-development-bundle before npx nx release publish --groups=publishable. The version command's pre-build embeds the old runtime version; a rebuild after versioning is required to align collector payloads with the new package manifests.

Check the lockfile before pushing

Step 1 regenerates package-lock.json. On macOS that can drop the Linux @next/swc-* bindings and break CI. The diff should be only the version lines for the six libs:

git diff --cached package-lock.json | grep -E '^-' | grep -icE 'linux|darwin|musl|gnu'
# must print 0

If it prints anything else, revert the lockfile and re-apply the version lines by hand.

First @threadplane release

The first publish under the @threadplane npm org is manual. The packages must exist on npm before trusted publishing can be configured package-by-package. Run this from a clean, merged main branch.

# 1. Install and build everything
npm ci
npx nx run-many -t lint,test,build --projects=chat,langgraph,ag-ui,render,a2ui,telemetry --skip-nx-cache

# 2. Verify release metadata
node scripts/verify-release-versions.mjs --tag v$(node -p "require('./libs/chat/package.json').version")
npx nx release publish --groups=publishable --dry-run

# 3. Publish manually.
npm publish dist/libs/telemetry --access public
npm publish dist/libs/a2ui --access public
npm publish dist/libs/render --access public
npm publish dist/libs/chat --access public
npm publish dist/libs/ag-ui --access public
npm publish dist/libs/langgraph --access public

# 5. Verify all package pages resolve.
npm view @threadplane/telemetry version
npm view @threadplane/a2ui version
npm view @threadplane/render version
npm view @threadplane/chat version
npm view @threadplane/ag-ui version
npm view @threadplane/langgraph version

After the first @threadplane release, configure npm trusted publishing for all six packages against .github/workflows/publish.yml. Subsequent patch bumps use the one-shot flow above.

Dry run

Always sanity-check before a real release. Dry-run each subcommand — the one-shot nx release patch --dry-run fails the same way the real command does:

npx nx release version --specifier=minor --dry-run
npx nx release changelog 0.0.57 --dry-run   # bare version; check the printed tag URL

These print what would happen without modifying anything.

Is a release actually needed?

Version bumps on main do not publish — only a pushed vX.Y.Z tag does. Main routinely drifts ahead of npm, and the version on disk can match the version on npm while the code differs. Check before assuming:

git rev-list --count "v$(npm view @threadplane/chat version)"..origin/main

Anything above 0 means main has unpublished commits.

Manual workflow trigger

Publish workflow accepts workflow_dispatch with a dry-run input (default true). Trigger from the GitHub Actions UI to verify CI's publish path without actually shipping.

Versioning policy

Releases bump the minor component (0.1.0 → 0.2.0 → …). Breaking changes can still land in any release while the major is 0, so consumers should lock to an exact version; the changelog names the breaking entries.

1.0.0 is a deliberate gate, not something to infer from scope or stability: ask the repository owner and wait for an explicit yes before cutting it.

Through v0.0.66 the project used patch-only bumps. That ended on 2026-09-08, when a backlog of breaking changes made the patch counter actively misleading.

Internal peer dependencies

Caret-prefixed ranges (^0.0.1) do not include subsequent 0.0.x patches. Nx updates internal peers during each synchronized release so a newly installed package resolves compatible companion APIs. Do not preserve stale narrow ranges or manually restore wildcard peers after versioning.