Repository navigation
ci: move macOS runners to macos-15 and pin the deployment target to 14.0 - #2849
Merged
Merged
Conversation
GitHub retires the macos-14 runner image on 2026-11-02, and its brownouts already cancel our macos-14 jobs. Move every macos-14 runner reference to macos-15 (arm64): the release darwin-arm64 build, the unix-macos14 and tsan-mac test legs, the smoke-mac PR leg (its two matrix.os guards move in lockstep), the release smoke, both soak legs, the memwaste event lane, the bug-repro board, the cache warmer and the all-platform smoke. Lane names stay unchanged: select-lanes.sh, ci-ok and the lane contracts key on them, never on the runner label. Two broad legs already ran on macos-15 (_test.yml BROAD_UNIX, _smoke.yml BROAD_UNIX) and smoke.yml listed both images, so the moved legs would have duplicated them. Those duplicates are dropped; PR CI keeps exactly the same legs. Without an explicit minimum, clang stamps the binary with the SDK's default (LC_BUILD_VERSION minos), so a release built on macos-15 would refuse to start on macOS 14. Makefile.cbm now folds -mmacosx-version-min=14.0 into CC/CXX next to ARCHFLAGS for Apple targets (detected from the compiler's target, not the host), so it reaches every compile and link, vendored objects included, on every build path. Proof on macOS 26.6 / SDK 26.5: the production binary built from origin/main reports minos 26.0; with this change it reports minos 14.0, with zero warnings under -Werror, no weak imports and an identical undefined-symbol set. The test runner (direct make, no env.sh) is minos 14.0 too; platform and daemon_ipc suites pass. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This was referenced Oct 31, 2026
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.
Why
GitHub retires the
macos-14runner image on 2026-11-02. The scheduledbrownouts before that date already cancel our
macos-14jobs, and after itevery job pinned to
macos-14stops getting a runner: the macOS arm64 PRlegs, the darwin-arm64 release build and the release smoke. This PR moves
all of them to
macos-15(arm64).That move alone would quietly change what we ship. No deployment target is
set anywhere, so clang stamps the binary with the SDK's default minimum
(
LC_BUILD_VERSION minos). Built onmacos-15, the darwin-arm64 releasewould refuse to start on macOS 14. So this PR also pins the minimum macOS to
14.0 for every Darwin build.
What changes
1. Runner labels (13 references in 9 workflows)
_test.yml:63 -> :66test-unixlaneunix-macos14ci-okneedstest; releasebuildneedstest_test.yml:95 -> :98test-tsanlanetsan-macpr.yml:178pr-smokelanesmoke-macci-okneedspr-smokepr.yml:217,pr.yml:257if: matrix.os == 'macos-15'(ccache install, build + smoke):178, so the macOS steps still run_build.yml:44 -> :46smoke/soakneedbuild,release-draftneeds both_smoke.yml:36release-draftneedssmoke_soak.yml:47,_soak.yml:338release-draftneedssoak); nightly: no_memwaste.yml:118event-macos(modefullonly)release-draft's needsbug-repro.yml:43workflow_dispatchonlycache-warm.yml:30smoke.yml:42qa/smoke-**pushDuplicates removed. Three places already ran a
macos-15leg next tothe
macos-14one. A plain rename would have produced two identical legs,so:
_test.ymlBROAD_UNIX: the broadmacos-15entry is dropped (the coreleg runs there now).
_smoke.ymlBROAD_UNIX: now[]. Its only entry wasmacos-15darwin-arm64, which is now the core leg.
smoke.yml: themacos-14entry is dropped; the existingmacos-15entry stays.
Effect, checked by executing the real "Compute matrices" scripts from main
and from this branch:
LANES= every lane,prshard profile): the same legs and thesame counts. Only
macos-14becamemacos-15.BROAD=true,LANES=all): one fewer macOS arm64test leg and one fewer smoke leg, because macOS 14 + 15 became macOS 15
only. No duplicate legs.
Lane names are unchanged.
unix-macos14,tsan-macandsmoke-macarelane keys:
scripts/ci/select-lanes.sh,scripts/test-impact/replay-selector.sh,tests/fixtures/select-lanes/cases.tsvand the lane contracts key on them.ci-ok(scripts/ci/require-all-green.sh) reads the lane back from theparenthesised matrix values of the job name. It takes the one value that is a
known lane, so the runner label inside the job name never matters. Renaming
unix-macos14would be a separate change, so this PR keeps it and adds acomment in
_test.yml. The two synthetic job names intests/test_lane_gate_contract.shnow saymacos-15, which proves the gatemaps the new names.
Not touched:
test-lsan-macosruns onmacos-latest(GitHub's alias). Fourcomments still mention
macos-14(
scripts/memwaste.sh,scripts/run-test-wave.py,src/foundation/subprocess.c,tests/test_watcher.c), but each one records a past observation on thatrunner, so they stay as written.
2. Minimum macOS pinned to 14.0 (
Makefile.cbm)-mmacosx-version-min=14.0is folded intoCC/CXXwithoverride,right next to the existing
ARCHFLAGSfold. This means it:use their own
*_CFLAGS(mimalloc, sqlite3, tre, zstd, lz4, the grammars);scripts/build.sh(release),scripts/test.sh,direct
make(cache-warm), and the recursive diag/LSan/coverage/fuzzlanes, which re-enter the Makefile with
CC=;is a flag and not an exported
MACOSX_DEPLOYMENT_TARGET;__APPLE__predefine, not the host, so a non-Apple cross compiler on a Macgets nothing. Linux and Windows builds are unchanged.
Why 14.0. Releases built on the
macos-14runner carried that image'sSDK default as their minimum, a 14.x value by the mechanism shown in the
proof below. So 14.0 drops no user who can run today's arm64 release. Going lower (13, 12, ...) would be a new
support-policy decision, and after 2026-11-02 no hosted runner older than
macOS 15 is left to back it up. The Intel binary (
macos-15-intel) gets thesame pin. Until now it carried that image's SDK default (15.x), so this
probably extends Intel support to macOS 14. Confirm on the next dry run (see
below).
API safety.
__builtin_available,@availableorAPI_AVAILABLEexists insrc/,internal/orvendored/.MAC_OS_X_VERSION_MIN_REQUIRED >= 10_15,sqlite
> 1050) resolve the same way at 14.0 as at the host default.is identical to main's. Clang weak-links any SDK API newer than the
deployment target, so nothing referenced is newer than macOS 14.0.
-Werrorbuild has zero warnings, so no-Wunguarded-availability-newhits and no linker "built for newer macOS"notes.
Proof (local, macOS 26.6, Apple clang 21, SDK 26.5)
LC_BUILD_VERSIONscripts/build.sh CC=cc CXX=c++)minos 26.0, sdk 26.5minos 14.0, sdk 26.5build/c/test-runnervia directmake(noARCHFLAGS)minos 14.0MacOSX15.4.sdk: unpinned givesarm64-apple-macosx15.4.0, pinned givesarm64-apple-macosx14.0.0. That isthe macos-15 runner case in miniature.
minos 14.0.none lacks it.
platformpassed 32/32.daemon_ipcpassed 60, with 2 skipped;both skips are Linux-only by design.
test_lane_gate_contract,test_lane_wiring_contract,test_select_lanes,test_release_gate_chain_contract,test_smoke_fixture_contract,test_soak_daemon_recovery_contract,test_venue_parity_contract,test_coverage_map,test_security_gate_fail_closed,test_windows_bundle_contract.Cost and flake surface
macos-15arm64 is the same standard runnerclass as
macos-14(3 vCPU M1, 7 GB). PR CI has the same leg count. Thedry run and release have one fewer macOS arm64 test leg and one fewer smoke
leg.
matrix.os. The firstmacos-15runs ofunix-macos14,tsan-macandsmoke-macmay buildcold, which the
_test.ymlcomment puts at about 8-12 minutes. That lastsuntil
cache-warmwritesmacos-15entries on main (it moves in this PRtoo).
-Werrora new warning would fail the gating legs. A local Apple clang 21build has zero warnings, so this is unlikely, but
unix-macos14is thefirst leg to read.
tsan-macis the leg most tied to the OS/Xcode pair. If itgoes red, attribute it first (runtime vs. code) before touching anything.
What to watch on the first run
test / test-unix (macos-15, ..., unix-macos14, ...)andtsan-mac:compile warnings, sanitizer runtime start-up, and the timing-sensitive
watcher/subprocess tests (same hardware class, so no change is expected).
pr-smoke (macos-15, smoke-mac):codesign --sign - --force, thensmoke-local.sh. The binary-security phase must still showcodesign --verifyrejecting the tampered copy (the deterministic checkfrom fix(smoke): de-flake 10c by corrupting the signature instead of removing it #692).
macos-15, therelease smoke, and the soak legs. Then run
vtool -show-build/otool -l | grep -A4 LC_BUILD_VERSIONon bothdarwin release candidates. Both must show
minos 14.0.Known limits / follow-ups (not in this PR)
the loader accepts the binary on macOS 14.0+, and the weak-import check
shows no newer API is referenced. But macOS-14 kernel behaviour is no
longer exercised in CI (for example, the
linkat/AT_SYMLINK_NOFOLLOW_ANYdifference documented in
src/daemon/ipc.c). A local macOS 14 VM legwould close that gap.
minos 14.0would guard the pin against regression. No runtime check ona macOS 15 runner can catch a raised minimum.
unix-macos14lane rename, and an optional second arm64 macOS versionin the broad matrices (e.g. a newer image), are separate decisions.
Test plan
minos 26.0vsminos 14.0minos 14.0;platform+daemon_ipcgreenunix-macos14,tsan-mac,smoke-macgreen onmacos-15minos 14.0