Всем привет!
В этом посте мы хотим поделиться опытом создания автоматизированной системы сборки мобильных приложений, в нашем случае – игр для платформы iOS.
Мы столкнулись с необходимостью автоматизировать сборку и деплоймент на тестовые устройства, когда размер парка устройств превысил два десятка, а количество проектов, одновременно находящихся в QA достигло 30+. При таких объемах деплоймент билда на тестовые устройства с помощью “Build & Run” в XCode начал заметно затормаживать процесс прохождения QA. Было принято решение об автоматизации процесса сборки и заливки билдов на устройства.
Наша обновленная билд-система состоит из трех основных компонентов:
- Репозитории с исходными кодами проектов;
- Сервер сборки;
- Сервер раздачи билдов на устройства.
Процесс прохождения версии проекта от разработчиков до тестировщиков выглядит следующим образом:
- Разработчик делает коммит версии в репозиторий;
- Билд-сервер запускает сборку соответствующего проекта;
- В случае успешной сборки, билд выкладывается на сервер раздачи;
- Итоговый IPA устанавливается на устройства “по воздуху”.
Остановимся чуть подробнее на каждом из основных компонентов.
Репозитории
В качестве хранилища исходных кодов мы используем Subversion, эта СКВ проста в использовании, клиент есть на маке у любого iOS-разработчика «из коробки». С SVN-ом есть всего два тонких момента:
- По умолчанию SVN-клиент настроен так, что игнорирует маску *.a, это приводит к тому, что файлы статичных библиотек не добавляются в репозиторий. Эту настройку надо переопределять на всех клиентских машинах.
- Для запуска сборки проекта в автоматическом режиме у нас настроен onAfterCommit-хук, который проверяет в комментарии к коммиту наличие тэга “READY”, которым разработчик помечает версию, готовую к сборке и передаче в QA.
Сервер сборки
Ядром сервера сборки мы выбрали Jenkins, развернутый на Mac-сервере. Jenkins открыт, бесплатен, прост в установке и настройке, легко расширяется сторонними плагинам и активно поддерживается.
Собственно сборка проекта заключается в чекауте исходного кода и вызове команды xcodebuild с соответствующими параметрами.
Основная (сборочная) часть – это bash-скрипт, который выглядит следующим образом:
# сборка проекта
xcodebuild -target "${TARGET}" -configuration "{$CONFIGURATION}" -project "${XCODEPROJ}" CODE_SIGN_IDENTITY="${CERTIFICATE}" PROVISIONING_PROFILE="${PROVISIONING_ID}" CONFIGURATION_BUILD_DIR="${CONFIGURATION_BUILD_DIR}"
# Здесь параметры $XCODEPROJ, $TARGET и $CONFIGURATION задаются в настройках проекта сборки
# Параметр $CONFIGURATION_BUILD_DIR задает путь, по которому будет расположена собранная app
# В параметрах $CERTIFICATE и $PROVISIONING_ID мы передаем гарантированно правильные (наши) сертификат и провижен профиль
# упаковка в IPA
xcrun -sdk iphoneos PackageApplication -v "${APPLICATION_NAME}.app" -o "${WORKSPACE}/orig_${APP_NAME}.ipa"
# заливка на сервер раздачи
curl -f -k --form "data[email]=${AIRONAPP_USER}" --form "data[password]=${AIRONAPP_PASSWORD}" --form "data[application]=${AIRONAPP_ID}" --form "data[ipa_file]=@${IPA_FILE}" ${AIRONAPP_URL}/api/1.0/http/uploadIPA
Учитывая, что наши разработчики работают на разных версиях XCode, мы поддерживаем сборку четырьмя разными версиями (по состоянию на момент написания поста): 4.2.1, 4.3.1, 4.5.1 и 4.5.2. По умолчанию используется последняя, с возможностью задать конкретную версию для конкретного проекта.
Эта возможность оказалась особенно актуальна в тот момент, когда игровой движок Unity3D имел известный баг совместимости с iOS SDK 6.0 и XCode 4.5.x. (фикс был выпущен в версии Unity3D 3.5.6)
После сборки полученный app пакуется в ipa с помощью утилиты PackageApplication, и итоговый ipa-файл отправляется на сервер раздачи билдов.
Если же сборка «разваливается» по какой-то причине, разработчик получает по почте полный лог консоли со всеми сообщениями об ошибках.
К Jenkins имеют доступ как релиз-менеджеры Alawar (для возможности запустить сборку какого-либо проекта вручную), так и внешние разработчики, например, для того, чтобы получить dSYM-файлы для анализа крэш-логов.
В качестве «железки» мы используем Mac Mini Server (Core i7 4*2.7GHz, 16Gb RAM, 1Tb HDD), данная конфигурация уверенно справляется с одновременной сборкой четырех игровых проектов. Средняя продолжительность сборки не превышает 15 минут (для проектов жанра «поиск предметов», где размер итогового ipa-файла составляет 400-600Mb). Jenkins сконфигурирован на работу в 1 мастер с 4-мя сборщиками. Из установленных плагинов можно отметить:
- Subversion Release Manager — позволяет явно указать ревизию для ручной сборки;
- Log Parser — парсит консольный вывод XCode по заранее заданным шаблонам и делает удобную навигацию по ошибкам;
- Clang Scan-Build — запускает статический анализатор и генерирует отчеты о потенциальных утечках;
- Priority Sorter — позволяет задавать проектам приоритеты и собирать более срочные/важные в первую очередь.
Сервер раздачи билдов «по воздуху»
В качестве сервиса раздачи ipa-файлов мы используем готовое решение от компании Arello Mobile – сервис AirOnApp. По сути, это аналог TestFlight с дополнительными «плюшками», такими как:
- Сервис развернут на нашей серверной площадке в офисе, что избавляет нас от внешнего трафика;
- Возможность удобного добавления новых устройств в командный аккаунт из админ-панели AirOnApp;
- Возможность паблишинга приложений в App Store из той же админ-панели.
Помимо сервера раздачи билдов мы используем небольшое приложение-клиент, на которое в случае успешной сборки отправляется push-уведомление содержащее ссылку на установку билда.
На сегодняшний день мы получили:
- Стабильно работающую автоматизированную сборку и деплоймент билдов. Она позволяет удобно и быстро принять версию у разработчиков, убедиться в корректности исходных кодов и разлить билд по тестовым устройствам с минимальным человеческим участием.
- Четкую схему версионирования проектов. С этой схемой любой участник процесса всегда знает, какая именно версия приложения установлена на устройство, в какой версии обнаружен баг и т.д.
- Удобный инструментарий по работе с Apple-аккаунтом. Он позволяет добавлять новое устройство в аккаунт, добавлять его также в провижен-профайлы, переподписывать билды обновленными провиженами, сабмитить приложения в стор.
В дальнейшем мы планируем реализовать поддержку системой автоматической сборки приложений для всех основных платформ, с которыми мы работаем (MacOS, Android, Windows, Windows 8 и тд), создав кластер из сборщиков на нескольких физических машинах под управлением соответствующих ОС с единой админ-панелью Jenkins.
Буду рад ответить на Ваши вопросы в комментариях или услышать истории о том, как подобные задачи решаются в вашей компании.
Автор: alexportnoy