/
Блог Хекслета
/
Код
/

GitLab: CI/CD и хранение кода — рабочий процесс команды

GitLab: CI/CD и хранение кода — рабочий процесс команды

1 июля 2026 г.

8 минут
GitLab: CI/CD и хранение кода — рабочий процесс команды

GitLab: CI/CD и хранение кода — рабочий процесс команды

Знакомая сцена. Утро понедельника, вы подтягиваете свежий код и садитесь работать — а проект не запускается. Кто-то из коллег в пятницу влил в основную ветку правку, которая ломает сборку. У него на машине всё работало, поэтому он спокойно ушёл на выходные. Теперь простаивает вся команда: пять человек по очереди выясняют, чей это коммит и как его откатить, вместо того чтобы делать свои задачи.

Пока разработчик один, такого не бывает: он сам себе и автор, и ревьюер. Но стоит собраться команде, и всё меняется. Правки летят в общую ветку без единой проверки, каждый тестирует по-своему или не тестирует вовсе, а «у меня работает» превращается в чужую проблему через сутки. Чем больше людей, тем чаще основная ветка оказывается сломанной — и тем дороже это стоит.

GitLab делает так, что сломанный код физически не попадает в общую ветку. Каждое изменение проходит через запрос на слияние, где его автоматически проверяет конвейер: собирает, гоняет тесты, показывает результат ревьюеру. Красный конвейер — ветку не вливают. Процесс команды перестаёт держаться на дисциплине каждого и становится правилом, встроенным в платформу.

Разберём, как GitLab организует работу команды: как хранит код, как устроен Merge Request с проверками, что такое CI/CD и как настроить путь от коммита до продакшена. По ходу сравним с привычным GitHub.

GitLab строится на Git и CI/CD — основы Git и командную работу с ветками разбирают на курсе «Введение в Git» и в программах по бэкенду и DevOps на Хекслете.

Что такое GitLab

GitLab — платформа, которая держит весь процесс разработки в одном месте. В её основе хостинг Git-репозиториев, как у GitHub: код, ветки, история, обсуждение изменений. Но GitLab шире — в него встроены CI/CD, отслеживание задач, реестр образов, управление выкатками. Команде не нужно сшивать пять сервисов между собой: код, проверки, задачи и деплой живут рядом.

Тем, кто работал с GitHub, многое будет знакомо, а разница — в акценте. GitHub вырос как хостинг кода, автоматизацию к которому добавляют через GitHub Actions. GitLab с самого начала строился как единая DevOps-платформа, где CI/CD не докручивается сбоку, а встроен внутрь. Для команды это значит меньше связок между инструментами и одно место, где виден весь путь изменения: от задачи до выката.

GitHub

GitLab

Хостинг Git

Да

Да

Запрос на изменения

Pull Request

Merge Request

CI/CD

GitHub Actions (отдельно)

Встроен изначально

Свой сервер

Ограниченно

Полноценная установка

Подход

Хостинг кода плюс надстройки

Единая DevOps-платформа

GitLab бывает облачным на gitlab.com и self-hosted — на своём сервере. Свой сервер выбирают там, где код нельзя отдавать наружу, облако — ради скорости старта. Базовые возможности бесплатны в обоих вариантах.

Хранение кода: ветки и Merge Request

Фундамент GitLab — обычный Git, и командная работа строится по знакомым правилам. Репозиторий хранит код и историю. Ветки дают каждому вести свою задачу отдельно, не задевая чужой код. А попадает всё это в общую ветку через Merge Request.

Merge Request (запрос на слияние) — это предложение влить одну ветку в другую с обязательной остановкой на проверку. В GitHub его аналог — Pull Request. Внутри запроса видны все изменения построчно, идёт обсуждение и ревью коллег, а рядом — результат конвейера. Именно здесь команда договаривается, что код готов, а не в личных сообщениях.

# каждый работает в своей ветке
git checkout -b feature/login

git add .
git commit -m "Добавил форму входа"

git push origin feature/login
# дальше в интерфейсе GitLab открываем Merge Request в main
gitlab_01_branches.png

