Пишу про полезные материалы про IT и собираю свой ламповый нетворкинг тут - https://t.me/+434aQiGpZtAyNTU6. Присоединяйтесь!
Оглавление.
Часть 1. Введение
Всем привет! Наверняка каждый, кто так или иначе связан с IT-сферой, слышал модную аббревиатуру CI/CD. Везде мы слышим о необходимости ее использования, преимуществах автоматизации процессов и т.д.
В вакансиях все чаще требуется опыт работы с одним из инструментов в этой инфраструктуре – Jenkins, Travis, AWS, GitLab CI/CD.
⚠️Я предлагаю вам посмотреть на этот процесс глазами простого разработчика: чем ему может помочь автоматизация, что в конечном итоге скрывается под этой аббревиатурой и как уже начать получать дивиденды в своей ежедневной рабочей практике.
Первые шаги
Мы рассмотрим внедрение инструментов автоматизации в приложение, построенное на базе React. Разберем именно основные подходы и моменты, на которые стоит обратить внимание в самом начале. На все эти грабли наступал я, когда решил автоматизировать проверки и деплой своего небольшого конвертера файлов. В итоге все получилось не неплохо: каждый мой пуш запускает все необходимые проверки, и мое приложение оказывается на сервере через пару минут.
В целом это будет актуально для любого стека.
Чаще всего я использую для хранения кодовой базы и групповой работе над проектами GitLab. Очень кстати, что эта площадка предоставляет инструментарий CI/CD.
Я пытался пару лет подступиться к этому вопросу. Стильно, модно, молодежно. Да, дает кучу преимуществ, но все попытки переварить официальную документацию заканчивались неудачей, а видео уроки или материалы в общем доступе чаще всего давали рецепт автоматизации какого-то конкретного кейса, который либо частично, либо полностью отличался от моего приложения.
Мне не хватало именно взгляда на основные шаги – что, зачем и как мы делаем. А уже потом реализации практических задач.
CI – continuous integration
Что же скрывается за термином "непрерывная интеграция"? Когда мы работаем над созданием программного продукта – в одиночку или в рамках команды, мы стараемся добавить в наш проект несколько строк кода. Новый функционал, исправление или доработки. Суть не особо важна. В конечном счете либо появляется новый код, либо появляются изменения в старом, и нам нужно убедиться, что эти новые изменения не содержат ошибок, которые могут вызвать проблемы или неработоспособность приложения. ⛔️
❗️Рассмотрим на примере стандартного подхода к разработке на основании git. Стандартный флоу – у нас есть 2 ветки: master для сборки продукта и develop для разработки. Разработчик, получая очередную задачу, создает ветку от develop, локально осуществляет реализацию, делает коммит, пуш и МR (merge request - запрос на слияние).
Потенциально его код может содержать ошибки: проблемы с системами линтинга. Если речь про экосистему JS,то за основу можно взять инструмент ESlint. На других языках – по аналогии. Например, в Python это может быть Flake8 и т.д.
Может не проходить процедура сборки – в нашем случае npm run build (если мы используем webpack или Vite), в компилируемых языках это процесс компиляции. В общем и целом исходный код нашего приложения может требовать некоторых подготовительных процедур, чтобы получить версию приложения, которую можно запускать в некоторой среде для эксплуатации.
В идеальном мире мы, как разработчики, можем локально запускать все необходимые проверки и тестовые процедуры: компиляцию, сборку и т.д.
npx eslint . --fix
npm run build
И если все проходит успешно – отправлять наш коммит в общее хранилище кода.
Мы, к сожалению или к счастью, разрабатываем наше ПО в реальном мире. Привет, Нео :-).
Можно забыть, проигнорировать или, наконец, не знать – и пропустить проверки. Случиться это может по самым разным причинам. Как итог – в кодовую базу попадает код с ошибками.😱
Что здесь можно автоматизировать? По сути, запуски всех необходимых проверок. И переход к следующему шагу только при их успешном завершении. В общем и целом это и есть процесс непрерывной интеграции. Мы хотим максимально часто доводить новый код до общей кодовой базы и убеждаться, что он не содержит ошибок или максимально быстро выявлять их.
Какой промежуточный вывод мы делаем здесь? Разберитесь, какие необходимые проверки и подготовительные шаги вам необходимо сделать. В нашем случае это запуск линтера и процесса сборки. И что не менее важно – какие инструменты и окружение нужны для того, чтобы этот процесс можно было бы осуществить.
CI/CD инструменты. GitLab
Если говорить коротко, то системы автоматизации – это совокупность вычислительных мощностей и программного обеспечения, которые в связке помогут нам осуществить требуемые шаги. В общем и целом это может быть что угодно, в том числе и ваш персональный компьютер.
Так, кстати, довольно часто делают. Если Вы знакомы с экосистемой JS/NodeJS, то могли слышать про библиотеку Husky. Эта штука помогает внедрить скрипты автоматизации. Например, перед выполнением команды git commit. Мы настраиваем запуск сборки и линтера, они запускаются перед коммитом, и сам коммит создается, только если предыдущие шаги успешно завершились. Чем вам не continuous integration? 😮
В целом да, но более продвинутые системы, как обычно бывает, предоставляют более мощную систему в плане функционала.
Мой выбор пал на GitLab CI/CD, по двум причинам. Во-первых, это знакомый инструмент. Во-вторых, он предоставляет необходимый функционал, и настройка под мои задачи в общем и целом довольна проста. Можно было бы сделать на другой платформе – есть из чего выбирать. Из тех, которых я касался – GitHub Actions и Jenkins. На GitНub – в целом, аналогично. Поэтому тут выбор я бы отнес к разделу вкусовщины или специфических кейсов, а вот Jenkins чуть посложнее. Тут уже надо более глубоко погрузиться в настройку самой среды. С AWS поработать не удалось.
В любом случае, я допускаю, что мелкие и средние задачи, плюс-минус, можно реализовывать на любом популярном решении.
Какие основные части нам понадобятся?
Вся настройка сводится к заполнению файла .gitlab-ci.yml в корне репозитория. При этом в разных ветках содержимое файла может быть разным. По умолчанию можно ориентироваться на то, что в текущей ветке этот файл будет содержать все CI/CD процессы, относящиеся к этой ветке.

