Bitbucket Pipelines macOS Runner: стандарт выхода в эксплуатацию для предприятий 2026

В официальной документации Atlassian указано, что шаги macOS Runner выполняются непосредственно на хосте через Bash, а не в изолированном контейнере — описание macOS Runner. Поэтому вывод простой: Bitbucket Pipelines macOS Runner допустим в производстве только как выделенный доверенный узел. Не запускайте на одном Mac непроверенный код, обычные тесты и задачи с производственной подписью. Сначала пройдите приёмку изоляции, маршрутизации, очистки, восстановления и нагрузки, затем увеличивайте объём задач поэтапно.

Эта статья предназначена для IT-руководителей, которые подключают Bitbucket Cloud к iOS CI/CD. Она также пригодится платформенной команде, принимающей самоуправляемые Mac-узлы, и техническому директору, сравнивающему собственные и удалённые мощности для сборки.

01 Критерий готовности: онлайн не означает безопасно

Зелёный статус Runner показывает доступность агента. Он не доказывает чистоту хоста, корректность прав или повторяемость сборки. Скрипт предыдущего задания может установить глобальный пакет, изменить настройки инструмента, оставить фоновый процесс или записать файл за пределами рабочей директории. Следующее задание получит тот же хост и может незаметно использовать это состояние.

Это особенно опасно для iOS CI/CD. Установка зависимостей, работа с Xcode, Keychain и архивами затрагивает не только каталог текущего репозитория. Если задача имеет права записи в домашний каталог или запускает команды от привилегированной учётной записи, обычная очистка checkout-каталога не является изоляцией.

Перед допуском узла зафиксируйте четыре доказательства:

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

В документации по регистрации Runner отдельно описывается подключение Runner к Bitbucket. Используйте эту процедуру как техническую регистрацию, но не как акт производственной приёмки.

Приёмочная проверка

  • [ ] Выполнено тестовое задание, которое создаёт файл вне рабочего каталога.
  • [ ] Проверено, может ли задание установить глобальный пакет или изменить системную настройку.
  • [ ] После завершения отсутствуют посторонние процессы и слушающие службы.
  • [ ] Удалены исходники, DerivedData, временные файлы и секретные логи.
  • [ ] Повторный запуск того же коммита не использует скрытое состояние предыдущего задания.
  • [ ] Для внешнего кода и релизной подписи определены разные пулы узлов.
  • [ ] Результат каждой проверки сохранён в журнале с указанием исполнителя и времени.

Если любой пункт не подтверждён, верните узел на доработку. Не компенсируйте отсутствие изоляции более длинным Bash-скриптом очистки: скрипт сам является частью доверенной поверхности и может завершиться до удаления всех побочных процессов.

02 Изоляция хоста измеряется остаточными изменениями

Главный вопрос для Mac-сборщика — не «удалился ли checkout», а «что может увидеть следующий процесс». Проверяйте состояние до и после задания. В область контроля входят:

  • рабочий каталог и каталоги выше него;
  • кэш Swift Package Manager, CocoaPods и других зависимостей;
  • DerivedData и архивы Xcode;
  • временный Keychain, профили и сертификаты;
  • переменные окружения;
  • фоновые процессы, launch agents и открытые порты;
  • журналы, дампы и файлы с параметрами доступа.

Разделяйте автоматическую очистку Bitbucket и действия вашей платформенной команды. Если платформа очищает рабочее пространство, это не означает автоматическое удаление глобальных пакетов, кэшей, процессов или пользовательских настроек macOS. Обе зоны должны быть перечислены в акте приёмки.

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

Важно: очистка — это контроль остаточного состояния, а не замена границе доверия. Для кода внешних участников и для публикации приложения используйте разные узлы даже при наличии автоматического удаления.

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

03 Область Runner и метки должны ограничивать маршрут

Repository Runner и Workspace Runner решают разные задачи. Первый привязан к репозиторию и уменьшает радиус случайного вызова. Второй может обслуживать репозитории рабочей области, поэтому удобен для общей инфраструктуры, но требует более строгого разделения пулов. Официальные настройки области Runner проверяйте в руководстве Atlassian по управлению Runner.

Метки в bitbucket-pipelines.yml должны описывать не только операционную систему. Укажите назначение узла и уровень доверия. Например:

runs-on:
  - self.hosted
  - macos
  - ios-test

Для производственной подписи используйте отдельную метку, связанную с отдельным пулом:

runs-on:
  - self.hosted
  - macos
  - ios-release

Синтаксис и правила сопоставления меток сверяйте с официальной документацией по runs-on. Не полагайтесь на название Runner в интерфейсе: именно набор меток определяет, куда будет направлена задача.

