Главная / Блог / Как развернуть B
ENGINEERING_BLOG · 2026.08.31

Как развернуть Buildkite Agent на удалённом Mac? Руководство по Xcode 27 CI на 2026 год

Развёртывание Buildkite Agent на удалённом Mac возможно, но узел с Xcode 27 следует держать отдельно от стабильной производственной среды и принимать только после реальных проверок. Начните с командной сборки, затем добавляйте Simulator, подпись и восстановление после перезапуска; одного статуса «Agent online» недостаточно.

Эта инструкция предназначена разработчикам iOS и macOS, которые переносят сборку с локального компьютера в Buildkite, DevOps-инженерам, поддерживающим постоянно доступный Mac, и руководителям платформ, тестирующим Xcode 27 Beta параллельно со стабильным pipeline. Если вам нужен только обычный Linux-узел или физический интерфейс iPhone, этот сценарий не закрывает задачу полностью.

Важно: на дату последней проверки, 31 августа 2026 года, Xcode 27 следует рассматривать как тестовую версию. Его совместимость, известные ограничения и требования нужно сверять с актуальными заметками к выпуску Xcode 27 Beta, а не с предположениями из форумов.

Последнее обновление: 31 августа 2026 года; сведения проверены по документации Apple и Buildkite, перечисленной в статье.

SECTION 01 До начала: какой узел вы действительно собираетесь развернуть?

Первое решение — не установка агента, а границы эксперимента. Для Xcode 27 выделите отдельный физический Apple Silicon Mac, на котором не выполняются критичные производственные сборки. Официальные требования к поддерживаемой версии macOS, SDK и Xcode проверяйте на странице системных требований Xcode. Если чип, система или установленный runtime не соответствуют требованиям, остановите настройку: агент не исправит несовместимость инструментария.

У удалённой схемы есть три независимых компонента:

  • управляющая плоскость Buildkite распределяет задания;
  • Buildkite self-hosted agent получает задания и запускает команды;
  • удалённый Mac предоставляет macOS, Xcode, рабочий каталог, Simulator и, при необходимости, ключи подписи.

Агенту не требуется произвольно открытый входящий порт для получения заданий: он устанавливает исходящее соединение с управляющей плоскостью. Это не означает, что сервер можно оставить без контроля. Вам всё равно нужны защищённый SSH-доступ, ограничение административных прав, сетевые правила исходящего трафика и понятная процедура восстановления. Рекомендации по модели работы описаны в официальной документации Buildkite для self-hosted Agent.

Сразу разделите нагрузку на три профиля:

  1. Командная сборка — разрешение зависимостей, компиляция, unit-тесты и создание результата.
  2. Графическая проверка — запуск iOS Simulator, UI-тесты и сбор диагностических файлов.
  3. Публикация — подпись, упаковка и передача релизного артефакта.

Первый профиль подходит для базового узла. Второй добавляет требования к пользовательской сессии и runtime Simulator. Третий требует отдельной модели секретов. Не смешивайте их только потому, что один Mac технически способен выполнить все команды.

Критерий остановки до установки

Не продолжайте, если у вас нет:

  • отдельного Apple Silicon Mac, соответствующего требованиям Xcode 27;
  • способа получить удалённый доступ после перезапуска;
  • отдельного аккаунта для Agent;
  • изолированной очереди для экспериментального инструментария;
  • плана удаления рабочей директории и отзыва ключей;
  • стабильного узла, куда можно вернуть производственные задачи.

Если нужен временный изолированный узел, заранее сравните условия аренды удалённого Mac VPSNIX с покупкой и самостоятельным размещением оборудования. Но сначала определите, какие проверки вы будете считать успешными.

SECTION 02 Первый час: отдельный пользователь, Queue и регистрация Agent

Шаг 1. Создайте операционный контур

Используйте специальную локальную учётную запись macOS без повседневных административных прав. Её имя в примерах обозначим как <CI_USER>. Не подставляйте в команды рабочее имя сотрудника: после увольнения, смены роли или удаления аккаунта это усложнит аудит и восстановление.

Под этим пользователем проверьте:

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

Официальная инструкция по установке Agent на macOS должна быть источником для конкретной схемы установки, расположения конфигурации и запуска через launchd. Не угадывайте путь к файлу buildkite-agent.cfg: сначала найдите фактическую конфигурацию на вашем узле и зафиксируйте её в документации команды.

Шаг 2. Зарегистрируйте узел без утечки секрета

Создайте отдельный <AGENT_TOKEN> с минимально необходимой областью действия. В примере ниже все значения условные:

buildkite-agent start \
  --token "<AGENT_TOKEN>" \
  --name "<REMOTE_MAC_NAME>" \
  --tags "xcode-27,apple-silicon,experimental"

Не записывайте настоящий токен в shell history, pipeline, скриншоты или журналы. Имя узла, Cluster и Queue также задавайте явно, чтобы диагностике не приходилось восстанавливать маршрут по косвенным признакам. Правила создания и назначения очередей сверяйте с документацией Buildkite по Queue.

Ваша цель на этом этапе — не «запустить CI», а доказать четыре факта:

  1. Agent зарегистрирован в правильном Cluster.
  2. Он виден в нужной Queue.
  3. Метки узла не совпадают случайно с производственными.
  4. Задание с тестовыми требованиями не может попасть на другой Mac.

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

sw_vers
uname -m
xcode-select -p
xcodebuild -version

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

SECTION 03 После регистрации: закрепите Xcode 27 и проведите командную сборку

Статус «online» сообщает только о связи процесса с Buildkite. Он не подтверждает доступ к репозиторию, корректность Xcode, работу зависимостей или возможность сформировать пригодный артефакт.

Шаг 3. Зафиксируйте путь к инструментарию

Проверьте установленные приложения и выберите Xcode 27 явно:

sudo xcode-select --switch "/Applications/<XCODE_27_APP>.app/Contents/Developer"
xcodebuild -version
xcrun --find xcodebuild

Используйте фактическое имя каталога, а не предположение о том, как Beta-версия названа на диске. Если производственный Xcode установлен рядом, не меняйте глобальный выбор без понимания последствий для других задач. Надёжнее передавать путь на уровне конкретного шага или Agent и записывать результат проверки в лог.

На этом узле не следует автоматически обновлять Xcode. Для экспериментального pipeline зафиксируйте версию и дату проверки; для производственного — оставьте стабильный инструментальный контур. Если Apple меняет требования или известные ограничения, повторите матрицу приёмки, а не объявляйте обновление безопасным по факту успешной установки.

Шаг 4. Дайте доступ к коду с минимальными правами

Учётной записи <CI_USER> нужен доступ только к тем репозиториям и веткам, которые требуются этому pipeline. Используйте машинную идентичность с возможностью ротации или управляемое хранилище секретов. Не копируйте личный SSH-ключ разработчика на постоянный CI-узел.

В правилах доступа к коду для self-hosted Agent проверьте, как именно ваш способ аутентификации передаёт ключ процессу, запущенному через launchd. Интерактивный терминал и фоновый сервис могут иметь разные переменные окружения, домашний каталог и доступ к связке ключей.

Для первой задачи зафиксируйте:

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

Шаг 5. Пройдите полный командный цикл

Возьмите небольшой реальный проект, а не пустую команду. Последовательность должна быть воспроизводимой:

set -o errexit
set -o pipefail

xcodebuild \
  -workspace "<WORKSPACE_PATH>" \
  -scheme "<SCHEME_NAME>" \
  -configuration Release \
  -sdk "<SDK_NAME>" \
  -destination "generic/platform=iOS" \
  clean build \
  | tee "<BUILD_LOG_PATH>"

Сначала проверьте разрешение зависимостей, затем компиляцию, unit-тесты и появление ожидаемого результата. Не считайте pipeline успешным, если команда завершилась без ошибки, но артефакт отсутствует или лежит в непредсказуемом каталоге.

На этом этапе также выявляются скрытые зависимости: переменные из интерактивного профиля, локальный кэш разработчика, незаписанный путь к сертификату или ручное подтверждение системного диалога. Каждую такую зависимость либо объявите в конфигурации, либо удалите. Если воспроизводимость невозможна, остановите расширение узла до Simulator и подписи.

Опыт эксплуатации: рабочая сборка из SSH не доказывает, что та же команда сработает через launchd. Сравнивайте пользователя, PATH, домашний каталог, права на рабочую директорию и доступ к связке ключей в обоих режимах.

SECTION 04 Нужен ли Simulator: графическая сессия и первый тест

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

Шаг 6. Проверьте runtime и пользовательскую сессию

Если pipeline содержит UI-тесты, убедитесь, что:

  • нужный runtime Simulator установлен и совместим с выбранным Xcode;
  • процесс Agent принадлежит ожидаемому пользователю;
  • пользовательская графическая сессия действительно доступна;
  • виртуальное устройство видно через xcrun simctl;
  • рабочий каталог не конфликтует с другой задачей.

Минимальная проверка может выглядеть так:

xcrun simctl list devices available
xcrun simctl boot "<SIMULATOR_UDID>" || true
xcrun simctl bootstatus "<SIMULATOR_UDID>" -b

Затем выполните один небольшой тестовый набор, соберите результат и удалите или сбросьте временное устройство по правилам вашей команды. Укажите в логе UDID, версию runtime и результат очистки, но не выводите секреты проекта.

