Skip to content

homebrew: preserve bottle compatibility for host build dependencies - #887

Closed
brandonpayton wants to merge 1 commit into
fix/homebrew-cache-isolationfrom
fix/homebrew-publisher-prefix
Closed

homebrew: preserve bottle compatibility for host build dependencies#887
brandonpayton wants to merge 1 commit into
fix/homebrew-cache-isolationfrom
fix/homebrew-publisher-prefix

Conversation

@brandonpayton

@brandonpayton brandonpayton commented Jul 11, 2026

Copy link
Copy Markdown
Member

Purpose

Allow trusted Kandelo bottle builds to consume ordinary Homebrew build-dependency bottles without weakening the temporary patch isolation used for Kandelo's Wasm bottle tags.

This is platform-owned publisher work in Automattic/kandelo; it changes no tap formula and must not be auto-merged.

Stack

This PR is intentionally stacked on #881, whose exact parent is bca9393a34abb786419fbbdcea032d3c46e7b7c5. The current head is 1e819fa6c02129698f9fd6fb0b528dca135bea86, and the PR base is fix/homebrew-cache-isolation so review shows only this prefix-preservation change.

Merge #881 first. After it lands, retarget this PR to main. The same-tap dependency-trust fix in #890 should then be rebased onto this head, followed by the tap-native under-lock composition work in #885.

Root Cause

scripts/homebrew-bottle-build.sh created a patched temporary Homebrew worktree and invoked that worktree's bin/brew directly. Homebrew derives HOMEBREW_PREFIX and the Cellar from the launcher path, so the temporary worktree also became a temporary Homebrew prefix.

That is harmless for formulas without Homebrew dependencies, but core bottles are built for /home/linuxbrew/.linuxbrew. In tap dry-run 29166233235, libcxx needed CMake; Homebrew found CMake's OpenSSL and ncurses closure but rejected those bottles as non-relocatable into the temporary prefix. brew install --build-bottle then refused source-built dependencies, so libc++ never reached its formula build.

Change

  • create the patched Homebrew checkout in the existing temporary worktree;
  • create a unique, short-lived launcher symlink under the selected Homebrew prefix's bin/ that targets the patched worktree's bin/brew;
  • rely on Homebrew's launcher behavior: the invocation location supplies the prefix/Cellar, while the symlink target supplies the repository and patched Ruby implementation;
  • assert at runtime that the selected prefix is unchanged and the repository is the detached overlay;
  • remove the generated launcher and worktree through the caller's EXIT trap, including after a post-launcher validation failure;
  • keep the original Homebrew checkout unmodified;
  • document the behavior in ci: isolate and verify Homebrew bottle publication #881's read-only build-and-test runner without changing its permissions, strict data handoff, upload, verification, or finalization boundaries;
  • document that local bottle builds must select a disposable Homebrew prefix because the target formula and missing build dependencies install there.

Validation

Current-head validation at 1e819fa6c02129698f9fd6fb0b528dca135bea86, run through scripts/dev-shell.sh on aarch64-apple-darwin:

  • bash scripts/test-homebrew-publish-workflow.sh: passed. This includes ci: isolate and verify Homebrew bottle publication #881's handoff, failure-publication, and structured workflow-trust checks plus the prefix-launcher regression.
  • bash scripts/test-homebrew-patched-launcher.sh: passed.
  • The same launcher fixture under macOS /bin/bash 3.2: passed.
  • bash -n on all touched shell scripts: passed.
  • git diff --check bca9393a34abb786419fbbdcea032d3c46e7b7c5..HEAD: passed.
  • The range-diff against original head 179754fb6227586287f3cef4526a3983cea79a64 shows the launcher implementation unchanged. Conflict resolution only translates its documentation into ci: isolate and verify Homebrew bottle publication #881's four-runner model and retains both regression-suite calls.
  • The final delta from ci: isolate and verify Homebrew bottle publication #881 is exactly five files; no reusable workflow, permission, handoff validator, uploader, verifier, or finalizer implementation changed.

Before the rebase, a direct probe against the installed Homebrew checkout reported the original /opt/homebrew prefix, /opt/homebrew/Cellar, unchanged OpenSSL/ncurses opt paths, and the detached patched repository. The implementation is patch-identical after the rebase, but that real-Homebrew probe was not repeated at the new commit.

A full libc++ bottle was not rebuilt locally. Hosted CI is rerunning for the rebased stack and remains required evidence before merge.

Contract Scope

This changes trusted Homebrew build tooling and its documentation. It does not change the kernel, host runtime, Node/browser behavior, Formula Ruby, package artifacts, VFS images, the ABI, or the ABI snapshot.

