Release & Publishing
Silvery uses two GitHub Actions workflows for releases:
verify.yml— runs on every push tomainand every PR. Pre-publish gate.release.yml— runs on tag push (v*). Publishes to npm + GitHub Release.
Both run the verify-publishable revision pinned in package.json and bun.lock.
Pre-publish gate (verify-publishable)
Pre-publish bugs are expensive — once a broken silvery@0.19.X reaches the npm registry it is forever-pinned in users' lockfiles. The gate catches three classes of bug before the tag push:
- Wrong
publishConfig.exports— theexportsfield reachable from a published tarball does not actually map to a file indist/. Silvery 0.19.0 shipped this way; consumers gotCannot find module ./src/index.ts. - Empty tarball / missing dist —
tsdowncrashed silently or ran from the wrong cwd; the package ships without its build output. - EPRIVATE on accidentally-listed public package — a package that is supposed to publish (e.g.
@silvery/color) still hasprivate: trueinpackage.json.npm publishwould refuse, halting the release midway.
The gate builds all workspaces, packs their exact tarballs, checks packed manifest targets, Publint and ATTW, then publishes them to an isolated local registry. It installs each of the ten public packages into a fresh Node 24 consumer and probes their imports and bins. The verifyPublishable.public list in package.json asserts the release set.
The legacy verify workflow ran npm install <packed-tarball.tgz> directly, which always failed during release windows because the tarball's transitive deps reference @silvery/<dep>@<thisversion> that wasn't on the public registry yet (chicken-and-egg). Verdaccio breaks the loop by hosting every cross-dep itself.
Run locally
bun run verify-publishableThis runs the pinned local binary. It builds first, then runs the local registry and fresh-consumer checks.
Useful flags:
--no-build— use artifacts already built from this checkout.--keep— retain the verifier's scratch directory for inspection.--output-dir <empty-dir>— retain verified tarballs and their SHA-512 digests for a publisher.
The gate normally takes 1-2 minutes (build dominates; the verdaccio cycle is ~30s).
What gets probed
The package manifest asserts these public names:
@silvery/ansi@silvery/color@silvery/command@silvery/commander@silvery/config@silvery/scope@silvery/selection@silvery/signals@silvery/syntaxsilvery(root barrel)
Private workspaces are published only to the isolated registry so internal dependencies resolve. They are not consumer-probed. To add a public package, update verifyPublishable.public and the release workflow in the same change.
Adding a public package
- Create the package under
packages/<name>/withtsdownbuild +publishConfig.exports. - Add its exact npm name to
verifyPublishable.publicin the rootpackage.json. - Add a publish step to
release.ymlin the right dependency-order layer. - Run
bun run verify-publishablelocally to confirm the gate is happy.
Release flow
Once verify-publishable is green on main:
- Bump
versionin every workspacepackage.json(keep them in lockstep —release.ymlpublishes in dependency order). - Commit + tag:
git tag v<version> && git push --tags. release.ymlruns: build → verify-publishable gate → publish in dep order → smoke test → GitHub Release.
If the gate fails on a release tag, no packages reach npm — fix the issue, retag.