Про CI / CD ⬇️
Возвращаемся к технической теме - CI / CD! Расскажу про развитие и планы на будущее CI в iOS команде Joom
Для простоты буду писать CI вместо CI / CD
А у вас в проекте есть CI?
🤔
83.5%
У кого ж его нет🤔
6.2%
Мы в процессе🤔
10.3%
Нет :(Два года назад в команде iOS Joom не было CI
У нас был один mac mini. К нему можно было подключиться через VNC и собрать билд для QA или для релиза
Но такую систему сложно назвать CI
Всё происходило в ручном режиме. Merge в develop не гарантировал, что приложение соберется. Ответственность лежала на плечах разработчика
Я взялся за CI. В Joom все команды использовали Jenkins
К тому моменту у нас были все нужные сценарии в fastlane: сборка, увеличение версии приложения, синхронизация переводов и т.п.
Поэтому задача сводилась к тому, чтобы подружить Jenkins и mac mini и вызвать fastlane команды
А какой CI у вас?
🤔
11.0%
Bitrise🤔
31.7%
Jenkins / TeamCity🤔
40.2%
Github Actions / Gitlab🤔
17.1%
ДругойЦентральная часть Jenkins - это master
К master подключаются узлы (nodes), у которых определены тэги (node tags)
В Jenkins master указываются работы (jobs), которые описывают логику в Jenkinsfile
В Jenkinsfile указывается node tag - так master выбирает нужный node
Jenkinsfile хранится в репозитории рядом с кодом приложения. В нём используется урезанная версия Groovy и это даёт большую гибкость при описании логики job
Можно вызвать bash, fastlane и всё что нужно для iOS разработки
Для подключения mac mini к Jenkins master достаточно вызвать несложную команду в терминале. Важно, чтобы на mac mini была нужная версия java, которая совместима с Jenkins
В итоге, у нас появился первый набор job, который собирал сборку для релиза и QA с одним mac mini
Конечный результат был неидеальным:
- Регулярно mac mini отсоединялся от master
- Нужно было поддерживать fastlane сессию для релиза
- Сертификаты хранились небезопасно
Наши потребности росли, а наши мощности стояли на месте. К тому же, наш mac mini было довольно старый и сборка происходила медленно
Мы докупили 2 mac mini помощнее. Нужно было их настроить и подключить к Jenkins master
Мы не хотели настраивать каждый mac mini вручную. На разных окружениях ошибки могли становится специфичными
Сделать окружения воспроизводимыми, используя, например, docker невозможно в условиях OS X
В дополнение нужно обновлять OS X, Xcode и fastlane сессию
Первый вариант от компании veertu.com
Veertu создала продукт anka, который предоставляют виртуальное окружение OS X вроде docker-а
Это решение было для нас слишком дорогим
Второй вариант - запускать полноценную виртуализацию
Пример, проекта github.com/bacongravy/mac…
macinbox вдохновлен эпизодом сериала Mr. Robot. В одной из серий Элиот запускает виртуальную машину, чтобы проверить небезопасный CD диск
Но такое решение требовало много ресурсов
Как тебе, кстати, сериал Mr. Robot?
🤔
29.8%
Супер!🤔
17.0%
Проходной🤔
53.2%
Не смотрел(-а)В конце концов мы рассмотрели: Ansible, Chef и Puppet
Эти инструменты автоматизируют настройку и деплой программного обеспечения
А какой инструмент используется у вас?
🤔
18.2%
Ansible (Python)🤔
3.0%
Chef / Puppet (Ruby)🤔
21.2%
Своё решение🤔
57.6%
Не используемМы выбрали Ansible, потому что:
Мы нашли проект github.com/geerlingguy/ma…, в котором были нужные нам сценарии (playbook): установка Xcode, Command Line, brew пакетов и т.д.
Python был привлекательнее Ruby
Через пару недель работы с Ansible у нас был готовый playbook, который подготавливал mac mini к использованию на CI
Мы получили одинаковые окружения на всех mac mini за счёт Ansible 🎉
Однако, с увеличением mac mini пришёл другой вызов
У CI есть общие данные. Например, номер билда хранился на mac mini. А ещё у нас была статистика скорости сборки, которая так же хранилась локально на mac mini
Как бы вы решили такую проблему? Перенёс данные в
🤔
51.5%
Репозиторий🤔
33.3%
Внешнее хранилище🤔
15.2%
Общую сетевую папкуЗа счёт того, что все mac mini находятся в одной сети, самым быстрым вариантом оказалось хранить данные в файловой системе в общей папке
Один из mac mini создавал общую папку. А остальные mac-и подключались к ней через smb протокол
Позже мы увеличили количество mac mini до 4
Но, наш CI оставался уязвимым, потому что данные хранились в общей папке на одном из mac mini
Это затрудняло обновление OS X и точкой отказа CI был один mac mini. Умирает этот mac - умирает весь CI
Поэтому, мы не затягивали с переходом на внешнее хранилище
После этого окончательно каждый mac mini стал полностью независимым
Что касается Jenkinsfile, то мы поняли, что его невозможно поддерживать
Проблема Jenkinsfile-ов в том, что их нигде не запустишь кроме как на самом Jenkins
К тому же эту логику сложно переиспользовать и тестировать
В дополнение, к тому моменту в нашем проекте был зоопарк языков: Groovy, Bash, Ruby, JS, Swift, Kotlin, и даже Apple Script к нам закрался 😵
CI становился всё более и более запутанным, и это нужно было решать
Так мы начали писать всю логику CI на Swift
Для парсинга аргументов командной строки используем Apple github.com/apple/swift-ar…
В результате переход на Swift позволил писать тесты на код и проверять логику до запуска на Jenkins
CI стал понятнее и доступнее
В итоге мы автоматизировали стандартные задачи для CI: запуск билда, тестов, интеграция с трекером задач и т.д.
Сделали более продвинутые: автоматизация создания и окончания релиза, интеграция с Slack, кэширование зависимостей и другие
Сейчас CI решает задачи только Joom Marketplace
Однако в Joom становится всё больше и больше iOS проектов, которым тоже нужен CI
И сделать CI переиспользуемым - это одна из наших следующих задач
Было ли полезно, узнал что-то новое?
🤔
38.2%
Всё итак знал🤔
17.6%
Узнал новое🤔
35.3%
Хочу ещё и больше деталей🤔
8.8%
Не понятно, не интересноМихаил Масло