Skip to content

Make the macOS compatibility job produce usable signal again - #194

Merged
arzafran merged 2 commits into
mainfrom
fix/compat-no-fail-fast
Jul 29, 2026
Merged

Make the macOS compatibility job produce usable signal again#194
arzafran merged 2 commits into
mainfrom
fix/compat-no-fail-fast

Conversation

@arzafran

@arzafran arzafran commented Jul 29, 2026

Copy link
Copy Markdown
Member

What this does

The macOS compatibility job has been red on every run since at least 21 July, across every branch. Two separate problems were keeping it that way, and neither was a real bug in the app.

1. The two macOS legs cancelled each other. fail-fast: true meant a failure on one killed the other, and GitHub reports a cancelled leg as a failure to gh pr checks. A leg that was passing when it got stopped read as broken. That produced two wrong conclusions in one afternoon, both only detectable by opening the raw log and finding ##[error]The operation was canceled after a run of passing tests.

2. Seventeen tests time out on the macos-15 runner — the same seventeen every run, verified by intersecting failure sets across independent runs. They are not broken on macOS 15. They are skipped on that leg only, and still run everywhere else.

Together: the job can go green again, and go red only when something is actually wrong.

Why these seventeen are not a macOS 15 bug

  • No OS-conditional code exists in any path they cover. No @available, no #available, no NSAppKitVersion checks. A genuinely unguarded macOS-26-only symbol could not compile here at all, since Swift checks availability against MACOSX_DEPLOYMENT_TARGET (14.0).
  • 4x more time changed nothing. Give the slow-runner test waits the same headroom as everything else #193 raised every wait via ciScale — 3s became 12s, 10s became 40s — and the same tests timed out. A 12-second wait expiring is not a slow overlay.
  • Unrelated subsystems fail in the same run. TerminalControllerSocketSecurityTests times out waiting for a raw Unix domain socket to appear; subprocess-log waits time out too. A BSD socket accept, a DispatchQueue.main.async closure, and an XCTNSPredicateExpectation poll share no SwiftUI or AppKit code. The only thing in common is needing an async completion serviced promptly.
  • Determinism is explained. The suite runs serially in fixed order, so a runner that degrades partway through starves the same tests every time — deterministic failures, non-deterministic cause.

No coverage is lost

Every quarantined test still runs on the macos-26 compat leg and in the main CI workflow's unit-tests job on every PR. The quarantine is scoped to one leg of one workflow. That includes the five TerminalControllerSocketSecurityTests entries, which are security tests and would otherwise be the most alarming thing on the list.

Summary

  • fail-fast: false on the compat matrix, with a comment recording why so it is not "optimised" back.
  • QUARANTINED_ON_COMPAT in scripts/ci-run-unit-tests.sh lists the 17 with the full evidence inline; applied only when PROGRAMA_UNIT_TEST_QUARANTINE is set.
  • The matrix sets quarantine: true on the macos-15 leg only, alongside the existing smoke / skip_zig flags.

This is a workaround for CI infrastructure, not a fix. The code comment says so and names the conditions to revisit under.

Test plan

Verified locally by stubbing PROGRAMA_XCODEBUILD_COMMAND=echo and inspecting the generated argument list:

  • Flag set → 18 -skip-testing: flags (1 pre-existing + 17 quarantined), and Quarantining 17 runner-starvation-prone tests is logged
  • Flag unset → 1 -skip-testing: flag, no quarantine notice — confirming it cannot leak into other jobs
  • bash -n scripts/ci-run-unit-tests.sh passes
  • workflow-guard-tests passes
  • macos-15 compat leg goes green, and reports its own conclusion rather than cancelled

arzafran added 2 commits July 29, 2026 16:23
The two macOS checks were set up so that if one failed, the other was
cancelled straight away. GitHub then shows the cancelled one as failed,
so a check that was passing when it got stopped looks broken.

That sent me down the wrong path twice today, both times concluding the
older macOS was broken when it had actually been cancelled partway
through while passing. You could only tell by opening the raw log.

Both now run to the end and report for themselves.
Seventeen tests time out on the older macOS runner, the same seventeen
every time. They are not broken on that version of macOS. Giving them
four times longer to finish changed nothing, and in the same run the
machine also fails to open plain network sockets and to read output from
programs it started. Those have nothing in common with each other except
needing the machine to get around to them.

So the runner stalls partway through and starves whatever is waiting.
The suite always runs in the same order, which is why it is always the
same seventeen.

They are skipped on that runner only. All of them still run on the newer
macOS and on every pull request, so nothing stops being checked. The
point is that the older runner can now come back green, and go red only
when something is actually wrong.
@arzafran arzafran changed the title Let both macOS versions finish instead of cancelling one Make the macOS compatibility job produce usable signal again Jul 29, 2026
@arzafran
arzafran merged commit 7a5be3a into main Jul 29, 2026
7 of 8 checks passed
@arzafran
arzafran deleted the fix/compat-no-fail-fast branch July 29, 2026 19:41
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.

1 participant