- PVSM.RU - https://www.pvsm.ru -
Всем привет. Это продолжение статьи [1] о том, как iOS-отдел компании Лайв Тайпинг [2] внедрил методологию CI и развернул сервер для автоматизации сборок на Jenkins. Как мы и обещали, вторая часть посвящена тому, как получить основные метрики кода, заархивировать проект в .ipa и настроить взаимодействие со Slack.
Для начала установим программы, которые будут собирать для нас статистику:
#Определение степени покрытие кода тестами
brew install gcovr
#Счётчик строк кода
brew install cloc
#Счётчик строк кода, альтернативный вариант
brew install sloccount
#Поиск дублирования кода
brew install pmd
#Генерация отчётов о результатах тестов (также генерирует данные для oclint)
sudo gem install xcpretty
#Статический анализ кода
brew tap oclint/formulae
brew install oclint
Далее нам нужно установить плагины для Jenkins, которые будут отображать полученную статистику в удобочитаемом виде:
Также установим вспомогательные плагины:
Для получения уведомлений о состоянии сборки в командном чате Slack, нам необходимо добавить соответствующую интеграцию с Jenkins в настройках Slack’а. Это можно сделать здесь [14].
После создания интеграции будет сгенерирован уникальный токен, который необходимо добавить в настройки Jenkins’а (либо в настройки отдельного job’а) — как в примере на скриншоте:
Далее настроим запуск сборок с помощью встроенного механизма команд в Slack’е. Для начала нам необходимо добавить интеграцию. Для этого пройём в подраздел Slash commands в разделе Custom Integrations и нажмём на кнопку Add configurations. Эту операцию можно выполнить здесь [15].
При настройке вам нужно указать название вашей команды, выбрать метод передачи данных POST и указать URL-адрес, на который будет идти запрос.
Рассмотрим пример формирования URL для запроса подробнее. Наш URL для примера выглядит так:
http://server:8080/buildByToken/buildWithParameters?job=JenkinsExecutor&token=XXXXXXXXXXXXXXXXX
Разберём его по составляющим:
В качестве примера будем использовать следующую структуру команды:
/build Example test master
Рассмотренная конфигурация позволит нам запускать сборку любого проекта с указанием нужной ветки, при этом будет использоваться единая команда: /build.
Данный job будет нужен нам для того, чтобы запускать другие job’ы. В нём также можно будет обрабатывать ошибки, если пользователь ввёл не существующий проект, и добавить информацию о команде (своеобразный help).
Заходим на сервер и создаём новую задачу со свободной конфигурацией и названием JenkinsExecutor. Далее в настройках job’а выставляем флаг, указывающий на то, что сборка является параметризированной и принимает параметр text. При запуске команды в Slack’е все данные (Example master test) будут передаваться единой строкой в переменной text.
Далее устанавливаем флаг, отвечающий за запуск сборки удалённо. Здесь нужно указать токен, идентичный тому, который мы установили в настройках команды в Slack’е:
Теперь нам необходимо извлечь значения из переменной text. Для этого переходим в раздел «Сборка» и добавляем шаг сборки «выполнить команду shell». Пример команды:
#Создаём массив из элементов строки, разделённых пробелом
IFS=' ' read -a array <<< "$text"
#Согласно нашему примеру, первое значение — это название проекта
JOB_NAME=${array[0]}
#Флаг, ответственный за тесты
TEST=${array[1]}
#Название ветки проекта
BRANCH=${array[2]}
#Если необходимо, можно также получить другие значения:
USER_NAME=${user_name}
CHANNEL_NAME=${channel_name}
Для запуска сборки с параметрами отправим POST-запрос на исполнение конкретного job’а. Для этого к предыдущей shell-команде добавляем следующую строчку:
curl -d TEST=${TEST} -d BRANCH=${BRANCH} -X POST
-u username:password http://127.0.0.1:8080/job/${JOB_NAME}/buildWithParameters
Здесь password — это API key пользователя username (пользователь должен иметь права на запуск job’ов).
Чтобы получить ключ:
Обратите внимание, что все запускаемые сборки должны быть параметризированными!
4.1. Первое, на что стоит обратить внимание при настройки job’а — это то, что сборка должна быть параметризированной. Для этого выставляем соответствующий флаг, добавляем текстовые параметры BRANCH и TEST и задаём им параметры по умолчанию:
Здесь стоит отметить, что для переменной BRANCH нужно дополнительно добавить значение по умолчанию. Дело в том, что если вы запустите сборку из Slack без указания ветки, то в переменной BRANCH будет пустое значение и соответственно будет ошибка. Для этого мы добавим флаг Run buildstep before SCM runs в разделе «Среда сборки». Затем добавим шаг «выполнить команду shell» и шаг inject environment variables. Делаем по примеру:
4.2. Настраиваем взаимодействие с GitLab.
Указываем адрес репозитория проекта. Указываем ветку сборки (в нашем случае это переменная BRANCH).
4.3. Настраиваем сборку по веб-хуку.
В триггерах сборки устанавливаем флаг «Сборка по пушу в GitLab». Добавляем нужные параметры и указываем ветку, для которой будет срабатывать триггер:
Затем в настройках проекта на GitLab в категории Web hooks добавляем веб-хук на сервер Jenkins’а:
4.4. Этап сборки начинается с выполнения shell-команды, которая устанавливает Pod’ы, если файл был обновлён:
if [ $(( $(date +"%s") - $(stat -f %m Podfile) )) -le 60 ]; then
pod install
fi
Затем для удобства установим некоторые переменные для проекта и запишем их в файл:
#Название .ipa-файла
PROJECT_NAME="Example"
#Название файла .xcworkspace
WORKSPACE_NAME="Example"
#Название исполняемой схемы
SCHEME_NAME="Example"
#Название папки с исходниками. Будет использоваться для подсчёта количества строк кода
FOLDER_NAME_WITH_CODE="Example"
#Записываем переменные в файл, чтобы использовать в других этапах сборки
echo PROJECT_NAME=$PROJECT_NAME > build.properties
echo WORKSPACE_NAME=$WORKSPACE_NAME >> build.properties
echo SCHEME_NAME=$SCHEME_NAME >> build.properties
В зависимости от установленного параметра TEST запускаем или пропускаем этап тестирования и генерацию отчётов. Пример того, как это может выглядеть:
if [ "$TEST" == "test" ]; then
#Создание папки reports, в которую мы будем складывать отчёты
if [ ! -d "reports" ]; then
mkdir "reports"
fi
#Тестирование и создание отчётов для анализа
xcodebuild -workspace ${WORKSPACE_NAME}.xcworkspace
-scheme ${SCHEME_NAME}
-configuration Debug
-sdk iphonesimulator
-destination 'platform=iOS Simulator,name=iPhone 6'
-IDECustomDerivedDataLocation="build_ccov"
GCC_GENERATE_TEST_COVERAGE_FILES=YES
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES
clean test | xcpretty -r junit -o reports/junit.xml -r json-compilation-database -o compile_commands.json
#Publish JUNIT test = **/reports/junit.xml
#Анализ синтаксической сложности кода
oclint-json-compilation-database -v -e Pods --
-rc=LONG_LINE=200
-rc=NCSS_METHOD=60
-rc=LONG_METHOD=100
-rc=MINIMUM_CASES_IN_SWITCH=1
-report-type pmd
-o reports/oclint.xml
-max-priority-1 1000
-max-priority-2 1000
-max-priority-3 1000
#Publish PMD analysis = **/reports/oclint.xml
#Анализ покрытия кода тестами
gcovr --object-directory="build_ccov/${SCHEME_NAME}/Build/Intermediates/${SCHEME_NAME}.build/"
"Debug-iphonesimulator/${SCHEME_NAME}.build/Objects-normal/x86_64/"
--xml
--print-summary
--exclude '.*Tests.*'
--exclude '.*Libs.*'
--exclude '.*ExternalFrameworks.*'
--exclude '.*Platforms.*'
--output=reports/coverage.xml
#Publish Cobertura Coverage = **/reports/coverage.xml
#Подсчёт строк кода (два варианта):
cloc ${WORKSPACE}/${FOLDER_NAME_WITH_CODE} -by-file -skip-uniqueness -xml -out=${WORKSPACE}/reports/cloc.xml
#Publish SLOCCount analysis = **/reports/cloc.xml
sloccount --duplicates --wide --details ${WORKSPACE}/${FOLDER_NAME_WITH_CODE} -v > reports/sloccount.sc
#Publish SLOCCount analysis = **/reports/sloccount.sc
#Анализ дублирования кода
pmd cpd --files ${WORKSPACE}/${FOLDER_NAME_WITH_CODE}
--minimum-tokens 10 --language objectivec
--encoding UTF-8
--format net.sourceforge.pmd.cpd.XMLRenderer | iconv -f macRoman -t utf-8 | sed 's/MacRoman/UTF-8/g' > reports/duplicated-code.xml
#Publish duplicate code = **/reports/duplicated-code.xml
else
touch reports/junit.xml
#Данная строчка нужна, чтобы избежать провала при сборке из-за генерации отчета плагином Publish JUNIT test result report
fi
Подробную информацию по синтаксису команд ищите на соответствующих страницах документации:
4.5. Записанные ранее переменные необходимо внедрить в процесс сборки. Для этого добавляем шаг сборки Inject environment variables и указываем нужный путь:
4.6. Следующий этап — создание сборки и архивирование в .ipa-файл. Для этого воспользуемся плагином Xcode. Делаем по примеру:
4.7. Последний шаг — добавить послесборочные операции.
Мы сгенерировали файлы для пяти отчетов, и теперь нам нужно передать эти файлы соответствующим плагинам:
На этом этапе мы можем отправить полученный в случае успеха .ipa-файл туда, куда нам нужно (на сервер, по e-mail и т.д.). Если вы хотите отправить файлы на сервер по SFTP и вы используете плагин Publish Over SSH, то нужно перейти в раздел «Среда сборки», установить флаг для Send files or execute commands over SSH after the build runs и настроить плагин в соответствии с вашими требованиями.
Последний шаг, который нам нужно добавить — Slack Notification, который, как вы догадались, отправляет уведомления в Slack. В расширенных настройках плагина можно указать индивидуальные настройки для текущего job’а. Стоит заметить, что в качестве сообщения можно указать переменную (пример: $MESSAGE), значение которой менять на разных этапах сборки и тем самым отправлять более информативные сообщения в Slack.
На этом внедрение CI можно считать оконченным. Мы надеемся, что наша статья будет для вас полезной, и просим делиться своими вопросами, соображениями и замечаниями в комментариях.
Автор: Лайв Тайпинг
Источник [22]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ios/130990
Ссылки в тексте:
[1] статьи: https://habrahabr.ru/company/livetyping/blog/302128/
[2] Лайв Тайпинг: http://livetyping.com/
[3] PMD Plug-in: https://wiki.jenkins-ci.org/display/JENKINS/PMD+Plugin
[4] SLOCCount Plug-in: https://wiki.jenkins-ci.org/display/JENKINS/SLOCCount+Plugin
[5] Test Results Analyzer Plugin: https://wiki.jenkins-ci.org/display/JENKINS/Test+Results+Analyzer+Plugin
[6] Cobertura Plugin: https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin
[7] DRY Plug-in: https://wiki.jenkins-ci.org/display/JENKINS/DRY+Plugin
[8] Environment Injector Plugin: https://wiki.jenkins-ci.org/display/JENKINS/EnvInject+Plugin
[9] Pre SCM BuildStep Plugin: https://wiki.jenkins-ci.org/display/JENKINS/pre-scm-buildstep
[10] Build Authorization Token Root Plugin: https://wiki.jenkins-ci.org/display/JENKINS/Build+Token+Root+Plugin
[11] Parameterized Trigger plugin: https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin
[12] Slack Notification Plugin: https://wiki.jenkins-ci.org/display/JENKINS/Slack+Plugin
[13] Publish Over SSH: https://wiki.jenkins-ci.org/display/JENKINS/Publish+Over+SSH+Plugin
[14] здесь: https://slack.com/apps/A0F7VRFKN-jenkins-ci
[15] здесь: https://slack.com/apps/A0F82E8CA-slash-commands
[16] OCLint: http://docs.oclint.org/en/stable/manual/oclint.html#
[17] Gcovr: http://gcovr.com/guide.html#gcovrCommand
[18] CLOC: http://cloc.sourceforge.net/#Options
[19] SLOCount: http://www.dwheeler.com/sloccount/sloccount.htm
[20] PMD (CPD): https://pmd.github.io/pmd-5.4.1/usage/cpd-usage.html
[21] Xcode Build: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html
[22] Источник: https://habrahabr.ru/post/302642/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.