Ключевой приём для команды — защищённая основная ветка. В настройки проекта закладывают правило: напрямую в main писать нельзя, только через Merge Request, и только когда конвейер зелёный, а изменения одобрены. Тогда история из начала статьи невозможна в принципе: сломанный код не долетит до общей ветки, потому что его остановит проверка ещё в запросе.

Merge Request как точка сборки

Стоит задержаться на Merge Request отдельно — для команды это главное место, куда стекается всё про одно изменение.

Что собрано в запросе

Зачем команде

Изменения кода построчно

Ревьюер видит ровно то, что меняется

Обсуждение и комментарии

Замечания привязаны к конкретным строкам

Результат конвейера

Сразу видно, прошли ли тесты и сборка

Одобрения ревьюеров

Правило: без одобрения ветку не вольют

Связанная задача

Понятно, зачем вообще делалась правка

Через полгода, когда кто-то спросит «почему тут так сделано», ответ найдётся прямо в запросе на слияние: и правки, и спор ревьюеров, и связанная задача. Знание команды остаётся в платформе, а не в чьей-то памяти или переписке.

Что такое CI/CD

Это сердце GitLab, и здесь важно разобраться в понятиях. За аббревиатурой CI/CD скрываются две связанные идеи.

CI — непрерывная интеграция (Continuous Integration). Каждое изменение кода проверяется автоматически: собирается проект, гоняются тесты, работают линтеры. В конвейер выносят и проверки API — например, коллекции запросов из Postman прогоняются на каждый коммит. Смысл — ловить поломки в момент коммита, а не копить их до релиза. Для команды это ещё и общий обязательный стандарт: проверки одинаковы для всех, независимо от того, кто и в каком настроении писал код.

CD — непрерывная доставка (Continuous Delivery/Deployment). Прошедший проверки код готовится к выкату и доставляется на серверы. Релиз перестаёт быть ручным ритуалом, которого боятся по пятницам, и становится продолжением обычной работы.

gitlab_02_cicd.png

Без CI/CD

С CI/CD

Тесты

Каждый гоняет по-своему или забывает

Идут сами на каждый коммит

Сборка

Собирают на своей машине

Собирается автоматически

Деплой

Ручной чек-лист из шагов

Запускается конвейером

Качество

Зависит от внимательности каждого

Задано единым правилом

Главная ценность не в экономии нажатий, а в том, что качество перестаёт зависеть от человека. Пока проверки ручные, один разработчик гоняет тесты, другой забывает, третий проверяет не то. Конвейер задаёт всем единый путь: одни и те же проверки на каждый коммит, кто бы его ни сделал.

Конвейер: файл .gitlab-ci.yml

Весь процесс автоматизации GitLab описывается одним файлом в корне репозитория — .gitlab-ci.yml. Он лежит рядом с кодом, версионируется вместе с ним и виден всей команде. GitLab находит файл сам и строит по нему конвейер.

stages:           # этапы конвейера, идут по порядку
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - npm install
    - npm run build

test-job:
  stage: test
  script:
    - npm test

deploy-job:
  stage: deploy
  script:
    - ./deploy.sh
  only:
    - main         # деплой только из основной ветки

В файле три уровня понятий. Стадии (stages) — крупные этапы: собрать, проверить, выкатить. Задачи (jobs) — конкретная работа внутри этапа со своим набором команд в блоке script. Эти команды и выполняются на сервере: в примере это команды npm, а для Java- или Kotlin-проектов на их месте была бы сборка через Gradle. Условие only ограничивает задачу: деплой пойдёт только из основной ветки, а не из каждой рабочей.

gitlab_03_anatomy.png

Важное следствие для команды: процесс не спрятан в чьих-то настройках, а лежит текстом в репозитории. Любой видит, что и как проверяется, а изменить процесс можно тем же Merge Request, что и код, — с ревью и обсуждением.

Как идёт конвейер

Когда кто-то делает git push, GitLab читает .gitlab-ci.yml и запускает конвейер. Порядок подчиняется двум правилам.