Успешный запуск Simulator отвечает только на вопрос о симулированной среде. Он не заменяет тест на физическом устройстве, проверку push-уведомлений, камеры, Bluetooth или публикации. Если сессия недоступна после перезапуска, вернитесь к чистому командному узлу и не маскируйте проблему увеличением таймаутов.

SECTION 05 Публикация: как не отдать ключи обычной сборке

Шаг 7. Разделите очереди, аккаунты и рабочие каталоги

Обычная проверка изменений не должна автоматически получать доступ к производственным сертификатам. Разумная схема выглядит так:

  • очередь <QUEUE_BUILD> — компиляция и тесты без закрытых ключей;
  • очередь <QUEUE_SIGNING> — ограниченный набор доверенных задач;
  • отдельная учётная запись или контролируемый шаг для подписи;
  • отдельный рабочий каталог для релизного процесса;
  • запрет параллельного доступа к одной связке ключей и одному набору DerivedData.

Перед первым релизным запуском проверьте соответствие сертификата, профиля и Team ID, но в документации и примерах оставляйте <CERTIFICATE_NAME>, <TEAM_ID>, <KEYCHAIN_PASSWORD> и <PROFILE_NAME>. Пароль не должен находиться в pipeline-файле или аргументах процесса, доступных диагностике.

Практические рекомендации по проблемам подписания и управлению ключами сверяйте с материалами Apple о code signing. Секреты лучше выдавать непосредственно ограниченному шагу и отзывать после завершения эксперимента, если это допускает ваша модель поставки.

Если один Agent выполняет несколько задач одновременно, тестируйте конкуренцию отдельно. DerivedData, Simulator, временные файлы и связка ключей могут стать общими точками конфликта. Без доказательства безопасной изоляции оставьте один процесс и последовательное выполнение. Масштабирование количеством Agent не является заменой раздельным каталогам и очередям.

SECTION 06 Перезапуск и первая неделя: когда узел можно считать готовым

Шаг 8. Настройте постоянный запуск через launchd

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

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

Проверяйте не только существование процесса:

launchctl print "system/<SERVICE_LABEL>"
ps aux | grep "[b]uildkite-agent"

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

Шаг 9. Выполните контролируемую перезагрузку

Перед перезапуском:

  • остановите активные задачи;
  • сохраните журналы;
  • отметьте текущий коммит и версию Xcode;
  • убедитесь, что есть удалённый путь возврата;
  • предупредите владельцев pipeline.

После перезапуска последовательно проверьте удалённый доступ, состояние пользовательской сессии, загрузку launchd-задачи, появление Agent в Queue и выполнение настоящей командной сборки. Затем отдельно повторите Simulator и подпись, если эти функции входят в назначение узла.

На первой неделе наблюдайте за ростом диска, очисткой рабочих каталогов, ротацией журналов, зависшими Simulator и правилами обновления Agent. Не удаляйте рабочие данные массовой командой, пока не определены каталоги, исключения и способ восстановления. В центре помощи VPSNIX можно сверить общие процедуры доступа и обслуживания удалённой Mac-среды, но проектную приёмку всё равно выполняйте на собственном pipeline.

SECTION 07 Контрольная точка перед добавлением в production

Отметьте каждый пункт только после получения наблюдаемого результата:

  • [ ] Узел использует Apple Silicon Mac и систему, совместимые с Xcode 27 по актуальным материалам Apple.
  • [ ] Xcode 27 установлен отдельно от стабильного производственного инструментария и выбран явно.
  • [ ] Agent работает от специальной низкопривилегированной учётной записи.
  • [ ] Токен хранится вне репозитория, командной строки в журналах и примеров документации.
  • [ ] Cluster, Queue и метки направляют тестовые задания только на нужный узел.
  • [ ] Минимальная задача выводит систему, архитектуру и путь к Xcode без секретов.
  • [ ] Реальный проект проходит разрешение зависимостей, сборку, unit-тесты и создаёт ожидаемый результат.
  • [ ] Simulator проверен только в том случае, если он входит в назначение узла.
  • [ ] Подпись вынесена в отдельную очередь, аккаунт или ограниченный шаг.
  • [ ] Нет доказанного конфликта DerivedData, Simulator, рабочих каталогов и связки ключей.
  • [ ] После перезапуска Agent появляется в нужной Queue и выполняет реальную задачу.
  • [ ] Есть стабильный узел или понятный маршрут отката для производственной сборки.

SECTION 08 Какой вариант размещения выбрать для Xcode 27 CI?

