Представьте что в Роскосмосе решили собрать новую ракету не имея при этом чертежей и четкого понимания как ракета должна быть устроена. Отдельный завод занимается корпусом ракеты, отдельный выпускает двигатели, еще один — сопла. Главный менеджер Роскосмоса сказал что он доверяет профессионалам, и мастерски сделегировал всю работу заводам.
Через год все составные части доставляются в главный сборочный цех, и выясняется, что двигатель не входит в корпус, а сопла начинают плавиться даже при тестовых запусках двигателя.
Чтобы такой фигни не случалось, в реальных проектах всегда есть этап планирования и проектирования, на котором фиксируются спецификации того как части будут взаимодействовать между собой и какими характеристиками ни должны обладать.
При разработке ПО мы не можем себе позволить долгий этап проектирования, т.к. за это время потеряется бизнес-ценность того что мы пытаемся разработать — нас тупо обойдут конкуренты.
Поэтому команды, разрабатывающие составные части программы(модули) зачастую вынуждены работать не до конца понимая как их модуль будет взаимодействовать с остальными частями.
Как и в случае с ракетой, при попытке выпустить новый релиз приложения, разрабатываемого по частям несколькими командами, может выясниться что какие-то из модулей не совместимы.
В 1991 году Гради Буч, видимо, устал от такого безобразия, и предложил делать сборку всего проекта каждый день, чтобы выяснять несовместимости не в день релиза, а пораньше — и назвал этот подход Continuous Integration.
Действительно, компилировать программу проще, чем собирать ракету (особенно из недоделанных компонентов), так почему бы не начать это делать раз в день? В Экстремальном Программировании решили эту тему усугубить, и устраивать сборку несколько раз в день.
Что такое сборка?
Ну, например, нужно скопировать модули в одно место и запустить компиляцию программы.
Если все получилось, то сборку можно считать успешной, если нет — то у команды появляется повод разобраться подетальнее, и решить проблему пока все не зашло слишком далеко.
В интерпретируемых языках типа PHP, Python и Ruby компилировать нечего. В них сборкой может являться запуск юнит-тестов, деплой веб-приложения на тестовый сервер, и прогон acceptance-тестов на этом тестовом сервере.
Итого, Continuous Integration — это практика. Назначение практики — уменьшить количество интеграционных факапов, повысить качество выпускаемого софта. Способ — запуск сборки проекта несколько раз в день.
Допускаю что Гради Буч в стародавние времена начинал практиковать CI вообще вручную, бегая по отделам своей компании, и заставляя всех давать ему дискеты с последними версиями модулей, а потом с языком наперевес все это вручную компилировал :)
Нам в нашем 2018 уже чуть попроще — процесс CI автоматизирован в куче систем — выбирай любую на свой вкус:
Про CI-системы
Их довольно много. Они разные. Есть специализированные под конкретный язык программирования. Есть заточенные под разработку мобильных приложений, есть встроенные в IDE, есть с настройкой через GUI, есть с настройкой через конфигурационный файл в репозитории. Часть работает только в облаке, некоторые можно устанавливать на свои сервера.
Мы не будем сейчас пытаться охватить их все. Возьмем только современные системы общего назначения, представляющие из себя веб-приложения.
Современная разработка подразумевает что вы используете Version Control систему.
Version Control — это почти всегда git.
Git — это почти всегда GitHub или аналогичный сервис.
Best practice современной разработки — фичебранчи и пулреквесты.
CI как раз отлично вписался в историю с пулреквестами.
Вы не только видите все изменения, обсуждаете разработку конкретной фичи в одном месте, у вас тут же показывается статус соответствующей CI-сборки:
(здесь сборка провалилась — надо идти в Details, выяснять что где поломалось и чинить)
Починили, закоммитили, запушили, и процесс начинается по новой — CI-система детектит новые изменения на ветке и запускает новую сборку:
Сборка может состоять из нескольких этапов. Самые типичные — тесты, компиляция, деплой.
Естественно, CI-системе нужно объяснить что из себя представляют эти этапы.
Настройка CI-систем
Все правильные CI-системы исповедуют принцип configuration as code, когда инструкции для CI-системы — это просто еще один файл в репозитории вашего проекта. Как то так сложилось, что в большинстве систем для инструкций используется формат YAML.
Простейший файл с инструкциями для GitLab CI может выглядеть так:
И тут мы вспоминаем что все эти инструкции должны где-то запускаться.
Что у CI-систем под капотом
На каждый пуш в репозиторий CI-система создает виртуальную машину, внутри которой запускает ваши инструкции, забирает результаты работы, и гасит машину:
Чистая система каждый раз нужна для того чтобы ограничить влияние внешних факторов на сборку.
Некоторые CI-системы используют для этого докер, некоторые выкручиваются без него. Хинт: берите ту, что с докером ;)
Зачем это всё обычному разработчику?
Чем больше аспектов разработки ты способен закрыть, тем больше твоя ценность. Если ты просто написал код, запушил, а дальше хоть трава не расти — это одно. Если ты при этом позаботился о тестах и о деплое приложения — совсем другое. Если ты это все автоматизировал в CI — третье :)
Просто поймите, что через время CI будет такой же дефолтной штукой как и Version Control.
Приведу вам пару ситуаций из практики. Вполне возможно что вы в какой-то из ни побывали:
Ситуация №1
Два разработчика разрабатывают на разных ветках. У каждого из них тесты проходят успешно, в том числе и после мержа c мастером.
Но как только обе ветки вмержены в мастер, тесты начинают падать. Проблема в том что без CI такой код запросто может уйти в продакшн, и наличие ошибки выяснится уже только там.
Сиуация №2
Команда из пятнадцати человек разрабатывает веб-приложение. У Василия на носу семейный праздник. Он отпросился у начальства уйти пораньше, не очень тщательно проверив работоспособность кода, запустил в командной строке деплой, и ушел с работы, залочив компьютер, и заодно отключив телефон — семья же важнее работы!
В результате продакшн поломан, логи деплоя остались на залоченном компе, оставшиеся разработчики рвут на себе волосы в попытках понять что же было задеплоено, и что пошло не так в процессе деплоя, и кто вообще виноват.
Если в команде используется CI-система, то все логи деплоя (и любых других задач) сохраняются в ней, так что всегда можно посмотреть что пошло не так.
Open source проект на GitHub скорее всего гоняет тесты в Travis CI. Вы не сможете с этим не столкнуться. Ок, берем Travis CI на заметку, но гуглить и обчитываться мануалами пока не бежим.
Если в двух словах, то исследовались текущие возможности CI-системы, потенциал для развития, и текущий размер рынка.
Кому интересна методология тестирования, читайте само исследование. Нам же интересны выводы.
В лидерах оказались:
4) CloudBees — это компания стоящая за Jenkins. Это одна из старейших CI-систем c открытым исходным кодом, и было бы странно не увидеть их в лидерах.
3) Circle CI уже во втором источнике оказался в лидерах. Значит тоже заслуживает внимания.
2) Microsoft — no comments. Огромная компания с огромным влиянием. Если вы разрабатываете софт под винду, то скорее всего у вас даже не будет стоять вопрос выбора. Если в компании куплены лицензии на майкрософтовский стек разработческих инструментов с TFS и их CI-системой, вы просто будете есть что дают, не особо смотря по сторонам
1) GitLab на первом месте. Для тех кто не следит за компанией последние несколько лет, это может оказаться полным сюрпризом. Поговорим про него поподробнее.
GitLab
Автор год работал в Гитлабе на позиции Developer Advocate, так что вы имеете полное право считать меня предвзятым и выкрутить регулятор скептичности на пару десятков процентов при прочтении следующих абзацев. Тем не менее считаю, что многие вещи про Гитлаб надо знать, а еще лучше — начинать им пользоваться.
Важно что Гитлаб отказался считать себя просто клоном Гитхаба, и в компании решили развивать Гитлаб в сторону “системы одного окна” для разработчика. Гитлаб уже сейчас способен заместить вам Гитхаб, Трелло, CI-систему, и так далее по списку. Все инструменты уже настроены и интегрированы между собой. Результат для разработчика — минимум возни с настройками.
Исходный код Гитлаба открыт, и его при желании можно бесплатно использовать на собственном сервере. Но нас в этой истории сейчас больше всего интересует облачная версия — GitLab.com и возможности которые она дает:
Хостинг неограниченного количества приватных проектов
2000 билд-минут в месяц для работы с встроенным CI бесплатно
Халява, ага. Ну и возможность поучиться, используя для личных проектов, как следствие.
Короче, вы уже догадались что моя личная рекомендация — это GitLab CI. Гитлаб имеет все шансы стать the next big thing в будущем. А быть опытным специалистом по внезапно ставшей модной штуке — это быть востребованным специалистом ;)
Если не готовы покидать Гитхаб, пробуйте Circle CI или Travis CI.
На начальных стадиях знакомства с CI избегайте Jenkins и TeamCity. В этих олдскульных системах слишком много оверхеда, так что придется больше разбираться с особенностями систем, чем фигачить сам CI.
Начнете думать что Jenkins это и есть CI, а это тупо. Возможное исключение — вы джавист, скалист или котлинист, и для вас там все работает прямо из коробки.
Если вам на роду написано программировать под Windows, то мимо Microsoft-стека вы мимо точно не пройдете, но по доброй воле я бы им пользоваться не стал.
Ок, едем дальше…
C каких задач начинать
Хорошие новости в том что не обязательно сразу становиться экспертом по CI. Для начала хватит и простого “быть в теме”. Поэтому начните с чего нибудь лайтового:
Например, научитесь деплоить личный сайт при пуше в мастер.
Запустите в CI второстепенного рабочего проекта пару линтеров.
Запустить свой первый билд внутри CI — задача двух минут. Чтобы запустить что-то полезное, придется потратить чуть больше времени, т.к. нужно настроить рабочее окружение для ваших скриптов.
Здесь мы в это углубляться не будем. Для заинтересовавшихся — ссылки в конце статьи.
А пока посмотрим как CI используется в больших проектах, и какую мощь он может вам дать.
Что дает CI в больших проектах
В больших проектах — серьезные требования. Тут уже запуском одной-двух команд не обойдешься. Легко можно представить себе логику типа такой: 1) выполняй задачу, только при коммите в определенные ветки, 2) при успехе выполняй следующие задачи, 3) игнорируй ошибки при выполнении определённых задачи и 4) жди ручной отмашки прежде чем задеплоить всё это дело.
1) Такое есть далеко не во всех CI-системах. Там где это есть — это дает команде визуальное представление происходящего в CI, и я считаю это дорогого стоит.
2) Кроме этого, файл настроек CI-системы становится работающей документацией процесса Continuous Integration в команде. Любой разработчик может там что-то добавить или изменить, создав пулреквест с желаемыми изменениями.
3) Наконец, CI-система становится центральным местом, в котором можно увидеть где и когда что пошло не так при деплое или прогоне тестов.
Ну и добавьте по вкусу все эти традиционные бла-бла-бла про ускорение процесса разработки, повешение надежности, и уменьшение рисков.
3) После того как освоитесь с одной CI-системой, выберите и поиграйтесь с любой другой из списка перспективных, чтобы удостовериться что принципе везде общие, и заполучить еще больше уверенности в своих силах.