CI/CD 2026.09.29

Xcode 27: не удаётся загрузить приватный Swift Package? Руководство по исправлению в 2026 году

Руководство предназначено разработчикам и DevOps-инженерам, которые собирают проекты Xcode на удалённом Mac и не могут получить приватные Swift Package. Мы разделяем ошибки SSH-аутентификации, проверки узла, разрешения версий и Git-настроек, а затем даём порядок безопасной проверки и выбора между исправлением учётной записи и изоляцией узла.

На этой неделе сначала проверьте, под какой учётной записью CI запускает сборку, и доступны ли именно ей SSH-ключ и known_hosts; затем сверьте Package.resolved и URL зависимостей. Не отключайте проверку SSH-хоста и не очищайте кэш до локализации сбоя: так легко замаскировать исходную причину. Этот порядок подходит, если проект собирается локально, но Xcode на удалённом Mac не загружает приватный Swift Package.

Материал для разработчиков, которые поддерживают проекты Xcode и зависят от закрытых пакетов: он помогает отделить отказ аутентификации от ошибки проверки узла и расхождения версий.
Для DevOps-инженеров, отвечающих за Mac CI, здесь есть порядок настройки минимально необходимых SSH-доступов для пользователя Runner.
Руководители мобильной разработки смогут проверить, связана ли проблема с учётной записью узла или с зафиксированным графом зависимостей.

01 Развилка по этапу сбоя Xcode 27 на удалённом Mac

Фраза «пакет не загружается» описывает результат, но не причину. Сначала найдите в логе первую ошибку, относящуюся к Swift Package Manager, и определите, на каком этапе остановился процесс: Git не получил доступ к репозиторию, SSH отверг ключ или хост, либо менеджер зависимостей не смог разрешить требуемую версию.

Сравнивайте не просто локальную и удалённую сборки, а один и тот же коммит, схему, параметры xcodebuild и состояние зависимостей. Если команды отличаются, сравнение не покажет, вызвана ли разница окружением или поведением процесса сборки. Запишите полный URL пакета из Package.resolved и сопоставьте его с URL, который реально использует Git.

Что видно в логе Вероятное направление проверки Что пока не следует менять
Ошибка доступа или отказ в авторизации Пользователь CI, доступность SSH-ключа, права на репозиторий Версии пакетов и кэш
Host key verification failed known_hosts, имя хоста, отпечаток ключа SSH-проверку хоста как меру безопасности
Запрос пароля или отсутствие ключа SSH-конфигурация процесса сборки и доступ к агенту Учётную запись администратора вместо пользователя CI
Версия или ревизия не соответствует ожиданиям Package.resolved, URL зависимости, параметры разрешения пакетов Массовое обновление зависимостей
Системный Git и Xcode ведут себя по-разному URL-переписывание, прокси и SSH-правила Одновременное изменение всех настроек

Это не таблица соответствия ошибок и причин «один к одному»: одна и та же строка в логе может появиться после нескольких предыдущих действий. Ищите первое сообщение об отказе, а не только финальное сообщение о неудачной сборке.

Почему удалённый Mac не получает приватную зависимость, хотя локальная сборка проходит? Обычно локальная и CI-среды используют разные пользовательские учётные записи, ключи или конфигурации SSH. На локальном Mac ключ может быть доступен из пользовательского агента, тогда как процесс CI работает от отдельного пользователя без этих данных. Сопоставьте вывод id -un внутри задачи и пользователя, для которого настроены SSH-файлы.

Проверьте и версионный контекст. Конкретное состояние Xcode 27, поддерживаемые версии macOS и изменения в поведении выпуска сверяйте с актуальными заметками о выпуске Xcode 27 и системными требованиями Xcode. Не предполагайте, что все удалённые узлы уже используют одинаковую версию: сначала запишите фактические версии на узле и сравните их с требованиями Apple.

02 Проверка SSH-учётной записи и полномочий

Задача CI использует окружение того пользователя macOS, от имени которого запущен Runner или другой исполнитель сборки. Поэтому наличие ключа в домашнем каталоге администратора, в его SSH-агенте или в интерактивной сессии не подтверждает, что ключ доступен сборочному процессу. В руководстве Apple по сборке Swift-пакетов и приложений в CI отдельно описаны настройка CI-учётных данных и размещение SSH-конфигурации для пользователя, выполняющего задачи.

Проверяйте в контексте именно этой учётной записи:

  • Какой пользователь запускает задачу? Зафиксируйте результат id -un в диагностическом шаге, но не выводите секретные переменные или содержимое закрытых файлов.
  • Есть ли у пользователя собственные ~/.ssh/config, закрытый ключ и ~/.ssh/known_hosts? Убедитесь, что права на файлы позволяют этому пользователю читать их и не предоставляют лишнего доступа другим.
  • Получает ли процесс ключ через ssh-agent или использует файл напрямую? Не считайте агент, открытый в сессии администратора, автоматически доступным сервису CI. У Apple есть отдельное техническое описание работы SSH-агента; сверяйте механизм с фактическим способом запуска Runner.
  • Имеет ли ключ разрешение только на чтение нужного репозитория? Для ключа развёртывания ознакомьтесь с описанием ограниченных прав deploy key, а затем проверьте, что область действия соответствует используемому приватному пакету.

