Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/app-host-test-rerun.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:
needs: plan
# A fork has no Blacksmith installation and no runner variables; the owner
# check comes first so a fork is never pointed at a label it cannot run.
runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-15' }}
runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || 'blacksmith-6vcpu-macos-15' }}
timeout-minutes: 60
env:
CMUX_CI_REQUIRED_MACOS_SDK_MAJOR: "26"
Expand Down
19 changes: 18 additions & 1 deletion .github/workflows/iroh-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,26 @@ permissions:

jobs:
client:
runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26' }}
runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26' }}
timeout-minutes: 15
steps:
- name: Verify GitHub-hosted route
env:
RUNNER_ENVIRONMENT: ${{ runner.environment }}
REQUESTED_RUNNER: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26' }}
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
# The self-hosted fleet also carries a macos-26 label, so a macos-*
# request must prove it landed on GitHub-hosted capacity before any
# checkout.
case "$REQUESTED_RUNNER" in
macos-*)
if [ "$RUNNER_ENVIRONMENT" != "github-hosted" ]; then
echo "::error::$REQUESTED_RUNNER resolved outside GitHub-hosted capacity: $RUNNER_CONTEXT_NAME"
exit 1
fi
;;
esac
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,23 @@ jobs:
CMUX_SKIP_ZIG_BUILD: "1"
CMUX_PRODUCT_RUNNER: ${{ needs.runner.outputs.label }}
steps:
- name: Verify GitHub-hosted route
env:
RUNNER_ENVIRONMENT: ${{ runner.environment }}
REQUESTED_RUNNER: ${{ needs.runner.outputs.label }}
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
# The self-hosted fleet also carries a macos-26 label, so a macos-*
# request must prove it landed on GitHub-hosted capacity before any
# checkout.
case "$REQUESTED_RUNNER" in
macos-*)
if [ "$RUNNER_ENVIRONMENT" != "github-hosted" ]; then
echo "::error::$REQUESTED_RUNNER resolved outside GitHub-hosted capacity: $RUNNER_CONTEXT_NAME"
exit 1
fi
;;
esac

- name: Validate Tart canary identity
if: ${{ startsWith(needs.runner.outputs.label, 'tart-') }}
Expand Down Expand Up @@ -696,6 +713,23 @@ jobs:
# instead, which is where the upload step reads from.
CMUX_APP_HOST_CAPTURE_XCRESULTS: "1"
steps:
- name: Verify GitHub-hosted route
env:
RUNNER_ENVIRONMENT: ${{ runner.environment }}
REQUESTED_RUNNER: ${{ needs.runner.outputs.label }}
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
# The self-hosted fleet also carries a macos-26 label, so a macos-*
# request must prove it landed on GitHub-hosted capacity before any
# checkout.
case "$REQUESTED_RUNNER" in
macos-*)
if [ "$RUNNER_ENVIRONMENT" != "github-hosted" ]; then
echo "::error::$REQUESTED_RUNNER resolved outside GitHub-hosted capacity: $RUNNER_CONTEXT_NAME"
exit 1
fi
;;
esac

- name: Validate Tart canary identity
if: ${{ startsWith(needs.runner.outputs.label, 'tart-') }}
Expand Down
65 changes: 58 additions & 7 deletions .github/workflows/test-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ on:
- iphone
- ipad
runner:
description: "macOS runner (auto follows MACOS_RUNNER_IOS; tart-ios uses the isolated VM fleet)"
description: "macOS runner (auto follows MACOS_RUNNER_TESTS, then MACOS_RUNNER_IOS; tart-ios uses the isolated VM fleet)"
required: false
default: "auto"
type: choice
Expand Down Expand Up @@ -214,13 +214,30 @@ jobs:
|| (needs.package-conventions-lint.result == 'skipped'
&& needs.detect-ios-changes.outputs.should_lint == 'false'))
&& (!(github.event_name == 'workflow_dispatch' && inputs.test_filter != '') || inputs.swift_package != '') }}
runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
# Focused runs build the shell and its macros from a cold SwiftPM cache.
timeout-minutes: ${{ inputs.swift_package != '' && 25 || 10 }}
env:
SWIFT_TEST_FILTER: ${{ inputs.test_filter }}
FOCUSED_SWIFT_PACKAGE: ${{ inputs.swift_package }}
steps:
- name: Verify GitHub-hosted route
env:
RUNNER_ENVIRONMENT: ${{ runner.environment }}
REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
# The self-hosted fleet also carries a macos-26 label, so a macos-*
# request must prove it landed on GitHub-hosted capacity before any
# checkout.
case "$REQUESTED_RUNNER" in
macos-*)
if [ "$RUNNER_ENVIRONMENT" != "github-hosted" ]; then
echo "::error::$REQUESTED_RUNNER resolved outside GitHub-hosted capacity: $RUNNER_CONTEXT_NAME"
exit 1
fi
;;
esac
- name: Validate package selection
env:
SELECTED_PACKAGE: ${{ inputs.swift_package }}
Expand All @@ -231,7 +248,7 @@ jobs:
esac

