Skip to content

Release Process

This project uses Changesets for automated version management and publishing.

For full details, see RELEASE.md in the project root.

Quick Reference

Adding a Changeset

pnpm changeset

This prompts you to select packages, choose a bump type (patch/minor/major), and write a description.

What Gets Published

On each release, the following are published automatically:

npm (46 packages): All @ifc-lite/* packages + create-ifc-lite

crates.io (7 crates): ifc-lite-core, ifc-lite-clash, ifc-lite-geometry, ifc-lite-processing, ifc-lite-export, ifc-lite-ffi, ifc-lite-wasm

GitHub Release: Version tag + server binaries for 6 platforms

How Publishing Authenticates

npm publishes use OIDC trusted publishing from GitHub Actions: the workflow exchanges an id-token for short-lived npm credentials and attaches provenance to every tarball, so no long-lived npm token is stored. One consequence: a brand-new package cannot bootstrap itself through OIDC, so new packages need a manual first publish by a maintainer before the automated flow can take over.

crates.io publishes run through scripts/release-crates.mjs (pnpm release:crates), which publishes the crates in dependency order and skips versions that already exist.

Release Scripts

The root package.json wires the flow together:

Command What it does
pnpm changeset Create a changeset for your PR
pnpm version changeset version + scripts/sync-versions.js
pnpm release Build, verify ESM entry points, then publish npm (changeset publish) and crates (scripts/release-crates.mjs)

Version Synchronization

Packages version independently. Changesets still propagates internal dependency bumps, and scripts/sync-versions.js keeps the root package version, Cargo.toml workspace version, and internal Rust workspace dependency versions aligned with the highest released workspace package version.

Expressing a Rust-only major

A changeset states a bump level for npm packages. A change can be additive in TypeScript and breaking in Rust — a new field on a pub struct callers construct literally, an extra parameter on a pub fn — and the crate would then publish under the TypeScript bump level.

rust-major-offset.json at the repo root is how that is said out loud:

{
  "$comment": "schema and tooling guidance",
  "majorOffset": 1,
  "reason": "cumulative history of earlier Rust-only breaks",
  "latestBreak": "the new break that spends this major",
  "refs": ["#3210"]
}

sync-versions.js adds majorOffset to the major of the npm-derived version when it writes the Rust manifests. npm 6.1.0 with majorOffset: 1 publishes the crates at 7.1.0; the npm packages, the root package.json and the v* tag stay on 6.1.0. At majorOffset: 0 the two versions are the same string; for the current value, read rust-major-offset.json, and the crates run that many majors ahead of the npm packages.

  • Minor and patch keep tracking npm, so raising the offset is a once per Rust-only major edit, not a per-release chore.
  • For a new Rust-only major, increment majorOffset by exactly one, append the outgoing latestBreak verbatim to reason, replace latestBreak with a non-empty description of the newly measured break, and append the new issue/PR references to refs without removing or reordering its existing entries. On the first transition from the legacy schema there is no outgoing latestBreak, so reason remains unchanged. The release revert oracle enforces this exact rotation so neither history nor the newest account can disappear.
  • A non-zero offset without a non-empty reason, non-empty latestBreak, and at least one refs entry is a hard failure: a permanent major-version claim about a published crate has to say both what history led here and which break caused the latest increment.
  • pnpm check:rust-major-offset (run on every PR) fails when the committed manifests do not match what the offset implies. Whether the offset is large enough is a different question, answered by scripts/check-rust-semver.mjs against the crate live on crates.io.

Workflow

  1. Create a PR with your changes and a changeset file
  2. Merge to main - the Changesets bot creates a "Version Packages" PR
  3. Review and merge the "Version Packages" PR to trigger publishing

See RELEASE.md for emergency manual release instructions, troubleshooting, and FAQ.