feat(macos): support Apple Silicon builds and self-update #132

Merged
David merged 3 commits from fix/macos-native-build into main 2026-07-28 11:14:06 +02:00
Owner

platform_filename() only knew linux-x86_64 and windows-x86_64, so every macOS host fell through to the catch-all arm and hard-errored with "no prebuilt binary for target_os=macos target_arch=aarch64". That broke yt version check and yt version update outright on macOS and failed 10 tests in the version module. The compile and link were always fine: cargo build --release produces a working arm64 Mach-O today.

Add a macos+aarch64 arm mapping to yt-macos-aarch64 and extend the catch-all not(any(...)) to match. Intel macs stay on the catch-all deliberately: no x86_64 darwin artifact is published, and claiming one would turn a clean "no prebuilt binary" error into a 404 partway through an update.

Add .forgejo/workflows/build-macos.yml to publish the artifact. It is the only build job that does not use Docker, because macOS cannot be containerised and darwin cannot be cross-compiled from Linux without the Apple SDK, so it builds natively via cargo build --release --locked --target aarch64-apple-darwin. It uses BSD date -u and shasum --algorithm 256 (macOS ships no sha256sum; the output is the same <hash> <file> GNU format the sidecar parser already expects), and verifies the artifact is an arm64 Mach-O with a valid ad-hoc signature before uploading. The job targets vars.RUNS_ON_MACOS and stays inert until a macOS runner is registered under that label.

Fix two test portability bugs surfaced by the same run: /bin/false does not exist on macOS (only /usr/bin/false), so probe both paths; and two assertions were gated behind #[cfg(all(target_os = "linux", target_arch = "x86_64"))], silently skipping their only real check off Linux. They now derive the expected filename from platform_filename() so they assert on every platform that resolves one.

Full suite is green on macOS arm64 (435 tests). The cfg arms were verified to stay mutually exclusive for x86_64-unknown-linux-musl, x86_64-pc-windows-gnu, aarch64-apple-darwin and x86_64-apple-darwin.

`platform_filename()` only knew linux-x86_64 and windows-x86_64, so every macOS host fell through to the catch-all arm and hard-errored with "no prebuilt binary for target_os=macos target_arch=aarch64". That broke `yt version check` and `yt version update` outright on macOS and failed 10 tests in the version module. The compile and link were always fine: `cargo build --release` produces a working arm64 Mach-O today. Add a macos+aarch64 arm mapping to `yt-macos-aarch64` and extend the catch-all `not(any(...))` to match. Intel macs stay on the catch-all deliberately: no x86_64 darwin artifact is published, and claiming one would turn a clean "no prebuilt binary" error into a 404 partway through an update. Add `.forgejo/workflows/build-macos.yml` to publish the artifact. It is the only build job that does not use Docker, because macOS cannot be containerised and darwin cannot be cross-compiled from Linux without the Apple SDK, so it builds natively via `cargo build --release --locked --target aarch64-apple-darwin`. It uses BSD `date -u` and `shasum --algorithm 256` (macOS ships no `sha256sum`; the output is the same `<hash> <file>` GNU format the sidecar parser already expects), and verifies the artifact is an arm64 Mach-O with a valid ad-hoc signature before uploading. The job targets `vars.RUNS_ON_MACOS` and stays inert until a macOS runner is registered under that label. Fix two test portability bugs surfaced by the same run: `/bin/false` does not exist on macOS (only `/usr/bin/false`), so probe both paths; and two assertions were gated behind `#[cfg(all(target_os = "linux", target_arch = "x86_64"))]`, silently skipping their only real check off Linux. They now derive the expected filename from `platform_filename()` so they assert on every platform that resolves one. Full suite is green on macOS arm64 (435 tests). The cfg arms were verified to stay mutually exclusive for x86_64-unknown-linux-musl, x86_64-pc-windows-gnu, aarch64-apple-darwin and x86_64-apple-darwin.
feat(macos): support Apple Silicon builds and self-update
Some checks failed
Check / fmt + clippy + build + tests (pull_request) Failing after 7s
f41188a3e5
`platform_filename()` only knew linux-x86_64 and windows-x86_64, so every macOS host fell through to the catch-all arm and hard-errored with "no prebuilt binary for target_os=macos target_arch=aarch64". That broke `yt version check` and `yt version update` outright on macOS and failed 10 tests in the version module. The compile and link were always fine: `cargo build --release` produces a working arm64 Mach-O today.

