Skip to content

Commit 9460bac

Browse files
committed
CI on macOS 27: ci-macos, ci-macos-e2e and both fresh-install channels
GitHub serves macOS 27 under the preview label xcode-27 (macOS 27.0 with Xcode 27, actions/runner-images#14404); there is no macos-27 label. Measured on #658: the label delivers macOS 27.0 (26A5406e), arm64, ImageOS macos27. - ci-macos and ci-macos-e2e run on macos-15 and xcode-27. - ci-fresh-install runs the xlings and Homebrew channels on macos-14 (the floor) and xcode-27 (the newest release). - Every macOS 27 leg asserts sw_vers major 27, because the label names an Xcode and its base OS has changed once. - setup-macos-llvm takes the image as an input and puts it in the xlings cache key, which named macos15 for every image.
1 parent 15e7dff commit 9460bac

6 files changed

Lines changed: 97 additions & 14 deletions

File tree

.agents/docs/2026-09-17-655-implementation-plan.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ reason).
165165
| E7 | `build/flag-words` note on the first plan | E1 | branch: e2e 736 D and E |
166166
| E8 | SPEC-004 §8, SPEC-005 R3.7, docs/04 and docs/30 with their Chinese mirrors, CHANGELOG | E1-E7 | branch |
167167
| E9 | version 2026.9.17.1 | - | branch |
168-
| E10 | CI green on every workflow of the pull request | E1-E9 | todo |
168+
| E10 | CI green on every workflow of the pull request | E1-E9, E11 | todo |
169+
| E11 | macOS 27 legs (maintainer request, 2026-09-17; label measured in §5.1): `ci-macos` and `ci-macos-e2e` run on `macos-15` and macOS 27; `ci-fresh-install` runs its xlings and Homebrew channels on `macos-14` and macOS 27; each macOS 27 leg asserts `sw_vers` major 27 | - | branch |
169170

170171
### 3.2 Release and ecosystem, in order
171172

@@ -227,6 +228,21 @@ Recorded after the release in §7.
227228

228229
Recorded as each row closes.
229230

