ci: ship a runnable aarch64-darwin archive with each release #363
No reviewers
Labels
No labels
priority/P0
priority/P1
priority/P2
release/v0.1.0
status/blocked
status/planned
type/bug
type/design
type/test-gap
type/tracker
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis!363
Loading…
Reference in a new issue
No description provided.
Delete branch "release/issue-360-macos-archive"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The macOS half of #360, on top of the Linux half in #361. A tag now attaches
felis-aarch64-darwin.tar.gzand the release's five assets are two tarballs, theWindows zip, the config schema and the proto.
felis-aarch64-darwin.txtis gone:the identity it carried is checked in CI against the archive's own
bin/felis,which is stronger than a text file naming a store path a non-Nix user cannot fetch.
What changed
nix/make-macos-app.shtakes--cli PATH. With it the client installs asContents/MacOS/felis-client(CFBundleExecutable follows), the CLI asContents/MacOS/felis, and the daemon beside them: that is the only directorythat can hold all three as the siblings
spawn.rslooks for. Without it thebehavior is unchanged, so a standalone
cargo build --releasekeeps working.nix/package.nixpasses--cli, so$out/Applications/felis.apphas the sameshape. CFBundleName and CFBundleDisplayName stay
felis.nix/dist-macos.shassembles the tree:felis.app, abin/felisscript thatexecs into it,
share/{terminfo,bash-completion,zsh,fish,man}, README, LICENSE.It walks
otool -ltransitively from the three executables, copies every/nix/storedylib intoContents/Frameworks(a second source for one basenamemust be byte-identical or the build fails), rewrites the reference to
@executable_path/../Frameworks/<name>from an executable and@loader_path/<name>between dylibs, sets-idon each copy, deletes everystore
LC_RPATH, then signs inside-out withrcodesign(dylibs, executables,bundle). It fails the build if any
LC_LOAD_DYLIB,LC_ID_DYLIBorLC_RPATHunder the app still names
/nix/store.nix/dist.nixgains a darwin branch (cctoolsandrcodesigninnativeBuildInputs) beside the Linux one, sharing the reproducible tar step.flake.nixexportspackages.felis-diston every system instead of Linux only.darwin.yml's build step builds.#felis-disttoo, so a broken bundler failsbefore a tag.
release.ymldarwin-publish: after the cache push it builds and unpacks thearchive, runs
tools/release/macos-archive-manifest.sh(required paths, no storepath in
bin/felisorshare/, theotool -lsweep) andtools/release/macos-archive-smoke.sh(the bundledfelis-client --versionrundirectly,
bin/felis --version,sessions spawn -- trueon an isolated socketwith the daemon's command line checked to be inside the extracted app,
daemon stop --force), plus/usr/bin/codesign --verify --strict --deepandverify.py --identityon the archive's ownbin/felis. Timeout raised to 90minutes to match
linux-package. Thereleasejob attaches the tarball and thenotes name both archives and the quarantine step.
workspace.md's
darwin-publishprose, asset row and P-2 sentence,reference/testing.md's
release.ymlrow, explanation/testing.md "A tag rebuildsrather than promotes", README.md and docs/README.md. Repository-wide sweep for
.txt,identity fileandstore pathcame back clean.Two deviations worth naming. The checks live in
tools/release/*.shrather thanworkflow heredocs, following #361.
otoolcomes fromnix shell --inputs-from . nixpkgs#cctools, because the macOS runner has no XcodeCommand Line Tools and
/usr/bin/otoolmay not exist there.Verified here
just fmt-check lint prose-check docs-links: all pass.bash -n/sh -non every new and edited script;shellcheck -xclean exceptone info-level SC2009 (the smoke needs the full command line, and macOS
pgrepcannot print it).
nix evaloffelis-dist.nameand.drvPathonaarch64-darwin,x86_64-linuxandaarch64-linux: the darwin derivation instantiates fully, socctoolsandrcodesignresolve in the flake's own nixpkgs.nix flake show --all-systems:felis-diston all three systems.nix build .#felis-diston x86_64-linux still produces the Linux tarball afterthe dist.nix restructure.
actionlinton both workflows: only the pre-existing Forgejo noise (thenixrunner label,
enable-openid-connect).make-macos-app.shwith and without--cli, run here: the layout andCFBundleExecutable are as described in each case.
dist-macos.shdriven against stubotool/install_name_tool/rcodesignandfake Mach-O files: the transitive walk copies both dylibs, rewrites the
executables to
@executable_path/../Frameworks/…and the dylib-to-dylib edge to@loader_path/…, sets the ids, drops the store rpaths, and fails as intended ona colliding basename and on a surviving store reference.
macos-archive-manifest.shpasses on a good tree and fails on a missing file andon a store path in a load command.
What only darwin can verify
I am on Linux, so none of the real macOS behavior ran here. The
darwin-buildjobis the first to exercise
nix build .#felis-distwith realotool,install_name_toolandrcodesignagainst real Mach-O binaries, and thev0.1.0-rc.3tag run is the first to exercisedarwin-publish: thecodesign --verify --strict --deepresult, whether dyld resolves the rewrittenbundle, the daemon spawn from the extracted tree, and the five-asset release page.
The client opening a window on macOS still rests on maintainer use; the runner has
no Aqua session.
Notarization,
aarch64-linuxand anything Linux stay out of scope.Closes #360
The darwin CI run on this branch built
.#felis-diston the real runner andpassed: the walk found
libiconv.2.dylibandlibcharset.1.dylibin theclosure, copied them into
Contents/Frameworks, rewrote the load commands, andrcodesignsealed the bundle inside-out, with the build-time"no
/nix/storein any load command" check clean. That covers everything inthis PR except the
darwin-publishsteps, which only a tag run reaches:codesign --verify --strict --deep, the archive's client and daemon actuallyrunning, and the five-asset release page.
The Criterion regression gate is red on this branch, as it was on the first
push. The diff contains no Rust (16 files: nix, workflows, shell scripts and
docs), so the regressed parser and socket benches are the shared runner's load,
not this change.