@brandonpayton
brandonpayton force-pushed the fix/homebrew-publisher-prefix branch from 179754f to 1e819fa Compare July 12, 2026 08:28
@brandonpayton
brandonpayton changed the base branch from main to fix/homebrew-cache-isolation July 12, 2026 08:28
@github-actions

Copy link
Copy Markdown
Contributor

Phase B-1 matrix build status — pr-887-staging

ABI v18. 69 built, 0 failed, 69 total.

Package Arch Status Sha
libcurl wasm32 built b16dfa55
libcxx wasm32 built a6a226bf
libcxx wasm64 built 05cc04c6
libpng wasm32 built fb0072b7
libxml2 wasm32 built 7693dffe
libxml2 wasm64 built 0e9bdba6
openssl wasm32 built 6079e850
openssl wasm64 built 96e12f2f
sqlite wasm32 built 5079ecc6
sqlite wasm64 built 41e589af
zlib wasm32 built 02809e96
zlib wasm64 built 74a9b521
bc wasm32 built e10365d5
bzip2 wasm32 built 78f873f3
coreutils wasm32 built 198092d9
curl wasm32 built db51ebb0
dash wasm32 built 01910f46
diffutils wasm32 built c730ca1d
dinit wasm32 built 7fa2cfc1
fbdoom wasm32 built 0560d7dc
file wasm32 built 0285fc03
findutils wasm32 built 7d4a601c
gawk wasm32 built 69d7773b
git wasm32 built de2da6a2
grep wasm32 built 41d5f22d
gzip wasm32 built cf0f7b2f
hello wasm32 built 0e7165f9
kandelo-sdk wasm32 built 911d8907
kernel wasm32 built 3a942356
less wasm32 built a926fd81
lsof wasm32 built 9415a3e3
m4 wasm32 built f653ae19
make wasm32 built 9cba934d
mariadb wasm32 built efe83b04
mariadb wasm64 built 8238b3ea
modeset wasm32 built 54395757
msmtpd wasm32 built 418b5b1b
nano wasm32 built 35094cd6
ncurses wasm32 built 95f1807e
netcat wasm32 built bc14b930
nginx wasm32 built b728d91a
php wasm32 built 1100861d
posix-utils-lite wasm32 built 2ba7af8b
ruby wasm32 built 646b371d
sed wasm32 built 4bb4d852
spidermonkey wasm32 built 5e0492a5
tar wasm32 built b41c7bad
tcl wasm32 built 889ee16d
unzip wasm32 built 54d97756
userspace wasm32 built 325ab8bf
vim wasm32 built 8e11f39b
wget wasm32 built 88792aab
xz wasm32 built f9fecf97
zip wasm32 built c26954c3
zstd wasm32 built 8fed2df5
bash wasm32 built 28a7bea0
mariadb-test wasm32 built 02fd8177
mariadb-vfs wasm32 built 9cc3a58b
mariadb-vfs wasm64 built f5340c57
nethack wasm32 built 86fd6eea
node wasm32 built abc37eda
spidermonkey-node wasm32 built 121e7aa3
vim-browser-bundle wasm32 built abedb1b1
nethack-browser-bundle wasm32 built 2b1fabb6
rootfs wasm32 built 3cb8e7f3
shell wasm32 built fe1e6492
lamp wasm32 built 8f3681cb
node-vfs wasm32 built 929cf9bb
wordpress wasm32 built 1bb5f5a5

Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.

@brandonpayton

Copy link
Copy Markdown
Member Author

Retested the exact temp-prefix regression on current Homebrew 6.0.9-121-ga4b13d4 against head 1e819fa6c02129698f9fd6fb0b528dca135bea86.

Inside scripts/dev-shell.sh, Homebrew's effective temp resolves to /private/tmp and the patched repository worktree was deliberately created below the Nix-shell temp directory. homebrew_patched_launcher_prepare completed without Homebrew's “HOMEBREW_PREFIX is in the Homebrew temporary directory” abort, and the live launcher reported:

original_prefix=/opt/homebrew
patched_prefix=/opt/homebrew
patched_repo=/private/tmp/nix-shell.XmqTdC/tmp.NjsHgBRtLL/homebrew-overlay
cmake_prefix=/opt/homebrew/opt/cmake

Cleanup removed the launcher and overlay. This confirms the launcher fixes the newly observed Homebrew 6 failure at the correct boundary: patched code comes from the disposable worktree while the prefix, Cellar, and native build-dependency kegs remain anchored to the original Homebrew installation. No Formula workaround is needed.

@brandonpayton

Copy link
Copy Markdown
Member Author

Superseded by #936, which retains this PR as patch-equivalent purpose commits in the consolidated Homebrew publisher batch and reruns the combined validation on current main.

@brandonpayton
brandonpayton deleted the fix/homebrew-publisher-prefix branch July 13, 2026 22:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant