Skip to content

Run the full macOS suite on main and nightly, with a one-job macOS gate on PRs into main - #925

Merged
JacobStephens2 merged 2 commits into
mainfrom
issue-893
Oct 21, 2026
Merged

JacobStephens2 merged 2 commits into
mainfrom
issue-893

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Oct 21, 2026 •

Copy link
Copy Markdown
Owner

Summary

CI's new macos-plan job decides which macOS work each event gets. The test-macos check stays on every run and requires that work to pass.

macos-plan                        suite      test-macos passes when
  push to main                    full       every shard passed
  schedule (nightly, main)        full       every shard passed
  workflow_dispatch               full       every shard passed
  PR into main + test:macos       full       every shard passed
  PR into main                    gate       the gate passed
  PR into any other base          none       gate and shards both skipped
 on:
   push: [main]
-  pull_request:
+  pull_request: [opened, synchronize, reopened, labeled]
+  schedule: nightly
+  workflow_dispatch:
 jobs:
   test, site-test, console-test           # unchanged, every PR
+  macos-plan                              # full | gate | none
+  test-macos-gate     if gate             # macos-26: clippy --all-targets -D warnings
+                                          #   + nextest --profile macos-gate
-  test-macos-shard                        # 4 hash shards, every PR
+  test-macos-shard    if full
   test-macos          always()            # passes on what the plan required
  • Filterset. The gate's tests live in .config/nextest.toml as the macos-gate profile's default-filter. A comment there says what the filter must cover: the #[cfg(target_os = "macos")] process identity, the non-Linux skills directory handle, and the platform branches in child Run handling.
  • Label. The test:macos label now exists, with a description of what it does.
  • Docs. docs/ci-performance.md records the table, the reasons, the trade-offs and what to do when the nightly run is red.
  • Unchanged. The concurrency group, the Linux jobs and the generated Release workflow (python3 scripts/generate-release.py --check passes).

Tests the gate selects

cargo nextest list --profile macos-gate gives 79 tests, the same 79 on Linux and in the macOS job ("Starting 79 tests across 3 binaries"):

Binary Tests Covers
bin/thirdshift logs::recording::tests 28 process start identity (process_identity::start)
bin/thirdshift logs::reading::tests 5 process start identity, reused process ids
bin/thirdshift logs::owner::tests 3
bin/thirdshift logs::stop::tests 1 process start identity
bin/thirdshift skills::tests 4 O_SEARCH skills directory handle
bin/thirdshift child_run::execution_tests / tests / asks::tests 20 / 5 / 1 child Run handling
stop (all) 10 macOS terminate through thirdshift stop
spec_run a_linear_spec_lands_each_ticket_in_order_then_opens_a_ready_spec_pr, a_signal_to_the_spec_run_alone_fails_the_ticket_run_then_ends_the_spec_run_as_interrupted 2 child Runs started from current_exe on macOS

Evidence

