Настройка автоматической раздачи билдов через TestFlight
Ручная загрузка через Xcode Organizer — источник боли в любой iOS-команде. Забытый флаг include bitcode, устаревший сертификат, который лежит только на MacBook одного разработчика, Upload Error 409 без внятного объяснения — всё это останавливает доставку билда тестировщикам на несколько часов. Автоматическая загрузка в TestFlight через altool или Fastlane убирает человека из этой цепочки.
Проблема с сертификатами в CI
Главный технический барьер — Code Signing. В Xcode Organizer это происходит «само», потому что Xcode берёт сертификат и provisioning profile из связки ключей macOS. В CI такой связки нет. Без настройки получаем:
error: exportArchive: No signing certificate "iOS Distribution" found
Варианта два: match от Fastlane (рекомендуется для команд) или sigh + cert (для одиночного проекта). match хранит сертификаты и профили в зашифрованном Git-репозитории, CI клонирует его перед сборкой и импортирует в временную keychain. Не нужно пробрасывать файлы вручную.
Как устроена автоматическая загрузка
altool (устаревший, но ещё рабочий) и xcrun altool --upload-app требуют App Store Connect API Key. Сейчас Apple рекомендует xcrun notarytool для macOS и altool для iOS, но на практике Fastlane pilot (deliver для метаданных) надёжнее — он обрабатывает ошибки и ретраи.
Типичный Fastfile для TestFlight:
platform :ios do
lane :beta do
setup_ci # настраивает временную keychain в CI
match(
type: "appstore",
readonly: true,
git_url: ENV["MATCH_GIT_URL"],
password: ENV["MATCH_PASSWORD"]
)
increment_build_number(
build_number: ENV["CI_BUILD_NUMBER"] || Time.now.to_i.to_s
)
build_app(
scheme: "MyApp",
configuration: "Release",
export_method: "app-store"
)
upload_to_testflight(
api_key_path: "fastlane/api_key.json",
skip_waiting_for_build_processing: true,
changelog: ENV["CHANGELOG"] || "Automated build"
)
end
end
skip_waiting_for_build_processing: true важен — без него Fastlane блокируется на 10–20 минут, пока Apple обрабатывает билд. В CI это занимает слот агента впустую.
App Store Connect API Key
Apple убрала поддержку логина по паролю (App-Specific Password) для altool в конце 2023 года. Теперь обязательно API Key. Создаётся в App Store Connect → Users and Access → Integrations. Нужна роль не ниже App Manager. Ключ (AuthKey_XXXXXX.p8) хранится в секретах CI, путь к нему передаётся через api_key_path или через переменные окружения APP_STORE_CONNECT_API_KEY_KEY_ID, APP_STORE_CONNECT_API_KEY_ISSUER_ID, APP_STORE_CONNECT_API_KEY_KEY.
Группы тестировщиков в TestFlight добавляются автоматически: groups: ["Internal Testers", "QA Team"] в upload_to_testflight. Внешние тестировщики требуют прохождения бета-ревью — это уже ограничение Apple, не автоматизируемое.
Инкремент Build Number
TestFlight отклоняет билд с тем же CFBundleVersion, что уже загружен. Стандартный подход — использовать номер сборки из CI: CI_BUILD_NUMBER в GitHub Actions, $CI_PIPELINE_IID в GitLab, $BITRISE_BUILD_NUMBER в Bitrise. Либо git rev-list --count HEAD как монотонно возрастающее число.
Процесс
Настройка App Store Connect API Key → конфигурация match для CI → написание Fastfile → тестирование на реальном CI-агенте с macOS → настройка групп тестировщиков → документация.
Срок: 1–3 дня в зависимости от того, настроен ли match уже или нужно выстраивать с нуля. Стоимость рассчитывается индивидуально.







