GitHub Actions makes it easier to automate builds, tests, and deployments for iOS and macOS applications. However, these workflows depend on the runner environment provided by GitHub. When GitHub retires an operating system image, workflows using that image must be updated.
This is particularly important for Apple-platform developers because their builds often depend on specific versions of macOS, Xcode, Swift, and iOS simulators.
Updating the runner label is straightforward, but checking compatibility is equally important. A new runner may have a different processor architecture, Xcode version, or set of installed tools.
Let's look at how to identify affected workflows and migrate them safely.
Understanding the macOS Runner Retirement
A GitHub-hosted runner is a virtual machine that executes the jobs defined in a GitHub Actions workflow.
For macOS projects, the runner includes development tools such as:
- Xcode and Swift.
- Apple command-line tools.
- iOS simulator runtimes.
- Git and other common utilities.
- Tools used for building and testing Apple applications.
GitHub regularly updates its runner images to provide newer operating systems and development tools. Older images eventually reach the end of their supported lifecycle.
The macOS 14 retirement affects these runner labels:
| Retired runner label |
Purpose |
| macos-14 |
Standard macOS runner |
| macos-14-large |
Large Intel macOS runner |
| macos-14-xlarge |
Extra-large macOS runner |
If your workflow still uses one of these labels, it needs to be updated.
Finding Workflows That Use macOS 14
Before making changes, identify every workflow that references the retired runner.
A typical GitHub Actions workflow might look like this:
name: iOS Build
on:
push:
branches:
- main
jobs:
build:
runs-on: macos-14
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Build application
run: swift build
The runs-on property specifies which runner GitHub should use.
In this example, GitHub attempts to start a macOS 14 runner. Since that image has been retired, the workflow needs a supported replacement.
You can search your repository for affected labels using:
grep -RInE 'macos-14(-large|-xlarge)?' .github/workflows
This command searches the workflow directory and displays matching file names and line numbers.
If your organization maintains multiple repositories, check each repository. Also inspect reusable workflows because the runner label may be defined in a shared workflow rather than the main application repository.
Choosing a Replacement Runner
GitHub provides newer macOS runner images, including macOS 15 and macOS 26.
The correct replacement depends on your project's requirements.
| Runner label |
Operating system |
Architecture |
| macos-15 |
macOS 15 |
Apple Silicon |
| macos-15-large |
macOS 15 |
Intel |
| macos-15-intel |
macOS 15 |
Intel |
| macos-26 |
macOS 26 |
Apple Silicon |
| macos-26-large |
macOS 26 |
Intel |
| macos-26-intel |
macOS 26 |
Intel |
The available runner sizes and labels should be checked against GitHub's current runner documentation before updating your workflow.
There are three important things to consider.
Check processor architecture
Apple Silicon runners use the ARM64 architecture, while Intel runners use x64.
Most modern Swift projects can work with Apple Silicon, but older projects may depend on Intel-specific binaries or libraries.
For example, a third-party framework might contain only Intel architecture binaries. Moving directly to an ARM64 runner could cause linking or build errors.
You can check the architecture of the runner using:
uname -m
The command returns arm64 for Apple Silicon and x86_64 for Intel.
Check the Xcode version
Your application may require a particular Xcode version.
A newer macOS runner does not necessarily provide the exact Xcode version used by your previous environment.
Check the installed version with:
xcodebuild -version
Also verify that the required iOS simulator runtime is available.
Check third-party dependencies
Review the dependencies used by your application before migrating.
Pay attention to:
- CocoaPods dependencies.
- Swift Package Manager packages.
- Carthage frameworks.
- Binary frameworks.
- Custom build scripts.
- Tools installed through Homebrew.
Some dependencies may require updates to support a newer operating system or processor architecture.
Updating the GitHub Actions Workflow
After selecting a replacement runner, update the runs-on property.
For example, if your application supports macOS 26 and Apple Silicon, the updated workflow could look like this:
name: iOS Build
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: macos-26
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Check environment
run: |
sw_vers
uname -m
xcodebuild -version
swift --version
- name: Build application
run: swift build
- name: Run tests
run: swift test
The main change is:
runs-on: macos-26
The additional commands display the operating system, processor architecture, Xcode version, and Swift version.
If your project still requires macOS 15, you can use:
runs-on: macos-15
For a project that requires an Intel environment, use an appropriate Intel runner label:
runs-on: macos-26-intel
The example uses Swift Package Manager. If you are working with an Xcode application project, use the appropriate xcodebuild commands for your project scheme and simulator destination.
Testing the Updated Workflow
Changing the runner label is only the first part of the migration. You should run the complete build and test process before merging the changes.
Verify the runner environment
Add a step to display the environment information:
- name: Verify environment
run: |
sw_vers
uname -m
xcodebuild -version
swift --version
This helps identify unexpected differences between runner images.
Check available simulators
iOS applications often depend on simulator versions for automated testing.
Use the following command to list available simulators:
xcrun simctl list devices available
If your workflow uses a specific simulator, confirm that the device and runtime are installed.
For example:
xcodebuild test \
-scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 17'
The simulator name is only an example. Use a destination available on the selected runner.
Build and test the application
Run the same commands used in your existing CI pipeline.
For an Xcode project, this might include:
xcodebuild build \
-scheme MyApp \
-destination 'generic/platform=iOS'
You should also run unit tests and any UI tests included in your project.
Check the generated build artifacts before considering the migration complete.
Supporting Intel and Apple Silicon With a Build Matrix
Some teams maintain libraries or applications that need to work on both Intel and Apple Silicon environments.
GitHub Actions provides a matrix strategy for running the same workflow on multiple runners.
name: Cross Architecture Build
on:
push:
branches:
- main
jobs:
build:
strategy:
matrix:
runner:
- macos-26
- macos-26-intel
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Check architecture
run: uname -m
- name: Build
run: swift build
- name: Test
run: swift test
GitHub creates a separate job for each runner in the matrix.
This approach is useful when developing SDKs, reusable frameworks, or applications that support multiple processor architectures.
However, it is not necessary for every project. Running multiple jobs increases build time and can increase GitHub Actions usage. Use a matrix when testing across architectures is part of your application requirements.
Common Migration Problems
A runner migration can expose issues that were not visible in the previous environment.
| Problem |
What to check |
| Build fails after migration |
Check Xcode and Swift versions |
| Framework cannot be linked |
Verify supported processor architectures |
| Simulator tests fail |
Check installed simulator runtimes |
| Build script cannot find a tool |
Verify tool installation and paths |
| Dependency installation fails |
Check package compatibility |
| Workflow starts but tests fail |
Review the complete build and test logs |
One mistake is replacing a specific runner label with macos-latest without testing the application.
The macos-latest label points to the latest supported macOS image. Its underlying environment can change as GitHub updates its runner images.
For predictable builds, use a specific supported macOS label when your project depends on a known environment.
Best Practices for Future Runner Updates
Runner retirement should be part of regular CI/CD maintenance.
A few practices can make future migrations easier:
- Keep a list of runner labels used across your repositories.
- Review GitHub Actions runner image announcements.
- Test new runner images before changing production workflows.
- Record the macOS, Xcode, Swift, and architecture versions used by important builds.
- Document tools that your build scripts require.
- Keep dependencies updated.
- Avoid relying on undocumented tools installed on hosted runners.
- Update shared reusable workflows when changing runner configurations.
These practices help development teams identify upcoming changes before they affect application builds.
Summary
GitHub's macOS 14 runner retirement affects workflows that use macos-14, macos-14-large, and macos-14-xlarge.
To migrate, first search your repositories for the retired labels. Then select a supported replacement based on your Xcode requirements, processor architecture, simulator availability, and third-party dependencies.
Update the runs-on property and test the complete build and test process. For projects supporting both Intel and Apple Silicon, consider using a GitHub Actions matrix.
Keeping runner configurations documented and reviewing GitHub's runner image announcements can help prevent unexpected CI/CD failures during future migrations.
Join the conversation! Your thoughts help the community grow.