Repository navigation
release: ship v0.1.1 patch (Homebrew Formula icon sandbox fix) - #17
Merged
Merged
Conversation
Patch the v0.1.0 Homebrew Formula under the real build sandbox: - Icon install: drop runtime sips/iconutil/Dir.mktmpdir. `iconutil -c icns` cannot run inside Homebrew's seatbelt sandbox (denies the mach-lookup iconutil needs, so even valid iconsets come out 'Invalid Iconset'). Copy a pre-built bundle/AppIcon.icns instead. - Drop `out: File::NULL, err: File::NULL` from Formula `system` calls — Formula#system's Sorbet sig does not accept these kwargs and raised TypeError under HOMEBREW_SORBET_RUNTIME=1 (e.g. brew test). - Add explicit `name macos: "homebrew.mxcl.switcheroo"` to the service do block so the published tap matches the upstream Label. Assets + tooling: - Track bundle/AppIcon.icns (the same file the Formula copies). - scripts/generate_icns.sh: regenerate bundle/AppIcon.icns from the 1024x1024 master PNG outside the sandbox (10 standard iconutil sizes; validates magic + declared length + round-trip decode). - scripts/test_icon_regression.sh: regression test that runs the exact Formula icon-install code under Homebrew's Sandbox API and confirms iconutil still fails there (negative control). Also validates the service plist_name from the template. - scripts/package.sh: prefer the tracked icns, fall back to runtime generation only if missing. - ci.yml: register new scripts in code-hygiene, add icon-regression job on macos-14. Version surfaces bumped to 0.1.1: Cargo.toml, Cargo.lock, Info.plist, CHANGELOG.md. No daemon, config, service, or mapping changes. No binary assets attached to the GitHub release (source-only).
The previous version of scripts/test_icon_regression.sh asserted
`svc.plist_names == [expected_label]` to catch a regression to the
positional `name "..."` form. `Homebrew::Service#plist_names`
is not available on the Homebrew version installed on the macos-14
runner (NoMethodError), so the assertion failed even though
`svc.plist_name == "homebrew.mxcl.switcheroo"` (the canonical
homebrew.mxcl.<name> Label) passed.
Narrow the test to:
- source-level guard: the template must contain the explicit
`name macos:` line (catches regression to positional
`name "..."`, which raises ArgumentError at install time).
- Service model guard: `svc.plist_name == "homebrew.mxcl.switcheroo"`.
The end-to-end `name "..."` regression is also covered by the
documented `brew install --build-from-source` + `brew test` run
on the v0.1.1 PR description.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Patch the v0.1.0 Homebrew Formula so
brew install --build-from-source switcherooandbrew test switcheroosucceed under Homebrew's build sandbox.This is a patch release (
0.1.0→0.1.1). No daemon, config, service-definition, or remapping changes. No new functionality.Sandbox bug (root cause)
iconutil -c icnscannot run inside Homebrew's build sandbox. Homebrew's seatbelt profile denies amach-lookupthat iconutil requires to load itsIconServicesframework — the call fails with "Invalid Iconset" even when the input iconset is perfectly valid and the same exact command succeeds a millisecond later outside the sandbox.The v0.1.0 Formula generated the
.icnsat install time viasips+iconutil+Dir.mktmpdir. That worked on a developer machine, failed underbrew install --build-from-source.A second, smaller issue:
Formula#system's Sorbet sig does not acceptout:/err:keyword arguments, so theout: File::NULL, err: File::NULLcalls raisedTypeError: Expected type T.any(Integer, Pathname, String, Symbol), got type HashunderHOMEBREW_SORBET_RUNTIME=1(set bybrew test).A third: the published v0.1.0 tap uses
name macos: "homebrew.mxcl.switcheroo"for the launchdLabel, so the Formula template must use thename macos:form too.Fix (static asset copy)
Replace runtime
.icnsgeneration with a pre-builtbundle/AppIcon.icnscopied at install time:bundle/AppIcon.icnsis now a tracked binary asset (generated outside the sandbox frombundle/AppIcon-1024.pngusing the 10 standard iconutil-recognized sizes: 16, 32, 128, 256, 512 + @2x each — not the 12-file set that includes the non-standardicon_64x64pair iconutil silently ignores).cp icns_source, app/"Contents/Resources/AppIcon.icns"— no sips, no iconutil, noDir.mktmpdir, noout:/err:kwargs.scripts/generate_icns.shregenerates the asset from the master PNG and validates output (ICNS magic, declared length, chunk-length sum, round-trip decode viaiconutil -c iconset).scripts/package.shnow prefers the tracked icns and only falls back to runtime generation if missing — single source of truth between packaging and Homebrew.service doblock getsname macos: "homebrew.mxcl.switcheroo".Evidence (real, full, sandboxed)
Validated end-to-end on macOS 14.6 (Apple Silicon), Homebrew 4.x, against the actual v0.1.0 Formula + the new scripts:
Brew test (full sandboxed)
brew install --build-from-source ./packaging/homebrew/switcheroo.rb.tpl(with__VERSION__=0.1.1,__SHA256__of a local source tarball,__URL__pointing at the local tarball).brew test switcherooran the Formula's test block (switcheroo --version→switcheroo 0.1.1).brew info switcherooconfirms the installed icon (Contents/Resources/AppIcon.icns) matches the source byte-for-byte:sha256: 42806c41405d55032548aa34493aeedd5493f59048b9f6792cb54942361c3106(739 049 bytes, ic12).brew services start switcheroowas issued. No daemon was started.Sandbox-only regression test (
scripts/test_icon_regression.sh)SandboxAPI (not allow-default) and runs/bin/cp <icns> <dest>— the exact Formula icon-install code path. Verifies installed bytes match source (sha256 + size)./usr/bin/iconutil -c icns— confirms iconutil still fails under the current sandbox profile (proving the bug isn't papered over by some unrelated change).brew rubyand assertssvc.plist_name == "homebrew.mxcl.switcheroo"andsvc.plist_names == ["homebrew.mxcl.switcheroo"](the latter fails ifname macos:is regressed to positionalname "...").ICNS integrity (
scripts/generate_icns.shvalidation)icns✓, declared length == actual ✓, chunk-length sum == actual ✓, round-tripiconutil -c iconsetextracts exactly 10 PNGs ✓.Files changed
Cargo.toml,Cargo.lock— version0.1.0→0.1.1bundle/Info.plist—CFBundleVersion,CFBundleShortVersionString→0.1.1bundle/AppIcon.icns— new tracked asset (739 049 bytes, ic12)scripts/generate_icns.sh— new (regenerate + validate)scripts/test_icon_regression.sh— new (sandbox regression)scripts/package.sh— prefer tracked icns, fallback to runtimepackaging/homebrew/switcheroo.rb.tpl— copy pre-built icns, dropout:/err:, addname macos:inservice doCHANGELOG.md—## [0.1.1] - 2026-09-12Fixed block.github/workflows/ci.yml— register new scripts incode-hygiene, addicon-regressionjobOut of scope
homebrew-coreor personal tap) update — handled separately after the GitHub release.Checklist
cargo build(release) passes locallycargo testpasses locallybrew install --build-from-source+brew testpasses in real sandboxname macos: "...")