Использование gitlab continuous integration для деплоя

    Совсем недавно гитлаб героически выкатил версию 8.0 своего конкурента гитхабу. Из интересного — движок continuous integration теперь встроен в платформу, а значит доступен в качестве бесплатного сервиса для всех желающих на gitlab.com. Совместно с бесплатными приватными репозиториями это делает облачный сервис гитлаб не только удобным местом для хранения кода, но также тестирования и деплоя. О последнем я и расскажу под катом.


    Continuous integration — это не только запуск юнит тестов при пуше нового кода в репозиторий. Это еще и возможность делать сборки продуктов, публиковать их в сторы, на сайты и в другие каналы распространения. Облачная телефония voximplant использует javascript сценарии, которые размещаются в нашем облаке и выполняются по команде “снаружи” или при поступлении входящего звонка. Многие клиенты для работы со сценариями используют встроенный в админку текстовый редактор, что вполне подходит для простых случаев. Но при разработке и поддержке сложных облачных систем, к примеру телефонии Bitrix24, нужно что-то более серьезное.


    Создавая voximplant мы решили не делать push-to-deploy как у heroku. У многих наших клиентов основной бизнес не связан с разработкой софта, и оставлять их один на один с git’ом не очень хорошо. Зато есть HTTP API с функцией “задеплоить сценарий”, который намекает понимающим людям что сценарии можно хранить на gitlab и деплоить с помощью shell скрипта и curl. Большинство клиентов так и делает, но у подхода есть серьезный недостаток: скрипт нужно не забыть вызвать. Более того, вызывать его надо только если код был запушен в production ветку. И только после того, как прошли тесты. Вообще много способов ошибиться.


    Настройка continuous integration в gitlab



    По умолчанию continuous integration в гитлабе выключено и необходимо его включить в настройках:



    После включения в левом меню настроек проекта появляется несколько новых пунктов, самый интересный для нас — это «runners». Continuous integration в гитлабе работает следующим образом:

    1. Вы делаете push в репозиторий
    2. Если в корне проекта есть файл .gitlab-ci.yml, то гитлаб понимает что для этого проекта будет использоваться continuous integration.
    3. Гитлаб ищет запущенный runner, подключенный для этого или для любого проекта. Runner — это приложение, которое обычно запускают на отдельном компьютере и которое будет собственно осуществлять continuous integration: прогонять тесты, собирать исполняемые файлы, осуществлять деплой. Можно запустить свой runner, к примеру на маке чтобы собрать приложение для iOS. Можно использовать “gitlab public runner”, но они не то чтобы очень безопасны и входящие очереди задач у них обычно многочасовые.
    4. Гитлаб передает yaml файл runner’у, который обновляет исходники в своем репозитории и выполняет команды, описанные в этом файле. Команды могут быть как простые, к примеру сделать деплой сценария в облако voximplant. Так и сложные: запуск docker контейнера, сборка в нем проекта, запуск тестов и так далее.
    5. После выполнения скриптов runner рапортует обратно гитлабу результаты, которые можно посмотреть рядом с соответствующим коммитом.


    Установка gitlab ci runner


    Для нашего примера мы запустим runner на машине разработчика. Инструкции по установки для windows/linux/osx доступна на официальном сайте, после установки мы получаем в свое распоряжение command line утилиту gitlab-ci-multi-runner. Запущенный runner подключается к гитлабу и ждет задачи на сборку. Но как гитлаб узнает, какие задачи какому runner’у давать? Чтобы “привязать” runner к своему аккаунту и проекту (или нескольким проектам) необходимо вызвать gitlab-ci-multi-runner с ключем register и ввести параметры подключение: url гитлаб (так как гитлаб может быть развернут локально в вашей сети) и токен регистрации, который, собственно, и определяет аккаунт/проекты:



    Зарегистрированный runner запускается командой gitlab-ci-multi-runner run и ждет задачу от гитлаба. С помощью ключей командной строки install и start runner можно зарегистрировать в системе как сервис, чтобы он автоматически стартовал после перезагрузки операционной системы.

    Конфигурация continuous integration для деплоя


    Как я уже писал, задачи continuous integration описываются в файле .gitlab-ci.yml который необходимо разместить в корне проекта. Редкоземельный синтаксис YAML является как-бы-человекочитаемой альтернативой JSON’у, документация доступна на официальном сайте. Конфигурационный файл для деплоя проекта в voximplant будет максимально простым, все что нам нужно — это сделать один вызов HTTP API как описано в нашей документации. Если исходить из предположения, что runner выполняется на компьютере где установлен curl, а код сценария находится в файле scenario.js, то конфигурационный файл для деплоя будет выглядеть следующим образом (Упрощенный пример. Настоящий побольше будет, к примеру api_key имеет смысл вынести в переменную окружения, см. комментарий nmike):

    before_script:
      - npm install
    stages:
      - deploy
    deploy:
      script:
      - curl -X POST "https://api.voximplant.com/platform_api/SetScenarioInfo/?account_id=1&api_key=2&required_scenario_name=foo" --data-urlencode scenario_script@scenario.js
    


    В curl используется синтаксический сахар нашего API, которое может принимать аргументы как в компоненте query передаваемого url, так и в body http запроса.

    Чтобы continuous integration заработал достаточно сделать push в репозиторий: гитлаб обнаружит файл .gitlab-ci.yml, найдет подключенный runner, передаст ему содержимое этого файла, runner обновит свою копию репозитория и запустит скрипт деплоя, который отгрузит исходный код в наше облако.

    Вопросы, уточнения, комментарии? Gitlab vs Jenkins vs Bamboo vs Teamcity?
    Voximplant
    Облачная платформа голосовой и видеотелефонии

    Comments 23

      +2
      Вкусно, но рецепт можно сделать так, чтобы деплой делался только при пуше (или аппруве мерж реквеста) в отдельную ветку, типа deploy или release, или еще как-то обозначающую, что это именно в релиз, а все остальные ветки, и даже теги, тестировать на других раннерах. Мастер, к примеру, можно выкатывать на тестовую среду, если таковая имеется.
        0
        Это настраивается на уровне .gitlab-ci.yml — директивы only и except в описании задачи doc.gitlab.com/ci/yaml/README.html
          0
          Спасибо, но это был не вопрос. По предложенной схеме мы работаем.
        +1
        а если мы сам yuml-файлик пушим, оно как его тестит?
          0
          Не понял вопроса. «Оно» и «Его» — это кто такие? О_О
            0
            Тестит сам файлик? Вот тут в самом низу есть
            Validate the .gitlab-ci.yml

            Each instance of GitLab CI has an embedded debug tool called Lint. You can find the link to the Lint in the project's settings page or use short url /lint.

              0
              Нужно добавить в .yaml файл вызов /lint с указанием этого файла.
            +1
            — curl -X POST «api.voximplant.com/platform_api/SetScenarioInfo/?account_id=1&api_key=2&required_scenario_name=foo» --data-urlencode scenario_script@scenario.js
            вот тут вы предлагаете приватные данные прям в репозиторий пушить? так нельзя делать.
            Для этого есть Variables
            Storing API keys

            In GitLab CI 7.12 a new feature was introduced: Secure Variables. Secure Variables can added by going to Project > Variables > Add Variable. This feature requires gitlab-runner with version equal or greater than 0.4.0. The variables that are defined in the project settings are send along with the build script to the runner. The secure variables are stored out of the repository. Never store secrets in your projects' .gitlab-ci.yml. It is also important that secret's value is hidden in the build log.

              0
              Согласен. Увы, если в статье писать вообще все что в настоящем ci делается — это будет wall of text, который никто никогда не будет читать :)
              +1
              Я столкнулся с проблемой, что когда я делаю пуллреквест, тесты запускаются только на последнем коммите пуллреквеста, что провоцирует методологию разработки «сделай как-нибудь, а потом допили до зеленой кнопочки».
              Может, кто-то смог это решить?
                0
                Ммм… Ну вообще DVCS именно так работает — мы коммитим-коммитим-коммимтим локально, а когда оно все готово и собирается — пушим и оно делает тест по последнему коммиту. Промежуточные как бы показывают процесс работы, оно и не должно собираться/тестироваться. Если я правильно понял вопрос, конечно :)
                  0
                  С моей точки зрения, каждый коммит должен быть (to the best of developers knowledge) рабочим чекпоинтом в жизни приложения. Все промежуточные нерабочие коммиты сквошатся в кошерные рабочие во время создания пуллреквеста.
                  Собственно, это следствие названия continious deployment. Если бы только некоторые коммиты представляли собой рабочие версии, deployment был бы не continious а какой-то discrete что-ли.
                    0
                    К этому есть два подхода — сквошить или не сквошить. Я уже старый, память плохая, большие коммиты читаю с трудом. Так что я за то, чтобы не сквошить — коммиты меньше, читать проще, комментарии к коммитам помогают.
                      0
                      Гранулярность коммитов — это ортогональный вопрос, я не предлагаю же все в один запихать. Чем больше, тем лучше, но работать должен каждый, чтобы сделать deployment continious.
                      Собственно, это все, наверное, философия, но факт в том, что я долго ковырялся в интернетах и так и не нашел, как запускать тесты на всех коммитах пуллреквеста. Вопрос-то про это был.
                        0
                        Видимо это от того, что большинство разработчиков придерживается того же подхода что и я: коммиты — штука промежуточная, результат работы — это пуш. Проверять надо только результат работы.

                        Чем помочь вам не знаю :(. На вскидку — форкнуть gitlab и сделать нужное поведение в коде. Но это вызывает множество вопросов с отображением, останавливаться ли если очередной коммит не прошел тесты, делать ли деплой на последнем или на всех… Вообщем странная и сложная штука. Если так нужно — дерзайте!
                          0
                          Я тоже пока вынужденно вашего метода придерживаюсь, но это только от безысходности :(
                            0
                            ну так настройте пушь после каждого коммита — будет вам счастье.
                              0
                              Что это значит? Я же не в мастер коммичу, я делаю бранч, в нем работаю, а потом делаю пуллреквест. И хочется запрещать мерж пуллреквеста, если в нем есть плохой коммит.
                                0
                                Вы работает в бранче. После комита в бранче, настройте автоматический пушь бранча. Так получите проверку каждого коммита. Только вот если у вас с коммитом плохо, все превращается, как вы сказали:
                                методологию разработки «сделай как-нибудь, а потом допили до зеленой кнопочки».


                                Вообще, вам не это вероятно надо, а настроить хуки на прогон тестов на локальной машине на каждый коммит и реджектить его, пока не станет «зеленым».

                                Просто не понятно, вот вы сделали 10 комитов в ветку и пушите. И на сервере есть проверка каждого коммита. И вот у вас 7 завалилось — чем это лучше? и что вы будут делать на сервере с уже запушинными «красными» комитами?
                          0
                          Зависит от того, придерживаетесь ли вы идеи с фичебранчами. Мне они нравятся как раз тем, что там можно творить любой ад и это не портит главную ветку репозитория. Бывают гигантские задачи с огромными по объёму рефакторингами. Закоммитить их в рабочем состоянии посередине может быть нереально.
                            0
                            При чем тут фичебранчи? Какой бы ветка ни была, при мерже её в мастер либо сквошить и терять историю, либо не сквошить и портить мастер плохими коммитами, либо пускать тесты как-то не через систему.
                              0
                              Я не совсем понимаю почему мастер будет испорчен плохими коммитами. Мы ж не ребэйзим, мы мёрджим, так? В мастере будет один коммит про то, что смёрджен бранч такой-то, какие бы коммиты в этом бранче не были.
                          0
                          А так откатили коммит и получили не рабочую версию. Непорядок.

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