Release Process
August 29, 2026 ยท View on GitHub
Base releases are explicit release ceremonies, not automatic side effects of ordinary pull requests.
Use this checklist when preparing and publishing a new Base release such as
0.3.1 or 0.4.0.
Ownership
The release spans two repositories:
basefoundry/baseowns Base source, release notes,VERSION, Git tags, and GitHub Releases.basefoundry/homebrew-baseowns the Homebrew formula that installs published Base releases, plus the Homebrew bottle artifacts for supported macOS hosts.
The Homebrew tap update happens after the Base tag and GitHub Release exist.
The formula points at a versioned tag archive and records that archive's
sha256, so the archive must be available before the formula can be updated and
validated. Supported macOS installs should use Homebrew bottles; source builds
remain a fallback for unsupported hosts or explicit source-build validation.
Base's current supported macOS floor is macOS 14 Sonoma. Keep Homebrew bottle
workflows, formula validation, and Base's macOS CI floor aligned with that
support contract until the Compatibility section in the top-level README is
changed intentionally.
Version Policy
Base keeps two related version identities during development:
VERSIONrecords the latest published Base release. Ordinary feature, fix, documentation, and maintenance PRs leave it unchanged.DEVELOPMENT_VERSIONrecords the numeric next development line. An untagged Git checkout reports it asDEVELOPMENT_VERSION-dev+g<short-sha>and appends.dirtywhen the checkout has local changes.
A clean exact vX.Y.Z checkout and a packaged install report VERSION without
a development suffix. A dirty checkout, including one based on a release tag,
reports the development identity with its revision and .dirty. This keeps a
published release such as 1.8.0 distinct from mutable main work targeting
1.9.0, including its prospective license state.
Stable consumer installs must use Homebrew or an explicit release tag. Source
checkout and main installs are contributor or dogfood paths and must name the
branch or ref intentionally. Do not make a mutable default branch the implicit
stable consumer input.
At release preparation time, update VERSION to the clean release number and
run the release checks against that exact number. Do not put a development
suffix or Git revision in a published tag. After the release, update
DEVELOPMENT_VERSION to the next development line on main.
Keep upcoming changes under the Unreleased section in CHANGELOG.md until a
release-prep PR moves them into a dated release section.
Release Assistant
Base-managed repositories can declare a release: section in
base_manifest.yaml with the version file, changelog, tag prefix, GitHub
repository, GitHub Release title, and optional Homebrew handoff metadata.
For an existing repository, basectl repo configure --release --repo <owner/name> adds the generic contract and a missing release guide without
overwriting an existing declaration or guide. Use basectl repo check --release
to verify adoption.
The inspection commands are read-only:
basectl release check --version X.Y.Z
basectl release check --version X.Y.Z --format json
basectl release plan --version X.Y.Z
basectl release notes --version X.Y.Z
Use check before publishing to validate the version file, changelog section,
Git worktree cleanliness, GitHub CLI authentication, and local and remote tag
availability. It also requires every origin fetch and push URL to identify
release.github.repository, resolves the live remote default branch through
git ls-remote --symref, and requires the checked-out branch and full local
HEAD SHA to match that current remote commit exactly. A stale local
origin/<branch> tracking ref is not accepted as release evidence. Use plan
to print the GitHub release target and downstream handoff requirements. Use
notes to print the changelog body intended for the GitHub Release.
The JSON check uses the stable shared v1 envelope documented in
Inspection JSON; readiness blockers stay in data.findings
with error: null.
Publishing is guarded:
basectl release publish --version X.Y.Z --dry-run
basectl release publish --version X.Y.Z
basectl release publish --version X.Y.Z --yes
publish reuses the release checks, refuses existing tags or GitHub Releases,
and rechecks the repository, branch, and full commit SHA immediately before its
first mutation. It creates an annotated tag, verifies the local peeled SHA,
pushes the tag, verifies the remote peeled SHA, and creates the GitHub Release
with --verify-tag in the configured repository. The successful command then
verifies GitHub's annotated tag object resolves to the same commit SHA. It does
not update the Homebrew tap; it prints the tap handoff checklist when
release.homebrew is declared.
Base Release Checklist
Complete these steps in basefoundry/base:
-
Choose the release version and create or use a GitHub issue for the release artifact work.
-
Create a release-prep branch and worktree from
origin/main. -
Update release metadata:
VERSION- README version badge
- README
Current Statussection current-release prose .ai-context/STATUS.mdCurrent ReleasesectionCHANGELOG.md, moving relevantUnreleasedentries into the new release section- maintained product and context docs: reconcile
Last reviewed,Base era reviewed, andCurrent releaseclaims withVERSIONandCHANGELOG.md
-
Validate the release-prep PR:
git diff --check bin/base-test -
Merge the release-prep PR into
main. -
Sync local
mainand confirmHEADexactly matches the current liveorigin/main. Do not publish from a feature branch, detached checkout, ahead/behind/diverged branch, stale remote-tracking ref, or a checkout whoseorigindoes not matchrelease.github.repository. -
Dry-run the guarded publish command:
basectl release publish --version X.Y.Z --dry-run -
Publish the GitHub-side release artifacts:
basectl release publish --version X.Y.ZUse
--yesonly when running from a trusted non-interactive release shell. -
Confirm the release tag and GitHub Release are visible on GitHub.
Homebrew Tap And Bottle Checklist
Complete these steps in basefoundry/homebrew-base after the Base tag exists:
-
Create a Homebrew tap update issue or PR for the new Base version.
-
Create a tap release branch. Do not run the bottle workflow from
main; it pushes the generated bottle stanza back to the branch that triggered it. -
Update
Formula/base.rb:urlto the new Base tag archivesha256to the checksum of that archiveversionto the new Base version
-
Compute the archive checksum from the published tag:
curl -fsSL https://github.com/basefoundry/base/archive/refs/tags/vX.Y.Z.tar.gz | shasum -a 256 -
Validate the formula source-build path from the tap repository when the host can run Homebrew source builds:
brew install --build-from-source Formula/base.rb brew test basefoundry/base/base brew audit --new --formula basefoundry/base/base -
Confirm the tap-owned
base-bash-libsformula remains Homebrew/core-ready. The formula should keep its stable release archive, SPDX license metadata,bashdependency, test block, andbase-bash-libspackage name so a futurebasefoundryHomebrew/core formula can depend on it directly:brew test basefoundry/base/base-bash-libs brew audit --new --formula basefoundry/base/base-bash-libs -
Run the
Build Base BottlesGitHub Actions workflow from the tap release branch. The workflow builds bottles on supported macOS runners, uploads bottle tarballs to the tap GitHub Release namedbase-vX.Y.Z, merges the generated bottle JSON intoFormula/base.rb, and pushes the bottle stanza back to the branch. -
Confirm the tap PR includes a
bottle doblock for supported macOS targets before merging. The bottleroot_urlshould point at the tap release created by the workflow. -
Open or update the tap PR, wait for checks, and merge it.
-
Smoke-test the consumer bottle and upgrade paths:
brew update
brew trust basefoundry/base
brew install --force-bottle basefoundry/base/base
brew test basefoundry/base/base
brew upgrade --no-ask basefoundry/base/base
Use brew reinstall --force-bottle basefoundry/base/base when Base is
already installed on the validation host.
11. Before 1.0.0, complete the
Homebrew Upgrade Rehearsal against a
release candidate or equivalent test formula. Record the exact commands,
host facts, pre-upgrade state, post-upgrade checks, and any follow-up issues.
Do not close the rehearsal issue until
brew upgrade --no-ask basefoundry/base/base and the post-upgrade Base
project checks pass on a qualified host.
Common Failures And Recovery
If Homebrew tap or bottle validation fails, check the Homebrew Upgrade Rehearsal for historical run records before retrying. Known recovery patterns include:
- Outdated Command Line Tools: stop the release host validation, update Xcode
Command Line Tools until
brew doctorno longer blocks package installation, then rerun the Homebrew checklist from the failed step. - Stale versioned Cellar paths after upgrade: clear the shell command cache with
hash -r, rerun/usr/local/bin/basectl update-profileor/opt/homebrew/bin/basectl update-profilewith inheritedBASE_*variables unset, then start a fresh login shell before recheckingbasectl version. - Homebrew source-build sandbox path failures: do not treat user-directory
cleanup as the release fix. Prefer bottle publishing for supported macOS
hosts, rerun the
Build Base Bottlesworkflow, and retry consumer validation withbrew install --force-bottle basefoundry/base/base.
Cleanup
After the Base release PR and Homebrew tap PR are merged, clean up their worktrees and branches. Keep the release issue or linked issue comments updated with the Base release URL and Homebrew tap PR URL so the release record has both halves of the ceremony.