Release guide¶
Fontdone publishes one Cargo crate, fontdone, one npm package, fontdone,
and a native C SDK on GitHub Releases. The internal fontdone-c-abi and
fontdone-wasm Cargo packages have publish = false. There is no PyPI package.
Latest release: 2.14.3-alpha.12.
Publication uses this repository's tag-triggered release.yml and GitHub OIDC.
Stable releases promise SemVer compatibility for the documented Rust and
JavaScript APIs. The FreeType-shaped C facade remains function-specific and
does not claim full FreeType replacement; consult the measured function and
platform evidence before depending on it. Deprecated FreeType aliases remain
part of the pinned compatibility contract.
1. Trusted publisher configuration¶
Configure these identities on the existing packages:
| Registry | Repository | Workflow filename | GitHub environment |
|---|---|---|---|
| crates.io | appunni-m/fontdone |
release.yml |
crates-io |
| npm | appunni-m/fontdone |
release.yml |
npm |
The publish jobs alone receive id-token: write. Crates.io authentication uses
rust-lang/crates-io-auth-action; npm uses Node 22.14.0 and npm 11.5.1 with
provenance. An environment configured with required reviewers will pause its
job until that review occurs. No repository secret containing a registry token
is needed. Keep publisher settings and workflow environment names identical.
This follows the isolated verification, artifacts, OIDC, and GitHub Release stages used by coverage-mcp's release workflow.
2. Release acceptance and support boundaries¶
Stable and prerelease tags use the same executed verification lanes. A stable tag freezes the documented Rust and JavaScript APIs under SemVer; it does not claim that the selected FreeType facade is a complete replacement. Incomplete source coverage and C-contract adoption remain visible as measured limitations.
Every executed test remains required: the fast gate and MSRV, all runnable exact parity comparisons, Rust/C/WASM/npm consumers, five native or emulated platform contracts, package checks, dependency audits, and benchmark checks. Coverage collection must succeed and retain its actual totals. No source files, inputs, expected results, or uncovered lines are removed from measurement to meet this policy. Undefined C inputs remain explicitly named pending cases.
make release-verify runs the release checks and reports measured contract
debt. make release-verify-complete additionally requires all twelve
C-contract categories and reviewed performance thresholds. Use the complete
gate before claiming full FreeType replacement or a passed performance budget.
It needs five fresh platform bundles. The current benchmark policy is still
collecting baselines and has no thresholds; CI records ten-sample reports
without claiming a regression budget passed.
The compatibility snapshot and adoption guide distinguish completed functionality, measured runtime parity, historical coverage, and unfinished C-contract requirements.
The alpha.8 local verification on 2026-09-15 passes 20,357/20,357 runnable cases in each of the Rust, C ABI, and WASM coverage lanes, with three named undefined-C cases pending. The combined source report measures 66,270/68,525 lines (96.7092%), 12,189/13,836 branches (88.0963%), 3,849/4,137 functions (93.0384%), and 91,297/94,949 regions (96.1537%). The WinFNT record conversion is exercised by the retained header inputs. Big-endian-only branches require the separate PowerPC runtime lane and are not measured by this macOS report. GitHub produces its own report for the final tag; this local result does not stand in for a successful publishing job.
3. Prepare and verify a version¶
- Increment the root Cargo version, both private workspace versions and their
exact root dependency requirements, and the npm version together. Run
make release-lock-updateto synchronize only workspace lockfile entries using the already downloaded dependency set. - Update the changelog, documentation source-version field, and package contracts.
Keep public installation blocks on the last published version. Regenerate derived
ABI metadata with
make generate-contracts. - Run
make test-parityandmake record-parity-snapshot. This binds the reported comparison counts to the measured sources. Then refresh the file ledger withmake repository-inventory. - Run
make ci-fastusing the pinned font-generation Python environment described in Development. Inspect packages withmake release-dry-run. Usemake release-verifyfor a local thorough run. - Commit, push to
main, and require successful CI for that exact commit. - Create an annotated, unused
v<version>tag on that commit and push it. Never move a published tag or overwrite an existing registry version.
For the published release, registry consumers use:
[dependencies]
fontdone = "=2.14.3-alpha.12"
A development path or pinned Git revision may be added, but a publishable consumer must retain the exact registry version.
4. What the tag runs¶
The tag starts the full CI matrix. Release preflight waits for successful CI on the exact tag commit; a fast branch run cannot satisfy that gate. It verifies the annotated remote tag object, synchronized versions, and downloads that run's checked Cargo/npm packages and platform evidence. It builds the native C SDK and produces a checksum manifest excluding the manifest itself.
The crates.io job compiles the packaged source before authentication and
compares the resulting archive with the downloaded CI artifact. Only then does
it mint an OIDC token and run make release-publish-oidc VERIFIED_CRATE=....
The helper rejects local invocation, the wrong repository/tag, missing OIDC
context, dirty sources, and archive differences. Cargo's duplicate verification
is skipped only after the identical archive has been compiled before token
minting. The published registry checksum must match the verified archive.
The npm job checks the bundle checksum and publishes the exact tested .tgz
with provenance under next. Existing versions are accepted only when the
registry integrity matches the candidate; network errors are not treated as
missing versions.
make npm-package-verify also stages a one-directory relative archive and runs
the same publish helper in offline dry-run mode. An existing artifact can be
checked with make release-npm-verify VERIFIED_NPM_ARCHIVE=<path>; real uploads
use make release-npm-publish-oidc in the exact GitHub tag job. Both paths resolve
the local filename before npm sees it, because
npm package specifiers
otherwise interpret release-bundle/archive.tgz as GitHub shorthand. Failed
uploads expose a bounded diagnostic in the public workflow annotations.
Only after both registries succeed does the final job attest the artifacts and
create the GitHub prerelease with compatibility notes, Cargo archive, npm
archive, native SDK, and SHA256SUMS. GitHub Release commands specify the
repository explicitly, including jobs without a source checkout.
5. Recovery and verification¶
Inspect the first failed job and its retained diagnostics. A skipped publish job has not tested OIDC authentication. A publisher identity rejection in a running publish job is a registry configuration issue; a failed parity, coverage-collection, or package job is a repository issue.
Rerun a transient failure on the same immutable tag. If source or workflow changes are needed, make a new version and tag. A partially published version must not be rebuilt into different bytes. Preserve earlier failed tags and run records as history.
After publication, check the exact crates.io version and checksum, npm version and provenance, and the GitHub prerelease assets. Confirm a fresh registry consumer can install and exercise the released APIs. A green preflight alone is not evidence that either registry accepted the release.
Refresh user documentation after publication¶
Wait for every registry job and the GitHub release to succeed, then run:
make docs-release-refresh
make docs-release-check docs-registry-examples
Review and commit the refreshed release record and installation blocks. The Documentation workflow checks freshness after a successful tag release and on its daily schedule. Keep source-candidate versions separate from published installation versions; do not send users to a version that is still building.