В какой учётной записи хранить SSH-ключ и known_hosts? В учётной записи macOS, от имени которой выполняется задача CI, а не в профиле пользователя, который вручную вошёл на узел. Если несколько независимых задач должны иметь разные права, лучше не складывать все ключи в общую домашнюю папку: разделите полномочия по учётным записям или изолированным исполнителям.

Для первичной диагностики можно выполнить из того же шага CI проверку SSH-соединения с тем же адресом, который использует URL зависимости. Проверка должна подтверждать доступ, но не печатать закрытый ключ, токен, пароль или содержимое агента. Успех подключения ещё не означает, что Swift Package Manager выберет правильную версию, — это отдельная проверка.

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

03 Проверка known_hosts и имени SSH-хоста

Если в логе есть Host key verification failed, это не сообщение о неверном пароле. SSH не смог подтвердить подлинность удалённого хоста с помощью имеющихся данных проверки. Описание именно этой ошибки приведено в документации по отказу проверки host key.

Сверьте имя хоста в URL приватного пакета с записью в known_hosts. Различие между псевдонимом из ~/.ssh/config, коротким именем узла и полным доменным именем может привести к тому, что SSH ищет запись не под тем идентификатором. Также проверьте порт и настройки, применяемые к этому адресу: правила Host могут менять используемый ключ или файл known_hosts. Синтаксис параметров и область действия правил можно проверить в справочнике ssh_config.

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

Можно ли временно выключить StrictHostKeyChecking? Не как штатное исправление CI. Отключение проверки ослабляет защиту от подмены удалённого узла, а успех сборки после такой перемены не подтверждает, что исходная проблема была решена безопасно. Если исключение необходимо для изолированной диагностики, зафиксируйте его область, не распространяйте на общие SSH-настройки и верните проверку после получения корректного отпечатка. Сравните поведение с исходным состоянием и сохраните в задаче только безопасные диагностические сообщения.

04 Сверка Package.resolved и адресов зависимостей

После того как SSH-аутентификация и проверка хоста проходят под пользователем CI, переходите к версиям. Файл Package.resolved нужен, чтобы фиксировать выбранные версии зависимостей, однако одного факта его наличия в репозитории недостаточно: проверьте, что файл относится к используемому проекту и схеме, не игнорируется при checkout и содержит адрес приватного пакета, доступный сборочному пользователю.

Сначала сравните файл из того же коммита локально и на узле. Затем проверьте URL каждого приватного пакета и выясните, совпадает ли он с адресом, для которого настроены SSH-правила. Если URL использует HTTPS, а доступ настроен только для SSH, это разные пути авторизации; наличие SSH-ключа само по себе не исправит несовпадение схемы и адреса.

Apple рекомендует включать Package.resolved в контроль версий и при прямом использовании xcodebuild отключать автоматическое разрешение зависимостей, чтобы сборка следовала зафиксированному состоянию. Сверьте применимость и точный синтаксис с руководством Apple по Swift Package Manager в CI. Для проверки можно использовать команду вида:

xcodebuild \
  -resolvePackageDependencies \
  -workspace App.xcworkspace \
  -scheme App \
  -disableAutomaticPackageResolution

Замените имя workspace и scheme на значения проекта. Смысл проверки — разрешить зависимости в контексте нужной сборки, но не разрешать менеджеру автоматически менять выбранные версии. Перед запуском проверьте параметры по актуальной документации для установленного Xcode; не переносите команду вслепую между проектами с разной структурой.

Что делать, если Package.resolved закоммичен, но CI выбирает другую версию? Не начинайте с удаления файла или принудительного обновления пакетов. Сначала подтвердите, что CI получает именно тот коммит, где файл присутствует, что xcodebuild запускается с ожидаемыми workspace и scheme и что автоматическое разрешение зависимостей не переопределяет lock-файл. После этого сравните записанный revision с фактически загруженным и отдельно проверьте, доступен ли этот revision по указанному URL.

Возможность получать приватные зависимости зависит также от выбранного CI-сервиса и конфигурации доступа. Apple описывает отдельные требования для доступности зависимостей в Xcode Cloud. Не переносите специфическую настройку Xcode Cloud на самостоятельный Runner без проверки: здесь рассматривается прямой доступ сборочного процесса на удалённом Mac.

05 Сопоставление Git и параметров xcodebuild

Когда пользователь, ключ, отпечаток хоста и lock-файл проверены, выясните, какой Git и какие настройки использует процесс сборки. В конфигурации могут влиять переписывание URL, пользовательский SSH-конфиг, переменные окружения или прокси. При этом не стоит заранее считать, что проблема вызвана встроенным Git Xcode: сначала соберите свидетельства, что именно используемый процесс применяет отличающиеся правила.

