This document walks maintainers through the build/sign/upload flow for each ipcprims release.
- GPG and minisign installed
- Signing keys configured (shared 3leaps release signing keys)
- Environment variables set (see step 2 below)
ghCLI authenticated with push access
- Update
VERSIONfile with new semver (e.g.,0.2.0) - Sync version to all manifests:
make version-sync- Syncs
Cargo.tomlworkspace,Cargo.lock, and allbindings/typescriptpackage.jsonfiles - Do not skip: version drift between
VERSIONandCargo.tomlis a hard failure inmake prepush
- Syncs
- Update
CHANGELOG.md(move Unreleased section to new version heading) - Create release notes:
docs/releases/vX.Y.Z.md
-
Run preflight checks:
make release-preflightThis is the single authoritative gate. It runs, in order:
- Working tree clean check
make prepush— fmt, clippy, tests, cargo-deny, version consistencymake version-check— full consistency:VERSION,Cargo.toml, all TypeScript packages- Release notes exist at
docs/releases/vX.Y.Z.md - Local/remote sync (no unpushed or unpulled commits)
Must pass before pushing or tagging.
-
Commit all changes with proper attribution:
git add -A git commit -m "chore: bump version to vX.Y.Z" # (see AGENTS.md for full attribution trailer format)
Note: The commit message must say
vX.Y.Z(the real version), notvX.Y.Z-dev. The-devsuffix is only meaningful in the post-release bump commit (step 4). -
Push to main:
git push origin main
Do not tag until CI on main is green. Tagging a broken commit creates an unusable release.
- Monitor CI run:
gh run list --branch main --limit 3 gh run watch <run-id>
- Confirm all jobs pass — no failures, no skipped required jobs
- Note the annotation
Restore cache failed: go.sum not foundon Go darwin job is a known non-fatal warning (the Go bindings dir is a CGo module without ago.sumat root)
Note: This section applies whenever
ipcprims-ffisource has changed since the last release. It is NOT optional for v0.1.2+. The workflow builds fresh prebuilt libs from the current source — the libs committed tobindings/go/ipcprims/lib/in the previous release are stale and must be rebuilt.Do not sign until this is complete. Signing against a tag that has stale FFI libs means Go consumers get the wrong binaries.
-
Verify current libs are stale (sanity check before running the workflow):
git log --oneline bindings/go/ipcprims/lib/ bindings/go/ipcprims/include/ | head -5 # Last commit should match the VERSION you are releasing, not a prior version
-
Run Go bindings workflow (builds fresh FFI libs on all platforms):
VERSION=$(cat VERSION) gh workflow run "Go Bindings (Prep)" -f version="${VERSION}"
Watch progress:
gh run list --workflow=go-bindings.yml --limit 3 gh run watch <run-id>
-
Review and merge the PR the workflow creates:
VERSION=$(cat VERSION) gh pr list --search "go-bindings/v${VERSION}" --state open
Confirm the PR actually updates libs across all platforms before merging:
bindings/go/ipcprims/lib/<platform>/libipcprims_ffi.a(all platforms)bindings/go/ipcprims/lib-shared/<platform>/(shared libs)bindings/go/ipcprims/include/ipcprims.h(regenerated header)
-
Wait for CI to pass on the merge commit — this is the commit you will tag.
gh run list --branch main --limit 3
-
Pull the merge commit locally:
git pull origin main
-
Verify Go bindings pass locally:
cd bindings/go/ipcprims && go test ./... && cd -
-
Verify TypeScript bindings pass locally:
cd bindings/typescript && npm test && npm run typecheck && cd -
Both tags must point to the same commit — the Go bindings PR merge commit.
-
Create annotated tags:
VERSION=$(cat VERSION) git tag -a "v${VERSION}" -m "v${VERSION}: <brief description of release>" git tag -a "bindings/go/ipcprims/v${VERSION}" -m "Go bindings v${VERSION}"
The Go submodule tag is required so
go get github.com/3leaps/ipcprims/bindings/go/ipcprims@v${VERSION}resolves correctly. Without it Go module resolution fails. -
Push both tags together (triggers release workflow):
git push origin "v${VERSION}" "bindings/go/ipcprims/v${VERSION}"
- Wait for GitHub Actions release workflow to complete on the tag
- Verify CI status is green:
gh run list --branch "v${VERSION}" - Check release draft has expected artifacts (binaries for all platforms)
Ordering is critical: TypeScript prebuilds and npm publish run after signing and upload are complete. They run from the tag ref, not from main.
Before running: verify all six npm packages exist. OIDC trusted publishing cannot create new packages — only update existing ones. If any are missing, do the manual first publish first. See
docs/guides/npm-publishing.mdfor the full guide.VERSION=$(cat VERSION) for pkg in "@3leaps/ipcprims" "@3leaps/ipcprims-darwin-arm64" "@3leaps/ipcprims-linux-x64-gnu" \ "@3leaps/ipcprims-linux-x64-musl" "@3leaps/ipcprims-linux-arm64-gnu" "@3leaps/ipcprims-win32-x64-msvc"; do result=$(curl -sf "https://registry.npmjs.org/${pkg}/${VERSION}" 2>/dev/null \ | python3 -c "import json,sys; print(json.load(sys.stdin).get('version','?'))" 2>/dev/null \ || echo "MISSING") echo "${pkg}: ${result}" done
-
TypeScript N-API prebuilds — run on the tag ref after upload:
VERSION=$(cat VERSION) gh workflow run "TypeScript N-API Prebuilds" --ref "v${VERSION}" gh run list --workflow=typescript-napi-prebuilds.yml --limit 3
Wait for completion. This builds
.nodebinaries and stages npm package directories. -
TypeScript npm publish — run on the tag ref after prebuilds complete:
VERSION=$(cat VERSION) gh workflow run "TypeScript npm Publish" --ref "v${VERSION}"
If any package is missing from npm, the workflow fails with
E404. In that case, follow the manual first publish steps indocs/guides/npm-publishing.md, then re-run the workflow.
Note: MFA is required for signing. Signing keys are protected by hardware token. The maintainer must be physically present to complete this step.
# Source the vars file:
source ~/devsecops/vars/3leaps-ipcprims-cicd.sh
# Or set individually:
export IPCPRIMS_RELEASE_TAG=v$(cat VERSION)
export IPCPRIMS_MINISIGN_KEY=/path/to/signing.key
export IPCPRIMS_MINISIGN_PUB=/path/to/signing.pub
export IPCPRIMS_PGP_KEY_ID="keyid!"
export IPCPRIMS_GPG_HOMEDIR=/path/to/gpg/homedir # optional-
Clean previous release artifacts
make release-clean
-
Download artifacts from GitHub release
make release-download
-
Generate checksum manifests
make release-checksums
Produces:
SHA256SUMS,SHA512SUMS -
Sign checksum manifests (minisign + PGP)
make release-sign
Produces:
.minisigand.ascsignatures for both checksum files -
Export public keys
make release-export-keys
Produces:
ipcprims-minisign.pub,ipcprims-release-signing-key.asc -
Verify everything before upload
make release-verify
Validates:
- Checksums match artifacts
- Signatures verify correctly
- Exported keys are public-only (no secret key material)
-
Copy release notes
make release-notes
Copies
docs/releases/vX.Y.Z.mdtodist/release/release-notes-vX.Y.Z.md -
Upload signed artifacts to GitHub
make release-upload
Note: Uses
--clobberto overwrite existing assets. Safe to rerun. -
Publish the release (promotes draft → public):
gh release edit v$(cat VERSION) --draft=falseThe release is a draft until this step. Do not announce until after this.
Or run the full signing + upload workflow in one command:
make release
# Then manually publish the draft:
gh release edit v$(cat VERSION) --draft=false- Verify release is public:
gh release view v$(cat VERSION) - Verify checksums match: download and verify locally
- Verify signatures with public keys
VERSION=$(cat VERSION)
# Download and verify
curl -LO "https://github.com/3leaps/ipcprims/releases/download/v${VERSION}/SHA256SUMS"
curl -LO "https://github.com/3leaps/ipcprims/releases/download/v${VERSION}/SHA256SUMS.minisig"
curl -LO "https://github.com/3leaps/ipcprims/releases/download/v${VERSION}/ipcprims-minisign.pub"
# Verify checksum
shasum -a 256 -c SHA256SUMS --ignore-missing
# Verify signature (minisign)
minisign -Vm SHA256SUMS -p ipcprims-minisign.pubAfter the release is uploaded and verified, bump VERSION for the next development cycle:
make version-patch # 0.2.0 -> 0.2.1
# or: make version-minor # 0.2.0 -> 0.3.0
# or: make version-major # 0.2.0 -> 1.0.0
make version-sync # sync new version to Cargo.toml and package.json files
git add VERSION Cargo.toml Cargo.lock bindings/typescript
git commit -m "chore: bump version to v$(cat VERSION)-dev"
git push origin mainImportant:
make version-syncmust be run immediately after the version bump. The-devsuffix in the commit message is a convention marking this as a development snapshot — it does not affect semver.make prepushwill catch any drift betweenVERSIONandCargo.tomlbefore the next release.
| Target | Description |
|---|---|
make release-preflight |
REQUIRED: Verify pre-tag requirements (tree, checks, version, notes, sync) |
make release-guard-tag-version |
Verify git tag matches VERSION file (runs automatically in make release) |
make release-check |
Version consistency + package check |
make release-clean |
Remove dist/release contents |
make release-download |
Download CI artifacts from GitHub |
make release-checksums |
Generate SHA256SUMS and SHA512SUMS |
make release-sign |
Sign checksums with minisign + PGP (requires MFA/hardware token) |
make release-export-keys |
Export public signing keys |
make release-verify |
Verify checksums, signatures, and keys |
make release-notes |
Copy release notes to dist |
make release-upload |
Upload signed artifacts to GitHub |
make release |
Full workflow (clean -> upload) |
Source the vars file or set the environment variable:
source ~/devsecops/vars/3leaps-ipcprims-cicd.shCreate the release notes file:
mkdir -p docs/releases
# Write release notes to docs/releases/vX.Y.Z.mdmake version-sync # sync VERSION -> Cargo.toml + package.json
make version-check # verify all are consistent- Fix the issue on main, push the fix
- Wait for CI to go green
- Only then proceed to tag
- Check GitHub Actions logs:
gh run list --branch "v${VERSION}" - Fix the issue on main
- Delete the tag and release draft:
git tag -d "v${VERSION}" git push origin --delete "v${VERSION}" gh release delete "v${VERSION}" --yes
- Start over from the tagging step
- Ensure you used the correct signing key
- Re-run
make release-sign - Re-run
make release-verifyto confirm
If rotating signing keys, update:
-
RELEASE_CHECKLIST.md- verification example public key -
README.md- verification snippet (when added)
- Patch (0.2.1): Bug fixes, security patches
- Minor (0.3.0): New features, backward-compatible
- Major (1.0.0): Breaking changes, API changes
See docs/decisions/ for versioning decisions.