- name: Validate Tart runner identity
if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }}
if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }}
env:
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
Expand Down Expand Up @@ -381,7 +398,7 @@ jobs:
|| (needs.package-conventions-lint.result == 'skipped'
&& needs.detect-ios-changes.outputs.should_lint == 'false'))
&& inputs.swift_package == '' }}
runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
timeout-minutes: 35
outputs:
artifact_id: ${{ steps.upload-product.outputs.artifact-id }}
Expand All @@ -392,8 +409,25 @@ jobs:
package_seconds: ${{ steps.package-product.outputs.seconds }}
upload_seconds: ${{ steps.upload-metrics.outputs.seconds }}
steps:
- name: Verify GitHub-hosted route
env:
RUNNER_ENVIRONMENT: ${{ runner.environment }}
REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
# The self-hosted fleet also carries a macos-26 label, so a macos-*
# request must prove it landed on GitHub-hosted capacity before any
# checkout.
case "$REQUESTED_RUNNER" in
macos-*)
if [ "$RUNNER_ENVIRONMENT" != "github-hosted" ]; then
echo "::error::$REQUESTED_RUNNER resolved outside GitHub-hosted capacity: $RUNNER_CONTEXT_NAME"
exit 1
fi
;;
esac
- name: Validate Tart runner identity
if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }}
if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }}
env:
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
Expand Down Expand Up @@ -691,15 +725,32 @@ jobs:
&& needs.ios-simulator-build.result == 'success'
&& needs.detect-ios-changes.outputs.should_run == 'true' && inputs.swift_package == '' }}
# Runtime-only consumers share the producer's exact Build/Products tree.
runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
timeout-minutes: 35
strategy:
fail-fast: false
matrix:
family: ${{ fromJSON(needs.detect-ios-changes.outputs.device_families) }}
steps:
- name: Verify GitHub-hosted route
env:
RUNNER_ENVIRONMENT: ${{ runner.environment }}
REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
# The self-hosted fleet also carries a macos-26 label, so a macos-*
# request must prove it landed on GitHub-hosted capacity before any
# checkout.
case "$REQUESTED_RUNNER" in
macos-*)
if [ "$RUNNER_ENVIRONMENT" != "github-hosted" ]; then
echo "::error::$REQUESTED_RUNNER resolved outside GitHub-hosted capacity: $RUNNER_CONTEXT_NAME"
exit 1
fi
;;
esac
- name: Validate Tart runner identity
if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }}
if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }}
env:
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/test-macos-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,23 @@ jobs:
runs-on: ${{ vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-15' }}
timeout-minutes: ${{ inputs.unit_test_suites != '' && 35 || 20 }}
steps:
- name: Verify GitHub-hosted route
env:
RUNNER_ENVIRONMENT: ${{ runner.environment }}
REQUESTED_RUNNER: ${{ vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-15' }}
RUNNER_CONTEXT_NAME: ${{ runner.name }}
run: |
# The self-hosted fleet also carries a macos-26 label, so a macos-*
# request must prove it landed on GitHub-hosted capacity before any
# checkout.
case "$REQUESTED_RUNNER" in
macos-*)
if [ "$RUNNER_ENVIRONMENT" != "github-hosted" ]; then
echo "::error::$REQUESTED_RUNNER resolved outside GitHub-hosted capacity: $RUNNER_CONTEXT_NAME"
exit 1
fi
;;
esac
- name: Clear stale git locks (self-hosted reused workspace)
shell: bash
run: |
Expand Down
15 changes: 12 additions & 3 deletions docs/ci-runners.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ gh variable list --repo manaflow-ai/cmux
| `LINUX_ARM64_RUNNER` | native ARM64 package entrypoint verification | `ubuntu-24.04-arm` | `ubuntu-24.04-arm` |
| `MACOS_RUNNER_15` | the macOS 15 default: `macos-compile-admission`, non-PR `app-host-unit-tests`, nightly helper and test-cache jobs, `iroh-release-gate.yml` streamed validation | `blacksmith-6vcpu-macos-15` | `blacksmith-6vcpu-macos-15` |
| `MACOS_RUNNER_PR` | **pull-request** macOS jobs except the striped `app-host-unit-tests` matrix, in `ci-macos.yml`, `cli-pipe-regressions.yml`, `terminal-hang-diagnostics.yml`, `ci.yml` (`claude-wrapper`) and `nightly.yml` (`refresh-test-compilation-cache`) | unset (see "Lanes" below) | `blacksmith-6vcpu-macos-15` |
| `MACOS_RUNNER_TESTS` | the manual test-debugging lanes: `test-e2e.yml` and `test-macos-suite.yml` | unset (see "Lanes" below) | `blacksmith-6vcpu-macos-26` for `test-e2e.yml`, `blacksmith-6vcpu-macos-15` for `test-macos-suite.yml` |
| `MACOS_RUNNER_TESTS` | test-only lanes that pick their Xcode by SDK and sign nothing: `test-e2e.yml`, `test-macos-suite.yml`, `test-ios.yml` (`auto`) and the `iroh-v2.yml` client | unset (see "Lanes" below) | each lane's own variable or Blacksmith label: `blacksmith-6vcpu-macos-26` for `test-e2e.yml`, `blacksmith-6vcpu-macos-15` for `test-macos-suite.yml`, `MACOS_RUNNER_IOS` for `test-ios.yml` and `iroh-v2.yml` |
| `MACOS_RUNNER_DUAL_XCODE` | `swift-package-tests` (SDK 15 release helper, then SDK 26 package tests) on **every** event, pull requests included | `blacksmith-6vcpu-macos-15` | `blacksmith-6vcpu-macos-15` |
| `MACOS_RUNNER_26` | the macOS 26 image: compatibility jobs, `release.yml` and nightly sign/notarize, the disk-heavy `release-build` universal app, and the nightly compilation-cache warmer | `blacksmith-6vcpu-macos-26` | `blacksmith-6vcpu-macos-26` |
| `MACOS_RUNNER_26_LARGE` | the larger macOS 26 machine: changed-revision universal Nightly app builds | `blacksmith-12vcpu-macos-26` | `blacksmith-12vcpu-macos-26` |
Expand Down Expand Up @@ -81,8 +81,17 @@ the same cost profile or the same urgency.
Blacksmith fallback. PR runs are cancelled on supersession by design, so
they are the wrong place to spend elastic paid capacity. A fork uses the
GitHub-hosted branch described below instead.
- **Manual test debugging** (`test-e2e.yml`, `test-macos-suite.yml`) resolves through
`MACOS_RUNNER_TESTS`, and deliberately does **not** follow `MACOS_RUNNER_15`.
- **Test-only lanes** (`test-e2e.yml`, `test-macos-suite.yml`, `test-ios.yml`
on `auto`, the `iroh-v2.yml` client) resolve through
`MACOS_RUNNER_TESTS` first, and deliberately do **not** follow `MACOS_RUNNER_15`.
Setting it moves every test lane off a backed-up pool in one edit without
touching `MACOS_RUNNER_IOS` or `MACOS_RUNNER_26`, which also route release,
nightly, TestFlight and App Store signing. A GitHub-hosted value (`macos-15`,
`macos-26`) is checked by each job's first step: the self-hosted fleet also
carries a `macos-26` label, so a job that lands anywhere but GitHub-hosted
capacity fails before checkout. `app-host-test-rerun.yml` does not follow it:
a rerun must build with the exact Xcode the products were compiled with, so it
stays on the Blacksmith macOS 15 pool it has always resolved to.
Re-running one test to chase a flake should never reach for paid capacity.
Both fallbacks stay on Blacksmith for that reason; `test-e2e.yml` falls back
to macOS 26 because the macOS 15 pool's queue-to-start p90 was 83 min against
Expand Down
4 changes: 2 additions & 2 deletions tests/test_ci_self_hosted_guard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,11 @@ check_ios_tart_canary() {
echo "FAIL: all macOS iOS test jobs must fail closed on Tart identity mismatch"
exit 1
fi
if [[ "$(grep -Fc "runs-on: \${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}" "$IOS_FILE")" -ne 3 ]]; then
if [[ "$(grep -Fc "runs-on: \${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}" "$IOS_FILE")" -ne 3 ]]; then
echo "FAIL: all macOS iOS test jobs must honor the dispatch runner override"
exit 1
fi
if [[ "$(grep -Fc "startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-')" "$IOS_FILE")" -ne 3 ]]; then
if [[ "$(grep -Fc "startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-')" "$IOS_FILE")" -ne 3 ]]; then
echo "FAIL: all macOS iOS test jobs must validate Tart identity for explicit and repo-variable routing"
exit 1
fi
Expand Down
Loading