Статьи

Непрерывная интеграция: создание сценариев для Xcode

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


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

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


Основным предметом этого урока будет Bash-скриптинг. Сценарии Bash позволяют нам автоматизировать множество вещей, таких как добавление пользователей в систему, итерация и проверка всех файлов в группе папок, автоматическое архивирование старых файлов и многое другое. В этом руководстве мы обсудим написание сценария Bash, который автоматически создает и подписывает файл «.ipa» из нашего проекта XCode.

Скрипты Bash работают так же, как и любой другой скрипт или код, который вы могли бы написать ранее. Мы указываем команды терминала, которые будут выполняться в определенном порядке, и операционная система отвечает за их выполнение.


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

Откройте текстовый редактор и создайте на рабочем столе новый файл с именем «BashScript.sh». В конце введите следующий текст:

1
2
#!/bin/sh
echo «Hello world from Bash!»

Вы должны быть в состоянии выяснить, что происходит в этом сценарии. Во-первых (и менее очевидно) мы указываем оболочку, которую мы будем использовать для сценария, в данном случае ‘sh’ (если вы не знаете, что такое ‘оболочка’, не беспокойтесь слишком сильно, ее не нужно писать базовые скрипты Bash. Вам просто нужно знать, что строка там пока есть) Вторая строка просто печатает «Привет!» на ваше окно терминала.

Давайте попробуем запустить его. Откройте новое окно терминала и введите следующее:

, /Users/username/Desktop/BashScript.sh

Если вы видите «Привет, мир от Bash!» все заработало!



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

Измените свой код, чтобы сказать следующее:

1
2
3
4
5
#!/bin/sh
  
name=»Frank»
  
echo «Hello world from $name»

Если вы выполните сценарий снова, вы должны увидеть «Hello world from Frank» (или любое другое имя, которое вы решили добавить туда). Мы также можем передавать переменные в скрипт из командной строки. Измените строку ‘name = «frank» на:

1
name=$1

и затем выполните скрипт из окна терминала, но добавьте имя в конце:

, / Users / /Desktop/BashScript.sh Frank

Скрипт будет использовать переменную, которая была передана как переменная «1» (в данном случае «Frank»).

Это основы использования переменных в Bash. Некоторые общие ошибки, которых следует избегать:

  • Вы должны использовать двойные кавычки («) при печати строки, содержащей переменные, иначе она не будет работать правильно.
  • В объявлениях переменных не должно быть пробела между именем и значением. Например, name = "Frank" не будет анализироваться правильно.

Теперь у вас есть основы Bash! Теперь, чтобы использовать его.


Есть два основных шага для автоматизации вашей сборки из скрипта Bash:

  • Создайте файл .app и dysm
  • Упакуйте и подпишите ваш .app в .ipa

Мы используем команду «xcodebuild», чтобы скомпилировать наши проекты в файл «.app», и мы используем «xcrun», чтобы подписать приложение с помощью сертификата разработчика и объединить его в файл IPA.

Прежде чем мы создадим его с помощью нашего скрипта, давайте запустим xcodebuild из командной строки. Откройте новое окно терминала на рабочей станции Mac и измените каталоги на один из ваших проектов. Оказавшись там, введите следующую команду:

1
xcodebuild -target <Target Name>

Если вы укажете подходящее имя цели, вы увидите компиляцию приложения в окне терминала:


Это создает .app и помещает его в каталог производных данных Xcode, расположенный по адресу:

/Users/usernameLibrary/Developer/DerivedData/appname.*/

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

1
xcodebuild -target <target name> OBJROOT=/Users/<username>/Desktop/Obj.root SYMROOT=/Users/<username>/Desktop/sym.root

Запустите сборку еще раз, и вы увидите две новые папки на рабочем столе, obj.root и sym.root. Объект obj.root не слишком важен для того, что мы хотим сделать, но если вы заглянете в sym.root, вы увидите наш файл .app вместе с файлом .dysm.

Для тех из вас, кто не знает, файл .dysm позволяет символизировать журналы сбоев. Когда вы загружаете бинарный файл в apple (или в сервис, такой как TestFlight), обычно рекомендуется загружать приложения, сопровождающие файл .dysm, поэтому важно следить за этим.


Теперь у нас есть файл .app, который мы должны подписать и связать. В окне терминала перейдите в папку sym.root:

CD / Пользователи / /Desktop/sym.root/Release-iphoneos

И выполните следующую команду:

1
2
xcrun -sdk iphoneos PackageApplication -v «AwesomeApp.app» -o
«/Users/<username>/Desktop/AwesomeApp.ipa» —sign «<certificate name here>»

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