Add a macos+aarch64 arm mapping to `yt-macos-aarch64` and extend the catch-all `not(any(...))` to match. Intel macs stay on the catch-all deliberately: no x86_64 darwin artifact is published, and claiming one would turn a clean "no prebuilt binary" error into a 404 partway through an update.

Add `.forgejo/workflows/build-macos.yml` to publish the artifact. It is the only build job that does not use Docker, because macOS cannot be containerised and darwin cannot be cross-compiled from Linux without the Apple SDK, so it builds natively via `cargo build --release --locked --target aarch64-apple-darwin`. It uses BSD `date -u` and `shasum --algorithm 256` (macOS ships no `sha256sum`; the output is the same `<hash>  <file>` GNU format the sidecar parser already expects), and verifies the artifact is an arm64 Mach-O with a valid ad-hoc signature before uploading. The job targets `vars.RUNS_ON_MACOS` and stays inert until a macOS runner is registered under that label.

Fix two test portability bugs surfaced by the same run: `/bin/false` does not exist on macOS (only `/usr/bin/false`), so probe both paths; and two assertions were gated behind `#[cfg(all(target_os = "linux", target_arch = "x86_64"))]`, silently skipping their only real check off Linux. They now derive the expected filename from `platform_filename()` so they assert on every platform that resolves one.

Full suite is green on macOS arm64 (435 tests). The cfg arms were verified to stay mutually exclusive for x86_64-unknown-linux-musl, x86_64-pc-windows-gnu, aarch64-apple-darwin and x86_64-apple-darwin.
David scheduled this pull request to auto merge when all checks succeed 2026-07-28 10:53:26 +02:00
fix(ci): verify the C toolchain before building on macOS
Some checks failed
Check / fmt + clippy + build + tests (pull_request) Failing after 5s
084d0046e8
The macOS job assumed a linker was present. `ring` and `libsqlite3-sys` compile C, so a runner without Xcode Command Line Tools fails partway through the dependency graph instead of at a preflight step. On macOS the failure is especially opaque: `/usr/bin/cc` is an xcrun stub that exists even when the tools are absent, so it surfaces as `xcrun: error: invalid active developer path` rather than a clean not-found.

Add a "Verify the C toolchain" step that probes `xcode-select --print-path` and `cc --version` up front and fails with the `xcode-select --install` remediation. Document the requirement in CLAUDE.md alongside the same exposure in `check.yml`, which runs cargo on a bare OpenSUSE runner with no container and no toolchain install, and therefore diverges from the local `just pre-commit` that runs the same steps inside rust-builder-musl.

Compress the comments added in the previous commit to the 1-2 line limit, moving the no-Docker and Gatekeeper rationale out of the workflow header and into CLAUDE.md.

Verified: preflight step exercised locally (reports developer dir and clang version, exit 0); fmt, clippy and the full 435-test suite still green.
fix(ci): install a C toolchain before running cargo in check.yml
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 49s
Create release / Create release from merged PR (pull_request) Has been skipped
d0cf8cf1b2
`check.yml` runs cargo natively on the runner rather than in a container, so it depends entirely on the runner image providing a linker. `ring` and `libsqlite3-sys` compile C, so an image shipping rustup without gcc fails at the first build script with ``error: linker `cc` not found`` before clippy ever reports a lint. Nothing in the repo has ever installed a C toolchain for the bare-runner path.

This is also the one case where the documented hook/CI parity claim does not hold: `just pre-commit` runs the identical steps inside rust-builder-musl, which always has a linker, so a green hook cannot detect a runner image missing one.

Add an "Ensure a C toolchain" step that short-circuits when `cc` is already present and otherwise installs gcc via zypper/apt-get/apk/dnf, using sudo only when not already root. Cargo arguments are untouched, so the byte-identical parity rule still holds. Document the requirement for both bare-runner jobs in CLAUDE.md, and note that the durable fix is baking gcc into the runner image rather than guarding in every repo.

Verified: check.yml parses, the step's bash passes `bash -n`, and the already-present branch was executed locally (prints the clang version, exits 0).
David merged commit 4faf68cda2 into main 2026-07-28 11:14:06 +02:00
David deleted branch fix/macos-native-build 2026-07-28 11:14:06 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
pandoras-box/youtrack-cli!132
No description provided.