Статьи

Непрерывная интеграция: улучшения скриптов

В этой серии руководств мы рассмотрим редко обсуждаемый (но очень ценный) процесс разработки программного обеспечения, который, к сожалению, отсутствует в мире iOS и мобильных устройств: непрерывная интеграция.


  1. Непрерывная интеграция: серия Введение
  2. Непрерывная интеграция: установка Tomcat
  3. Непрерывная интеграция: установка Hudson
  4. Непрерывная интеграция: создание сценариев для Xcode
  5. Непрерывная интеграция: улучшения скриптов

В первой части мы обсудили концепцию непрерывной интеграции и то, как она может помочь нам быстрее разрабатывать программное обеспечение. Часть 2 прошла установку Apache Tomcat, веб-сервера, на котором работает программное обеспечение нашего CI-сервера. В третьей части мы установили и настроили Hudson для мониторинга нашего проекта и запускаем процесс сборки всякий раз, когда мы обновляем наш репозиторий проекта. В части 4 мы написали базовый скрипт сборки, который скомпилировал наш проект и сгенерировал файл IPA.


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


Скрипты Bash могут использовать функции так же, как и другие языки. Большие сценарии сборки могут быть довольно длинными, поэтому важно организовать их как можно больше. Функции — отличный способ сделать это.

Давайте поместим весь наш существующий код в функцию под названием «buildApp». Откройте ваш скрипт и введите следующий код:

1
2
3
4
function buildApp
{
    #existing code goes here
}

Чтобы вызвать нашу функцию «buildApp», просто введите следующее ниже объявления функции:

1
buildApp

Поскольку вы добавляете больше функциональности в ваш скрипт, вы можете размещать их в функциях с разными именами, таких как «distribteApp» или «signApp».


TestFlight — один из самых популярных сервисов, которые разработчики используют для тестирования своих приложений. TestFlight — это отличный (бесплатный!) Онлайн-сервис, который позволяет разработчикам легко загружать свои специальные IPA, а TestFlight заботится о распространении.

TestFlight предоставляет API загрузки, который мы можем вызвать из нашего скрипта bash. Это означает, что всякий раз, когда мы завершаем сборку, мы можем сразу же загрузить ее для тестирования и сообщить нашим тестировщикам, что доступна новая сборка.

Во-первых, убедитесь, что у вас есть учетная запись и получите свой API-токен и командный токен. Как только это будет сделано, добавьте API и командный ключ в верхнюю часть вашего скрипта в качестве переменных.

Во-вторых, нам нужно подготовить файл * .dysm для загрузки. Если вы не помните, для чего нужен файл * .dysm, вернитесь к статье 4 для получения дополнительной информации. Файл * .dysm должен быть заархивирован, прежде чем его можно будет загрузить в TestFlight или Apple, поэтому рекомендуется сделать это как часть процесса сборки.

Добавьте следующий код после команды «xcodebuild»:

1
2
3
4
#zip dYSM file for distribution
cd «$build_location/sym.root/$configuration-$sdk/» ||
rm -f «$appname.app.dSYM.zip»
zip -r «$appname.app.dSYM.zip» «$appname.app.dSYM»

Приведенный выше код просто меняет каталог на местоположение файла * .dysm и удаляет все zip-файлы, которые могли существовать ранее. Затем он создает ZIP-файл файла * .dysm.

После того, как это было добавлено, добавьте следующую функцию в ваш скрипт сборки:

01
02
03
04
05
06
07
08
09
10
function deployToTestFlight
{
    /usr/bin/curl «http://testflightapp.com/api/builds.json» \
    -F file=@»$build_location/$appname.ipa» \
    -F dsym=@»$build_location/sym.root/$configuration-$sdk/$appname.app.dSYM.zip» \
    -F api_token=»$TESTFLIGHT_APIKEY» \
    -F team_token=»$TESTFLIGHT_TEAM» \
    -F notes=»$appname uploaded via the testflight upload API»\
    -F notify=»False»
}

Теперь, если вам нужно выполнить развертывание в TestFlight, все, что вам нужно сделать, — это вызвать функцию «deployToTestFlight» после создания сборки.

Для получения полной информации об API загрузки TestFlight, посетите https://testflightapp.com/api/doc/ .


