docs(release): recommend Homebrew on macOS; publish bundles, checksums, and tap formula - #30
Conversation
…s and checksums Root cause is the com.apple.quarantine attribute, not a missing signature: Go's linker already emits an ad-hoc (linker-signed) signature for darwin/arm64 even when cross-compiling from Linux. - README/QUICKSTART: curl and go install paths, quarantine escape hatch - build-release: systemica-<os>-<arch> bundles + SHA256SUMS.txt - packaging/homebrew: formula template + render script (no tap created) - docs/MACOS_DISTRIBUTION.md: notarization decision record Co-Authored-By: jason.han <jason.han@jpl.nasa.gov>
Original prompt from Devin Bot
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…t tap formula - packaging/homebrew/Formula/systemica.rb: real formula (renderable) with per-platform urls/checksums, install of both binaries, and a test block - packaging/homebrew/README.md: exact steps to create Open-MBEE/homebrew-tap and to bump the formula each release - render script: reads the formula source, fails on leftover placeholders - README/QUICKSTART: brew tap Open-MBEE/tap first, direct download + xattr fallback Co-Authored-By: jason.han <jason.han@jpl.nasa.gov>
Summary
The macOS "developer cannot be verified" prompt is quarantine, not a missing signature — this PR lands the mitigations that need no Apple credentials, makes Homebrew the recommended macOS install path (the maintainer-accepted stopgap), and records what notarization would cost.
Evidence for the root cause (measured on Linux with Go 1.25.0, cross-compiling
cmd/sysmlexactly asbuild-releasedoes, parsing the Mach-O load commands):LC_CODE_SIGNATUREdarwin/arm640xfade0cc0)0x20002=adhoc, linker-signeddarwin/amd64Go's linker already ad-hoc signs darwin/arm64 when cross-compiling from Linux (golang/go#42684 reports the same
flags=0x20002(adhoc,linker-signed)fromcodesign -dv), which is what Apple silicon requires to execute. What blocks users iscom.apple.quarantine, set by the browser on the downloaded tarball and propagated to the extracted binaries. Addingcodesign -s -in CI would therefore change nothing.curl/wget/go install/brew installnever set the attribute, which is why those paths are prompt-free (Homebrew quarantines casks only — hence the cask-only--no-quarantineflag — not formulae).What changed
README.md/docs/QUICKSTART.md:brew tap Open-MBEE/tap && brew install systemicais the recommended macOS path; directcurldownload plus checksum-verify-then-xattr -d com.apple.quarantineis the documented fallback;go installfor anyone with a Go toolchain. Also corrected:sysml-grpcwas listed as a release binary, butbuild-releasedoes not build it..circleci/config.yml(build-release): additive only — after the existing per-binary tarball loop, stagesysml+sysml-lspunder their plain names intosystemica-<os>-<arch>.tar.gz/.zip, thensha256sum ./*.tar.gz ./*.zip > SHA256SUMS.txt.publish-github-releasemoves the checksum file intodist/release/soghruploads it with the archives.packaging/homebrew/Formula/systemica.rb: the formula the tap will carry —desc/homepage/license,on_macos/on_linux×on_arm/on_intelurl + sha256,bin.install "sysml", "sysml-lsp", and atest dothat asserts--versionfor both binaries and evaluates an expression (sysml -e '5 + 3'→= 8, verified against a locally built binary).scripts/render-homebrew-formula.sh <tag> [SHA256SUMS.txt]: substitutes the five per-release values from the release'sSHA256SUMS.txt(downloading it if not passed), strips the maintainer header comment, and fails if any placeholder remains.docs/MACOS_DISTRIBUTION.md: the decision record — options with cost/benefit, and a concrete "what the maintainer must provide" list for notarization.Homebrew tap: what the maintainer must do
The documented
brewcommands do not work yet.Open-MBEE/homebrew-tapdoes not exist; nothing here creates or publishes it, and nothing was deployed anywhere. The docs say so explicitly in bothREADME.mdanddocs/QUICKSTART.md. One-time setup (also inpackaging/homebrew/README.md):Open-MBEE/homebrew-tap(thehomebrew-prefix is what makesbrew tap Open-MBEE/tapresolve).Formula/systemica.rb:systemica-*bundles andSHA256SUMS.txt.brew tap Open-MBEE/tap && brew install --verbose systemica && brew test systemica && brew audit --strict --online Open-MBEE/tap/systemica.Per release the artifact names are stable, so only five values change (
version+ foursha256): tagvX.Y.Z, let CircleCI publish, then in the tap run./scripts/render-homebrew-formula.sh vX.Y.Z > Formula/systemica.rb, commit, push. This can be automated later — a tag-triggered job could render and push the tap commit — but that needs a token with write access toOpen-MBEE/homebrew-tapas a CI secret, which is a maintainer decision and is deliberately not set up here.Notarization (not implemented, decision recorded)
Needs an Apple Developer Program membership ($99/yr), a Developer ID Application cert (
.p12+ password), an App Store Connect API key fornotarytool, and a team ID — plus a macOS runner. CircleCI macOS VMs are 200 credits/min and unavailable on the Free plan (the 400k OSS credits are Linux/Arm/Docker only); GitHub Actionsmacos-latestis a standard runner and free for public repos, so the recommendation is a tag-triggered GHA job for the darwin artifacts. Stapling is impossible for bare executables per Apple's docs; a.pkg/.dmgwould be needed for that.Why the CI change is safe for tag builds
Existing per-binary archive names and the
ghrupload are untouched, so current download links keep working. New archives are built from copies in astage/dir that is deleted beforesha256sumruns; thefor binary in sysml-*glob is evaluated before the newsystemica-*files exist (and would not match them anyway).circleci config validatepasses, and I dry-ran the exact shell of both jobs against dummy files, confirming thedist/release/listing and thatsystemica-darwin-arm64.tar.gzcontainssysmlandsysml-lsp.Untested / not verified
I am on Linux and could not run Gatekeeper,
codesign,notarytool, orbrew. Every macOS runtime claim is cited to Apple/Go/Homebrew docs; the Mach-O table above is the only thing measured directly. The formula was not installed or audited by Homebrew (no macOS host); the.circlecirelease path only runs on av*tag and was not executed end-to-end.Out of scope, mentioned only: Windows artifacts are unsigned too, so SmartScreen shows "Windows protected your PC". Documented, not fixed.
Verification — run locally; CI was NOT used (repo CI is down)
Corpus gate matches the 81/100 baseline;
training_examples_expected.txtwas not touched (no Go code changed in this PR).Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/f3e06cc1e62e40f2811fa71002d14f73
Requested by: @HuiJun