Объяснение непрерывной интеграции iOS с сервером Xcode
Опубликовано: 2022-03-11Введение
До Xcode 9 использование инструментов непрерывной интеграции Apple было утомительным и сложным процессом, требующим покупки и установки дополнительного приложения macOS Server. Это привело к тому, что многие разработчики отказались от идеи непрерывной интеграции своих проектов iOS или обратились к сторонним решениям с очень разным уровнем успеха.
Однако после выпуска Xcode 9.0 в сентябре 2017 года процесс был значительно упрощен, включая возможность автоматической подписи кода, и теперь он полностью интегрирован в Xcode. Поэтому он не требует никаких дополнительных приложений или инструментов.
В то время как сторонние решения, такие как Fastlane, Bluepill и т. д., очень полезны и могут сделать за вас много рутинной работы, в этой статье будут рассмотрены возможности использования только инструментов Xcode и Apple для ваших потребностей в непрерывной интеграции. Мы также будем использовать ручную подпись кода, так как это часто кажется проблемой для многих людей, а автоматическая подпись также не является оптимальным решением, когда речь идет о множественных конфигурациях сборки.
Примечание. Эта статья основана на Xcode 9.4.1 и посвящена разработке приложений для iOS, но многое из нее применимо к Xcode 10 (в настоящее время доступно в виде бета-версии 5) и разработке приложений для macOS.
Настройка сервера Xcode
Наряду с упрощением фактического процесса интеграции, Xcode 9 также упростил процесс настройки сервера Xcode.
Запустите приложение Xcode на своем компьютере с macOS, который был назначен вашим сервером CI, и откройте «Настройки».
Перейдите на последнюю вкладку под названием « Серверы и боты ».
Включите возможности Xcode Server, щелкнув переключатель в правом верхнем углу. Затем вам будет предложено выбрать пользователя для запуска и выполнения сценариев сборки на этом компьютере. Вероятно, хорошей идеей было бы иметь выделенного пользователя только для этой цели, вместо того, чтобы использовать уже существующего.
Обратите внимание, что этот пользователь должен войти в систему для запуска любого бота Xcode. После входа в систему вы должны увидеть зеленый кружок рядом с именем пользователя.
Вот и все! Давайте подробнее рассмотрим ботов Xcode.
Как настроить Xcode-ботов
Теперь вы готовы приступить к настройке ботов Xcode для работы на этом сервере. Это можно сделать на любой машине разработки, подключенной к той же сети, что и сервер.
Откройте Xcode на своем компьютере для разработки и нажмите Xcode > Preferences в верхнем меню. Затем перейдите на вкладку « Учетные записи » и нажмите значок « + » в левом нижнем углу. Выберите сервер Xcode в появившемся диалоговом окне.
Чтобы создать бота, просто откройте свой проект в Xcode и выберите пункт « Продукт» > «Создать бота… » в верхнем меню. Настройка бота состоит из нескольких шагов, и мы рассмотрим их в следующих разделах.
Автоматизация распространения приложений
Одним из наиболее частых применений автоматизации сборки приложений iOS является настройка бота для загрузки приложения на платформу распространения iOS, такую как TestFlight, Fabric и т. д.
Как я объяснял ранее, в этой статье будет рассмотрена только загрузка в App Store Connect и загрузка непосредственно с вашего сервера Xcode, поскольку это собственные инструменты Apple для распространения приложений iOS.
Распространение App Store Connect с использованием Xcode
Перед настройкой бота убедитесь, что у вас есть запись приложения App Store Connect, которая соответствует идентификатору пакета вашего проекта разработки приложения. Также стоит отметить, что каждая сборка должна иметь уникальный идентификатор, состоящий из версии сборки и номера сборки. Мы рассмотрим, как обеспечить выполнение этих условий, когда мы будем обсуждать настройки бота Xcode позже.
Шаг 1. Настройка правильной конфигурации сборки является важным шагом для получения того, что вы хотите. Убедитесь, что вы выбрали схему и конфигурацию, которые создают приложение, которое вы хотите загрузить в App Store Connect. Это включает в себя проверку того, что в конфигурации сборки используется соответствующий идентификатор пакета, зарегистрированный на портале Apple Developer вашей команды (используется для подписи кода), а также на портале App Store Connect (используется для автоматической загрузки приложения). .
Шаг 2: На вкладке «Конфигурация» нам нужно указать параметры экспорта. Мы собираемся изучить список свойств параметров экспорта, поэтому убедитесь, что выбрано «Использовать список настраиваемых параметров экспорта».
Шаг 3: Настало время составить список свойств параметров экспорта. Полный список ключей, которые будут использоваться в этом файле, доступен, если вы введете xcodebuild --help
, но мы рассмотрим те, которые используются в этой конфигурации бота, здесь:
-
compileBitcode
— Bitcode — это промежуточный формат вывода Apple для исходного кода приложения. Другими словами, это формат, в котором ваш исходный код преобразуется перед компиляцией в машинный код для конкретной архитектуры. Он направлен на то, чтобы иметь единый контейнер кода, который можно дополнительно оптимизировать, если оптимизация будет выполнена в наборе инструкций, а также иметь возможность компилировать его для будущих архитектур из того же формата. Однако это никак не повлияет на ваше приложение. Вам решать, хотите ли вы включить его или нет. -
method
— этот аргумент указывает, какой продукт вы экспортируете. Apple различает продукты по их назначенной аудитории: разработка позволяет вам устанавливать их только на устройства, указанные в профиле подготовки, предприятия разрешают устанавливать их всем, но они должны явно доверять этому профилю разработки перед запуском приложения, а магазин приложений предназначен для распространение его в App Store или App Store Connect, поэтому мы собираемся использовать это значение. -
provisioningProfiles
— это говорит само за себя. Но здесь следует отметить пару вещей: Профили обеспечения в списке свойств параметров экспорта представляют собой словарь, в котором ключ соответствует идентификатору пакета продукта, а значение соответствует имени профиля обеспечения, используемого для кодовой подписи. -
signingCertificate
— еще один очевидный аргумент. Значением этого поля может быть полное имя сертификата или хэш SHA-1. -
teamID
— еще один очевидный аргумент. Это 10-символьный идентификатор, который Apple выдала вашей организации, когда вы зарегистрировались в программе Apple Developer. -
uploadBitcode
— следует ли загружать бит-код (если вы решили скомпилировать его), чтобы его можно было использовать в AppStore Connect для создания новых оптимизированных сборок или сборок для будущих архитектур. -
uploadSymbols
— загружает ваши символы отладки, чтобы вы могли получить содержательный отчет о сбое, а не просто дамп памяти и стек сборки.
Итак, теперь ваш список свойств параметров экспорта может выглядеть примерно так:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>compileBitcode</key> <false/> <key>method</key> <string>app-store</string> <key>provisioningProfiles</key> <dict> <key>com.bundle.id</key> <string>ProvisioningProfileName</string> </dict> <key>signingCertificate</key> <string>Signing Certificate Exact Name or SHA-1 hash value</string> <key>teamID</key> <string>??????????</string> <key>uploadBitcode</key> <false/> <key>uploadSymbols</key> <true/> </dict> </plist>
Шаг 4: Выберите созданный вами .plist в качестве списка свойств параметров экспорта.
Шаг 5: Далее идет вкладка «Расписание» — настройте ее в соответствии с вашими предпочтениями.
Шаг 6. На вкладке «Подписание» снимите флажок «Разрешить серверу Xcode управлять моими сертификатами и профилями» и самостоятельно загрузите соответствующий сертификат подписи и профиль обеспечения на странице « Сертификаты и профили ».
Шаг 7. Вкладку « Устройства » следует оставить без изменений, поскольку мы загружаем приложение, а не тестируем его.
Шаг 8. Вкладка « Аргументы » позволяет явно указать аргументы xcodebuild или переменные среды, которые можно использовать в сценариях сборки или до и после интеграции.
Шаг 9: Наконец, мы переходим на вкладку « Триггеры », которая также является последней вкладкой в настройке бота непрерывной интеграции Xcode. Это самый мощный инструмент в арсенале Xcode Server. Для начала я хотел бы добавить следующие две команды в качестве сценария предварительной интеграции:
#!/bin/sh set printenv
Первый печатает все переменные, которые использует сервер Xcode, и их значения в текущем запуске интеграции. Второй печатает все переменные среды и их значения. Как и ожидалось, это может быть полезно при отладке ваших скриптов, поэтому я удачно назвал это «информация об отладке».
Помните, что мы упоминали, что нам необходимо убедиться, что каждая сборка, загруженная в App Store Connect, должна иметь уникальную пару версии сборки и номера сборки. Мы можем использовать встроенный инструмент PlistBuddy, но нам также нужен способ получить уникальный номер сборки. Одна вещь, которая всегда присутствует во время интеграции Xcode Server, а также является удобной уникальной, — это номер интеграции, поскольку он автоматически увеличивается. Мы создадим еще один сценарий предварительной интеграции с именем «установить номер сборки» со следующим содержимым, чтобы каждый раз у нас был уникальный номер сборки:

