Команды с коротким циклом арендуют cloud Mac runner посуточно, чтобы протолкнуть сборки в TestFlight без покупки железа. Подпись — место, где эта модель упирается в реальность: эфемерные диски, параллельные job и хранилище секретов, которое не должно сливаться с кодом приложения. Fastlane Match по-прежнему практичный дефолт: сертификаты и профили хранятся как зашифрованные объекты в Git, затем на каждом runner подтягиваются в ключницу. Сбои предсказуемы — устаревшие профили, рассинхрон пароля к репозиторию, два job, меняющих одну ветку, — но лечатся скучной инженерией, как только разделить чтение и запись и зафиксировать параллелизм.
Match и шифрованный Git: что реально оказывается на runner
Match рассчитан на отдельный (часто приватный) репозиторий с зашифрованными .p12 и mobileprovision и метаданными. Пароль от шифрования в Git не кладётся — подставляйте из секретного хранилища CI переменной окружения. На посуточном cloud Mac считайте каталог checkout одноразовым: чистый клон, match в режиме только чтения для archive lane, а readonly: false включайте лишь в охраняемом админ-job, который продлевает сертификаты. Одна такая политика убирает большинство инцидентов вида «CI переписал мой репозиторий».
Ветки и права доступа
Для окружения заведите основную ветку (например master или main для прод-материалов подписи) и ограничьте право merge. Токены CI на чтение — с областью только репозитория Match и правом contents:read. Людям-админам оставьте отдельный путь учётных данных для перевыпуска. Если в одном репозитории смешаны ad hoc и App Store-профили, явно разнесите каталоги, чтобы типы Match не перезаписывали друг друга при параллельных запусках.
Клоны только по HTTPS на cloud Mac runner
HTTPS с узко ограниченным personal access token или deploy key, привязанным к HTTPS, проще аудировать, чем долгоживущие SSH-ключи, скопированные на арендованные машины. Задайте GIT_TERMINAL_PROMPT=0, чтобы зависшая авторизация падала быстро, и для репозитория Match предпочитайте shallow clone — меньше минут списания на коротких сессиях. Если провайдер меняет пулы IP, следите за лимитами Git-хоста; backoff логичнее держать в обёртке пайплайна, а не внутри Match.
export GIT_TERMINAL_PROMPT=0 export MATCH_READONLY=true # archive / test lanes # По желанию: таймаут низкой скорости для крупных LFS export GIT_HTTP_LOW_SPEED_LIMIT=1000 export GIT_HTTP_LOW_SPEED_TIME=120
Матрица решений: конфликты сертификатов при нескольких job
Два параллельных job, оба вызывающие Match с правом записи, или с конфликтующими type для одного app_identifier, могут гоняться за push в Git или установкой в ключницу. Перед масштабированием параллелизма сверьтесь с таблицей. Про размер пула runner и когда добавлять второй macOS-пайплайн против выноса задач на Linux-агенты — в Короткий цикл CI в 2026: второй macOS-пайплайн или Linux-агенты — матрица решений и FAQ по очередям и секретам; про эластичный пул облачных Mac и постоянные узлы для GitHub Actions — в Короткие пики CI в 2026: self-hosted GitHub Actions на macOS — эластичный пул облачных Mac или постоянные узлы?.
| Параллельная ситуация | Риск | Решение |
|---|---|---|
Все job с MATCH_READONLY=true, одна ветка |
Низкий: только конкуренция за чтение | Параллелизм по runner разрешён |
| Смесь чтения и одного job перевыпуска | Средний: гонки push, частичные клоны | Сериализовать запись меткой-мьютексом; чтение на других runner |
| Два job перевыпуска, те же идентификаторы | Высокий: двойная выдача сертификата, конфликт в Git | Жёсткий single-flight; авто на ветках отключить |
| Разные приложения, общий репо и пароль | Средний: человеческая ошибка в app_identifier |
Разнести репозитории или зафиксировать git_branch на продукт |
Исполняемый чеклист и FAQ
Прогоняйте список на каждом новом образе cloud Mac или метке runner до включения прод-подписи.
- Preflight — мажор Xcode согласован с
DEVELOPMENT_TEAM; промежуточные сертификаты Apple на месте. - Секреты —
MATCH_PASSWORD, ключ API App Store Connect и HTTPS-токен Git только на репозиторий Match. - Сеть — исходящий 443 к Apple и Git-хосту; неинтерактивный режим (
CI=1, где Fastlane это уважает). - Параллелизм — в обычном пайплайне по умолчанию
MATCH_READONLY; снимается только в workflow продления. - Post-job — сброс ключницы или скрипт выхода на общих пулах; артефакты выгружены, временные каталоги удалены.
Короткие ответы
«Codesign хочет доступ к ключнице» — в CI разблокируйте отдельной файлом ключницы в $TMPDIR, не login keychain. Профиль истёк посреди спринта — один lane продления, обновить профили, коммит в репозиторий Match, затем разнести readonly job. Два приложения, опечатка в bundle ID — падает на загрузке, не на компиляции; добавьте проверку метаданных перед gym.
На облачном Mac mini подпись предсказуемее
Fastlane и Xcode рассчитывают на настоящую macOS-ключницу и цепочку Apple codesign — на Linux-агентах это остаётся обходным путём. Выделенный cloud Mac mini даёт фиксированную базу Sonoma или Sequoia, нативный Unix для скриптов и достаточно унифицированной памяти Apple Silicon, чтобы archive не конкурировал за RAM со всплесками компиляции Swift.
Узлы на Apple Silicon в ожидании ответов API Apple потребляют очень мало энергии; стек подписи совпадает с тем, что ревьюеры гоняют локально, и сюрпризов «только в CI» меньше. Gatekeeper и SIP остаются в русле требований дистрибуции, без налога на эмуляцию или чисто удалённые тулчейны.
Если нужны посуточные runner без покупки железа, облачный Mac mini M4 от VPSSpark — практичная площадка для readonly Match и archive-пайплайнов — смотрите тарифы и держите короткие релизы на рельсах.