feat: ship a Universal 2 (arm64 + x86_64) darwin release binary - #112
Open
chrisl10 wants to merge 1 commit into
Open
feat: ship a Universal 2 (arm64 + x86_64) darwin release binary#112chrisl10 wants to merge 1 commit into
chrisl10 wants to merge 1 commit into
Conversation
The release pipeline builds and ships only the maintainer's native arch (arm64), so Intel Macs have no signed/notarized binary to install and are stuck on unsigned `go install` builds. That blocks universal cookie delivery on Intel sinks, since the sink daemon needs a signed binary to read Chrome Safe Storage via teamid. Build one Universal 2 binary (arm64 + x86_64) with lipo, signed and notarized once, so a single asset runs natively on both architectures: - Makefile: add `build-universal` (cross-compiles each slice with CGO on, pinning the target arch via CC="clang -arch ..." so the build host is irrelevant, then lipo-fuses them). `release` now depends on it. - release-tarball.sh: detect the binary's archs via `lipo -archs` and name the asset darwin-universal (or darwin-arm64 / darwin-amd64 for a single-arch dev build). - install-beta.sh: prefer the darwin-universal asset, fall back to an arch-matched asset for older releases. - release.yml: upload the darwin-universal bundle. - docs: update download filenames and note Intel is supported. Signing/notarization scripts are unchanged and arch-agnostic; no new secrets are required. Verified locally on Apple Silicon: both slices cross-compile with CGO, lipo produces a working universal binary, and the tarball arch-detection resolves universal / arm64 / amd64 correctly.
Greptile SummaryThis PR changes the Darwin release flow to ship one Universal 2 beta binary. The main changes are:
Confidence Score: 5/5This looks safe to merge after a small release-upload guard.
.github/workflows/release.yml Important Files Changed
Reviews (1): Last reviewed commit: "feat: ship a Universal 2 (arm64 + x86_64..." | Re-trigger Greptile |
| @@ -102,7 +103,7 @@ jobs: | |||
| - name: attach beta bundle to release | |||
| run: | | |||
| gh release upload "${{ github.ref_name }}" \ | |||
There was a problem hiding this comment.
Universal Asset Can Be Skipped
If scripts/release-tarball.sh ever names the bundle darwin-arm64 or darwin-amd64 instead of darwin-universal, this glob matches no local files and the release can be published without the beta tarball. The tarball script has a silent fallback when lipo -archs fails, so this path needs an explicit file existence check before upload.
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.
Problem
Releases only ship a
darwin-arm64asset, so Intel Macs have no signed,notarized binary to install. On an Intel sink that matters beyond
convenience: the sink daemon needs a Developer-ID-signed binary to read
Chrome Safe Storage via the
teamidpath, so an unsignedgo installbuild is stuck in degraded delivery (
mode=sidecar+adapter+cdp) and cannever write the real Chrome profile. Intel users effectively can't get
universal cookie delivery.
The
install-beta.shdownloader is also hardcoded to--pattern '*darwin-arm64.tar.gz', so even if an Intel asset existed theinstaller wouldn't fetch it.
Approach
Ship a single Universal 2 (arm64 + x86_64) binary rather than two
per-arch assets. One
lipo-fused binary runs natively on botharchitectures and is signed + notarized once — the maintainer's release
ritual (and notarization time) stays the same, but Intel is covered.
build-universaltarget. Each slice cross-compileswith
CGO_ENABLED=1(the code links C for SQLite + the Keychain),pinning the target arch through
CC="clang -arch ..."so the build hostis irrelevant, then
lipo -creates them.releasenow depends onbuild-universalinstead ofbuild. Plainmake buildstays native forfast local dev.
archs via
lipo -archs→darwin-universal(ordarwin-arm64/darwin-amd64for a single-arch dev build).darwin-universalasset, fallback to an arch-matched asset for older releases (maps
uname -mx86_64→amd64).darwin-universalbundle.scripts/sign.shandscripts/notarize.share unchanged and alreadyarch-agnostic (a universal Mach-O signs and notarizes as one file). No
new CI secrets are required.
Testing
Verified locally on Apple Silicon (macOS, Go 1.26):
GOARCH=amd64 CC="clang -arch x86_64"and
GOARCH=arm64 CC="clang -arch arm64".make build-universalproducesbin/agentcookieasMach-O universal binary with 2 architectures [x86_64] [arm64], runs onthis host, and is version-stamped.
release-tarball.sh'slipo -archsdetection resolvesuniversal →
darwin-universal, arm64-only →darwin-arm64, amd64-only→
darwin-amd64.bash -nclean on both edited scripts.Signing/notarization couldn't be exercised without the Developer ID cert;
those steps run unchanged in the maintainer's release environment.
Notes
install-beta.shstill installs olderdarwin-arm64-only releases via the fallback path..goreleaser.yamlalready listsamd64, but releases are cut through themake release+release-tarball.shbeta-bundle path, which is what thisPR updates. The goreleaser path is left untouched to keep scope tight.