Важно отметить, что мы не указали профиль обеспечения для использования. Xcodebuild и xcrun используют профиль, который был последний раз выбран в настройках проекта Xcode.


Теперь, когда мы знаем, как это сделать из командной строки, давайте обновим наш скрипт сборки. Откройте файл «build_script.sh» (он должен находиться в папке «Scripts» на верхнем уровне рабочего каталога ваших проектов).

Удалите строку эха, чтобы у нас был пустой скрипт. Прежде всего, мы собираемся добавить некоторые переменные, которые облегчат повторное использование скрипта:

1
2
3
4
5
6
7
8
#!/bin/sh
  
appname=»AwesomeApp»
target_name=»$appname»
sdk=»iphoneos»
certificate=»iPhone Distribution: Aron Bury»
project_dir=»$HOME/Documents/Apps/iOS/awesomeapp/$appname»
build_location=»$Home/Builds/$appname

Объяснение переменных:

appname: имя приложения — это имя приложения, которое мы в основном используем для наших собственных ссылок и структур каталогов.

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

SDK: это SDK, против которого мы будем строить. Вообще говоря, это либо iPhone OS, либо симулятор. Мы, очевидно, хотим построить для iPhone OS.

сертификат: это имя сертификата в цепочке для ключей, с которым мы будем подписывать приложение.

project_dir: это каталог проекта на вашем компьютере. Переменная $ HOME — это встроенная системная переменная, которая относится к домашнему каталогу текущего вошедшего в систему пользователя.

build_location: здесь мы будем хранить файлы сборки в системе. Файлы .app и .ipa будут расположены здесь после сборки.

Очевидно, вам нужно изменить значения переменных в соответствии с вашими собственными значениями проекта. После того, как вы это сделали (и дважды проверили, что они верны), добавьте следующее в ваш скрипт под объявлениями переменных:

1
2
3
4
5
if [ !
    mkdir -p «$build_location»
fi
  
cd «$project_dir»

В приведенном выше коде мы проверяем, существует ли место сборки. Если этого не произойдет, мы создадим это. Затем мы говорим сценарию изменить каталог в каталог нашего проекта.

Наконец, мы добавляем две команды, чтобы скомпилировать, связать и подписать наше приложение. Добавьте следующее ниже команды «cd»:

1
2
3
xcodebuild -target «$appname» OBJROOT=»$build_location/obj.root» SYMROOT=»$build_location/sym.root»
  
xcrun -sdk iphoneos PackageApplication -v «$build_location/sym.root/Release-iphoneos/$appname.app» -o «$build_location/$appname.ipa» —sign «$certificate»

И это скрипт сборки! Давайте удостоверимся, что это работает. Сохраните скрипт, откройте окно терминала и выполните скрипт. Если все пойдет хорошо, у вас будут файлы сборки в указанном нами месте. Если вы получили какие-либо ошибки, не волнуйтесь. Убедитесь, что вы правильно указали свои значения и убедитесь, что приложение действительно компилируется (откройте проект в Xcode и убедитесь, что сборка прошла успешно).


Хотя приведенный выше скрипт отлично работает, путь к каталогу на нашем CI-сервере будет неправильным. Нам нужно сделать одну небольшую корректировку, прежде чем мы добавим ее в репозиторий. Вы помните последний раз, когда мы использовали переменную $ WORKSPACE в Hudson? Мы собираемся передать это значение в сценарий через Hudson. Сначала измените строку project_dir на:

1
project_dir=»$1/$appname»

А в Hudson откройте конфигурацию системы заданий и измените команду на следующую:

$ WORKSPACE / Scripts / build_script.sh $ WORKSPACE

Сохраните изменения в своем сценарии и конфигурации работы Hudson и зафиксируйте их в хранилище. Когда Хадсон обнаружит изменение, он обновит скрипт и выполнит его. Если все идет хорошо, вы должны увидеть, что сборка прошла успешно и все нужные вам файлы ждут вас в каталоге «Build» серверов, вошедших в систему пользователя!


Если есть одна вещь, которая постоянно ломает сервер iOS CI, это то, что в системе не установлены нужные сертификаты и / или профили обеспечения. Если член команды фиксирует в рабочей области XCode с выбранным сертификатом, которого сервер CI не имеет в системе, он не сможет скомпилироваться и сборка будет прервана. Это связано с тем, что Apple требует, чтобы любой код, скомпилированный для устройства, был подписан сертификатом (отдельно от подписи приложения в .ipa). По этой причине для разработчиков было бы разумно иметь систему управления этим.

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

Есть более элегантные способы решения этой проблемы, которые мы подробно обсудим в следующем уроке.


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

PS: Вы можете просмотреть и скачать готовый скрипт здесь:

https://gist.github.com/1404051