По объявлению GitHub от 26 февраля 2026 года, macOS 26 уже доступна для GitHub-hosted runners. Это означает, что миграцию GitHub Actions на macOS 26 нельзя выполнять простой заменой macos-15 на macos-latest: сначала зафиксируйте явный тег, параллельно проверьте Xcode, архитектуру, зависимости, подпись и кэш, а затем принимайте решение о переключении.
Симптом → быстрый способ исправления
YAML не менялся, но сборка начала падать после обновления образа: проверьте фактические ОС, архитектуру, версию образа и Xcode в логе, а не только значение macos-latest.
Релизная цепочка зависит от фиксированного инструментария, ключей подписи или длительного кэша: оставьте стабильный тег и рассмотрите отдельный удалённый Mac с self-hosted Runner.
Эта статья предназначена разработчикам мобильных приложений, которые всё ещё используют macos-latest, и CI-инженерам, обслуживающим CocoaPods, SwiftPM, Node.js, Ruby или нативные бинарные зависимости. Она также пригодится руководителям платформенных команд, выбирающим между GitHub-hosted Runner и постоянно доступным Mac-узлом.
Быстрый аудит фактического Runner
Что означает macos-latest сейчас
macos-latest — это подвижный указатель, а не обещание конкретной версии macOS. GitHub сообщил о доступности macOS 26 для размещённых Runner, а план перехода тега macos-latest на эту систему охватывал период с 15 июня по 15 июля 2026 года — эти даты следует рассматривать в контексте официального объявления и проверять по текущей документации, поскольку отображение тегов может измениться.
Для миграции GitHub Actions на macOS 26 начните с минимального диагностического задания:
name: runner-audit
on:
workflow_dispatch:
jobs:
audit:
runs-on: macos-15
steps:
- name: System and toolchain
run: |
set -euxo pipefail
sw_vers
uname -m
xcode-select -p
xcodebuild -version
xcrun --sdk macosx --show-sdk-path
node --version || true
ruby --version || true
python3 --version || true
brew --version || true
clang --version
openssl version || true
После запуска сохраните полный лог. Сверьте его с официальным описанием меток GitHub-hosted Runner и актуальным репозиторием образов actions/runner-images. Важно зафиксировать не только sw_vers, но и uname -m, путь xcode-select, версию Xcode и фактические пути исполняемых файлов.
| Что проверить | Где искать доказательство | Почему это важно |
|---|---|---|
| Метка задания | runs-on в YAML |
Показывает намерение, но не всегда объясняет фактически выбранный образ |
| ОС и версия образа | sw_vers, системные переменные и лог Runner |
Позволяет отличить macOS 26 от старой среды |
| Архитектура | uname -m |
arm64 и x86_64 могут использовать разные бинарные зависимости |
| Xcode и SDK | xcodebuild -version, xcrun |
Компиляция может зависеть от версии SDK и выбранного пути |
| Среда выполнения | версии и пути Node.js, Ruby, Python, Homebrew | Версия пакета без пути не объясняет подмену инструмента |
Если проект ещё использует macos-latest, не делайте вывод о системе по имени метки. Сначала добавьте аудит в отдельную ветку или диагностическое задание. Для публикации и подписания используйте явный тег, пока параллельная проверка не покажет совпадение артефактов.
Xcode, SDK и тестовые цели
Почему сборка ломается после обновления
Наиболее заметный симптом — ошибка компиляции, недоступный SDK, отсутствие нужного симулятора или тесты, которые выбирают другую платформу. Причина может находиться не в самой macOS 26, а в том, что Runner получил другой Xcode, другой SDK или иной набор симуляторов.
Проверяйте четыре значения до и после перехода:
- результат
xcode-select -p; - вывод
xcodebuild -version; - SDK, возвращаемый
xcrun --sdk iphonesimulator --show-sdk-path; - список доступных назначений через
xcodebuild -showsdksиxcrun simctl list.
Требования Apple к сочетаниям Xcode и macOS меняются вместе с выпусками, поэтому сверяйте рабочую матрицу с официальной таблицей системных требований Xcode. Не смешивайте стабильный Xcode с отдельными сведениями о будущих или тестовых версиях: если инструмент ещё не объявлен стабильным, он не должен быть единственной опорой для production Job.
Признак скрытой зависимости — workflow не выбирает Xcode явно, а сборка «случайно» проходит на образе с подходящей версией. Исправьте это одним из двух способов:
- для воспроизводимого задания задайте требуемую версию Xcode средствами, которые поддерживает текущий Runner, и проверьте путь перед сборкой;
- если нужное сочетание недоступно на размещённом образе, перенесите job на заранее подготовленный self-hosted узел.
Для iOS-проектов отдельно создайте матрицу как минимум по системе Runner, Xcode, SDK и цели тестирования. В таблице должна быть не только строка «сборка успешна», но и результат тестов на нужной версии симулятора или физического устройства. Успешная компиляция не доказывает, что приложение корректно работает на всех заявленных целях.
Нужно ли переносить macOS 15 на macOS 26
Если workflow выполняет только статические проверки или тесты без привязки к конкретному SDK, переход можно проводить после аудита и параллельного прогона. Если он создаёт архив, подписывает приложение, публикует пакет или зависит от конкретного симулятора, сначала зафиксируйте текущую рабочую среду и только потом добавляйте macOS 26 в отдельную ветку проверки.
| Тип задания | Действие при переходе | Условие допуска |
|---|---|---|
| Линтеры и независимые unit-тесты | Проверить на явном теге macOS 26 | Результат и отчёты совпадают с базовой веткой |
| Сборка iOS/macOS | Запустить параллельно со старым окружением | Совпадают SDK, тестовые цели и ключевые артефакты |
| Архивирование и публикация | Не менять production Job сразу | Есть проверенная подпись, архив и план отката |
| Редкие нативные зависимости | Сначала исследовать архитектуру и бинарные файлы | Все расширения и инструменты запускаются в целевой архитектуре |
Apple Silicon и нативные зависимости
Архитектурный разрыв
Переезд на Apple Silicon нельзя сводить к проверке успешной компиляции. В цепочке могут участвовать предварительно собранные утилиты, Ruby-gem с нативным расширением, CocoaPods-плагины, бинарные SDK и скрипты, которые принимают решения по значению uname -m.
Разделите диагностику на четыре класса:
- предварительно собранные бинарные файлы — проверьте
file путь/к/файлуи, если это универсальный Mach-O,lipo -info путь/к/файлу; - нативные расширения — найдите этап компиляции и убедитесь, что зависимость собирается для той же архитектуры, что и приложение;
- скрипты с проверкой архитектуры — ищите условия по
arm64,x86_64,unameи переменным окружения; - межархитектурные артефакты — не передавайте результат сборки одной архитектуры в job, которая ожидает другую, без явной проверки.
В логе должны присутствовать команды проверки, а не только финальная ошибка. Документация GitHub по Runner отдельно описывает архитектурные варианты self-hosted окружений; для размещённых Runner сведения о доступных образах и архитектурах сверяйте с README конкретного образа, например macOS 26.
Критерий прохождения строгий: тест должен выполняться на реальной архитектуре, для которой вы заявляете поддержку. Сборка arm64, завершившаяся без ошибок, не подтверждает запуск Intel-версии, а успешная работа через слой совместимости не доказывает отсутствие проблем с производительностью или нативными расширениями.
Runtime, пакеты и системные библиотеки
Ошибки после обновления часто выглядят как проблема macOS, хотя фактическим источником оказывается незакреплённая версия Node.js, Ruby, Python, Homebrew, Clang или OpenSSL. Особенно опасен случай, когда workflow вызывает команду по имени, а PATH уже указывает на другой исполняемый файл.
Перед установкой зависимостей выведите версии и расположение:
which node ruby python3 brew clang openssl || true
node --version || true
ruby --version || true
python3 --version || true
brew --prefix || true
clang --version
openssl version || true
Затем выберите причину по минимальному воспроизведению:
- запустите только диагностику Runner;
- установите зависимости без сборки приложения;
- выполните минимальную компиляцию;
- добавьте тесты;
- отдельно запустите архивирование и подпись.
Если ломается уже второй шаг, ищите несовместимость пакетного менеджера или lock-файла. Если зависимость устанавливается, но падает нативная компиляция, проверяйте архитектуру и Clang. Если минимальный пример работает, а полный проект нет, анализируйте Action, собственные скрипты и порядок шагов. Не приписывайте любой красный job обновлению macOS 26 без такой последовательности.
Для кэша зафиксируйте ключи по ОС, архитектуре, версии инструмента и lock-файлу. Документация GitHub по кэшированию зависимостей объясняет базовую механику cache action, но не гарантирует, что старый кэш безопасно использовать после смены архитектуры или SDK. На миграции полезно один раз выполнить холодную сборку с новым ключом, затем отдельный прогон с восстановлением кэша. Если результат меняется только при включённом кэше, проблема находится в состоянии кэша, а не обязательно в Runner.
Подпись, секреты и повторный запуск
Публикационный job требует более строгой проверки, чем обычный тест. Сравните идентичность сертификата, профиль provisioning, настройки keychain и команды импорта секретов. Проверяйте подпись созданного приложения командой codesign --verify --deep --strict, а сведения о профиле и сертификате сохраняйте в артефакт диагностики без приватных ключей и секретных значений.
Не переносите старый кэш в новую архитектуру без проверки. Не храните signing identity в открытом логе. Не делайте первый переход на macOS 26 одновременно с изменением схемы подписи, Action и набора зависимостей — иначе при сбое вы не сможете установить причинный фактор.
Минимальный критерий допуска для release job:
- два независимых успешных прогона после холодного старта;
- повторный запуск с восстановлением кэша;
- проверка подписи и профиля;
- сопоставление идентификаторов и контрольных сумм ожидаемого артефакта;
- успешный прогон старого задания после возврата на прежний тег.
Условия выбора: hosted Runner или удалённый Mac
Ниже — решение не по принципу «новее всегда лучше», а по степени контроля, которую требует ваш pipeline.
- Если job не хранит состояние между запусками, не использует фиксированную подпись и допускает проверку на свежем образе, выберите GitHub-hosted Runner с явным тегом macOS 26 после параллельной валидации.
- Если публикация зависит от конкретного Xcode, SDK или набора симуляторов, оставьте production job на зафиксированной системе, а macOS 26 проверяйте отдельно. Возвращайтесь к миграции только после совпадения артефактов и тестов.
- Если проблема вызвана только устаревшим кэшем, создайте новый ключ по версии ОС, архитектуре и lock-файлу; переход на self-hosted Mac в этом случае не является лечением.
- Если проект использует бинарную зависимость только для Intel или только для Apple Silicon, сначала исправьте поставку артефактов либо ограничьте job правильной архитектурой.
- Если нужны постоянное состояние, фиксированные ключи подписи, предсказуемый Xcode и длительно подготовленная среда, добавьте отдельный удалённый Mac с self-hosted Runner.
- Если команда не готова обновлять Runner и контролировать доступ к репозиториям, не переносите release pipeline на self-hosted узел только ради стабильности.
Для self-hosted сценария нужны изоляция прав, отдельная учётная запись, ограничение доступа к приватным репозиториям, регулярное обновление Runner и процедура удаления узла из организации. Инструкция GitHub по регистрации self-hosted Runner прямо связывает такой режим с безопасностью: узел получает задания и секреты, поэтому его нельзя размещать в незащищённой общей среде.
Если вам нужно заранее подготовить конкретную версию Xcode, полезно изучить методы фиксации Xcode на удалённом Mac. Для команды, которая передаёт узлу ключи подписи и доступ к исходному коду, также стоит сверить внутренние правила с рекомендациями по конфиденциальности SSHMac.
План миграции без остановки релизов
- Снимите базовую конфигурацию. Сохраните YAML, фактические значения
sw_vers,uname -m, Xcode, SDK, runtime, пути инструментов и идентификаторы важных артефактов. - Уберите неопределённость
macos-latest. Для production укажите явную версию системы.latestоставьте только там, где команда действительно готова регулярно проверять изменения образа. - Создайте параллельный job. Он должен запускать ту же сборку на macOS 26, но не публиковать результат и не менять production-секреты.
- Разделите диагностику зависимостей. Отдельно проверьте пакетный менеджер, нативные расширения, предварительно собранные бинарные файлы и системные библиотеки.
- Соберите матрицу Xcode и целей. Включите нужные SDK, симуляторы и архитектуры; не ограничивайтесь одним успешным
xcodebuild. - Проверьте кэш с холодного старта. Новый ключ должен учитывать систему, архитектуру, инструмент и lock-файл; затем повторите запуск с восстановлением кэша.
- Проведите безопасную проверку подписи. Импортируйте секреты в изолированный keychain, выполните архивирование, проверку
codesignи контроль профиля. - Отработайте откат. Верните старый тег в отдельной ветке и убедитесь, что прежняя цепочка снова создаёт проверяемый артефакт.
- Только после этого измените release job. Зафиксируйте дату, выбранный тег, версию Xcode, условия кэша и ответственного за последующий пересмотр.
Текущую карту образов проверяйте в день публикации: GitHub может изменить связь macos-latest с системой, состав предустановленных инструментов, доступные архитектуры или срок поддержки. Для каждого изменения повторяйте короткое диагностическое задание и сохраняйте лог рядом с результатом сборки.
Для длительных задач важна не только возможность подключить Mac, но и операционная модель: кто обновляет узел, как изолируются секреты и как подтверждается доступ Runner к репозиторию. Если вы рассматриваете аренду Mac для такой схемы, сравните варианты аренды Mac mini для CI/CD с требованиями конкретного pipeline, а не только с ценой.
Напоминание. Постоянный self-hosted узел не отменяет миграционную дисциплину: обновление macOS, Xcode или Runner на нём также нужно проводить через тестовый контур, журнал изменений и заранее проверенный откат.
Текущий размещённый Runner удобен тем, что каждая job получает чистое окружение и не требует обслуживания железа, но за это вы платите зависимостью от движения образов, ограниченным контролем над кэшем и необходимостью повторять установку инструментов. Для release-процесса добавляются ещё два недостатка: сложнее удерживать строгое сочетание Xcode и SDK, а состояние подписи и подготовленные зависимости нельзя бездумно сохранять между запусками. Если вашему проекту нужны фиксированный Xcode, постоянная среда и управляемый signing keychain, выделенный удалённый Mac SSHMac может оказаться более предсказуемым каналом сборки; если же задачи одноразовые и полностью воспроизводимы с нуля, продолжайте использовать hosted Runner, предварительно закрепив тег и проверив миграцию.