gitlab_04_pipeline.png

Стадии идут строго по очереди: сначала вся build, потом test, потом deploy. Задачи внутри одной стадии, наоборот, запускаются параллельно — несколько проверок в стадии тестов идут одновременно. И главное: если хоть одна задача упала, конвейер останавливается и до следующих стадий не доходит.

push  →  [ build ]  →  [ test ]  →  [ deploy ]
            │             │            │
         собрать       тесты        выкатить
                       линтер
                    (параллельно)

         тест упал → deploy не запустится

Отсюда ключевое свойство. Стадия деплоя стоит после тестов, поэтому сломанный код не может выкатиться: до deploy конвейер просто не дойдёт, если упал хоть один тест. И тот самый пятничный коммит, который ломал сборку, здесь не прошёл бы дальше стадии проверок — до общей ветки он не добрался бы.

Раннеры, артефакты и переменные

Три понятия, без которых конвейер не работает на практике.

Раннеры — исполнители: программы, которые реально выполняют команды задач. Сам GitLab ничего не запускает, он раздаёт задачи раннерам. Они бывают общими (их даёт GitLab) и своими, установленными на сервере команды, — когда нужно особое окружение или контроль над мощностью.

Артефакты — файлы, которые задача оставляет после себя и передаёт дальше по конвейеру. Стадия сборки собрала проект — результат становится артефактом, и стадия деплоя берёт готовое, а не пересобирает заново.

build-job:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/        # результат сборки уедет в следующие стадии

Переменные CI/CD — секреты и настройки, которым не место в коде: пароли, токены, ключи. Их задают в настройках проекта, а в конвейере используют по имени. Так секрет не попадает в репозиторий, который видит вся команда, и не утекает вместе с кодом.

Деплой и окружения

Вершина CI/CD — автоматический выкат. Места, куда выкатывается приложение, в GitLab называют окружениями: staging для проверки, production для боевого сервера. GitLab помнит, какая версия куда выкачена, — команде всегда видно, что сейчас крутится в проде.

gitlab_05_deploy.png

Здравый командный приём — выкат в staging автоматически, а в production по кнопке. Перед боевым сервером остаётся ручная точка контроля: тесты прошли, на промежуточном сервере всё живо, ответственный человек нажимает «выкатить».

deploy-staging:
  stage: deploy
  script: ./deploy.sh staging
  environment: staging        # выкат автоматический

deploy-production:
  stage: deploy
  script: ./deploy.sh production
  environment: production
  when: manual                # выкат по кнопке
  only:
    - main

Получается полный путь: коммит в ветку запускает конвейер, тесты проходят, приложение уезжает на промежуточный сервер, а на боевой уходит по нажатию. Весь маршрут описан в одном файле и виден команде в одном интерфейсе.

Не только код и конвейеры

GitLab задуман как платформа на весь цикл, поэтому вокруг репозитория и CI/CD собрано то, что иначе команда держала бы в отдельных сервисах.

Возможность

Зачем команде

Задачи (Issues)

Список работы, баги и обсуждения рядом с кодом

Доски (Boards)

Канбан-доска из задач: видно, что в работе, что готово

Реестр образов

Хранить собранные Docker-образы внутри проекта

Проверка безопасности

Искать уязвимости в коде и зависимостях в конвейере

Wiki и Pages

Документация и статические сайты из репозитория

Связка получается плотной: задача связана с веткой, ветка — с Merge Request, запрос — с конвейером, конвейер — с выкатом. По одному изменению видно всю цепочку. В этом и смысл единой платформы для команды — не собирать картину из четырёх вкладок, чтобы понять судьбу одной правки.

Практика: рабочий процесс команды

Соберём процесс, при котором сломанный код не доходит до общей ветки.

Шаг 1. Защитить основную ветку. В настройках проекта запрещаете прямую запись в main — только через Merge Request с одобрением.

Шаг 2. Добавить конвейер. Кладёте в корень .gitlab-ci.yml с проверками и выкатом:

stages:
  - test
  - build
  - deploy

test-job:
  stage: test
  script:
    - npm install
    - npm test