Проверки маршрутизации

  • [ ] Тестовая задача с правильными метками попадает в ожидаемый пул.
  • [ ] Ошибочная метка не отправляет задачу на узел с более высоким уровнем доступа.
  • [ ] Задача без подходящего Runner остаётся в очереди или завершается предсказуемо, а не запускается на другом пуле.
  • [ ] Занятый релизный узел не подменяется тестовым узлом.
  • [ ] Repository Runner не вызывается репозиторием, которому он не назначен.
  • [ ] Workspace Runner не получает задачи с неподходящим уровнем доверия.
  • [ ] В логах сохраняется связь между репозиторием, метками и фактическим узлом.

Проверьте сценарий переполнения. Оставьте узел занятым тестовым заданием и отправьте задачу подписи. Вы должны заранее знать, будет ли она ждать, завершится с ошибкой или попадёт в другой узел. Неприемлемо, чтобы запасной маршрут случайно предоставлял доступ к чужому Keychain.

04 Базовая среда Apple Silicon должна быть зафиксирована

Повторяемость зависит не только от коммита. Зафиксируйте операционную систему macOS, Xcode, SDK, командные инструменты, менеджеры зависимостей, архитектуру Apple Silicon и учётную запись запуска. Версии и поддерживаемые команды проверяйте по справочнику Apple для инструментов командной строки Xcode, а не по случайной копии конфигурации из другого Pipeline.

Не переносите настройки Linux Runner на Mac без проверки. Пути, права файлов, доступность системных утилит, работа Keychain и поведение фоновых процессов отличаются. Команда, которая молча предполагает наличие контейнера или отдельного эфемерного окружения, может оставить состояние на физическом хосте.

Выполните повторный запуск одного и того же коммита:

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

Сравнивайте не только успешный статус. Анализируйте разрешение зависимостей, попадание в кэш, содержимое архива, подпись и отсутствие скрытых файлов. Если второй запуск успешен только благодаря кэшу, отдельно проведите чистую сборку.

Ограничения macOS Runner и недоступные функции должны быть записаны рядом с заменяющим процессом. Например, если конкретная операция требует ручного доступа или не поддерживается выбранным типом Runner, обозначьте это до миграции, а не после первой неудачной публикации.

05 Подпись и доступ к коду требуют разных границ

Для iOS-релиза разделите как минимум четыре секрета:

  • регистрационные данные Runner;
  • доступ к исходному коду и артефактам;
  • сертификаты и профили Apple;
  • права публикации.

Не записывайте их в репозиторий, общий скрипт или постоянный файл на Mac. Используйте переменные и секреты Bitbucket согласно официальным правилам работы с variables and secrets. Секрет не должен попадать в командную строку, подробный лог или архив Pipeline.

Проверяйте весь жизненный цикл:

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

Для структуры сертификатов и рисков их использования применяйте техническое описание Apple TN3161. Правила подписи и проверки результата дополнительно сверяйте с документацией Apple по подписанному коду.

Отдельно проверьте отмену задания. Секрет должен удаляться и при штатном завершении, и при прерывании Pipeline. Если очистка работает только в последней команде Bash, принудительное завершение процесса может оставить сертификат или профиль на хосте.

06 Восстановление и очередь превращают узел в сервис

Производственный Runner должен восстанавливаться без ручного входа. Проверьте не только остановку процесса, но и последовательность отказов:

  • процесс Runner завершён;
  • агент отображается офлайн;
  • Mac перезапущен;
  • сеть временно недоступна;
  • задание отменено;
  • очередь содержит ожидающие задачи.

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

Официальные правила параллелизма и состояние очереди описаны в документации Atlassian по concurrency и очереди шагов. Используйте фактические данные ваших Pipeline: длительность сборки, пики очереди, долю повторных запусков, время простоя и резерв на отказ. Число разработчиков само по себе не говорит, сколько узлов потребуется.

Не подменяйте расчёт ёмкости рекламным параметром процессора. Для каждого типа задачи определите:

  • среднюю и максимальную длительность;
  • количество задач в пиковом окне;
  • допустимое ожидание;
  • долю неуспешных повторов;
  • резерв при недоступности узла;
  • разницу между тестовой и релизной очередью.

Если один Mac обслуживает тесты и подпись, очередь тестов может задержать выпуск. Если добавить общий Workspace Runner без новых границ доверия, вы получите не только конкуренцию за ресурсы, но и расширенный радиус доступа. В руководстве по Bitbucket Cloud сверяйте текущие требования к регистрации и работе macOS Runner перед каждым существенным изменением образа.

