Does GitHub Actions Support Apple Silicon Runners?
Yes. GitHub Actions macOS runners are ARM64 on Apple Silicon. A label such as warp-macos-15-arm64-6x gives 6 vCPU and 22GB of memory at $0.08 a minute.
Last verified:
Yes. Every macOS runner in the WarpBuild catalog is Apple Silicon hardware on ARM64, and a job moves onto one by changing runs-on to a label such as warp-macos-15-arm64-6x, which provisions 6 vCPU with 22GB of memory and a 120GB SSD at $0.08 per minute. The larger configuration, warp-macos-15-arm64-12x, provisions 12 vCPU with 44GB of memory and a 270GB SSD at $0.16 per minute (WarpBuild cloud runners, checked on 2026-08-13).
This page covers what Apple Silicon means once a GitHub Actions job is running on it: the sizes and rates in the catalog, what changes inside the job when the machine is ARM64, the three limits worth planning around, and the list-price arithmetic against GitHub's published macOS rate.
Answer
There are three ways to put a GitHub Actions job on Apple Silicon, and all three are native ARM64 execution.
GitHub-hosted macOS runners. GitHub publishes macos-latest and versioned labels such as macos-15, plus larger macOS runners on paid plans. The per-minute rates are in the GitHub Actions billing reference and on the GitHub pricing page.
Self-hosted Macs. The runner agent ships a macOS ARM64 release on github.com/actions/runner, so a Mac you own registers against a repository or organization and advertises labels. You own the hardware, the Xcode installs, the disk cleanup, and the state left behind between jobs.
Managed macOS runners. A provider registers ephemeral macOS virtual machines against your GitHub organization and you select them by label. WarpBuild runs this shape. The macOS line is ARM64 only.
The catalog carries multiple sizes and configurations per chip. On macOS there are two, and they scale memory and disk with the core count rather than holding either fixed. Every figure comes from the cloud runners documentation, checked on 2026-08-13.
| Configuration | vCPU | Memory | Storage | Per minute | Per vCPU-minute | Labels carrying it |
|---|---|---|---|---|---|---|
| 6x | 6 | 22GB | 120GB SSD | $0.08 | $0.0133 | warp-macos-26-arm64-6x, warp-macos-15-arm64-6x, warp-macos-14-arm64-6x |
| 12x | 12 | 44GB | 270GB SSD | $0.16 | $0.0133 | warp-macos-26-arm64-12x, warp-macos-15-arm64-12x |
Five labels cover three images: macOS 26, macOS 15, and macOS 14. The label grammar is warp-macos-<os version>-arm64-<size>x, so the architecture segment reads arm64 on every macOS label in the catalog. warp-macos-latest-arm64-6x and warp-macos-latest-arm64-12x are aliases that resolve to the macOS 15 image, in sync with GitHub's own macos-latest tag, so a job that must stay on one image names the versioned label instead of the alias. The full per-label list is on the macOS runner catalog.
A workflow that builds a Swift binary for both architectures looks like this. The build runs natively on ARM64 and cross-compiles the x86_64 slice from the same machine:
name: macos-universal-build
on:
pull_request:
push:
branches: [main]
jobs:
build:
runs-on: warp-macos-26-arm64-12x
steps:
- uses: actions/checkout@v4
- name: Record the machine
run: |
uname -m
arch
sysctl -n hw.ncpu
sw_vers -productVersion
- name: List the Xcode versions on this image
run: |
ls -1 /Applications | grep '^Xcode'
xcodebuild -version
- name: Resolve Swift package dependencies
run: swift package resolve
- name: Build a universal binary
run: swift build -c release --arch arm64 --arch x86_64
- name: Confirm both slices are present
run: lipo -archs .build/apple/Products/Release/mytool
- uses: actions/upload-artifact@v4
with:
name: mytool-universal
path: .build/apple/Products/Release/mytoolKeep the Xcode listing step in the log while you are moving labels around. It prints the exact application paths on the image, which is what you pin DEVELOPER_DIR to when a project needs one specific Xcode rather than the image default.
Detail
What changes inside a job when the machine is Apple Silicon
An Apple Silicon runner runs an arm64 kernel and an arm64 userspace, so the compiler emits arm64 instructions, the linker resolves arm64 objects, and the simulator runtimes are arm64 images. Nothing is translated on the way through. Five values are worth printing on your first run, because they are the ones a migrated workflow tends to assume:
| Command | Value on an Apple Silicon runner |
|---|---|
uname -m | arm64 |
arch | arm64 |
sysctl -n hw.ncpu | 6 on a 6x label, 12 on a 12x label |
swift -print-target-info | a triple beginning arm64-apple-macosx |
| Homebrew prefix | /opt/homebrew |
The Homebrew prefix is the most common source of a broken step. Scripts written against Intel Macs hardcode /usr/local/bin/... for tools installed by Homebrew, while the Apple Silicon prefix is /opt/homebrew (Homebrew installation docs). Call the tool by name and let PATH resolve it, or read the prefix with brew --prefix instead of writing the path in.
The second source is a downloaded binary. Any step that fetches a release asset, a linter, or a code-signing helper by URL needs the arm64 or universal asset rather than the x86_64 one. The failure shows up as a bad CPU type error rather than as a missing file, so it is easy to misread as a permissions problem.
Cross-compilation runs in the other direction from what teams expect. Producing an x86_64 slice on an Apple Silicon runner is a build flag, as in the swift build --arch arm64 --arch x86_64 step above, or ARCHS="arm64 x86_64" for xcodebuild. Verify the result with lipo -archs in the same job so a single-slice binary never reaches a release.
The tooling on each image is the set published by GitHub for the matching upstream image, so an existing Xcode workflow works as a drop-in target. Package lists are per image: macOS 14 ARM64, macOS 15 ARM64, and macOS 26 ARM64. The macOS 26 labels also ship Xcode 27.0 (build 27A5194q) with the iOS, tvOS, watchOS, and visionOS 27.0 simulator runtimes, an addition on top of the upstream GitHub macOS 26 image while GitHub's upstream macOS 27 runner image is in beta. A dedicated macOS 27 image follows once that image is released. The per-image matrix is on the Xcode image reference.
Tailscale is preinstalled on every runner image, including macOS, and the daemon starts on demand when networking is configured for the runner (preinstalled software documentation).
Choosing between the two configurations
Both configurations bill at $0.0133 per vCPU-minute, so the question is whether the job can use twelve cores and whether it needs the disk.
Xcode work parallelizes unevenly. Compiling a large module graph and running a test plan split across several simulators both spread across cores, while a single simulator boot, a code-signing step, and an archive upload do not. A job dominated by the serial steps spends the same wall clock on 12x as on 6x and bills twice as much for it, so measure the step timings before you resize.
Disk is the specification that decides more macOS failures than cores. Derived data, a resolved Swift package checkout, several simulator runtimes, and an archive of a large app add up quickly against the 120GB SSD on the 6x configuration. The 12x configuration takes that to 270GB. If a workflow currently spends steps deleting simulator runtimes or clearing derived data to stay under a ceiling, the 12x size removes the reason for those steps and the deleted minutes come back off the bill.
Runner storage is ephemeral in both cases and is deleted when the runner terminates, so .xcresult bundles, crash logs, and build products go to an artifact before the job ends.
Three limits to plan around
No Docker. macOS runners do not support nested virtualization and cannot run Docker (cloud runners documentation). A pipeline that builds an iOS app and then packages a container image needs two jobs on two platforms.
The container half moves elsewhere. Container builds go to a Linux runner or to a remote Docker builder while the macOS job keeps Xcode, Swift, and the simulators.
Concurrency is quota governed. Since July 27, 2026, concurrency on the macOS fleet is governed by per-organization quotas, and jobs beyond the quota wait for capacity to free up (July 2026 changelog). Size a wide macOS matrix against the quota your organization holds, and contact support to raise it rather than assuming the Linux and Windows behavior carries over.
What an Apple Silicon minute costs
Both sides below are list prices. The WarpBuild rate comes from the cloud runners documentation. The GitHub rate comes from the GitHub Actions billing reference and the GitHub pricing page, checked on 2026-08-13.
| Label | Shape | Per minute | Per vCPU-minute | GitHub-hosted comparison | GitHub per minute | GitHub per vCPU-minute |
|---|---|---|---|---|---|---|
warp-macos-latest-arm64-6x | 6 vCPU, 22GB | $0.08 | $0.0133 | Largest GitHub-hosted macOS ARM64 runner, 5 vCPU with 14GB | $0.102 | $0.0204 |
warp-macos-latest-arm64-12x | 12 vCPU, 44GB | $0.16 | $0.0133 | No shape match at 12 vCPU | not compared | not compared |
warp-macos-latest-arm64-6x at 6 vCPU and 22GB costs $0.08 per minute against $0.102 per minute for the largest GitHub-hosted macOS ARM64 runner at 5 vCPU and 14GB: 22 percent lower list price, with one more vCPU and 8GB more memory on the WarpBuild side. GitHub list price checked on 2026-08-13.
Worked model: one iOS repository. The repository queues 1,500 macOS jobs a month at 9 minutes each on a 6 vCPU runner. That is 13,500 macOS minutes.
warp-macos-latest-arm64-6xat $0.08 per minute: 13,500 x $0.08 = $1,080.00 per month.- Largest GitHub-hosted macOS ARM64 runner at $0.102 per minute: 13,500 x $0.102 = $1,377.00 per month.
- Difference: $297.00 per month, $3,564.00 over twelve months, which is 22 percent lower list price (GitHub pricing, checked on 2026-08-13).
- The $10 in signup credits covers the first $10 of that bill, so month one lands at $1,070.00 out of pocket at this volume.
Every cost statement on this page carries a number, a source link, and a checked-on date, and the same numbers appear on the macOS runner cost guide, where you can run the model against your own job count and minute length.
Related Questions
Are GitHub Actions macOS runners ARM64 or x86-64?
ARM64. Every macOS label in the WarpBuild catalog carries the arm64 architecture segment and runs on Apple Silicon, so uname -m prints arm64 and the toolchain produces arm64 slices without emulation. The label list is on the macOS runner catalog.
What sizes do Apple Silicon runners come in?
Two configurations. 6 vCPU with 22GB of memory and a 120GB SSD at $0.08 per minute, and 12 vCPU with 44GB of memory and a 270GB SSD at $0.16 per minute. Both work out to $0.0133 per vCPU-minute, so the choice is about cores and disk rather than about rate efficiency.
Can an Apple Silicon runner run Docker?
No. macOS runners do not support nested virtualization and cannot run Docker. Container builds move to Linux runners or to remote Docker builders, and the macOS job keeps the Xcode, Swift, and simulator work. The macOS support answer covers the job split.
How many Apple Silicon jobs can run at once?
Concurrency on the macOS fleet is governed by per-organization quotas as of July 27, 2026. Jobs beyond the quota wait for capacity to free up, and support raises the quota on request (July 2026 changelog).
Pick a label from the macOS runner catalog, check the Xcode set for that image on the Xcode image reference, price the change on the pricing page, and change one runs-on line to move the job.
Start with $10 in free credits
Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.