build-job:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

deploy-job:
  stage: deploy
  script:
    - ./deploy.sh
  environment: production
  when: manual
  only:
    - main

Шаг 3. Работать через ветки. Каждый заводит ветку под задачу, коммитит, открывает Merge Request. Конвейер сам прогоняет тесты, коллеги смотрят изменения.

Шаг 4. Вливать только зелёное. Ветку вливают, когда конвейер прошёл и есть одобрение. На боевой сервер выкатывают по кнопке.

Готово. Теперь у команды один прозрачный процесс: сломанный код не попадёт в общую ветку, проверки одинаковы для всех, а деплой — кнопка вместо чек-листа. Пятничный инцидент из начала статьи в такой схеме просто не случится.

Антипаттерны

Открытая основная ветка. Если в main можно писать напрямую, любой коммит способен сломать её для всей команды. Основную ветку защищают: запись только через Merge Request с прошедшим конвейером и одобрением.

Конвейер без тестов. Конвейер, где только сборка и деплой, автоматизирует выкат сломанного кода. Смысл CI — в проверках: стадия тестов должна стоять до деплоя и реально гонять тесты.

Секреты прямо в .gitlab-ci.yml. Пароль или токен в файле конвейера попадает в репозиторий и виден всей команде. Секреты хранят в переменных CI/CD, а в файле используют по имени.

Игнорировать красный конвейер. Упавший конвейер, который «починим потом», быстро становится фоновым шумом, и команда перестаёт замечать настоящие поломки. Красный конвейер чинят сразу — иначе он бесполезен.

Ревью для галочки. Одобрение Merge Request не глядя обесценивает всю схему: сломанный по смыслу код проходит, хотя конвейер зелёный. Ревью — это разбор изменений, а не формальная кнопка.


FAQ

Чем GitLab отличается от GitHub?

Оба — хостинг Git с ревью изменений. Разница в подходе: GitHub изначально про хостинг кода, CI/CD добавляется через GitHub Actions; GitLab задуман как единая DevOps-платформа со встроенным CI/CD, реестром образов и задачами. Команде, которой важно держать весь процесс в одном месте и на своём сервере, GitLab часто удобнее.

GitLab бесплатный?

Базовые возможности бесплатны и в облаке на gitlab.com, и при установке на свой сервер. Платные тарифы добавляют функции для крупных команд: продвинутую безопасность, аналитику, тонкое управление доступом. Для учёбы и небольших команд бесплатного тарифа хватает с запасом.

Нужно ли знать Git перед GitLab?

Да, Git — обязательная база. GitLab строится поверх него: ветки, коммиты, слияния — это всё Git. Если вы работали с GitHub, переход будет простым, основные понятия совпадают. А CI/CD — новая тема, которую осваивают уже в GitLab.

Как защитить основную ветку от случайных поломок?

В настройках проекта основную ветку делают защищённой: прямая запись запрещена, слияние идёт только через Merge Request, а влить можно лишь при зелёном конвейере и одобрении ревьюера. Так сломанный код не попадёт в общую ветку, даже если кто-то ошибся.

Можно ли внедрять CI/CD постепенно?

Да, и так чаще всего и делают. Начинают с малого — конвейер только с тестами на каждый коммит. Потом добавляют автоматическую сборку, затем выкат на промежуточный сервер, и в последнюю очередь — на боевой. Каждый шаг полезен сам по себе, строить всё сразу не нужно.

Обязательно ли настраивать свой раннер?

Нет. На gitlab.com есть общие раннеры, на которых конвейер заработает сразу. Свой раннер нужен, когда требуется особое окружение, доступ в закрытую сеть или контроль над мощностью. Для старта команде хватает общих.


Читайте также

Пройти путь от основ Git до командного процесса с CI/CD системно можно на курсе «Введение в Git» и в программах по бэкенду и DevOps на Хекслете.

Никита Вихров

3 дня назад

0

Категории

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

108813 г. Москва, вн.тер.г. поселение Московский,
г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3
ОГРН 1217300010476
ИНН 7325174845