Prerelease management enables controlled pre-production releases with coordinated versioning across multiple packages, supporting alpha, beta, and release candidate workflows.
Main function for entering and exiting prerelease mode with coordinated state management.
/**
* Manages prerelease mode (enter/exit) with coordinated state tracking
* @param cwd - Working directory path
* @param options.command - Either "enter" to start prerelease mode or "exit" to end it
* @param options.tag - Prerelease tag (required for enter, optional for exit)
*/
function pre(
cwd: string,
options: {command: "enter", tag: string} | {command: "exit", tag?: string}
): Promise<void>;Usage Examples:
import { run } from "@changesets/cli";
// Enter prerelease mode with beta tag
await run(["pre", "enter", "beta"], {}, cwd);
// Enter prerelease mode with alpha tag
await run(["pre", "enter", "alpha"], {}, cwd);
// Exit prerelease mode
await run(["pre", "exit"], {}, cwd);Prerelease mode maintains state to coordinate releases across packages:
interface PreState {
mode: "pre";
tag: string; // Prerelease tag (e.g., "beta", "alpha")
initialVersions: Record<string, string>; // Package versions when entering prerelease
changesets: string[]; // Changesets consumed in prerelease mode
}When entering prerelease mode:
.changeset/pre.json)# CLI usage
changeset pre enter beta
# This creates .changeset/pre.json:
{
"mode": "pre",
"tag": "beta",
"initialVersions": {
"@myorg/ui": "1.2.0",
"@myorg/utils": "2.1.0"
},
"changesets": []
}While in prerelease mode, version updates follow prerelease patterns:
// Standard versions become prereleases
// 1.2.0 -> 1.2.1-beta.0 (first prerelease)
// 1.2.1-beta.0 -> 1.2.1-beta.1 (subsequent prereleases)
// 2.0.0 -> 2.0.0-beta.0 (major prerelease)When exiting prerelease mode:
# CLI usage
changeset pre exit
# Versions graduate to stable:
# 1.2.1-beta.3 -> 1.2.1
# 2.0.0-beta.1 -> 2.0.0In prerelease mode, version bumps follow special rules:
// Patch changes: 1.0.0 -> 1.0.1-beta.0
// Minor changes: 1.0.0 -> 1.1.0-beta.0
// Major changes: 1.0.0 -> 2.0.0-beta.0
// Subsequent prereleases increment prerelease number:
// 1.0.1-beta.0 -> 1.0.1-beta.1
// 1.1.0-beta.0 -> 1.1.0-beta.1All packages in prerelease mode are coordinated:
// Even if only one package has changes, all packages get prerelease versions
// This ensures consistent prerelease state across the entire projectStandard changeset workflow applies in prerelease mode:
# 1. Enter prerelease mode
changeset pre enter beta
# 2. Create changesets as normal
changeset add
# 3. Version with prerelease calculation
changeset version
# 4. Publish with prerelease tag
changeset publish --tag betaPrereleases should be published with matching npm dist-tags:
import publish from "@changesets/cli/src/commands/publish";
// Publish with matching tag to prevent affecting latest
await publish(cwd, { tag: "beta" }, config);
// This ensures: npm install @myorg/ui@beta
// Instead of affecting: npm install @myorg/ui (latest)Different tags can represent different stages:
# Development flow
changeset pre enter alpha # Early development
# ... development and testing ...
changeset pre exit
changeset pre enter beta # Feature complete
# ... testing and stabilization ...
changeset pre exit
changeset pre enter rc # Release candidate
# ... final testing ...
changeset pre exit # Graduate to stableCustomize prerelease version formats:
{
"snapshot": {
"prereleaseTemplate": "{tag}.{datetime}.{commit}"
}
}interface Config {
privatePackages: {
version: boolean;
tag: boolean; // Whether to tag private packages in prereleases
};
}Support for parallel prerelease tracks:
# Feature branch prereleases
changeset pre enter feat-new-ui
# Hotfix prereleases
changeset pre enter hotfix-security
# Each track maintains independent stateIntegration with CI/CD for automatic prerelease management:
# Automatic prerelease entry based on branch
if [[ $BRANCH == "develop" ]]; then
changeset pre enter beta
elif [[ $BRANCH == "release/*" ]]; then
changeset pre enter rc
fiWhen exiting prerelease mode, versions graduate appropriately:
// Prerelease versions graduate to their base version
// 1.2.0-beta.3 -> 1.2.0
// 2.0.0-alpha.1 -> 2.0.0
// Additional changes since entering prerelease may bump further
// If entering at 1.0.0 with minor changes -> 1.1.0-beta.0
// On exit with patch changes -> 1.1.1 (not 1.1.0)Changesets consumed during prerelease are tracked:
{
"mode": "pre",
"tag": "beta",
"changesets": [
"brave-lions-sing",
"wild-dogs-jump",
"calm-birds-fly"
]
}These changesets determine final version calculation on graduation.
// Manual state cleanup if needed
fs.unlinkSync('.changeset/pre.json');
// Reset to normal versioning mode
// Warning: This loses prerelease tracking state# GitHub Actions example
name: Prerelease
on:
push:
branches: [develop]
jobs:
prerelease:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: changeset pre enter beta
- run: changeset version
- run: changeset publish --tag beta# Automatic prerelease management based on branch patterns
case $GITHUB_REF in
refs/heads/develop)
changeset pre enter beta
;;
refs/heads/release/*)
changeset pre enter rc
;;
refs/heads/main)
changeset pre exit # Graduate to stable
;;
esac