Если к вам уже приходили с вопросом «Где можно получить свежую сборку?», то вы прекрасно понимаете, зачем нужна автоматизация сборки и распространения. Никто не хочет тратить лишнее время на рутинную работу. Раньше мы пользовались утилитой под названием iOSBetaBuilder (http://www.hanchorllc.com/betabuilder-for-ios/). Это приложение предназначено для упрощения распространения AdHoc сборок iOS-приложения: нужно только ввести название и версию проекта, адрес (URL), где хочется выложить сборку, и получаются сгенерированные index.html и manifest.plist. На первое время этого достаточно.
Но когда проект достигает стадии багфиксинга, тратить лишние 5 минут на сборку и перепубликацию для QA – неохота и некогда. А когда проектов становится много, а их сборки становятся дольше… В рамках компании затраты времени помноженные на количество проектов становятся слишком существенными, и приходит время автоматизации.
В этой статье мы расскажем как настроить автоматическую сборку iOS приложений, рассылку уведомлений по почте и публикацию приложения на FTP-сервере для тестирования и демонстрации заказчику.
Для тех, кто уже в теме, есть интересный раздел в конце статьи: как настроить сборки с различными версиями Xcode на одной машине.
Как настроить автоматическую сборку iOS-приложений с помощью Jenkins?
Необходимо установить Jenkins, добавить и настроить несколько плагинов, добавить агента для сборки и настроить распространение OTA. Если хочется получать еще уведомления по почте, то надо настроить дополнительный плагин.
Итак.
Что такое Jenkins? Jenkins — это сервер непрерывной интеграции. Jenkins написан на Java и имеет большое число плагинов для расширения функционала. Всю необходимую информацию для установки можно найти здесь https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins
Для поиска плагинов — https://wiki.jenkins-ci.org/display/JENKINS/Plugins, но и Гугл тоже неплохо справляется, когда знаешь, что хочешь найти.
Архитектура нашей системы получилась следующая:
- Jenkins установлен на машине с Ubuntu 12.04 LTS. Он используется для различных проектов, поэтому Xcode установлен на отдельной машине. Если вам нужно собирать только проекты для iOS, то можно установить Jenkins на компьютер с Mac OS X, и не нужно будет конфигурировать дополнительного агента.
- Разработчики заливают код в репозиторий — в нашем примере это Git.
- Jenkins запускает агента (машина с Xcode и VCS).
- Агент выкачивает код, собирает проект и, если сборка завершена успешно, заливает на сервер по FTP для распространения.
- Jenkins рассылает уведомления.
Для реализации этой системы нам понадобятся следующие плагины:
Настройка плагинов
Рассмотрим на примере сборки конкретного приложения. У нас есть некий проект, исходный код которого находится в Git-репозитории:
git@github.com:ShareKit/ShareKit.git
Мы хотим собрать его и выложить на наш внутренний сервер для распространения через Internet. Доступ Jenkins’а к серверу осуществляется по FTP, на сервере настроен Apache, и все что мы выкладываем, становится автоматически доступно нашему отделу QA или заказчикам на специальном сайте.
FTP
Чтобы настроить плагин для FTP после его установки необходимо открыть страницу настроек Jenkins:
Jenkins -> Manage Jenkins -> Configure System
В настройках найти раздел про FTP и прописать информацию для доступа к серверу.
Сохранить.
Git
Чтобы настроить Git, необходимо добавить описание Git installation на странице
Jenkins -> Manage Jenkins -> Configure System
Путь указывает, при помощи какой команды будет запускаться Git на агенте. Необходимо указать полный путь, по которому находится git на той машине, где установлен Xcode. Может появиться сообщение об ошибке, но не стоит обращать на него внимание, потому что Jenkins проверяет путь к Git на локальной машине, а не на удаленной, где мы будем его использовать.
Сохраняем.
Xcode Agent
Для работы любого агента Jenkins на удаленной машине необходимо добавить credentials для доступа к удаленной машине на странице настроек
Jenkins -> Manage Jenkins -> Manage Credentials
Также необходимо добавить публичный ключ машины, на которой стоит Jenkins в папку authorizedKeys той машины, на которой стоит Xcode. Username в форме должен совпадать с именем пользователя, под аккаунтом которого будет запускаться Xcode. Путь к файлу с публичными ключами в нашем случае будет такой: /Users/jenkins/.ssh/authorizedKeys
В нашем примере Xcode установлен на машине с IP-адресом 192.168.154.24.
Чтобы добавить агента, который будет использоваться для сборки проекта, на странице списка нод
Jenkins -> Manage Jenkins -> Manage Nodes
Нажимаем на New Node, назовем наш узел XcodeAgent, выбираем Dumb Slave, нажимаем OK.
Количество исполнителей можно поставить любое, в зависимости от мощности машины и нагрузки. У нас приложений не очень много, и один поток вполне справляется. Директория должна быть доступна пользователю, в нашем случае — /Users/jenkins/jenkinsCI
Указываем IP адрес машины, и выбираем наши Credentials:
После того, как мы нажали Save, можно переходить к созданию Job’а.
Настройка сборки – New Job
Создаем новую задачу:
Jenkins -> New Job
Вводим название задачи, выбираем тип Build a free-style software project. Нажимаем OK. В будущем для создания задач, подобных существующим, лучшим вариантом будет “Copy existing job”.
В разделе Source Code выбираем Git, указываем адрес репозитория (на картинке для примера указан ShareKit) и Git executable, который мы сконфигурировали ранее:
Заполняем остальные настройки:
С какой частотой мы хотим опрашивать систему контроля версий на наличие обновлений – мы поставили «каждую минуту». Как вы видите, Jenkins предлагает использовать параметр H, который означает, что опрос будет происходить 1 раз в час в случайную минуту, чтобы снизить нагрузку.
Конфигурация в обычном случае довольна проста. Мы используем AdHoc профили для сборки приложений для тестирования и демонстрации заказчику.
Добавляем еще один Build Action. На этот раз нас интересует публикация приложения на нашем сервере – по FTP:
Добавляем рассылку уведомлений по почте
Если у вас есть мейл-сервер, на Jenkins можно настроить рассылку писем по результатам сборки.
Сначала на странице настроек
Jenkins -> Manage Jenkins -> Configure System
указываем email адрес, с которого пользователи будут получать письма:
Указываем адрес SMTP сервера, порт и тот же email.
Плагин, который мы установили, добавляет еще один раздел настроек:
Мы можем указать формат темы письма и используемый шаблон. Все шаблоны лежат в файловой системе. Подробности о темплейтах можно почитать на странице плагина https://wiki.jenkins-ci.org/display/JENKINS/Email-ext+plugin#Email-extplugin-TemplateExamples
Кроме этого, плагин позволяет задавать список получателей и различные конфигурации для каждого статуса сборки: например, если приложение не собралось – уведомление отправляется разработчикам, собралось – тестировщикам. На картинке пример для статусов неудачной сборки и исправления.
После этого добавляем в нашу сборку Post-build Action:
Сохраняем, запускаем и радуемся!
Второй Xcode
Все хорошо, когда вы только начали делать проект и поддерживаете только самые свежие версии iOS, но время идет, мир меняется, а Apple выпускает новую iOS и новый Xcode для нее. Заказчик просит поддерживать что было и что есть, и встает вопрос о необходимости править баги старой версии, пока разрабатывается новая.
Понятное дело, мы создаем новый бранч, вешаем метки и создаем новый адрес для публикации тестовой версии. А как же Xcode?
Плагин не поддерживает переключение между версиями Xcode, поэтому у нас есть два (может кто-то придумает больше – но мы не смогли) варианта:
- настроить вторую машинку с Xcode и добавить агента в Jenkins
- заставить Jenkins переключать Xcode с помощью shell script
Мы пошли вторым путем.
Сменить Xcode можно с помощью довольно простого скрипта:
sudo xcode-select -switch $XCodePathToDeveloperFolder
– для переключения установленных Xcode необходимо обладать правами root
Однако при запуске команд по ssh возникают сложности с паролем и можно получить такую ошибку:
sudo: no tty present and no askpass program specified
Это происходит потому, что команды на Jenkins-агенте запускаются через ssh, который не предоставляет терминала.
Для решения этой проблемы нужно создать файл, например, /Users/jenkins/pass, в который поместить пароль нашего пользователя.
Нужно добавить через конвейер в скрипт по переключению Xсode команду вывода содержимого нашего файла с паролем:
cat /Users/jenkins/pass | sudo xcode-select -switch /Applications/XcodeVX.X.app/Contents/Developer
Эту команду в виде Build step – Execute shell мы добавляем первым шагом в разделе Build нашей задачи – перед Xcode.
После запуска задачи Xcode изменится, и все остальные задачи, настроенные на старую версию Xcode будут собираться неправильно. Чтобы этого избежать необходимо вернуть Xcode, на который настроены остальные проекты.
Можно было бы добавить такую же команду после выполнения Xсode, но если сборка поломается, то выполнение последовательности Build step прервется.
Нужно добавить Post-build action – Post build task, и вернуть все на место:
Собираем. Все отлично работает.
Стоит отметить, что количество executors, которое мы указали при настройке агента может повлиять на сборку, если поставить больше 1. Тогда для всех сборок придется добавить переключение Xcode на нужную версию.
Заключение
Автор: eastbanctech