Вариант Когда подходит Главный риск Решение для Xcode 27
Локальный Mac разработчика Нерегулярные ручные проверки и отладка Сборка зависит от занятости и состояния рабочего компьютера Не использовать как единственный CI-узел
Собственный Mac mini в офисе Долгий стабильный проект при наличии администрирования Электропитание, сеть, удалённое восстановление и обслуживание ложатся на команду Подходит после теста перезапуска и доступа
Удалённый Mac в аренду Временная Beta-проверка, изолированный pipeline, отсутствие собственного Apple Silicon Mac Нужно проверить задержку, доступность сессии, дисковое пространство и правила обслуживания Хороший кандидат для отдельной Queue и поэтапной приёмки
Виртуальная или неподходящая среда Эксперименты, не требующие полного macOS-инструментария Нельзя заранее считать совместимость Xcode, Simulator и подписи доказанной Не выбирать для обязательной публикации без реальной проверки

Таблица не заменяет тестирование: совместимость проекта, время сборки, стабильность Simulator и восстановление после перезапуска должны быть подтверждены именно на том узле, который попадёт в pipeline. Производительность без привязки к модели Mac, версии macOS, проекту и дате измерения нельзя считать универсальным показателем.

SECTION 09 Частые вопросы

Можно ли использовать удалённый Mac как Buildkite Agent?

Да, если это реальный Mac с совместимыми macOS и Xcode, доступом к сети и отдельной учётной записью. Для получения заданий Agent использует исходящее соединение, но SSH-доступ, графическая сессия и восстановление после перезапуска требуют самостоятельной проверки.

Как указать Xcode 27 для конкретной сборки?

Назначьте узлу отдельные метки и Queue, а в шаге явно выберите каталог Xcode 27. Затем проверьте xcodebuild -version внутри задания. Если путь задан только в профиле интерактивного shell, фоновый Agent может использовать другой Xcode.

Может ли macOS CI продолжить работу после перезапуска Mac?

Может, если Agent зарегистрирован как launchd-служба, конфигурация доступна нужному пользователю, а сеть и сессия восстанавливаются без ручного входа. Проверяйте полный тестовый pipeline, а не только процесс иконки или строку «online» в интерфейсе.

Достаточно ли Simulator для приёмки iOS-приложения?

Нет. Simulator подтверждает работоспособность конкретного симулированного runtime и сценария теста. Он не заменяет проверку на физическом устройстве, аппаратных функций, поведения подписанного приложения и финальной процедуры публикации.

Как защитить сертификаты на self-hosted Mac?

Разделите сборочные и подписывающие очереди, используйте отдельную связку ключей и минимальные права, а секреты передавайте только ограниченному шагу. После эксперимента проверьте журналы и историю shell: в них не должны появиться токены, пароли, Team ID или закрытые ключи.

Если текущая схема основана на личном Mac разработчика, офисном мини-компьютере или нестабильной виртуальной среде, у неё обычно обнаруживаются три слабых места: непредсказуемая доступность, ручное восстановление после перезапуска и смешение экспериментальных сертификатов со стабильной сборкой. Для краткого теста Xcode 27 практичнее взять отдельный удалённый Apple Silicon Mac в аренду у VPSNIX, выполнить описанную приёмку и только затем решать, нужен ли вам собственный постоянно обслуживаемый узел. Условия можно проверить на странице тарифов VPSNIX; долгую тяжёлую эксплуатацию и сценарии с обязательным физическим устройством следует заранее сравнить с покупкой собственного оборудования.

SECTION 10 Часто задаваемые вопросы

Можно ли установить Buildkite Agent на удалённый Mac в дата-центре?

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

Как направить сборку на узел с Xcode 27?

Назначьте изолированному Agent отдельные Cluster и Queue, добавьте проверяемые метки и в pipeline явно укажите требуемую очередь. На самом Mac зафиксируйте путь к Xcode 27 через xcode-select или переменную, заданную в конфигурации агента. Перед публикацией проверьте, что задача действительно попала на нужный узел, а не только отображается как ожидающая.

Что нужно настроить, чтобы macOS Agent снова появился после перезагрузки?

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

Поддерживает ли self-hosted Mac Agent тесты iOS Simulator?

Да, удалённый Mac может выполнять задачи с iOS Simulator, если на нём установлены совместимые Xcode и runtime, а процесс запускается в пригодной графической пользовательской сессии. Для этого нужна отдельная проверка запуска устройства, выполнения теста, сбора результата и очистки. Успешный Simulator не доказывает работоспособность тестов на физическом iPhone или готовность к публикации.

Как отделить сертификаты подписи от обычных Buildkite задач?

Разделите очереди или учётные записи для обычных Pull Request-сборок и публикации, а доступ к закрытым ключам предоставляйте только контролируемому шагу. Используйте отдельную связку ключей, минимальные права, временные секреты и явную проверку профилей. Не помещайте сертификаты, пароли, Team ID и токены в pipeline, репозиторий или диагностический вывод.