231+
## 5.1 macOS 27 on GitHub-hosted runners
232+
233+
GitHub publishes no `macos-27` label. The runner-images README (read on
234+
2026-09-17) lists macOS 26 as the newest GA image (`macos-26`, `macos-latest`)
235+
and macOS 14 as deprecated (unsupported from 2026-11-02). macOS 27 is served as
236+
the preview label `xcode-27`, whose base OS moved from macOS 26 to macOS 27.0 on
237+
2026-09-16 (actions/runner-images#14404), with a warning that capacity may
238+
queue. A temporary pull request (#658) measured which labels are served; its
239+
first run, naming `macos-27`, `macos-27-arm64`, `macos-26` and `macos-latest`,
240+
was cancelled while every job was still queued behind this repository's runner
241+
limit, and the second names `xcode-27` and reads
242+
`label=xcode-27 27.0 build=26A5406e arch=arm64 xcode=Xcode 27.0 clang=Apple clang
243+
version 21.0.0` with `ImageOS=macos27` (run on 2026-09-16T19:16Z). Because the label names an Xcode and its
244+
base OS has changed once, every macOS 27 leg asserts that `sw_vers` reports 27.
245+
230246
## 8. Residuals
231247

232248
- `ldflags`, `dialect_cxxflags` and `std-module-flags` keep their current

.github/actions/setup-macos-llvm/action.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ inputs:
1616
# .github/actions/bootstrap-mcpp/action.yml for why 0.4.69 is required
1717
# (two packages named `lua` in one repo need openxlings/xlings#381).
1818
default: '2026.9.16.1'
19+
image:
20+
description: >
21+
The runner label the job runs on (macos-15, xcode-27). It is part of the
22+
xlings cache key: the cache holds installed binaries, and a key that does
23+
not name the OS release lets one image restore what another installed.
24+
required: false
25+
default: 'macos-15'
1926

2027
runs:
2128
using: composite
@@ -24,9 +31,9 @@ runs:
2431
uses: actions/cache@v4
2532
with:
2633
path: ~/.xlings
27-
key: xlings-macos15-arm64-v3-xl${{ inputs.xlings-version }}-${{ hashFiles('.xlings.json') }}
34+
key: xlings-${{ inputs.image }}-arm64-v3-xl${{ inputs.xlings-version }}-${{ hashFiles('.xlings.json') }}
2835
restore-keys: |
29-
xlings-macos15-arm64-v3-xl${{ inputs.xlings-version }}-
36+
xlings-${{ inputs.image }}-arm64-v3-xl${{ inputs.xlings-version }}-
3037
3138
- name: Bootstrap xlings
3239
shell: bash

.github/workflows/ci-fresh-install.yml

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -357,13 +357,25 @@ jobs:
357357
# ──────────────────────────────────────────────────────────────────
358358
macos-fresh:
359359
needs: [wait-index]
360-
name: macOS fresh install
360+
name: macOS fresh install (${{ matrix.image }})
361361
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
362+
# Two images, the two ends of the supported range.
363+
#
362364
# macos-14: the support floor (mcpp ≥0.0.50 / xlings ≥0.4.50 ship
363365
# minos=14.0 static-libc++ binaries). A fresh install passing here
364366
# is the continuous proof of the macOS 14 floor — and of host-tool
365367
# independence (this image has no sha256sum; macos-15 does).
366-
runs-on: macos-14
368+
#
369+
# xcode-27: macOS 27, the newest release, served under the preview label
370+
# `xcode-27` (actions/runner-images#14404; there is no `macos-27` label).
371+
# The same released binaries, the same steps; a failure only here is a
372+
# change in the newest system (SDK, loader, system libc++ headers) that the
373+
# floor cannot show.
374+
strategy:
375+
fail-fast: false
376+
matrix:
377+
image: [macos-14, xcode-27]
378+
runs-on: ${{ matrix.image }}
367379
timeout-minutes: 30
368380
env:
369381
# The one derived value (see the header comment): every install job names
@@ -372,6 +384,14 @@ jobs:
372384
steps:
373385
- uses: actions/checkout@v4
374386

387+
- name: The image is the macOS it names
388+
run: |
389+
echo "macOS $(sw_vers -productVersion) | $(uname -m)"
390+
# See ci-macos.yml: `xcode-27` names an Xcode, not an OS.
391+
if [ "${{ matrix.image }}" = xcode-27 ]; then
392+
[ "$(sw_vers -productVersion | cut -d. -f1)" = 27 ] || { echo "::error::xcode-27 delivered macOS $(sw_vers -productVersion), not 27"; exit 1; }
393+
fi
394+
375395
- name: Install xlings
376396
env:
377397
XLINGS_NON_INTERACTIVE: '1'
@@ -452,16 +472,24 @@ jobs:
452472
# channel healthy the entire time. So the trust gate itself is asserted
453473
# from BOTH sides: refused before `brew trust`, accepted after.
454474
macos-brew-fresh:
455-
name: macOS fresh install (Homebrew)
475+
name: macOS fresh install (Homebrew, ${{ matrix.image }})
456476
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
457-
# Same floor as macos-fresh: the formula declares `depends_on macos:
458-
# :sonoma` + arm64, and macos-14 is the oldest image satisfying it.
459-
runs-on: macos-14
477+
# Same two images as macos-fresh: the formula declares `depends_on macos:
478+
# :sonoma` + arm64, macos-14 is the oldest image satisfying it, and
479+
# xcode-27 is macOS 27, the newest release.
480+
strategy:
481+
fail-fast: false
482+
matrix:
483+
image: [macos-14, xcode-27]
484+
runs-on: ${{ matrix.image }}
460485
timeout-minutes: 30
461486
steps:
462487
- name: Environment
463488
run: |
464489
echo "macOS $(sw_vers -productVersion) | $(uname -m) | $(brew --version | head -1)"
490+
if [ "${{ matrix.image }}" = xcode-27 ]; then
491+
[ "$(sw_vers -productVersion | cut -d. -f1)" = 27 ] || { echo "::error::xcode-27 delivered macOS $(sw_vers -productVersion), not 27"; exit 1; }
492+
fi
465493
466494
# ① The command README.md documents, on a machine that has never tapped.
467495
# Fully qualified, so Homebrew treats it as explicit intent.

.github/workflows/ci-macos-e2e.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@ concurrency:
2222

2323
jobs:
2424
e2e:
25-
name: e2e suite (macOS ARM64, self-host)
26-
runs-on: macos-15
25+
name: e2e suite (macOS ARM64, self-host, ${{ matrix.image }})
26+
# The same two images as ci-macos.yml; `xcode-27` is macOS 27 (see there).
27+
strategy:
28+
fail-fast: false
29+
matrix:
30+
image: [macos-15, xcode-27]
31+
runs-on: ${{ matrix.image }}
2732
timeout-minutes: 60
2833
# NOTE: no MCPP_VERBOSE — the e2e suite asserts mcpp's default quiet
2934
# output (tests 48/53).
@@ -37,6 +42,8 @@ jobs:
3742
with:
3843
submodules: recursive
3944
- uses: ./.github/actions/setup-macos-llvm
45+
with:
46+
image: ${{ matrix.image }}
4047

4148
- name: Build mcpp from source (self-host)
4249
run: |

.github/workflows/ci-macos.yml

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,22 @@ concurrency:
1919

2020
jobs:
2121
macos-xlings-llvm:
22-
name: macOS ARM64 — xlings LLVM end-to-end
23-
runs-on: macos-15
24-
timeout-minutes: 30
22+
name: macOS ARM64 — xlings LLVM end-to-end (${{ matrix.image }})
23+
# Two images: macos-15, the image every other macOS job uses, and macOS 27,
24+
# the newest macOS release. The newest release is where a change of the SDK,
25+
# the system libc++ headers or the loader first shows; the packaged binaries
26+
# carry minos=14.0, and ci-fresh-install covers that floor.
27+
#
28+
# GitHub serves macOS 27 under the preview label `xcode-27` (macOS 27.0 with
29+
# Xcode 27, actions/runner-images#14404); there is no `macos-27` label, and
30+
# a job naming one waits for a runner that never comes. The "System info"
31+
# step prints the OS the label delivered.
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
image: [macos-15, xcode-27]
36+
runs-on: ${{ matrix.image }}
37+
timeout-minutes: 45
2538
# NOTE: no MCPP_VERBOSE here — keep this job's output shape identical to
2639
# ci-macos-e2e.yml, which asserts mcpp's default quiet output (48/53).
2740
steps:
@@ -31,10 +44,18 @@ jobs:
3144
run: |
3245
uname -a
3346
sw_vers
47+
# `xcode-27` names an Xcode, not an OS, and the image changed its base
48+
# OS once already; the leg exists for macOS 27, so it says so or fails.
49+
if [ "${{ matrix.image }}" = xcode-27 ]; then
50+
major=$(sw_vers -productVersion | cut -d. -f1)
51+
[ "$major" = 27 ] || { echo "::error::xcode-27 delivered macOS $(sw_vers -productVersion), not 27"; exit 1; }
52+
fi
3453
xcrun --show-sdk-path
3554
echo "SDK: $(xcrun --show-sdk-version)"
3655
3756
- uses: ./.github/actions/setup-macos-llvm
57+
with:
58+
image: ${{ matrix.image }}
3859

3960
- name: Inspect LLVM package structure
4061
run: |

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ libarchive、bzip2、lz4、xz、zlib 与 zstd 的每个 C 文件都无法解析
2929
这样的元素。
3030
- Windows 上 `shell_quote_arg` 按 MSVCRT 规则加倍引号前与结尾处的反斜杠,以 `\` 结尾的
3131
词不再吞掉闭合引号。
32+
- **CI 覆盖 macOS 27。** `ci-macos` 与 `ci-macos-e2e` 在 `macos-15` 与 macOS 27 上各跑一遍,
33+
`ci-fresh-install` 的 xlings 与 Homebrew 两条安装渠道在 `macos-14` 与 macOS 27 上各跑一遍。
34+
GitHub 以预览标签 `xcode-27` 提供 macOS 27(无 `macos-27` 标签),每条 macOS 27 的腿断言
35+
`sw_vers` 主版本为 27。
3236

3337
### 内置 xlings 升至 2026.9.16.1(2026.9.16.2)
3438

0 commit comments

Comments
 (0)