Release Checklist (npm + Homebrew)
For a guarded, phased flow, run
./scripts/release.sh <phase>(gates | artifacts | publish | smoke | tag | github-release | all); it stops on the first error so you can resume after fixing issues.
- Version & metadata
- [ ] Update
package.jsonversion (e.g.,1.0.0). - [ ] Update any mirrored version strings (CLI banner/help, docs metadata) to match.
- [ ] Confirm package metadata (name, description, repository, keywords, license,
files/.npmignore). - [ ] If dependencies changed, run
pnpm installsopnpm-lock.yamlis current. - [ ] Source
~/.profileso codesign/notary env vars are available before building the notifier.
- Artifacts
- [ ] Run
./scripts/release.sh artifacts(buildsdist/, packs npm, and generates checksums). - [ ] Verify
binmapping inpackage.jsonpoints todist/bin/oracle-cli.js.
- [ ] Keep the generated
.release-artifacts/oracle-<version>.tgz{,.sha1,.sha256}for the GitHub release. .release-artifacts/is gitignored; do not commit these files.- Set
ARTIFACT_DIRto override the artifact directory; use the same directory forgithub-release. - [ ] Rebuild macOS notifier helper with signing + notarization:
cd vendor/oracle-notifier && ./build-notifier.sh(requiresCODESIGN_IDandAPP_STORE_CONNECT_*).- Signing inputs (same as Trimmy):
CODESIGN_ID="Developer ID Application: Peter Steinberger (Y5PE65HELJ)"plus notary env varsAPP_STORE_CONNECT_API_KEY_P8,APP_STORE_CONNECT_KEY_ID, andAPP_STORE_CONNECT_ISSUER_ID. - Sparkle ed25519 private key lives at
/Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle; exportSPARKLE_PRIVATE_KEY_FILEto that path whenever the build script needs to sign an appcast/enclosure. - Verify tickets:
xcrun stapler validate vendor/oracle-notifier/OracleNotifier.appandspctl -a -t exec -vv vendor/oracle-notifier/OracleNotifier.app.
- Changelog & docs
- [ ] Update
CHANGELOG.md(or release notes) with highlights. - [ ] Keep changelog entries product-facing only; avoid adding release-status/meta lines (e.g., “Published to npm …”)—that belongs in the GitHub release body.
- [ ] Verify changelog structure: versions strictly descending, no duplicates or skipped numbers, single heading per version.
- [ ] Ensure README reflects current CLI options (globs,
--status, heartbeat behavior). - [ ] Release notes must exactly match the version’s changelog section (full Added/Changed/Fixed/Tests bullets, no omissions). After creating the GitHub release, compare the body to
CHANGELOG.mdand fix any mismatch.
- Validation
- [ ]
pnpm run check(zero warnings allowed; fail on any lint/type warnings). - [ ]
pnpm vitest - [ ]
pnpm run lint - [ ] Optional live smoke (with real
OPENAI_API_KEY):ORACLE_LIVE_TEST=1 pnpm vitest run tests/live/openai-live.test.ts - [ ] MCP sanity check: with
config/mcporter.jsonpointed at the local stdio server (oracle-local), runmcporter list oracle-local --schema --config config/mcporter.jsonafter building (pnpm build) to ensure tools/resources are discoverable.
- Publish (npm)
- [ ] Ensure git status is clean; commit and push any pending changes.
- [ ] Avoid repeated browser auth: create a granular access token with write + Bypass 2FA at npmjs.com/settings/~/tokens, then export it (e.g.,
export NPM_TOKEN=...in~/.profile) and set//registry.npmjs.org/:_authToken=${NPM_TOKEN}in~/.npmrc. - [ ] Use the
NPM_TOKENfrom~/.profile(our “NPM out token”). Ifnpm publishopens browser auth, the token wasn’t loaded—rerun withsource ~/.profile. - [ ] Confirm auth:
npm whoami. - [ ] Decide tag before publish:
- If npm
latestis ahead (e.g.,npm view @steipete/oracle versionshows a higher major), publish with--tag legacy. - If this should become latest, publish with
--tag latest(or publish thennpm dist-tag add @steipete/[email protected] latest). - [ ]
npm publish --access public --tag <legacy|latest>(2FA OTP required even with token). - [ ] If promoting later:
npm dist-tag add @steipete/[email protected] latest --otp <code>(OTP required). - [ ]
npm view @steipete/oracle version(and optionallynpm view @steipete/oracle time) to confirm the registry shows the new version. - [ ] Verify positional prompt still works:
npx -y @steipete/oracle "Test prompt" --dry-run.
- Homebrew (tap)
- [ ] The
Update Homebrew Tapworkflow preflights the tarball and both checksum assets after the GitHub release is published: it verifies their hashes and the public tarball URL before dispatchingsteipete/homebrew-tap. - [ ] Missing assets or failed verification stop the job before dispatch. Run
./scripts/release.sh github-release, then re-run.github/workflows/update-homebrew-tap.ymlviaworkflow_dispatchwith the release tag (tag=vX.Y.Z). For an older release, do not rebuild: download the published npm tarball (npm view @steipete/[email protected] dist.tarball), verify it againstdist.integrity, place it inARTIFACT_DIRasoracle-X.Y.Z.tgzwith.sha1/.sha256files, and run the phase withVERSION=X.Y.Z. - [ ] Confirm the tap workflow updated
Formula/oracle.rbto the GitHub release asset and committed the SHA256. - [ ] Verify install:
brew uninstall oracle || truebrew tap steipete/tap || truebrew install steipete/tap/oracleoracle --versionbrew uninstall oracle
- Post-publish
- [ ] Run
./scripts/release.sh tagsovX.Y.Zexists on origin (always tag each release). - [ ] Run
./scripts/release.sh github-release: create a draft with titleX.Y.Zand the full version's changelog section (without its heading), upload the tarball and both checksums, verify the downloads, publish, and re-verify the public tarball URL. Publishing triggers the Homebrew tap workflow, which also waits for that URL to become available. - Existing releases keep their notes; identical assets are skipped, and conflicting assets fail without overwriting.
- [ ] Confirm the GitHub release body exactly matches the
CHANGELOG.mdsection forX.Y.Z(full bullet list). If not, update withgh release edit vX.Y.Z --notes-file <file>. - [ ] Confirm npm shows the new version:
npm view @steipete/oracle versionandnpx -y @steipete/[email protected] --version. - [ ] Promote desired dist-tag (e.g.,
npm dist-tag add @steipete/[email protected] latest). - [ ] From a clean temp directory (no package.json/node_modules), run
npx @steipete/[email protected] "Smoke from empty dir" --dry-runto confirm the package installs/executes via npx. - [ ] After verification, remove the generated tarball/checksum assets (
trash .release-artifacts, or the overriddenARTIFACT_DIR). - [ ] Announce / share release notes.