Repository navigation
ci: run macOS jobs on the Studio self-hosted runner (toggleable, Xcode 27) - #48
Merged
Merged
Conversation
…led by a repo variable What: build.yml (build), release.yml (build), testflight.yml (testflight), tests.yml (test) and lint.yml (swift, clang-format) can now run on the Mac Studio runner. Same pattern as Provenance-Emu/Provenance and JoeMatt/iFly. Toggle: repo variable MACOS_RUNNER_LABELS = ["self-hosted","studio"]. Unset (or empty) keeps today's behaviour: macos-26 / macos-latest on GitHub-hosted. Pull requests from forks always stay GitHub-hosted, so untrusted fork code never reaches the persistent machine. Ubuntu jobs and mcp-tests.yml are untouched. Xcode: hosted keeps maxim-lobanov/setup-xcode with XCODE_VERSION 26.3 (those steps are now guarded to github-hosted). Self-hosted uses Xcode 27 only: a first step, before checkout, writes DEVELOPER_DIR=<XCODE_PATH>/Contents/Developer to GITHUB_ENV (XCODE_PATH is an optional repo variable, default /Applications/Xcode.app), fails clearly if it is missing and prints xcodebuild -version. It must precede checkout because the job-level DEVELOPER_DIR names the hosted-only Xcode_26.3.app and a missing Xcode breaks the /usr/bin/git shim. No sudo xcode-select anywhere. Other self-hosted hygiene: brew installs are guarded with command -v and HOMEBREW_NO_AUTO_UPDATE / HOMEBREW_NO_INSTALL_CLEANUP are set (the Studio's Homebrew belongs to another user). testflight.yml now logs to RUNNER_TEMP instead of /tmp and its if: always() cleanup also removes the p12, ASC .p8, export dir and archives besides the temporary keychain. tests.yml keeps ccache in ~/Library/Caches/ccache-icube on self-hosted (checkout's git clean would wipe a workspace cache) and skips actions/cache there, and shuts down the simulator it booted. The simulator picker already chooses any iPhone runtime at or below the selected SDK, so it resolves to an iOS 27 runtime with Xcode 27. No build logic, secrets, triggers or schedules changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: c9bca5db-0db7-4419-93b5-0a5424784d12) |
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.
ci: let macOS jobs run on the self-hosted Mac Studio (Xcode 27), toggled by a repo variable
Applies the same pattern already merged in Provenance-Emu/Provenance (
testflight.yml,build.yml) and JoeMatt/iFly to iCube's macOS jobs.Toggle
Set repo variable
MACOS_RUNNER_LABELS=["self-hosted","studio"]to run on the Studio. Leave it unset/empty and nothing changes (GitHub-hostedmacos-26/macos-latest).Pull requests from forks always stay GitHub-hosted (
github.event.pull_request.head.repo.full_name == github.repositorycheck), so untrusted code never touches the persistent machine. Nopull_request_targetis involved.Jobs switched
build.ymlbuildrelease.ymlbuildtestflight.ymltestflight(ios + tvos matrix)tests.ymltestlint.ymlswift,clang-formatLeft alone: every
ubuntu-latestjob (testflight.ymlplan/tag,build.ymlalpha-release) andmcp-tests.yml.Xcode
maxim-lobanov/setup-xcode+XCODE_VERSION: 26.3(steps now guarded withif: runner.environment == 'github-hosted').DEVELOPER_DIR=<XCODE_PATH>/Contents/Developerto$GITHUB_ENV, fails with a clear message if it is missing, and printsxcodebuild -version.XCODE_PATHis an optional repo variable, default/Applications/Xcode.app. It has to come before checkout because the job-levelDEVELOPER_DIRnames the hosted-onlyXcode_26.3.app, and a missing Xcode breaks the/usr/bin/gitshim.sudo xcode-selectanywhere. The onlyXcode_14.2.appreference (inbuild.yml) is a long-dead commented-out step; nothing depends on it, so it is left as is.Self-hosted hygiene
command -v X >/dev/null || brew install X;HOMEBREW_NO_AUTO_UPDATEandHOMEBREW_NO_INSTALL_CLEANUPset (the Studio's Homebrew is owned by another user and already has the tools).testflight.yml: log moved from/tmpto$RUNNER_TEMP; the existingif: always()keychain cleanup now also removes the p12, the ASC.p8, the export dir and the archives.tests.yml: on self-hosted, ccache lives in~/Library/Caches/ccache-icube(checkout'sgit clean -ffdxwould wipe a workspace-local cache every run) andactions/cachefor ccache is skipped there; the booted simulator is shut down in anif: always()step (it is picked, not created, so it is not deleted).tests.ymlalready selects any available iPhone on an iOS runtime at or below the selected SDK, so with Xcode 27 it resolves to an iOS 27 runtime. There are noOS=26destinations in the workflows.Not changed
Build logic, secrets, triggers, schedules, timeouts.
actionlintoutput is identical todevelop(pre-existing findings only, e.g.actions/checkout@v2inbuild.yml).Risks / things to check on first self-hosted run
Xcode 27 vs Xcode 26.3 is a real toolchain change for the self-hosted legs only (hosted stays on 26.3).
Tuist.swifthascompatibleXcodeVersions: .all; the first run is the test.actions/checkout'sgit clean -ffdxstill wipesbuild-Xcode*DerivedData andbuild/in the workspace each run.build.ymlkeeps restoringbuild/throughactions/cache. Settingclean: falseon self-hosted would keep them, butbuild.yml'smkdir productsis not idempotent, so that is a follow-up.Tuist is installed via
miseinto~/.localandmise use -gwrites the runner user's global config; fine on a dedicated runner user, but jobs share it.-allowProvisioningUpdatesleaves Xcode-managed provisioning profiles in~/Library/MobileDevice; the signing keychain, p12 and ASC key are removed.release.yml(onrelease: published) andtestflight.yml(nightly schedule) will use the Studio too when the variable is set; the TestFlight run is the highest-stakes one, so consider aworkflow_dispatchdry run first.Lint latency: with a single Studio runner instance, the two lint jobs queue behind multi-hour build/tests/testflight jobs, which defeats their quick-feedback purpose. Consider leaving lint on hosted (drop it from the toggle or give it its own variable).
Parallel runner instances: the keychain search list is per user; if more than one runner runs as
ghrunner, the iOS and tvOS testflight legs could race on it.TestFlight on Xcode 27: confirm
xcodebuild -versionon the Studio is a GA build, since App Store Connect rejects beta-toolchain builds for external TestFlight.Simulator devices are per user:
ghrunnerneeds an iPhone device in its own device set, or the picker intests.ymlfails with "No available iPhone simulator".Prerequisite: a runner labelled
self-hosted, macOS, ARM64, studiomust be registered for this repo (currently a repo-level runnerstudio-icubeis online) before the variable is set; otherwise jobs sit queued.Enable / disable
🤖 Generated with Claude Code
Note
Medium Risk
Toggling the Studio switches release/TestFlight builds to Xcode 27 and a shared persistent runner (signing material cleanup, simulator state, job queuing), while hosted behavior stays on 26.3; misconfiguration or parallel TestFlight matrix legs could affect CI reliability or App Store uploads.
Overview
Adds an optional
MACOS_RUNNER_LABELSrepo variable so macOS jobs inbuild,release,testflight,tests, andlintcan run on the Mac Studio instead of GitHub-hostedmacos-26/macos-latest. Fork PRs always stay on hosted runners so untrusted code never executes on the persistent machine.Self-hosted path: a pre-checkout step sets
DEVELOPER_DIRfromXCODE_PATH(default/Applications/Xcode.app, Xcode 27) because the job-level path targets hosted-onlyXcode_26.3.app.maxim-lobanov/setup-xcoderuns only ongithub-hosted(still pinned to 26.3). Workflow-wideHOMEBREW_NO_AUTO_UPDATE/HOMEBREW_NO_INSTALL_CLEANUPandcommand -v … || brew installavoid disturbing the Studio’s shared Homebrew.Hygiene on the Studio: TestFlight logs and failure artifacts use
$RUNNER_TEMP; signing keychain cleanup also removes p12, ASC keys, archives, and export dirs. Unit tests relocate ccache outside the workspace (checkout would wipe it), skipactions/cachefor ccache on self-hosted, and shut down the booted simulator after the job.Reviewed by Cursor Bugbot for commit 12463bd. Configure here.