Экосистема GitLab: репозиторий, MR, реестр, issues
Разбираем компоненты GitLab, на которые опирается пайплайн, чтобы понимать контекст джоб.
Merge Request (MR) — аналог Pull Request в GitHub: предложение влить ветку, к которому привязан code review и собственный пайплайн.
Почему важно знать платформу
Пайплайн не существует в вакууме. Он реагирует на события репозитория, публикует образы в реестр, привязывается к окружениям деплоя и оставляет следы в Merge Request. Чтобы писать осмысленные пайплайны, нужно представлять, с чем они взаимодействуют.
Удобно держать в голове карту того, как компоненты связаны и кто кого запускает. Репозиторий — источник событий; событие порождает пайплайн; джобы пайплайна пишут в реестр и регистрируют деплои в окружениях; результат всплывает обратно в Merge Request, где его видит человек. Это замкнутый круг: от коммита до работающего приложения и обратно к ревью.
repo (push / MR)
│
▼
pipeline → jobs →→ Container Registry (образы)
→→ Environments (деплой + откат)
→→ Package Registry (npm/PyPI/...)
│
▼
Merge Request (статус, diff, обсуждение)Репозиторий и ветки
Git-репозиторий — основа всего. GitLab умеет защищать ветки (protected branches): запрещать прямой push в main, требовать MR и зелёный пайплайн перед слиянием. Это базовый кирпич надёжного процесса, и пайплайн часто настраивают по-разному для защищённых и обычных веток.
Различие «защищённая / обычная ветка» — не формальность, а механизм безопасности. Секретные переменные CI/CD в GitLab можно пометить как protected: тогда они подставляются в джобы только в пайплайнах защищённых веток и тегов. Логика проста: продакшен-ключи нужны лишь джобам деплоя, которые бегут на main, и не должны утекать в пайплайн, запущенный из чужого форка или временной ветки. Поэтому, проектируя пайплайн, всегда держите в уме вопрос «на какой ветке это выполняется и какие права у него должны быть» — он определит, увидит ли джоба нужный секрет.
Merge Requests
MR — центральное место работы команды. В нём виден diff, идёт обсуждение, и прямо здесь отображается статус пайплайна. GitLab умеет блокировать кнопку Merge, пока пайплайн не стал зелёным. Особая фишка GitLab — review apps: на каждый MR можно автоматически развернуть временную копию приложения, чтобы ревьюер посмотрел изменения вживую. Мы дойдём до них в разделе про деплой.
Полезно знать, что для MR GitLab умеет собирать merge request pipeline — пайплайн не на сам коммит ветки, а на результат предполагаемого слияния с целевой веткой. Это ловит коварный класс ошибок: ваша ветка зелёная, целевая ветка зелёная, но вместе после merge они конфликтуют или ломают тест. В GitHub Actions это поведение давно по умолчанию (события pull_request работают с merge-коммитом), а в GitLab его включают явным правилом в конфигурации. Различие стоит запомнить: одинаковый на вид пайплайн на двух платформах может проверять разные вещи.
Container Registry
В каждый проект GitLab встроен реестр Docker-образов. Пайплайн может собрать образ и запушить его туда командой docker push, авторизуясь встроенными переменными. Не нужен внешний Docker Hub — образ лежит рядом с кодом, под теми же правами доступа.
echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
docker build -t "$CI_REGISTRY_IMAGE:latest" .
docker push "$CI_REGISTRY_IMAGE:latest"Переменные CI_REGISTRY, CI_REGISTRY_USER, CI_REGISTRY_IMAGE GitLab подставляет автоматически — об этом будет урок про предопределённые переменные.
Зачем встроенный реестр вообще нужен и почему это удобнее внешнего Docker Hub? Во-первых, права доступа едины: кто видит код проекта, тот видит и его образы — не надо вести отдельный список доступов. Во-вторых, авторизация бесплатна и автоматична: переменные CI_REGISTRY_* уже в окружении джобы, не надо хранить логин и пароль Docker Hub в секретах. В-третьих, образы тегируют по коммиту или ветке ($CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA), и тогда легко понять, из какого именно коммита собран конкретный образ. Привычка тегировать latest вместо SHA — частый источник путаницы: latest молча перезаписывается, и вы теряете прослеживаемость.
Issues и связь с кодом
Issue-трекер интегрирован с Git: упоминание Closes #42 в сообщении коммита или MR автоматически закроет issue при слиянии. Для CI/CD это менее важно, но показывает идею сквозной связности платформы — от задачи до задеплоенного результата.
Environments и реестры пакетов
GitLab знает понятие environment — именованной цели деплоя (staging, production). Джоба может объявить, что она деплоит в окружение, и тогда в интерфейсе появится история деплоев, кнопка отката и ссылка на работающее приложение. Помимо Container Registry есть и Package Registry для npm, Maven, PyPI и других пакетов.
Чтобы не путать два реестра и понятие окружения, сведём роли в таблицу — каждый компонент отвечает за свой кусок жизненного цикла.
| Компонент | Что хранит / делает | Когда пригодится в пайплайне |
|---|---|---|
| Container Registry | Docker-образы проекта | джоба build пушит образ, джоба deploy его тянет |
| Package Registry | пакеты npm, Maven, PyPI, NuGet | публикация библиотеки как артефакта релиза |
| Environment | история деплоев, откат, ссылка на приложение | джоба deploy объявляет цель и регистрирует развёртывание |
| Protected branches/vars | правила доступа и секреты | пускать продакшен-ключи только в пайплайны main |
Окружения дают ещё один скрытый бонус — наблюдаемость деплоев. Без environment деплой остаётся просто строчкой в логе джобы: что-то куда-то поехало. С объявленным environment GitLab рисует ленту «кто, когда и какую версию выкатил», показывает текущую активную версию и даёт откатить одной кнопкой на предыдущий успешный деплой. Для команды это превращает «а что сейчас в проде?» из расследования в один взгляд на экран.
Как работает под капотом
Все эти компоненты живут в единой базе GitLab и связаны правами доступа проекта. Когда пайплайн пушит образ в реестр или регистрирует деплой в окружение, он действует от лица временного токена джобы (CI_JOB_TOKEN), у которого права ограничены текущим проектом. Поэтому интеграция бесшовна: не нужно вручную раздавать ключи между сервисами.
Стоит подчеркнуть слово «временный». CI_JOB_TOKEN живёт ровно столько, сколько выполняется джоба, и умирает вместе с ней. Это принципиально безопаснее долгоживущего личного токена: даже если значение случайно утечёт в лог, оно протухнет через минуты. По той же причине токен джобы — предпочтительный способ авторизации между джобами и сервисами внутри GitLab: его не надо хранить, ротировать и отзывать вручную, платформа делает это за вас. Когда позже встретите задачу «дать одной джобе доступ к другому проекту», первым делом вспоминайте про область видимости CI_JOB_TOKEN, а не про создание персонального ключа.
Частые ошибки
- Считать Container Registry и Package Registry одним и тем же. Первый — для Docker-образов, второй — для пакетов языков.
- Забывать включить реестр контейнеров в настройках проекта (на self-hosted он может быть выключен администратором).
- Деплоить без объявления environment — тогда GitLab не покажет историю деплоев и не даст удобного отката.
- Тегировать образы только как
latestи терять связь образа с коммитом; тегируйте по$CI_COMMIT_SHORT_SHA. - Полагать, что секретная переменная доступна везде: помеченная protected, она появится лишь в пайплайнах защищённых веток и тегов.
Итоги
- Пайплайн взаимодействует с репозиторием, MR, реестром, окружениями и issue-трекером — это замкнутый круг от коммита до прода и обратно к ревью.
- Container Registry встроен в проект; пуш образа авторизуется предопределёнными переменными; тегируйте по коммиту.
- Environment даёт историю деплоев, откат и ссылку на приложение — наблюдаемость «что сейчас в проде».
- Интеграция держится на временном
CI_JOB_TOKENс правами текущего проекта — безопаснее личных ключей.