Azure Pipelines: вывод macOS-14 из эксплуатации — выбор миграции в 2026

Azure Pipelines: вывод macOS-14 из эксплуатации — выбор миграции в 2026

Победитель — смешанный пул: стандартные PR-сборки следует перевести на поддерживаемый Microsoft-hosted образ, а фиксированный Xcode, приватные зависимости и production signing оставить на изолированных self-hosted Mac. Не следует одновременно менять vmImage, Xcode и цепочку подписи: сначала нужно провести двойной запуск одного коммита, затем закрывать macOS-14.

Эта статья предназначена для владельцев Azure Pipelines, которые должны завершить миграцию до удаления macOS-14. Она также полезна IT-руководителям, выбирающим между hosted Mac, self-hosted macOS agent и смешанным пулом, а также командам, отвечающим за Xcode, приватные зависимости, сертификаты и непрерывность релизов.

Последнее обновление: 20 сентября 2026 года. Даты brownout и удаления сверены с официальной документацией Microsoft; состояние образов проверяется по официальному репозиторию runner-images.

Почему миграция после вывода macOS-14 из Azure Pipelines требует разделения задач

По состоянию на 20 сентября 2026 года macOS-14 в Azure Pipelines находится в процессе вывода: Microsoft планирует brownout в октябре 2026 года, а окончательное удаление — 2 ноября 2026 года. Эти даты необходимо сверять с официальным планом отключения hosted-образов, поскольку изменение статуса образа влияет не только на запуск агента, но и на саму воспроизводимость сборки.

Brownout важен как ранний сигнал. Pipeline, который сегодня успешно проходит на macOS-14, может начать падать в отдельные периоды до окончательного удаления. Поэтому проверка «агент подключился» недостаточна. Нужно подтвердить весь маршрут: зависимости, компиляцию, тестирование, архивирование, экспорт и публикацию.

В существующем YAML сначала следует найти:

  • vmImage: macos-14;
  • явные версии Xcode и xcode-select;
  • требуемые Simulator Runtime;
  • плагины, CocoaPods, Swift Package Manager и закрытые бинарные зависимости;
  • задачи подписи, Keychain, provisioning profile и публикации;
  • переменные, связывающие pipeline с конкретным Agent Pool.

Затем активы фиксируются в реестре. Такой реестр должен принадлежать не одному разработчику, а владельцу сервиса.

Актив pipeline Что зафиксировать Признак блокировки
Образ агента Метка vmImage, источник образа, дата последней проверки Образ удаляется или меняет состав ПО
Инструменты Версия Xcode, SDK, Simulator Runtime, плагины Проект требует точной версии
Зависимости Приватные Git-репозитории, Artifactory-подобные хранилища, закрытые SDK Нет доступа из hosted-среды
Подпись Сертификаты, профили, Keychain, права pipeline Секрет нельзя размещать в общем пуле
Владелец Команда, ответственный инженер, резервный контакт Нет человека, принимающего решение о возврате

Такая инвентаризация отвечает на вопрос, что произойдёт с конвейером после удаления macOS-14. Часть задач получит ошибку выбора образа. Другая часть запустится, но изменит SDK или поведение симулятора. Третья может пройти сборку и остановиться на подписи.

Hosted-образ против self-hosted Mac: решение по типу workload

Не все задачи требуют одинакового уровня контроля. Стандартный PR без приватной сети имеет иной профиль риска, чем production signing с сертификатом распространения. Поэтому миграция после вывода macOS-14 из Azure Pipelines должна начинаться с маршрутизации задач, а не с выбора одной универсальной метки.

Сценарий Microsoft-hosted образ Self-hosted Mac Рекомендуемый маршрут
Компиляция PR без закрытых зависимостей Чистая среда, быстрый старт Избыточный контроль Поддерживаемый hosted-образ
Unit-тесты и статический анализ Подходит после проверки SDK Нужен при фиксированном окружении Сначала hosted, затем исключения
Старый Simulator Runtime Может отсутствовать Можно сохранить локально Короткий совместимый пул или self-hosted
Приватный Git и внутренний реестр Доступ зависит от сетевой схемы Можно ограничить маршрут Self-hosted в корпоративной сети
Production signing Нежелательно использовать общий контур Контроль Keychain и аккаунта Изолированный доверенный Mac
Релизный пик Возможны очереди и изменение доступности Контролируемая ёмкость Смешанный пул с резервом