Среда для выполнения кода
Сервис GitLab предоставляет вам необходимые вычислительные мощности бесплатно из коробки. В базовом варианте это сводится к тому, что где-то на сервере для наших нужд создается Docker-контейнер, в котором специальная программа Runner выполняет команды из файла .gitlab-ci.yml.
На этом этапе достаточно этой информации: при определенных действиях, например при пуше ветки в репозиторий, будет создан Docker-контейнер, в котором некоторый инструмент выполнит команды автоматизации, которые мы перечислили в файле .gitlab-ci.yml.
Сам процесс выполнения шагов называют pipeline. Вы сами определяете, какие шаги (этапы) будут в вашем случае выполняться. Что здесь интересно для нас? GitLab предоставляет визуальный интерфейс для заполнения .gitlab-ci.yml файла. Он находится в репозитории, в основном меню: Build => Pipeline editor. В самом начале здесь предложат создать и заполнить файл с настройками.

По этому пункту весь процесс рассматривают как некоторое множество задач, называемых внутренним термином Pipeline. Пока ничего сложного.
Jobs
Сам процесс, как я сказал выше, разделяют на шаги или Jobs. Каждая из них будет выполняться независимо, в отдельном контейнере, последовательно. Можно настроить, чтобы одна Jobs передавала другой некоторые результаты работы, гибко настроить порядок и условия их запуска. Но это более сложные кейсы, которые мне, как и вам, еще предстоит освоить.
Пример базовой конфигурации
Давайте уже перейдем хоть к минимальной, но практике. Настроим нашу первую Jobs, которая успешно отработает. Тем самым мы убедимся, что не боги обжигают горшки, искорка появится в наших глазах, и наконец-то мотивация поднимется на достаточный уровень, чтобы разобраться и победить CI/CD. 🫡
Перейдем в Pipeline editor, выберем ветку develop и нажмем кнопку Configure pipeline. Мы попадем в окно визуального редактора. По идее, команды можно писать в файле .gitlab-ci.yml напрямую. Преимущества визуального редактора – он хорошо подсвечивает ошибки в yaml синтаксисе и иногда дает базовые подсказки. В остальном – дело вкуса.
Для визуальной и логической компоновки ваших Jobs здесь есть так называемые стадии -stages. Не более чем группировка. В процессе работы pipeline можно будет смотреть, какая стадия и какая jobs в ней выполняется.
Добавим первую стадию check:

Дальше начнем добавлять непосредственно jobs. Для нее укажем стадию, к которой она относится. И самый важный на этом этапе момент – выберем образ для докера.

Здесь lint – название для Jobs.
Image – настройка образа.
ubuntu:22.04 - название и версия Docker образа.
Если вы не знакомы с системой контейнеризации, на этом этапе имеет смысл посмотреть какие-то базовые руководства или дождаться моего материала. Если в двух словах – Docker, программа для запуска контейнеров. Контейнер – по сути, операционная система, запущенная в рамках хост-среды основной операционной системы на том устройстве, где вы работаете. К примеру, вы можете установить на свою машину с Windows10 Docker и через него создать и запустить контейнер (программу, процесс) с установленной выбранной операционной системой. Штука, близкая к виртуализации, с небольшими отличиями. 😨
Для нас здесь достаточно того факта, что для наших задач GitLab где-то запускает выбранную операционную систему и в ней начинает выполнять наши шаги (команды) автоматизации. Очень важный вопрос - касательно операционной системы. Вообще, эту настройку можно не указывать, тогда GitLab автоматически установит образ ruby, операционную систему и среду для выполнения кода на этом языке.
Нас этот вопрос будет касаться напрямую – контейнер - это среда для нашей автоматизации и соответственно нужно выбирать подходящую операционную систему для тех или иных команд, программ и процессов. К этому вопросу мы вернемся в следующей статье, когда будем производить непосредственную настройку. Пока нам достаточно будет Ubuntu.
Последняя на сегодня настройка – это script. Насколько я вынес на текущем этапе, это раздел для указания непосредственных команд, которые будут выполнятся в консоли нашей операционной системы в контейнере, и где мы сможем указывать команду или команды, запуск которых мы хотим автоматизировать.
Для теста выведем в консоль фразу “GitLab CI/CD works!”

В выводе мы увидим подготовку и запуск контейнера, некоторые предварительные команды настройки и выполнение команд из нашего скрипта.
Это работает! 🫡

Какие итоги?
На этом этапе мы получили в свое распоряжение операционную систему (которую мы можем выбирать и настраивать), которая запускается при пуше в наш репозиторий. В ней мы можем указывать команды, которые также автоматически будут запускаться. В целом это уже боевой задел на автоматизацию. Дальше нужно будет добавить, настроить и запускать нужные инструменты и более сложные сценарии.
PS. Вам удалось лучше разобраться с базовыми основами CI/CD? Чего не хватило в материале? Оставляйте комментарии или присоединяйтесь ко мне в телеграм - https://t.me/+434aQiGpZtAyNTU6
Удачи!