Сделайте диагностические действия раздельно:

  • Выведите безопасные сведения о версии системного Git и Xcode; не включайте в лог секретные значения переменных окружения.
  • Проверьте Git-настройки, которые относятся к URL приватного репозитория, включая правила insteadOf, и сравните их с ожиданиями проекта.
  • Сопоставьте SSH-команду и конфигурацию для точного адреса зависимости с настройками пользователя CI.
  • Если ошибка указывает на различие между Git, который вызывает Xcode, и системным Git, испытайте альтернативный вариант в отдельной задаче. Не меняйте одновременно Git, прокси, URL и ключ: иначе результат не покажет причину.
  • Сохраните безопасный лог разрешения пакетов и выбранных ревизий для повторного сравнения.

Настройка SSH-агента особенно важна, если ключ не читается процессом напрямую. Агент может быть запущен в одной сессии, но недоступен фоновой задаче из-за другого контекста пользователя или окружения. Не публикуйте вывод команд, способный раскрыть секреты, и не добавляйте отладку ключа в постоянные логи CI. Цель — подтвердить, какой способ доступа применён, а не вывести материал авторизации.

Если переключение на системный Git временно помогает, считайте это диагностическим признаком, а не окончательным объяснением. Зафиксируйте версию инструментов и минимальное изменение, которое меняет результат; затем выясните, связано ли оно с правилами Git URL, SSH или прокси.

06 Повторная сборка и выбор между исправлением учётной записи и изоляцией

Завершайте разбор чистым повтором на том же коммите и с теми же параметрами. Используйте исходного пользователя CI, а не интерактивную учётную запись администратора. Зафиксируйте безопасные сведения: этап отказа, URL зависимости без секретных данных, выбранную ревизию, результат проверки SSH и итог разрешения пакетов. Не удаляйте кэш до получения сравнимого результата: очистка может временно изменить симптом, но не доказывает исправление доступа.

Как xcodebuild получает SSH-настройки пользователя CI? Запускайте его в том же пользовательском контексте, где настроены домашний каталог, ~/.ssh/config и known_hosts, и убедитесь, что нужный ключ действительно доступен процессу. Если Runner стартует как служба, не делайте выводы по терминалу администратора: его переменные окружения и доступ к агенту могут отличаться. При необходимости проверьте это отдельной тестовой задачей, не записывая секреты в вывод.

Для решения используйте ветвление по результату:

  • Если SSH-аутентификация не проходит, но хост проверен и URL соответствует настроенному ключу, исправьте доступ для пользователя CI или область полномочий ключа. Не расширяйте права общей учётной записи без необходимости.
  • Если ошибка касается host key, восстановите корректную проверку для фактического имени и пользователя задачи. Не оставляйте отключённую проверку как постоянное состояние.
  • Если SSH проходит, а версии отличаются, сверьте коммит, Package.resolved, workspace, scheme и флаг разрешения зависимостей. Не обновляйте lock-файл, пока не установлено, почему он не применяется.
  • Если настройки конфликтуют между задачами или разные проекты требуют несовместимых секретов, перейдите к независимой учётной записи или изолированному исполнителю. Не передавайте всем сборкам единый широкий доступ к приватным репозиториям.
  • Если чистый повтор с тем же коммитом и пользователем стабильно проходит, зафиксируйте подтверждённую причину и изменённую настройку, а затем верните только те временные диагностические параметры, которые больше не нужны.

Мы рекомендуем сверять рабочий порядок настройки удалённой среды с материалами в разделе JEXCLOUD, а выбор доступного варианта удалённого Mac — с условиями заказа. Используйте эти страницы для оценки среды, а не как замену диагностике: доступ к пакетам всё равно нужно настроить для пользователя, выполняющего сборку.

Если сейчас используется общий Mac-узел, у него могут быть три существенных недостатка: несколько задач конкурируют за общие ресурсы и настройки; общий контекст повышает риск слишком широких прав SSH; сбой или изменение окружения затрагивает сборки разных проектов. Для длительной предсказуемой нагрузки собственный Mac может быть рациональнее, особенно если нужны постоянные локальные устройства или физические интерфейсы. Но когда требуется контролируемый удалённый macOS-узел для CI без покупки отдельного компьютера, аренда Mac у JEXCLOUD позволяет оценить такой вариант отдельно от общей машины. Перед переносом проверьте, что выбранная схема обеспечивает нужную изоляцию учётной записи и безопасную передачу ключей; если среда не подходит по требованиям безопасности или доступа, сначала исправьте процесс на текущем узле.

JEXCLOUD

Собирайте проекты Xcode на выделенном Mac с JEXCLOUD

Запускайте сборки на физическом Mac с Apple Silicon и проверяйте доступ к приватным Swift Package в отдельной среде.

Подключайтесь к удалённому узлу по SSH и настраивайте учётные данные и Git так, как требует ваш проект.

Арендовать сейчас