release-process.md
May 17, 2026 ยท View on GitHub
Release Process
This guide is the canonical source of truth for templjs branching, prerelease publishing, promotion, and stable release publication.
Branch Strategy
templjs uses two long-lived branches:
staging- prerelease integration branch
- default target for normal contributor PRs
main- stable promotion branch
- only branch from which stable releases are cut
- only branch where the Changesets version PR is consumed
Short-lived branches should branch from staging:
feature/*fix/*chore/*
Emergency hotfixes may branch from main, then back-merge into staging.
Merge policy:
- PRs into
staging:squash - PRs into
main:rebase - merge commits are disallowed on long-lived branches
Version Authority
templjs intentionally splits prerelease and stable version authority.
Stable version authority:
- Changesets
- consumed only on
main
Prerelease version authority:
- CI-generated ephemeral versions
- applied only inside GitHub Actions on
staging - never committed back to the repository
Versioning Model
Changesets configuration lives in ../.changeset/config.json.
Public npm package set:
@templjs/core@templjs/cli@templjs/volar@templjs/context-graph@templjs/language-core@templjs/language-service@templjs/language-server@templjs/semantify
Fixed synchronized train:
@templjs/core@templjs/cli@templjs/volar@templjs/context-graph
Public dependent packages are published with the package release lane and should remain compatible with the synchronized train. @templjs/semantify is public and participates in the same package release inventory.
Independent extension:
vscode-templjs
Staging Prerelease Lane
Pushes to staging can publish prerelease artifacts automatically.
Scope rules:
- npm prereleases publish when the merged diff touches
src/packages/** - VS Code prereleases publish when the merged diff touches:
src/extensions/vscode/**src/packages/core/**src/packages/volar/**src/packages/context-graph/**src/packages/language-core/**src/packages/language-service/**src/packages/language-server/**src/packages/semantify/**
Version rules:
- npm packages use:
0.0.0-staging.<run_number>.<run_attempt>
- VS Code uses a CI-generated next-minor plain semver:
- stable version
X.Y.Z - staging prerelease version
X.(Y+1).N Nderived from workflow run number and attempt
- stable version
Publishing rules:
- npm publishes to dist-tag
next - VS Code publishes with
--pre-release - no routine staging tags are created
- no GitHub Release prerelease checkbox is involved
Main Stable Lane
Stable releases are tag-driven from main.
Stable tag lanes:
- npm packages:
vX.Y.Z - VS Code extension:
vscode-vX.Y.Z
Publishing starts only after a GitHub Release is published from one of those tags.
Stable outputs:
- npm publishes to dist-tag
latest - VS Code publishes without
--pre-release
Contributor Flow
- Branch from
staging - Implement the change
- Add a Changeset if the change affects released artifacts
- Open a PR to
staging - Merge after required CI passes
Changeset rule:
- if a PR changes
src/packages/**orsrc/extensions/vscode/**, it must include at least one.changeset/*.md - CI enforces this through
Require Changeset - the automated version PR on
mainis exempt
Staging Validation Posture
staging is the prerelease soak branch.
Required on staging:
- core CI jobs from
ci.yml
Informational on staging:
Benchmark SuiteAnalyze (javascript-typescript)
Those checks still run on staging, but they do not block prerelease integration there.
Promotion Flow: staging to main
Promotion is intentional and maintainer-driven.
Maintainer steps:
- Open a PR from
stagingtomain - Wait for all required
mainchecks to pass - Merge using
rebase
Required on main promotion PRs:
- all core CI checks from
ci.yml Benchmark SuiteAnalyze (javascript-typescript)
This encodes the intended policy:
- benchmark and CodeQL are informational on
staging - benchmark and CodeQL become gating only when promoting to
main
Stable Release Flow
1. Merge the Version PR on main
The release workflow maintains an automated Changesets version PR on main.
That PR:
- applies pending Changesets
- keeps the fixed npm train aligned
- publishes all public
@templjs/*workspace packages included in the package release lane - updates the VS Code extension independently when selected
- regenerates
src/extensions/vscode/CHANGELOG.mdwhen the extension version changes
2. Create the Stable Tag
Choose the correct lane:
# npm packages
git tag v0.2.0
git push origin v0.2.0
# VS Code extension
git tag vscode-v0.3.0
git push origin vscode-v0.3.0
3. Publish the GitHub Release
In GitHub:
- publish a release from the stable tag
- do not mark it as a prerelease
4. Let Automation Publish
The workflow then:
- verifies the tag format and release lane
- verifies the tagged commit is already reachable from
main - verifies the tagged version matches the workspace version for that lane
- builds the workspace
- generates release notes
- publishes only the selected lane
- updates the GitHub Release body
- attaches VSIX assets and checksums for extension releases
Required Configuration
Branch Protection
Protect both long-lived branches:
stagingmain
Shared required checks:
Install DependenciesLintType CheckLint Work Item FrontmatterRequire ChangesetRequire Release MetadataDocs API Guard- all required matrix
Testjobs Build
main-only additional required checks:
Benchmark SuiteAnalyze (javascript-typescript)
GitHub Environments
Create:
prereleaserelease
npm Trusted Publishing
Configure trusted publishing for:
@templjs/core@templjs/cli@templjs/volar@templjs/context-graph@templjs/language-core@templjs/language-service@templjs/language-server@templjs/semantify
Use ../.github/scripts/prepare-npm-trusted-publishing.sh to print the exact package URLs and trusted-publisher values.
Use:
- owner:
templjs - repository:
templ.js - workflow filename:
release.yml - environment name: leave blank
VS Code Marketplace
Configure:
VSCODE_PUBLISHER_TOKEN- publisher membership and publish rights for
templjs
Tag Protection
Protect:
v*vscode-v*
Routine staging prereleases do not use tags.