#!/bin/sh buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}") buildNumber=$XCS_INTEGRATION_NUMBER /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
Если вы используете CocoaPods и решили не фиксировать каталог Pods в DVCS, вам также следует включить сценарий предварительной интеграции со следующим содержимым:
#!/bin/sh cd $XCS_PRIMARY_REPO_DIR pod install
Шаг 10: Мы почти закончили, но мы нигде не указали, что мы хотим загрузить сборку в AppStore Connect или в какую учетную запись. С этой целью мы добавим сценарий постинтеграции и еще один встроенный инструмент под названием Application Loader. Вставьте в скрипт следующее:
#!/bin/sh /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool --upload-app -f $XCS_PRODUCT -u $TESTFLIGHT_USERNAME -p $TESTFLIGHT_PASSWORD
$XCS_PRODUCT
— это переменная сервера Xcode, которая содержит путь к приложению, созданному в ходе текущего выполнения интеграции. Однако $TESTFLIGHT_USERNAME
и $TESTFLIGHT_PASSWORD
не являются ни системными, ни переменными сервера Xcode. Они должны быть настроены вами и иметь значение вашего Apple ID и пароля. К сожалению, Apple прекратила поддержку генерации ключа API для загрузки сборки AppStore Connect. Поскольку это конфиденциальная информация, рекомендуется настроить ее непосредственно на сервере Mac (при условии, что это ваш собственный) в качестве переменной среды, а не в конфигурации бота Xcode Server.
Распределение сервера Xcode
Бот дистрибутива Xcode Server фактически использует ту же конфигурацию, что и для дистрибутива App Store Connect, за исключением сценариев после интеграции. Тем не менее, загрузка приложения и его установка все еще могут быть сложными. Вам по-прежнему необходимо убедиться, что профиль подготовки, с помощью которого вы подписали свое приложение, позволяет установить приложение на используемое вами устройство.
После этого вам нужно будет открыть Safari на вашем устройстве iOS и перейти к веб-панели Xcode Server вашего сервера. Например, если имя вашего сервера «Mac server», вы можете найти его по адресу «mac-server-name.local/xcode», если вы находитесь в той же сети, что и сервер. Там вы найдете список всех ваших ботов Xcode и статистику их последних интеграций.
Выберите тот, который создал приложение, которое вы хотите загрузить. На следующем экране у вас будет две кнопки — « Установить » и « Профиль ». Если это ваша первая загрузка с этого сервера, вам нужно нажать на Профиль , чтобы добавить его сертификат в список доверенных источников. После этого нажмите кнопку « Установить » на той же странице, и вы увидите диалоговое окно подтверждения iOS «Вы уверены, что хотите установить * на свое устройство?» Подтвердите это, нажав « Да », и ваше приложение будет установлено и запущено с главного экрана.
Для iOS 10.3 и более поздних версий причина, по которой может произойти сбой с сообщением «Не удается подключиться к *.local», заключается в том, что самозаверяющему сертификату необходимо вручную доверять в настройках на тестовом устройстве.
Следуй этим шагам:
Шаг 1: Установите самозаверяющие сертификаты со страницы ботов сервера Xcode на свой iPhone.
Шаг 2. Перейдите в « Настройки iPhone» > «Основные» > «О программе» > «Настройки доверия сертификатов» .
Шаг 3: Найдите самозаверяющие сертификаты вашего сервера в разделе ENABLE FULL TRUST FOR ROOT CERTIFICATES и включите переключатель.
Шаг 4: Вернитесь на страницу интеграции с ботом на Xcode Server, нажмите « Установить ».
Xcode Server Автоматическое тестирование приложений
Еще одно полезное применение Xcode Server — автоматическое тестирование приложений, будь то модульное тестирование или тестирование пользовательского интерфейса. Для этого вам необходимо настроить соответствующую цель для вашего проекта. То есть вам нужно иметь цель, которая запускает модульные или UI-тесты, в зависимости от вашей цели.
Процесс настройки такой же, как и предыдущий, но мы выберем другие параметры. Первое существенное отличие заключается во вкладке « Конфигурация ». Очевидно, мы собираемся установить флажки «Анализ» и «Тестирование», поскольку это наша основная цель. Я бы также не советовал ни архивировать, ни экспортировать продукт с этим ботом. Можно добиться как тестирования, так и распространения с одной и той же конфигурацией бота. Однако эти два сценария различаются по своим результатам, а также по расписанию. Распределение часто выполняется в конце цикла.
Независимо от того, работаете ли вы в Scrum, Kanban или какой-либо другой среде, должен быть предопределенный цикл, управляемый временем или событиями, в конце которого вы должны экспортировать и использовать продукт. С другой стороны, вы должны запускать своего тестирующего бота при каждом коммите, так как это ваша первая линия защиты от регрессии. Поскольку тестовый бот, очевидно, запускается чаще, объединение этих двух ботов в один может быстро израсходовать дисковое пространство на вашем сервере. Кроме того, для завершения каждой интеграции потребуется больше времени.
После этого мы переходим на вкладку «Расписание», и мы уже рассмотрели это в предыдущем абзаце. Итак, следующая интересующая нас тема — подпись кода. Обратите внимание, что даже если ваша цель тестирования может указать, что ей не нужен профиль подготовки на странице настроек вашего проекта, вы должны настроить ее на использование той же команды и сертификата подписи, что и в ведущем приложении. Это необходимо, если вы хотите протестировать свое приложение на устройстве iOS, а не только на симуляторе. Если это ваш случай, вам также необходимо убедиться, что устройство iOS, используемое для тестирования, не будет заблокировано из-за бездействия, поскольку это может привести к тому, что ваш запуск интеграции зависнет на неопределенный срок без уведомления вас.
Теперь мы находимся на вкладке «Устройства», которая не нуждается в особых пояснениях. Просто выберите одно, несколько или все устройства (iOS и симулятор), на которых вы хотите протестировать свой код. Вы также можете проверить, следует ли запускать тесты на нескольких устройствах параллельно или последовательно. Чтобы настроить это, вы должны учитывать потребности вашего проекта (нацелены ли вы на определенный набор устройств или все поддерживаемые устройства iOS), а также аппаратные ресурсы сервера.
На вкладке « Аргументы ». нет необходимости указывать что-либо явно, так как мы будем использовать только встроенные переменные среды.
Наконец, на вкладке « Триггеры » мы представим один сценарий до интеграции и один сценарий после интеграции. Первый предназначен только для того, чтобы помочь нам в отладке, если мы столкнемся с некоторыми проблемами. На самом деле это тот, который мы уже использовали:
#!/bin/sh set printenv
Второй — тот, который уведомит нас, если один или несколько наших тестов не пройдут в текущей интеграции. Убедитесь, что он настроен на запуск только при сбоях теста. И введите следующее:
#!/bin/sh echo "$XCS_TEST_FAILURE_COUNT test(s) failed for $XCS_BOT_NAME bot on build $XCS_INTEGRATION_NUMBER" echo "You can see bot integration at:" echo "https://$HOSTNAME/xcode/bots/$XCS_BOT_TINY_ID/integrations/$XCS_INTEGRATION_TINY_ID"
Здесь следует пояснить пару вещей. Во-первых, переменные $HOSTNAME хранят значение следующего формата: имя-компьютера.local. Очевидно, что ссылка будет работать только в том случае, если вы можете подключиться к этому серверу через локальную сеть. Кроме того, при переходе по этой ссылке вы, скорее всего, получите предупреждение о безопасности от своего браузера, поскольку это https-соединение с пунктом назначения, которому нельзя доверять. Наконец, это всего лишь отправная точка для вашего сценария «Ошибка теста». Вы можете отправить электронное письмо всей команде разработчиков или открыть задачу JIRA через запрос API или что-то еще, что вы считаете наиболее подходящим и продуктивным.
Подведение итогов
Надеюсь, эта статья побудила вас не торопиться с изучением возможностей Xcode Server помимо простого создания приложения. Хотя этот пост, возможно, не помог вам именно так, как вы хотели или ожидали, его цель состояла в том, чтобы познакомить вас с открытым способом использования встроенных сред и переменных Xcode Server для достижения более высокого уровня автоматизации.
Существует множество сторонних сервисов, которые обеспечивают больше функциональности и могут выполнять гораздо больше работы за вас, включая Fabric, Bluepill и Fastlane. Но, неизбежно, полагаясь на третью сторону, вы вносите новую зависимость в свой проект и требуете иногда простой, а иногда сложной установки и настройки. Для описанных здесь методов требуются только инструменты, уже установленные на каждом Mac, поэтому они не требуют времени на настройку, кроме настройки тех самых ботов, которые будут запускать ваши автоматизированные сборки!