🔥

Тред (Михаил Масло)


Про 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% Не понятно, не интересно

Михаил МаслоМихаил Масло