07 Условия решения перед запуском

Используйте следующий порядок решения, а не общее ощущение готовности:

  • Если задача пишет только в контролируемую рабочую область, узел не имеет релизных секретов и очистка подтверждена отрицательным тестом, то направляйте её в тестовый пул.
  • Если задача использует Apple-подпись или права публикации, то направляйте её только на выделенный релизный пул с отдельным Keychain.
  • Если несколько репозиториев должны использовать один пул, то выбирайте Workspace Runner только после проверки общей области доступа и разделения метками.
  • Если внешний код может изменить хост, установить службу или прочитать окружение, то не допускайте его на релизный узел; используйте отдельный низкодоверенный пул.
  • Если после перезагрузки или отмены требуется ручное вмешательство, то верните узел на доработку и не увеличивайте очередь.
  • Если нагрузочное испытание показывает непредсказуемое ожидание или ошибочный маршрут, то пересмотрите метки и ёмкость до подключения производственного репозитория.
  • Если все проверки имеют воспроизводимые логи и владельцев, то запускайте сначала ограниченную производственную группу, а затем расширяйте охват.

Сохраните итог в одном пакете доказательств: конфигурация меток, журналы очистки, результаты повторной сборки, подтверждение удаления секретов, тесты перезапуска и наблюдения за очередью. Такой пакет нужен не только для запуска. Он позволит объяснить, почему узел остаётся доверенным после обновления macOS, Xcode или Runner.

08 FAQ для корпоративной приёмки

Вопросы ниже закрывают типовые поисковые сценарии, но решение всё равно должно опираться на журналы конкретной инфраструктуры. Возможности Bitbucket и требования Apple меняются, поэтому перед обновлением проверяйте актуальные официальные страницы и текущие логи узлов.

Как подготовить Bitbucket macOS Runner к iOS CI/CD?

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

Может ли один Workspace Runner обслуживать разные репозитории?

Может, если все репозитории имеют сопоставимый уровень доверия и одинаковые требования к среде. Для проектов с разными правами этого недостаточно. Разделите тестовые и релизные пулы, назначьте разные метки и проверьте, что репозиторий с более низким доверием не может вызвать узел подписи. Очистка каталога не заменяет такое разделение.

Что проверять после очистки рабочего пространства?

Проверяйте не только отсутствие исходников. Ищите DerivedData, кэши, временные Keychain, профили, файлы с секретами, фоновые процессы и изменённые настройки. Запустите следующий тест под тем же типом учётной записи и подтвердите, что он не видит маркеры предыдущего задания. Отдельно документируйте действия Bitbucket и команды эксплуатации.

Подходит ли Mac Runner для постоянной публикации iOS-приложений?

Подходит при наличии выделенного пула, контролируемой подписи, повторяемой среды и автономного восстановления. Нельзя делать вывод по одному успешному Pipeline. Проверьте отказ процесса, перезапуск Mac, сетевую паузу, отмену задания и заполненную очередь. Если хотя бы один сценарий требует непредусмотренного ручного доступа, публикацию следует оставить в ограниченном режиме.

Как планировать количество узлов для Bitbucket Cloud?

Считайте не разработчиков, а поток задач. Возьмите фактическую длительность сборки, пик очереди, допустимое ожидание, повторы и резерв при отказе. Тестовые и релизные задачи считайте отдельно: смешивание даёт ложное ощущение свободной мощности. После измерений проведите контрольный прогон с реальными Pipeline и сохраните состояние очереди как доказательство ёмкости.

Текущий вариант — общий Mac с широкими правами — часто выглядит дешевле, но скрывает три недостатка: остаточное состояние между задачами, ошибочный маршрут к релизным секретам и ручное восстановление после сбоя. Покупка отдельных Mac для каждого разработчика устраняет часть совместного риска, но добавляет разнородные среды, обслуживание и неравномерно используемое оборудование. Для пилота или переменной нагрузки аренда Mac в CALMVPS позволяет выделить удалённый узел под проверяемый пул, не смешивая его с рабочими станциями команды. Начните с изолированной непроизводственной Pipeline, а условия аренды удалённого Mac сопоставьте с требованиями к сроку, доступу и резерву.

Если все проверки пройдены, используйте страницу тарифов CALMVPS для расчёта фиксированной ёмкости или временного узла. Если же вам нужна постоянная высокая загрузка, физические периферийные устройства или полностью контролируемая локальная сеть, собственный Mac может быть рациональнее. В любом случае сначала зафиксируйте критерии приёмки, затем подключайте производственную подпись и увеличивайте объём задач небольшими партиями.