Актуальный состав Microsoft-hosted образов и доступные метки следует сверять с официальным списком runner-images. Название macos-latest не является гарантией постоянной версии Xcode. Для воспроизводимой сборки лучше использовать конкретную поддерживаемую метку, пока проект проходит период миграции.

Что меняется при переходе на macOS-15 или macOS-26

Ответ на выбор между macOS-15 и macOS-26 нельзя строить только на принципе «новее — лучше». Сначала оценивается совместимость проекта:

  1. разрешаются все Swift Package Manager и CocoaPods-зависимости;
  2. проверяются предупреждения и ошибки компилятора;
  3. запускаются нужные Simulator Runtime;
  4. создаётся архив приложения;
  5. выполняется экспорт с тем же типом подписи;
  6. артефакт проходит публикацию в существующее хранилище.

macOS-15 и macOS-26 должны рассматриваться только в рамках актуального официального списка. Если конкретная метка ещё имеет preview-статус, это не является основанием для немедленного перевода production. Для каждой версии нужен заранее определённый rollback на предыдущий рабочий пул.

Критерий Консервативная миграция на macOS-15 Переход на macOS-26 Как принять решение
Изменение SDK Проверить проект и плагины Проверка обязательна Выбрать среду с меньшим числом несовместимостей
Simulator Runtime Сверить фактический набор Не считать наличие метки гарантией Проверить реальные тестовые схемы
Xcode Проверить установленную версию Проверить состояние образа Версия должна быть закреплена в отчёте
Откат Обычно проще при поэтапной миграции Нужен отдельный старый пул Не закрывать macOS-14 до контрольного прогона
Production Не переводить автоматически Не переводить автоматически Подпись валидируется отдельно

Первый этап: двойной запуск одного коммита

Главное доказательство миграции — не успешный запуск нового агента, а совпадение результатов на одном исходном состоянии. Для этого выбирается коммит, который уже прошёл production-подобный маршрут на macOS-14. Он запускается параллельно на новом hosted-образе и на целевом self-hosted Mac, если такой контур нужен.

Минимальная схема маршрутизации в YAML должна быть явной:

stages:
- stage: PullRequest
  jobs:
  - job: HostedValidation
    pool:
      vmImage: macos-15
    steps:
    - script: xcodebuild -version
      displayName: Проверка Xcode

- stage: Signing
  dependsOn: PullRequest
  jobs:
  - job: ProductionSigning
    pool:
      name: SecureMacPool
      demands:
      - macOS
      - SigningEnabled
    steps:
    - script: ./ci/sign-and-export.sh
      displayName: Подпись и экспорт

Ожидаемый вывод проверки должен сохраняться в артефактах:

Xcode 26.x
SDK: iPhoneOS...
Simulator Runtime: iOS ...
DEPENDENCIES=RESOLVED
BUILD=PASSED
TESTS=PASSED
ARCHIVE=PASSED
EXPORT=PASSED
SIGNING=PASSED

Конкретные версии в примере не следует воспринимать как утверждение о составе образа. Их нужно получать непосредственно во время запуска и сопоставлять с официальным README образа.

Сравнивать нужно как минимум:

  • предупреждения компилятора и ошибки линковки;
  • список разрешённых зависимостей;
  • число и типы тестов;
  • размер и содержимое архива;
  • результат codesign и экспорт IPA;
  • публикацию артефактов;
  • время ожидания в очереди;
  • возможность повторного запуска после сбоя.

Кэш нельзя считать доказательством эквивалентности. Hosted-job обычно создаёт чистую среду, а self-hosted Mac может сохранять DerivedData, SDK-кэш или локальные зависимости. При первом сравнении кэш следует отключить либо явно разделить результаты холодного и тёплого запуска.

Второй этап: фиксированный Xcode, Simulator Runtime и Apple Silicon