Before: every pull_request, whatever its base, ran four macos-26 shards (#870's Ticket PR waited over an hour on them).

After: real runs:

Run Event macOS jobs test-macos
39537982242 this PR into main gate success, shards skipped success
39539107043 this PR, labeled test:macos on the same head shards 1-4 success (10-17 min, each queued ~3 s), gate skipped success
39538002225 probe #926 into throwaway issue-893-probe-base none: gate and shards skipped success
39541320165 this PR's final head, label removed gate success, shards skipped success
  • Gate timing. In 39537982242 the gate took 2 min 44 s from creation to completion, with a 3 s queue: clippy 27 s, building the tests 35 s, then Summary [74.006s] 79 tests run: 79 passed (2 slow), 1175 skipped. In 39541320165 it took 2 min 40 s.
  • Linux. test, site-test and console-test ran and passed in every run above.
  • Probe cleanup. Probe Probe for #925: a PR into a non-main base gets no macOS jobs #926 is closed, and both of its branches are deleted.
  • Local. On x86_64 Linux cargo nextest run gave Summary [1448.331s] 2168 tests run: 2168 passed. cargo clippy --all-targets -- -D warnings, python3 -m unittest discover -s scripts -p 'test_*.py' and python3 scripts/generate-release.py --check all pass. actionlint reports only that it doesn't know the existing macos-26 label.
  • Not observed yet. The push-to-main, nightly schedule and workflow_dispatch paths only run once this is on main. All three take the full branch of the same macos-plan step that 39539107043 exercised.

Merge Danger

Door: two-way

Reverting ci.yml restores the four shards on every PR.

Blast Radius: CI

  • Later macOS signal. A macOS-only regression outside the gate's filterset now shows up on main or overnight, not on its PR. One from a Spec's Ticket shows up at the Spec PR.
  • Nightly notifications. GitHub sends nightly failure notifications to whoever last changed the schedule cron.
  • Labelling mid-run. Adding a label while CI is running cancels that run, and its cancelled check runs stay on the same head, where the CI watch reads them as failed. The docs say to label after the run finishes, and CI watch reads a same-head run's cancelled checks as failed after a PR is labelled #927 asks the Day shift to choose a fix.

Unaddressed findings

Review reports: Standards and Spec, against main. Every changed file was read by both axes; no file was left unread, and there were no generated-output exclusions.

Standards

  • Duplicated setup steps between test-macos-gate and test-macos-shard, with drifted step names. Declined. The gate's step installs and uses the clippy component and is named like the Linux test job's step, which does the same (.github/workflows/ci.yml, the test job's "Install the Rust version and components rust-toolchain.toml names"). The shards run no clippy. Sharing four steps would need a composite action file.
  • full | gate | none string switched on in several places. Declined. macos-plan is the one place the rule is decided. The job if:s and the aggregate's case (with *) exit 1) only compare its output, and Actions job outputs are strings.
  • Rename "gate". Declined. Run the full macOS suite on main and nightly, with a one-job macOS gate on PRs into main #893's brief calls it "the gate job" ("The gate job is one macos-26 job…"), and docs/research/macos-ci-speed.md uses the same word.

Spec

Security

  • None. The change keeps the pull_request trigger (no pull_request_target), adds no secrets or permissions, passes github.base_ref and the label check to the plan step through env: rather than inline expressions, and the gate restores the macOS cache read-only (save-if: false). The new schedule and workflow_dispatch triggers run code already on the chosen ref, and workflow_dispatch needs write access. test-macos fails closed when the plan produced no output.

Closes #893

🤖 Generated with Claude Code

Built with claude · claude-opus-5-5 · medium

Security review outcome

No unaddressed introduced findings.

…PRs into main

A macos-plan job picks the macOS work per event: the four shards on pushes
to main, nightly, by hand or for a PR into main labelled test:macos; one gate
job (clippy plus the macos-gate nextest profile) for other PRs into main; and
none for PRs into other bases, such as Spec branches. The test-macos check
passes only on the work its plan required.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2 JacobStephens2 added the test:macos On a PR into main: run the full 4-shard macOS suite instead of the one-job macOS gate (#893) label Oct 21, 2026
… gate's cache read-only

The nextest profile's comment now defers to docs/ci-performance.md for which
runs get the full suite, and names the console installer's Linux-only
refusal as uncovered. The gate no longer saves the shared macOS cache, so a
labelled PR's shards restore main's full build. The docs now state that a
label added mid-run leaves the cancelled run's checks on the same head (#927).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2 JacobStephens2 removed the test:macos On a PR into main: run the full 4-shard macOS suite instead of the one-job macOS gate (#893) label Oct 21, 2026
@JacobStephens2
JacobStephens2 merged commit 887766b into main Oct 21, 2026
18 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-893 branch October 21, 2026 04:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Run the full macOS suite on main and nightly, with a one-job macOS gate on PRs into main

1 participant