Иногда нам может понадобиться изменить или прочитать значения из файла * .plist. Например, мы можем захотеть хранить сборки для каждой версии приложения. Мы можем прочитать версию приложения из файла PLIST и сохранить ее в соответствующей папке. Мы также можем захотеть отредактировать значок, используемый для конкретной сборки, или иногда даже идентификатор пакета.

Чтобы установить идентификатор пакета (т.е. перезаписать исходное значение), команда:

1
/usr/libexec/PlistBuddy -c «Set :CFBundleIdentifier $bundle_id» Info.plist

Как видно из приведенного выше изображения, «CFBundleIdentifier» является ключом для значения идентификатора пакета, поэтому мы просто «устанавливаем» его как любое значение $bundle_id .

Если мы хотим прочитать значение из PLIST и установить его в качестве переменной в нашем скрипте, это немного сложнее. Нам нужно сделать немного хитрости:

1
app_version_number=$(/usr/libexec/PlistBuddy -c «Print :CFBundleVersion» Info.plist)

Приведенный выше код в скобках просто выводит значение для ‘CFBundleVersion’, а скрипт bash захватывает это значение как переменную и присваивает его переменной ‘app_version_number’.


В XCode вы можете использовать различные конфигурации для вашего проекта. Каждая конфигурация может использовать различные параметры сборки, параметры подписи кода и даже компилироваться по-разному в зависимости от макросов препроцессора. Хотя создание новых конфигураций, настройка параметров сборки и добавление макросов препроцессора выходит за рамки данного руководства, я могу показать вам, как создавать их.

При сборке используется конфигурация по умолчанию «Release», но ее можно установить с помощью специального флага при вызове команды «xcodebuild».


В этом примере у нас есть конфигурация под названием «Тестирование». Для сборки для этой конфигурации мы просто настраиваем наш скрипт сборки на основе следующего:

1
2
3
4
configuration=»Testing»
  
xcodebuild -target «$appname» -configuration «$configuration» OBJROOT=»$build_location/$app_version/$configuration/obj.root» SYMROOT=»$build_location/$app_version/$configuration/ sym.root»

Здесь мы создаем наш проект Xcode на основе определенной конфигурации и помещаем его в свою собственную папку вместе с собственным номером версии (который мы можем получить, посмотрев на info.plist, см. Добавление 3).


Если вы работаете в средних и крупных организациях, скорее всего, вы будете использовать более одного сертификата разработки / распространения для подписи своих приложений. Если вы не контролируете создание этих сертификатов, существует также вероятность того, что все сертификаты будут содержать названия ваших компаний.

Это проблема, потому что цепочка для ключей не позволяет подписывать сертификат, когда он «неоднозначен». К счастью, мы можем использовать команду «security» для добавления и удаления сертификатов в процессе сборки.

Во-первых, вам нужно будет экспортировать соответствующие сертификаты и их закрытые ключи из цепочки для ключей и добавить их в каталог скриптов. Когда вы экспортируете свой сертификат и ключ, связка ключей предложит вам ввести ключевую фразу. Введите кодовую фразу и затем сохраните файл * .p12 в каталоге сценариев вашего хранилища. Установите файл * .p12 в качестве имени переменной в вашем скрипте.


Во-вторых, удалите все сертификаты на сервере сборки, которые могут конфликтовать с используемым сертификатом.

Наконец, добавьте следующую строку для импорта сертификата:

1
security import «$WORKSPACE/Scripts/$CERTIFICATE_FILE.p12» -P «$password» -A -k ~/Library/Keychains/login.keychain

Эта строка импортирует обозначенный * .p12 в цепочку для ключей входа в систему, используя пароль «$ password».

Когда вы закончите сборку, удалите ее из цепочки для ключей следующим образом:

1
security delete-certificate -c «$certificate»

Используя описанный выше метод, вы можете создать свое приложение несколько раз, используя несколько сертификатов, которые в противном случае были бы неоднозначными.


Хотя это полезные дополнения к любому сценарию сборки, всегда найдутся конкретные способы, которые помогут вам лучше его работать. Я сделал все возможное, чтобы научить вас основам и обеспечить достаточную основу для того, чтобы у вас была прочная основа для экспериментов и дальнейшего развития.

Сценарий, содержащий все описанные выше шаги, можно найти по адресу https://gist.github.com/1404526.

Я надеюсь, что вам понравился этот учебник, и вы можете внедрить CI и автоматизированные процессы в рабочий процесс разработки. Пусть у вас будет много синих огней! 🙂