Задачи, связанные с историческим SDK, старым Simulator Runtime или плагином конкретного Xcode, нельзя безусловно отправлять на macos-latest. Такая метка может изменить набор инструментов независимо от намерений владельца pipeline.

Отдельная проверка требуется для Xcode 27. Образ Xcode 27 для Arm64 следует считать доступным только в том состоянии, которое указано в официальном описании Xcode 27 Arm64. Preview или новая метка полезны для совместимости, но не заменяют приёмку настоящего проекта.

Нужно различать три варианта:

  • Microsoft-hosted образ с опубликованным состоянием;
  • управляемый Apple Silicon Agent с заданным способом предоставления;
  • self-hosted Apple Silicon Mac с контролем окружения и перезапуска.

Для проекта, которому требуется Apple Silicon, проверяются не только архитектура процессора, но и нативность цепочки:

  • не запускаются ли критичные инструменты через неожиданный translation layer;
  • совместимы ли закрытые SDK и бинарные плагины;
  • создаётся ли архив в ожидаемой архитектуре;
  • проходят ли simulator-тесты;
  • сохраняются ли настройки подписи и публикации;
  • возможно ли быстро вернуть pipeline на предыдущий узел.

Новый образ следует принимать отдельным change record. В нём фиксируются версия образа, состояние Xcode 27, перечень тестов, ограничения preview и решение о допуске в production.

Третий этап: приватная сеть и production signing

Приватный Git, внутренний пакетный реестр и фиксированный исходящий IP радикально меняют выбор. Если hosted-агент не имеет разрешённого сетевого маршрута, задача будет падать до компиляции. Self-hosted Mac в этом случае нужен не ради производительности, а ради контролируемой сетевой границы.

Подпись требует ещё более строгого разделения. Общий агентный пул не должен одновременно обслуживать случайные PR и ключи production. В корпоративной схеме создаются как минимум:

  • общий пул для неконфиденциальных сборок;
  • совместимый пул для фиксированного Xcode;
  • доверенный пул для production signing;
  • резервный маршрут для релизного сбоя.

Self-hosted Agent работает с правами операционной системы и доступом к рабочему каталогу. Официальные рекомендации по жизненному циклу и безопасности агентов описаны в документации Microsoft об агентах. Дополнительные ограничения для macOS следует сверять с руководством по macOS Agent.

Минимальная проверка доступа:

  • Agent Pool доступен только нужным pipeline;
  • учётная запись запуска не имеет лишних административных прав;
  • сертификаты не размещены в общем рабочем каталоге;
  • Keychain открывается только в задаче подписи;
  • после Job удаляются временные профили и архивы;
  • логи не содержат секреты;
  • входящие соединения к Mac ограничены;
  • есть владелец ротации сертификатов;
  • отключён автоматический запуск непроверенных pipeline на signing-пуле.

Эти меры должны подтверждаться журналами доступа и тестом отрицательных прав. Простого заявления «узел изолирован» недостаточно. Общие рекомендации Microsoft по защите pipeline собраны в официальном обзоре безопасности.

Смешанный пул для пиков, отказов и возврата

Смешанная модель подходит компаниям, у которых обычный поток можно стандартизировать, но релизный контур требует постоянной среды. PR-задачи уходят на hosted-образ. Фиксированный Xcode и приватные зависимости — на self-hosted Mac. Подпись — на отдельный доверенный узел. Резерв используется только по понятному правилу, а не как общий бесконтрольный пул.

До закрытия macOS-14 следует оценить:

  • длину очереди для PR и релизов;
  • долю успешных запусков;
  • совпадение архивов и тестов;
  • восстановление после перезагрузки Mac;
  • время возврата на старую схему;
  • доступность резервного signing-узла;
  • права каждого pipeline;
  • суммарную стоимость владения, включая поддержку, простой и резерв.

Подробности о способах предоставления удалённых Mac и периодах аренды можно сопоставить на странице вариантов аренды Mac mini. Это не заменяет корпоративный PoC: перед закупкой следует проверить сетевой маршрут, доступ по SSH или VNC, reboot recovery, Agent Pool и работу Keychain именно в целевом проекте.

Итоговую модель удобно формализовать так:

