company_banner

Как переехать с BuddyBuild на GitLab CI за 4 часа



    Предыстория


    Полтора года назад команда iOS FunCorp переехала на новый сервис для простой организации CI в iOS и Android-проектах.

    До этого мы использовали CI на Bamboo, но с ним было много проблем, поэтому мы совсем отказались от него и перешли на BuddyBuild.

    Он работал настолько просто, что можно было даже не знать, что такое CI и как заливать приложение в AppStore, а спокойно заниматься кодом, тестами и продуктовой разработкой.
    Но времена поменялись, и BuddуBuild уже не тот, поэтому мы начали поиск альтернативы.
    В этой статье мы расскажем о новом решении, которое выбрала наша команда, и дадим несколько скриптов для организации CI собственными силами.

    Просто — значит хорошо


    В BuddyBuild нас привлекла простота. Для начала нужно сделать всего несколько шагов:

    1. Авторизоваться через GitHub/GitLab/BitBucket.
    2. Указать репозиторий с проектом.
    3. Отдать сервису аккаунт и distribution-сертификат.
    4. Подождать, пока «случится магия» на стороне сервиса.

    И сразу после этого можно получать тесты и артефакты по всем веткам, настраивать правила сборки с помощью понятного UI, быстро переключаться между версиями XCode и релизить в AppStore/TestFlight прямо из сервиса.

    Когда мы начинали работать с BuddyBuild, его можно было использовать бесплатно, но через несколько месяцев это закончилось. Сейчас стартовый пакет стоит $79 в месяц. Для себя мы выбрали план с тремя конкурентными сборками за $279.

    BuddyBuild работал хорошо, но это длилось недолго.

    С ростом популярности сервиса, а также с увеличением количества кода в iFunny время сборки увеличилось со стабильных 20 минут на тесты и сборку артефакта до 70 минут.

    Мы пробовали найти решение для кеширования средствами сервиса, но ничего достойного в простых настройках не нашлось.

    Тем временем сервис выкупила Apple, и мы приняли окончательное решение от него отказаться.

    Требования к CI/CD


    Исходя из предыдущего опыта работы с CI, у нас было несколько требований к новой системе.

    1. Она должна быстро разворачивать агентов и среду для сборки с минимальным количеством заходов в UI агентов.
    2. Обновлять Xcode без захода в UI агента и иметь возможность переключения между несколькими версиями.
    3. Интегрироваться с системой pull requests.
    4. Использовать минимум сторонних зависимостей для сборки и выгрузки в AppStore.
    5. Иметь возможность настраивать и кастомизировать шаги сборки для разных веток.
    6. Запускать сборку артефакта только по кнопке из UI.

    GitLab CI


    Вместе с решением отказаться от BuddyBuild появилась идея мигрировать c GitHub на GitLab, а в нём уже есть встроенная CI/CD система, то есть присутствует необходимая нам интеграция с merge requests.

    Установка рабочего окружения на агента


    Первым делом нужно включить возможность доступа к агенту по SSH с помощью Screen Sharing. Это делается в настройках Sharing:



    Теперь, чтобы подключаться к CI-агенту, мы можем использовать терминал и SSH-клиент:

    ssh user@local.ip

    После успешного подключения по SSH нужно отключить использование пароля для команды sudo. Может показаться, что это небезопасно, но с учётом, что все агенты у нас доступны только внутри локальной сети, для лучшей автоматизации мы отключаем пароль для sudo. Для этого:

    sudo visudo

    Откроется стандартный редактор Vim, в котором нужно поменять строку:

    %admin            ALL = (ALL) ALL

    на строку

    %admin          ALL = (ALL) NOPASSWD: ALL

    Многие iOS-разработчики не любят копаться в консоли и редко используют Vim, поэтому держите пошаговую инструкцию, как поменять эти строки:

    1. Нажимаем i, входим в режим insert.
    2. Стрелками находим нужную строку и меняем её.
    3. Далее esc.
    4. Вводим :w для сохранения.
    5. Вводим :q для выхода из visudo.

    Первым делом на каждом агенте нам понадобится менеджер пакетов Homebrew, который можно установить следующей командой:

    sudo echo | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

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

    • XCPretty. Он позволяет красиво форматировать вывод стандартной команды для билда iOS-проектов xcodebuild;

      sudo gem install xcpretty
    • fastlane. Его возможности мы используем по минимуму, так как не хотим, чтобы билд проекта сильно зависел от чего-то стороннего;

      sudo gem install fastlane
    • xcode-install. Этот инструмент позволит устанавливать Xcode без захода в AppStore и переключаться между несколькими версиями;

      sudo gem install xcode-install
    • CocoaPods. Этот менеджер зависимостей знаком каждому iOS-разработчику.

      sudo gem install cocoapods


    Теперь можно установить Xcode, запустив последовательно команды:

    export FASTLANE_USER="your@account.todevapple"
    export FASTLANE_PASSWORD="yourpasswordtoaccont"
    xcversion install 9.2

    Можно не выполнять export, но тогда e-mail и пароль от Apple ID будут запрошены в процессе установки.

    После этих несложных действий агент готов к тому, чтобы собирать большинство iOS-проектов.

    Регистрация агента


    Для того чтобы проект на Gitlab CI увидел ваш агент, необходимо установить его и зарегистрировать.

    Это также можно выполнить с помощью SSH и командной строки на агенте:
    Сначала скачиваем и устанавливаем агента:

    curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64

    Даём права на выполнение:

    chmod +x /usr/local/bin/gitlab-runner

    Устанавливаем gitlab-runner как сервис и запускаем его:

    gitlab-runner install
    gitlab-runner start

    Теперь нужно зарегистрировать runner на CI, это выполняется командой:

    gitlab-runner register -n --url CI_URL --registration-token TOKEN --tag-list fastlane,cocoapods,osx_10-13,xcode_9-2 --executor shell

    Это команда, которую стоит пояснить подробно.
    CI_URL и TOKEN можно взять в настройках проекта на GitLab:
    Settings -> CI/CD -> Runners ->блок Setup a specific Runner manually
    --tag-list: указываются теги, которые потребуются нам далее при настройке самого проекта.

    Их также можно будет менять, например, в зависимости от того, какие версии Xcode установлены на агенте или какой тип задач мы планируем выполнять на нём.
    --executor shell: указываем, что на агенте необходимо выполнять действия в командной строке.

    Чтобы не возникло проблем с CocoaPods, также нужно выполнить команды:

    echo 'export LC_ALL="en_US.UTF-8"' >> ~/.bash_profile
    echo 'export LANG=en_US.UTF-8' >> ~/.bash_profile

    Это необходимо, чтобы при установке подов не было ошибок с кодировкой.
    После успешной регистрации агента его можно будет увидеть в настройках.
    Settings -> CI/CD -> Runners



    Настройка проекта


    Осталось настроить Xcode-проект для работы с GitLab CI.

    Сделать это достаточно просто: нужно положить файл .gitlab-ci.yml с описанием в корень проекта.

    После того как данный файл будет добавлен в репозиторий, CI система начнёт выполнять команды, указанные в нём.

    Пример нашего yml-файла:

    stages:
      - test
      - archive
    
    before_script:
        - git submodule init
        - git submodule update --recursive
        - pod install --repo-update
    
    archive_project:
      stage: archive
      script:
        - fastlane match appstore
        - xcodebuild -workspace iFunny.xcworkspace -scheme iFunny archive -archivePath build/iFunny.xcarchive | xcpretty
      only:
        - master
        - triggers
        - web
      artifacts:
        paths:
        - build/iFunny.xcarchive
      tags:
        - xcode_9-2
        - osx_10-13
        - cocoapods
        - fastlane
    
    test_project:
      stage: test
      script:
        - xcodebuild test  -workspace iFunny.xcworkspace -scheme iFunny -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.2' | xcpretty
      tags:
        - xcode_9-2
        - osx_10-13
        - cocoapods
        - fastlane
    

    yml-формат для GitLab CI достаточно хорошо описан здесь.

    Чтобы можно было легко использовать пример файла, опишу основные моменты, которые используем мы:

    • before_script — описываем набор инструкций, которые необходимо выполнять перед каждой работой на CI. Для нас это стандартный набор из обновления сабмодулей и установки подов;
    • archive_project — название, которое используется, для получения артефакта с xcarchive.

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

    fastlane match appstore

    Для синхронизации сертификатов у fastlane есть хорошая команда match (подробнее про использование match можно прочитать на сайте fastlane).

    Основная команда на запуск сборки архива:

    xcodebuild -workspace Project.xcworkspace -scheme ProjectScheme archive -archivePath build/Project.xcarchive | xcpretty
    

    Project.xcworkspace — файл с workspace.
    ProjectScheme — схема с основным таргетом.
    build/Project.xcarchive — путь, по которому соберётся рабочий артефакт. Далее этот путь используем в artifacts: он указывает CI, откуда нужно забрать архив.

    В блоке only указываем, что данную работу нужно выполнять только на ветке мастер или при запуске из веба, то есть при запуске по кнопке Run Pipeline в CI/CD.

    tags — это те теги, которые должны быть прописаны на агенте, чтобы он мог запускать эту работу. Сейчас они полностью повторяют то, что мы указывали при регистрации агента.
    Далее в файле идёт описание работы test_project.

    Из интересного здесь — строка запуска тестов:

    xcodebuild test  -workspace Project.xcworkspace -scheme ProjectScheme -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.2' | xcpretty
    

    В настройке -destination указываем тот симулятор, который точно доступен на агентах.

    Посмотреть список доступных устройств на агенте можно через SSH командой:

    instruments -s list

    После того как будет сконфигурирован файл .gitlab-ci.yml, можно добавлять его в репозиторий и автоматически будет произведён запуск тестов в ветке, содержащей файл.

    Заключение


    Чтобы настроить всю связку GitLab и встроенной CI/CD-системы, мы потратили примерно половину рабочего дня, что несколько больше 20 минут, потраченных на настройку BuddyBuild.
    Но что мы получили от переезда:

    • собственных агентов для сборки проектов и систему работы с ними;
    • удалось сократить с 70 до 6 минут время на сборку с тестами или до 30 минут на полную сборку с тестами и архивами;
    • возможности для оптимизации времени сборок;
    • нам доступна любая кастомизация и интеграция с любым сервисом.

    Для нашей команды GitLab CI — это временное решение, сейчас мы готовимся к переезду на Jenkins, в котором добавим ещё больше автоматизации в проект.

    Возможно, описанный в статье опыт позволит читателям переехать на GitLab CI менее чем за 4 часа.

    А чтобы это легче было сделать, вот пара скриптов с командами, описанными в статье:

    FunCorp
    Разработка развлекательных сервисов

    Comments 6

      0
      Когда бадди билд офигел и запел что не гитхаб репозитории нельзя юзать без покупки бизнес акка за 400 баксов, вроде бы. Я тут же начал искать альтернативу. И нашёл, это bitrise.io.

      Можно настраивать не только иос и андроид, а свои скрипты писать. По сути конструктор.
        0
        С ростом популярности сервиса, а также с увеличением количества кода в iFunny время сборки увеличилось со стабильных 20 минут на тесты и сборку артефакта до 70 минут.
        я может что то упускаю, но какое отношение CI имеет к скорости сборки артефактов и запуска тестов на удаленных агентах? Если удаленный агент перегружен, выполняет много билдов в данный момент, то как поможет смена CI как такового?
          0
          На BuddyBuild мощности одного агента распределяются между несколькими проектами.
          После переезда сборка артефактов происходит на наших мощностях. В стороннем сервисе мы этим не управляли.
          +3
          Для нашей команды GitLab CI — это временное решение, сейчас мы готовимся к переезду на Jenkins, в котором добавим ещё больше автоматизации в проект.

          Вас в чем-то ограничивает GitLab CI?
          Какие дополнительные возможности открывает Jenkins для автоматизации?
            –2
            Вот почему будет Jenkins:
            • Большое сообщество
            • Есть несколько интересных нам плагинов с интеграцией
            • Команде DevOps проще поддерживать решение на нём

            GitLab CI можно порекомендовать небольшим командам, у которых пока нет инфраструктуры CI совсем.
              0
              Какие дополнительные возможности открывает Jenkins для автоматизации?
              из личного опыта так сказать (последние пару лет работаю исключительно с Jenkins, в котором можно сделать все, на что только хватит фантазии). В GitLab CI с этим было очень печально, какие то базовые вещи без проблем, но шаг влево или вправо и приплыли. Да и сам gitlab тяжелый очень, помню на машине с 2 Гб он еле ворочался.

              Так же очень не нравилось, что с каждым выпуском они почти полностью меняли UI, честно говоря утомляло каждый раз привыкать к новому расположению. Обновления самого гитлаба были частенько кривыми (я использовал omnibus пакет) и запросто могли разломать систему

              Может кто подсказать, кто активно использует gitlab:

              1. Есть ли там возможность гибкой настройки авторизации по проектам? Например, создать группы, которые смогут только запускать просматривать джобы, только запускать

              2. Как обстоят дела с multi-configuration проектами? Т.е. когда для запуска используется сложная матрица?

            Only users with full accounts can post comments. Log in, please.