Хочу поделиться опытом попытки внедрения непрерывной интеграции и «безболезненного» деплоинга для php приложений. Я попытаюсь рассмотреть некоторые аспекты по данному вопросу:
- Что такое Continuous Integration
- Что такое деплоинг, как он вписывается в CI
- Немного о тестировании в рамках этого «конвеера»
Непрерывная интеграция — что это?
Непрерывная интеграция (англ. Continuous Integration) — это практика разработки программного обеспечения, которая заключается в выполнении частых автоматизированных сборок проекта для скорейшего выявления и решения интеграционных проблем.
Когда я впервые услышал о CI, для меня это было что-то непонятно-заоблачное. Я попытался разобраться, что же это. Немного погуглив, я наткнулся на phpUnderControl который идет аддоном к CruiseControl и рассказы о том как это круто, и что с помощью него можно непрерывно лить на продакшен сервера.
Я поднял у себя его на локалке, подключил к нему все что попало в поле зрения, в итоге увидел кучу различных графиков и возможности просмотров о состоянии тестов. Круто, но какой в этом смысл если мы не пишем тестов? Как делать билды, да и деплоить нигде не нашел. Понятия «билдить» и php у меня вообще в голове никак не вязались, так со временем CI забросил.
Прошло некоторое время, за которое я успел углубиться во фронтэнд и вопрос о прекомпиляции LESS в CSS с оптимизацией r.js на dev серверах встал ребром — я решил все же разобраться с CI. Так как на локальном окружении все пересобиралось на лету по факту сохранения файла либо обычным запуском grunt'a, то проблем не было.
Вопрос решился быстро: поднял на сервере Jenkins, сделал ему задачу, которая по крону тянула из репозитория последнюю ревизию и если чего нашла запускала grunt. В случае ошибок при запуске grunt(в less файле кто-то накосячил, либо linting js кода не проходил) сразу приходили уведомления. Nginx настроили, чтоб проксировал на workspace этой таски и теперь на dev сервере можно смотреть все собранное. Все довольны, проблема решена.
Резюмируя, Continuous Integration — это практика для постоянного контроля состояния приложения. При наличии минимального набора функциональных и интеграционных тестов, можно сразу заметить если отвалится какая-либо часть и по коммиту выследить виновника.
Круто, а как деплоить то?
Деплоинг — процесс разворачивания приложения в различных окружениях. Происходит все подобным образом:
- через ssh заходим на сервер
- делаем pull с репозитория
- в нашем случае еще запускаем phing, который за собой тянет grunt
- профит
- повторяем это на всех продакшен серверах
Это все можно автоматизировать, привязав к нашему Jenkins серверу, в качестве отдельной задачи. Да-да, Jenkins не только работает в режиме слежки за кодом. Указав все сервера и доступы к ssh, можно все заливать нажатием одной кнопки.
Пока все идет в одной ветке репозитория и можно случайно не то задеплоить. Сейчас исправим эту ситуацию.
Билдинг и php — все же можно связать?
Разделим разработку на 2 ветки, dev и stable, где в dev мы ведем основную разработку, а то что уже готово сливаем в stable и вешаем тег версии. В реалии их не 2, а на много больше и этому можно посвятить целую тему, но пока можно просто познакомиться с A successful Git branching model, где довольно хорошо все описано.
Для того, чтобы не делать все вручную, мы сделаем дополнительную таску в Jenkins, которая будет мержить stable с dev и вешать тег.
У нас появилась стабильная ветка, почему б её тоже не мониторить? Сделаем аналогичную таску с «Dev CI job», которая будет следить за этой кухней плюс добавим еще один хост для nginx.
Теперь у нас есть некий конвеер(pipeling), точками я пометил задачи, которые вызываются вручную.
«Stage CI job» вызывается только если «Make release» прошел успешно.
Выглядит уже лучше, теперь подключим тестеров.
Тестирование и превью релиза
У нас теперь есть более-менее удобная система управления релизами и деплоингом. Разработчики за процессом дальше шага «Make release» не следят. Выпустили стабильную версию и она ушла на stage сервер, где тестировщики могут отвести душу и можно показать заказчикам продукт. Выливать его на продакшен или нет, решают последние.
Сейчас мы двигаемся в сторону автоматизации тестирования средствами Selenium, потому что ни для кого не секрет, что интеграционные и юнит тесты, которые пишут разработчики, не защищают от багов. Поэтому после «Stage CI job» добавится еще один шаг, который будет проводить системное и функциональное тестирование.
Скорее всего придем к подобной схеме, потому что для некоторых разработчиков возможно понадобится своя песочница, чтоб показать готовые фичи. В QA команде тоже нужно будет несколько песочниц, чтоб не мешали друг другу. И отдельная песочница для нагрузочного тестирования, чтоб искать узкие места в приложении.
Автор: enleur