Условие Решение Обязательный откат
PR не использует закрытую сеть и старый SDK Поддерживаемый hosted-образ Предыдущая метка до завершения сравнения
Нужен фиксированный Xcode или локальный Runtime Self-hosted Mac или короткий совместимый пул Сохранённый старый узел
Используются приватные зависимости Self-hosted в разрешённом сегменте Второй узел того же класса
Есть production signing Отдельный доверенный signing-пул Ручной или автоматизированный резерв
Нагрузка меняется по релизному календарю Смешанный пул Hosted для PR, выделенный Mac для релиза

Не следует закрывать macOS-14 только потому, что новый Job завершился со статусом Succeeded. Закрытие оправдано, когда одна и та же ревизия прошла полный маршрут, владельцы приняли расхождения, а возврат проверен заранее.

Частые вопросы перед отключением macOS-14

Что произойдёт с pipeline после удаления macOS-14?

Задачи с жёсткой ссылкой на удалённую метку перестанут планироваться или начнут попадать в периодические brownout. Задачи без явной привязки могут перейти на другой образ и получить изменённый Xcode, SDK или Simulator Runtime. Поэтому сначала проверяется YAML, затем выполняется полный двойной прогон, включая архивирование и подпись.

Как выбрать macOS-15 или macOS-26?

macOS-15 выбирается как более осторожный кандидат только после проверки текущего проекта и официального состава образа. macOS-26 имеет смысл тестировать, если проект готов к изменениям SDK и инструментов. Ни одна метка не должна попадать в production лишь из-за имени latest; решение принимается по результатам компиляции, тестов, архива и публикации.

Какие iOS-задачи переводятся на self-hosted Mac Agent?

Это задачи с приватным Git, внутренними пакетами, фиксированным исходящим адресом, локальным Simulator Runtime, особым Xcode или production-сертификатами. Обычный PR-поток без закрытых ресурсов не обязан использовать self-hosted Mac. Чем чувствительнее секрет и стабильнее требуемая среда, тем сильнее аргумент в пользу отдельного пула.

Как проверить Xcode и signing до brownout?

Нужно выполнить один и тот же коммит на macOS-14 и целевом контуре. Сравниваются разрешение зависимостей, компиляция, тесты, архив, экспорт и публикация. Подпись проверяется отдельно на доверенном узле. Все расхождения записываются вместе с версией образа, владельцем исправления и подтверждённым способом возврата.

Как объединить hosted и self-hosted Mac?

В YAML задаются разные pool для разных стадий. Hosted используется для массовой валидации, self-hosted — для фиксированного окружения и закрытых ресурсов, signing-пул — только для релизных задач. В Azure Pipelines нужно также ограничить права Agent Pool и запретить неподходящим pipeline использовать доверенный узел.

Решение перед закрытием старого пула

Для большинства компаний лучший маршрут — не «переключить всё на macOS-latest», а провести два PoC: одну реальную PR-сборку и один production-подобный релиз. Первая показывает, можно ли использовать поддерживаемый hosted-образ. Вторая выявляет проблемы Keychain, приватной сети, фиксированного Xcode и публикации.

У Microsoft-hosted варианта есть реальные ограничения: изменяемый состав образа, чистая среда каждого Job и зависимость от опубликованной доступности. У полностью self-hosted схемы другие недостатки: требуется постоянный контроль Mac, восстановление после сбоев, обновление инструментов и резервная ёмкость. Если добавить физические устройства, изолированные сертификаты и приватный маршрут, инфраструктура становится сложнее.

Для временного переходного контура или нерегулярных релизных пиков разумно рассмотреть выделенный удалённый Mac по циклу аренды. Такой вариант не отменяет проверку безопасности, но позволяет получить реальный Mac-хост без немедленной закупки нескольких физических машин. При выборе следует заранее согласовать период предоставления, регион, доступ, перезапуск, Agent Pool и процедуру удаления секретов. Если нужен именно такой PoC, условия можно изучить через страницу заказа удалённого Mac.

Финальное решение можно принимать только после прохождения трёх ворот: успешный двойной прогон, подтверждённая изоляция signing-задач и проверенный rollback. До этого macOS-14 следует оставить как временный резерв, а не как основной production-маршрут.