fix(release): preserve Homebrew formula version (#2488)
This commit is contained in:
@@ -362,6 +362,8 @@ describe("release desktop artifacts", () => {
|
||||
|
||||
it("keeps the generated tap formula on the installed runtime smoke contract", () => {
|
||||
const formula = readRepoFile("scripts/release/kandev.rb");
|
||||
const updater = readRepoFile("scripts/release/update-homebrew-tap.sh");
|
||||
const versionDeclaration = 'version "__VERSION__"';
|
||||
|
||||
expect(formula).toContain(
|
||||
'assert_equal "v#{version}", shell_output("#{bin}/kandev --version").strip',
|
||||
@@ -370,7 +372,11 @@ describe("release desktop artifacts", () => {
|
||||
expect(formula).toContain("/health");
|
||||
expect(formula).toContain('"status":"ok"');
|
||||
expect(formula).toContain("<title>Kandev</title>");
|
||||
expect(formula).not.toContain('version "__VERSION__"');
|
||||
expect(formula).toContain(versionDeclaration);
|
||||
expect(formula.indexOf(versionDeclaration)).toBeLessThan(
|
||||
formula.indexOf('license "AGPL-3.0-only"'),
|
||||
);
|
||||
expect(updater).toContain('-e "s|__VERSION__|$VERSION|g"');
|
||||
});
|
||||
|
||||
it("bumps desktop package and Tauri versions during release preparation", () => {
|
||||
|
||||
@@ -18,12 +18,12 @@ Kandev uses one semantic version across the Git tag, native runtime bundles, des
|
||||
|
||||
The workflow has four mutually exclusive operating modes:
|
||||
|
||||
| Mode | Inputs | Result |
|
||||
|---|---|---|
|
||||
| Normal release | `bump=patch`, `minor`, or `major` | Creates and merges a release PR, tags its merge, builds, and publishes |
|
||||
| Dry run | `dry_run=true` | Computes the next version and exercises CLI package/lock plus changelog generation in the runner; no PR, tag, artifact build, or publication |
|
||||
| Desktop validation | `desktop_validation_only=true` | Builds web, five runtime bundles, and five desktop targets from the selected commit; no PR, tag, GitHub release, GHCR, npm, or Homebrew publication |
|
||||
| Backfill | `backfill_tag=vX.Y.Z` | Rebuilds and repairs channels for the latest existing release tag without creating a version or tag |
|
||||
| Mode | Inputs | Result |
|
||||
| ------------------ | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Normal release | `bump=patch`, `minor`, or `major` | Creates and merges a release PR, tags its merge, builds, and publishes |
|
||||
| Dry run | `dry_run=true` | Computes the next version and exercises CLI package/lock plus changelog generation in the runner; no PR, tag, artifact build, or publication |
|
||||
| Desktop validation | `desktop_validation_only=true` | Builds web, five runtime bundles, and five desktop targets from the selected commit; no PR, tag, GitHub release, GHCR, npm, or Homebrew publication |
|
||||
| Backfill | `backfill_tag=vX.Y.Z` | Rebuilds and repairs channels for the latest existing release tag without creating a version or tag |
|
||||
|
||||
`dry_run` and desktop validation are not release candidates. Backfill cannot be combined with either and accepts only the latest exact SemVer tag after version manifests are checked for agreement.
|
||||
|
||||
@@ -65,7 +65,7 @@ Normal mode performs these stages:
|
||||
5. **Build containers.** Publish amd64/arm64 base manifests, enforce the universal-image size gate, then publish multi-architecture universal images.
|
||||
6. **Publish GitHub Release.** Attach runtime archives, checksums, desktop artifacts, notes, and the updater feed when eligible.
|
||||
7. **Publish npm.** Use OIDC trusted publishing for five `@kdlbs/runtime-*` packages first, then the `kandev` launcher. Existing versions are skipped; the main package is not published after a runtime-package failure.
|
||||
8. **Update Homebrew.** Push the formula update to `kdlbs/homebrew-kandev` using release checksums and the deploy key.
|
||||
8. **Update Homebrew.** Push the formula update to `kdlbs/homebrew-kandev` using release checksums and the deploy key. The generated formula records `X.Y.Z` explicitly; platform archive suffixes such as `x64` are not version identifiers.
|
||||
|
||||
GHCR images are built before the GitHub Release. npm and Homebrew start only after the GitHub Release and may run in parallel. A late failure can therefore leave some channels complete and others missing.
|
||||
|
||||
@@ -105,7 +105,7 @@ After publication, verify:
|
||||
- the Git tag points at the generated release merge;
|
||||
- GitHub notes, five runtime archives, checksums, expected desktop installers, and conditional `latest.json`;
|
||||
- all five runtime npm packages plus `kandev`, including a clean `npx kandev@latest`;
|
||||
- Homebrew install/upgrade and `kandev --version`;
|
||||
- Homebrew install/upgrade, a `Cellar/kandev/X.Y.Z` install path, and `kandev --version`;
|
||||
- GHCR base and universal images on amd64 and arm64, including their immutable version tags;
|
||||
- desktop launch on affected platforms and signed/notarized status where configured;
|
||||
- backend health, a minimal task, agentctl startup, and Updates-screen behavior;
|
||||
|
||||
@@ -17,12 +17,12 @@ Kandev is currently installable via `brew install kdlbs/kandev/kandev` from the
|
||||
## What
|
||||
|
||||
- Add a package-manager build contract that produces the native runtime bundle from an already-installed source checkout. It builds the Vite SPA, syncs it into the Go embed input, compiles the host `kandev` and `agentctl` binaries, and cross-compiles the four Linux/macOS remote `agentctl` helpers.
|
||||
- Keep package-manager dependency installation outside that contract. Homebrew declares Go, Node 24, and pnpm as build dependencies and Git as a runtime facility.
|
||||
- Keep package-manager dependency installation outside that contract. Homebrew declares Go, Node 24, and pnpm 10 as build dependencies. Git is part of Homebrew's standard environment and is not declared as a formula dependency.
|
||||
- Compile only the host `kandev` binary with cgo and the `fts5` tag. `mattn/go-sqlite3` supplies the SQLite amalgamation, so the formula does not declare an external SQLite dependency unless build or linkage evidence requires it.
|
||||
- Merge and publish the source-build contract in a Stable Kandev release before authoring the Core formula. Core must consume the immutable GitHub tag archive for that release, never a branch or unreleased commit.
|
||||
- Install the bundle under `libexec/bin` and expose one `bin/kandev` wrapper produced by `write_env_script`. The wrapper sets `KANDEV_BUNDLE_DIR=<libexec>` and `KANDEV_VERSION=<version>`.
|
||||
- Use stable numeric tags for `livecheck`; prerelease and Nightly npm versions are not Homebrew channels.
|
||||
- Keep `kdlbs/homebrew-kandev` as the upstream binary fast path alongside Homebrew Core's source-built bottles. The shared release-bundle validator must run before those binary archives are published, and the generated tap formula must smoke-test its version, readiness endpoint, and embedded SPA.
|
||||
- Keep `kdlbs/homebrew-kandev` as the upstream binary fast path alongside Homebrew Core's source-built bottles. The generated tap formula must set the Stable SemVer explicitly because platform archive names end in architecture tokens such as `x64`, and it must smoke-test its version, readiness endpoint, and embedded SPA. The shared release-bundle validator runs before those binary archives are published.
|
||||
- Preserve all four remote `agentctl` helpers in custom-tap installations. The tap must use an exact-path Homebrew mismatched-binary audit allowlist rather than pruning helpers, so Docker and SSH targets can differ from the Homebrew host. Decision: [ADR-2026-08-05-homebrew-remote-helper-audit](../../decisions/2026-08-05-homebrew-remote-helper-audit.md).
|
||||
|
||||
The runtime bundle contains exactly:
|
||||
@@ -44,6 +44,7 @@ The Darwin arm64 helper must carry a Mach-O code signature so Apple Silicon can
|
||||
- **GIVEN** a new kandev release `vX.Y.Z` is tagged, **WHEN** Homebrew's auto-bump worker runs, **THEN** `livecheck` resolves the new tag from GitHub Releases and a bump PR is opened against the formula.
|
||||
- **GIVEN** a maintainer reviews the PR, **WHEN** they run `brew install --build-from-source kandev` locally, **THEN** the build completes without network or sandbox failures and `brew test kandev` passes.
|
||||
- **GIVEN** a Stable release updates `kdlbs/homebrew-kandev`, **WHEN** its platform archive is built and the tap formula is tested, **THEN** the archive contains the complete executable runtime and the installed launcher serves both `/health` and the embedded Kandev page.
|
||||
- **GIVEN** a Stable release updates `kdlbs/homebrew-kandev`, **WHEN** Homebrew evaluates a platform archive URL ending in `x64` or `arm64`, **THEN** the generated formula's explicit version keeps the Cellar path and `version` value at `X.Y.Z` rather than the architecture suffix.
|
||||
- **GIVEN** a tap archive contains remote helpers for CPU architectures other than the Homebrew host, **WHEN** Homebrew audits the installed formula on macOS or Linux, **THEN** only the four declared remote-helper paths are exempted and the complete runtime remains installed.
|
||||
|
||||
## Out of scope
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
class Kandev < Formula
|
||||
desc "Manage tasks, orchestrate agents, review changes, and ship value"
|
||||
homepage "https://github.com/kdlbs/kandev"
|
||||
# Conditional asset names end in x64/arm64; without this, Homebrew uses version 64.
|
||||
version "__VERSION__"
|
||||
license "AGPL-3.0-only"
|
||||
|
||||
on_macos do
|
||||
|
||||
@@ -118,6 +118,7 @@ mkdir -p "$(dirname "$FORMULA_PATH")"
|
||||
GITHUB_BASE="https://github.com/kdlbs/kandev/releases/download/${TAG}"
|
||||
|
||||
sed \
|
||||
-e "s|__VERSION__|$VERSION|g" \
|
||||
-e "s|__GITHUB_BASE__|$GITHUB_BASE|g" \
|
||||
-e "s|__SHA_MACOS_ARM64__|$SHA_MACOS_ARM64|g" \
|
||||
-e "s|__SHA_MACOS_X64__|$SHA_MACOS_X64|g" \
|
||||
|
||||
Reference in New Issue
Block a user