В разработке любого приложения все начинается с исходного кода, а заканчивается приложением, которое доступное пользователю. В зависимости от типа приложения (веб приложение, мобильное или десктопное) процесс преобразования исходного кода в финальных продукт может отличаться. Назовем этот процесс – процесс релиза.
Процесс релиза может отличаться в зависимости от типа приложения, но этапы остаются всегда одни и те же.
Исходный код – файлы, которые вы создаете и в которых пишете код. Они обычно хранятся в вашем VCS (git, svn, mercurial, и др)
Артефактом будем называть результат сборки исходных кодов. Это может быть бинарный файл или собранный js bundle. Это тот ресурс, который будет использовать пользователь.
Этапы релиза
- Тестирование исходников
- Сборка артефакта
- Тестирование артефакта
- Сохранение артефакта
- Развертывание артефакта
Тестирование исходников
На этом этапе мы работаем с исходным кодом. Мы проверяем его юнит тестами, интеграционными тестами, запускаем линтеры для анализа форматирования и статического анализа кода.
Все что мы можем проверить без сборки – мы проверяем тут. Это обычно быстрые проверки.
- Юнит тесты
- Интеграционные тесты
- Статистические анализаторы кода (линтеры, статические проверки типов)
- Просчет процента покрытия тестами
Сборка артефакта
На этапе сборки мы собираем наш проект. Это может быть компиляция мобильного приложенияили сборка js бандла для фронтенд проектов. В общем, тут мы собираем финальную версию артефакта, который мы в последствии доставим пользователю. Сборка Docker контейнера – это как раз для этого этапа. Ведь именно этот Docker контейнер будет работать на наших production и dev средах.
Требование к артефакту
Приложение должно удовлетворять 12 факторам. Для нас критично следующее:
- Разделение кода и конфигурации
Вы должны иметь возможность развернуть ваш артефакт как для production использования, так и для beta или alpha тестирования. И если вам, например, потребуется поменять настройки доступа к базе данных или параметры доступа к АПИ – вы должны это уметь делать через внешний конфигурационный файл.
Этот пункт важен для следующего этапа. Мы будет запускать автоматическое приемочное тестирование. Обычно, для приёмочного тестирования используется dev или beta среда, а в процессе развертывания на production мы будем использовать другую конфигурацию, без повторной сборки.
Лакмусовой бумажкой того, правильно ли разделены конфигурация и код приложения, является факт того, что кодовая база приложения может быть в любой момент открыта в свободный доступ без компрометации каких-либо приватных данных.
Если вы чувствуете себя неуверенно в этом моменте – пожалуйста, углубитесь в этот материал: https://12factor.net/ru/config
Тестирование артефакта
После того, как мы собрали артефакт – мы его можем потестировать. Как вы помните, юнит и интеграционные тесты мы уже запускали, значит теперь время для приемочного (acceptance) тестирования.
Для веб приложения – это selenium тесты. Чтобы их запустить мы должны, например запустить наш Docker контейнер, и прогнать эти тесты на нем. Также на этом этапе может проводится тестирование в визуальный регрессий – сравниваем скриншоты предыдущей и текущей версий и находим отличия.
Для мобильного приложения – Appium тесты. Мы тестируем наш .ipa или .apk файл с помощью приемочных тестов – симулируем работу пользователей с нашим приложением.
Сохранение артефакта
После того как артефакт протестирован – мы его сохраняем. Обычно на этом шаге мы уверенны, кто наше приложение работоспособное по тем тест кейсам, на которые у нас есть автотесты.
В зависимости от требований проекта мы можем сохранять, а можем и не сохранять артефакты, которые не прошли успешно этап тестирования артефакта. Для процессов сборки, где решения должен принимать человек – например, как в тестировании визуальной регрессии, человек принимает решение о том, правильные ли изменения зафиксированы или нет. В этом случае нам нужно сохранять все артефакты, и которые имеют изменения, и которые нет. Чтобы решение мог принять разработчик.
Хранить артефакты можно по-разному: Docker Hub, CDN, просто zip файлы на каком то файловом хранилище. Это не столь важно. Главное точно нужно указать версию и ссылку на коммит (конечно, если вы используете vcs) и чтобы было удобно работать с этим хранилищем на следующем этапе – этапе развертывания.
Между этапом хранения и развертывания может быть еще множество этапов ручного тестирования и одобрения артефакта. Главное, что мы работаем с уже собранным артефактом, который мы частично протестировали и который в последствии будет разворачиваться в среде.
Развертывание артефакта
Для веб проектов – обновление веб сервера
Дл мобильный и десктопных приложений – загрузка в магазин приложений или в любое место распространения приложения (например, отправка издателю для печати дисков :)).
Этот этапе мы работаем с 3 сущностями: среда, куда мы развёртываем, артефакт, который мы развертываем, и конфиг, с помощью которого мы развертываем.
- Где? Среда
- Что? Артефакт
- Как? Конфиг
Артефакт мы загружаем из нашего хранилища. Конфиг хранится в среде развертывания. А сама среда знает как работать с этими 2 сущностями.
Примеры
Kubernetes, Docker, Docker Hub
Система – Kubernetes. У нас есть конфигурация Kubernetes, в которой прописана конфигурация нашего приложения. Для того, чтобы обновить приложение – мы меняем версию Docker контейнера и запускаем команду обновления. Новый артефакт (Docker образ) будет загружен из нашего хранилища (напр, Docker Hub) в нашу среду (Kubernetes) и наш собранный артефакт заработает на нашей среде.
Повторюсь. На этом этапе не должно происходить никакой сборки. Мы только загружаем артефакт из хранилища и запускаем его с конфигом. Наш артефакт уже протестирован. И если мы его будем собирать на этапе развертывания могут быть проблемы с откатыванием на предыдущую версию.
Неудачный пример #1
Веб приложение, git, circle ci, surge
Приложение тестируется на circle ci и в случае успешного прохождения тестов из ветки develop развертывается в на тестовой среде.
Развертывание production среды происходит руками.
Что не так?
Сборка проекта происходит каждый раз перед развертывание production. В случае неудачной версии, когда нужно вернуться на предыдущую версию – нам нужно снова пересобирать артефакт. Результат может отличаться. Например, хеши в названиях файлов, которые используются для обновления кеша будут другие. В некоторых случаях это может привести к проблеме.
Решение: собирать артефакт на CI и выгружать в хранилище. Настроить деплой из хранилища.
Неудачный пример #2
Веб приложение, git, nginx
Простой веб проект. Процесс развертывания выглядит след образом. Программист подключается к веб серверу по ssh, стягивает нужный commit, обновляет зависимости, запускает процесс сборки.
Что не так?
Нельзя быть на 100% уверенным в сборке. Собранная версия не протестированная. Даже если версия работает локально – не факт что сборка прошла корректно на удаленной машине.
Что делать?
Пересмотреть процесс сборки. Разделить сборку и развертывание приложения. Сохранять артефакты сборки в хранилище и использовать их в процессе деплоя.
Выводы
Разделив процесс релиза на этапы вы будете четче понимать весь процесс. Каждый этап имеет свою цель, а также входные данные и результат. Настаивайте ваш процесс грамотно и гладких вам релизов ?