Настройка stages и jobs, правила выполнения, условия и фильтры.
GitLab CI/CD предоставляет мощный и гибкий синтаксис для настройки пайплайнов. Изучите основы: stages, jobs, rules и условия выполнения.
Базовая структура конфигурации GitLab CI:
stages:
- build
- test
- deploy
variables:
NODE_VERSION: "20"
build_job:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
test_job:
stage: test
script:
- npm test
needs:
- build_job
deploy_job:
stage: deploy
script:
- ./deploy.sh
needs:
- test_job
only:
- mainStages определяют порядок выполнения jobs.
stages:
- prepare
- build
- test
- deployПравила выполнения:
stages:
- lint
- build
- test
- deploy
lint:
stage: lint
script:
- npm run lint
build:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
unit-test:
stage: test
script:
- npm run test:unit
needs:
- build
integration-test:
stage: test
script:
- npm run test:integration
needs:
- build
deploy:
stage: deploy
script:
- ./deploy.sh
needs:
- unit-test
- integration-test
only:
- mainВизуализация:
lint (parallel)
↓
build
↓
unit-test ──┐
├→ deploy
integration-test ──┘
Job — базовая единица выполнения в GitLab CI.
my_job:
script:
- echo "Hello, GitLab CI!"build:
stage: build
image: node:20-alpine
services:
- docker:dind
variables:
NODE_ENV: production
before_script:
- npm ci
script:
- npm run build
after_script:
- echo "Build complete"
artifacts:
paths:
- dist/
expire_in: 1 week
cache:
paths:
- node_modules/
tags:
- docker
allow_failure: false
timeout: 30m
when: on_success
rules:
- if: $CI_COMMIT_BRANCH == "main"| Директива | Описание |
|---|---|
stage | Этап, к которому относится job |
image | Docker-образ для выполнения |
services | Docker-сервисы (базы данных и т.п.) |
variables | Переменные окружения job |
before_script | Команды перед основным скриптом |
script | Основные команды job |
after_script | Команды после основного скрипта |
artifacts | Файлы для передачи между jobs |
cache | Кэшируемые директории |
tags | Теги для выбора runner |
allow_failure | Продолжать пайплайн при ошибке |
timeout | Максимальное время выполнения |
when | Когда выполнять job |
rules | Условия выполнения job |
needs | Зависимости от других jobs |
rules — современный способ управления выполнением jobs.
deploy:
stage: deploy
script:
- ./deploy.sh
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: on_success
- if: $CI_COMMIT_BRANCH == "develop"
when: manual
- when: never # Default ruleПравила обрабатываются по порядку:
when: never используется как fallbacktest:
script:
- npm test
rules:
# Ветка main — всегда запускать
- if: $CI_COMMIT_BRANCH == "main"
when: on_success
# Feature ветки — запускать для MR
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: on_success
# Теги версий — запускать тесты
- if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/
when: on_success
# Остальные случаи — пропускать
- when: never| Переменная | Описание |
|---|---|
CI_COMMIT_BRANCH | Имя ветки (для branch pipelines) |
CI_COMMIT_TAG | Имя тега (для tag pipelines) |
CI_COMMIT_REF_NAME | Имя ветки или тега |
CI_PIPELINE_SOURCE | Источник пайплайна |
CI_COMMIT_SHA | SHA коммита |
CI_PROJECT_ID | ID проекта |
CI_USER_ID | ID пользователя |
Значения CI_PIPELINE_SOURCE:
push — push в репозиторийweb — ручной запуск из UIschedule — по расписаниюapi — через APIexternal — external pipelinepipeline — downstream pipelinetrigger — trigger pipelinemerge_request_event — merge requestexternal_pull_request_event — external PRparent_pipeline — parent pipelineondemand_dast_scan — on-demand DASTondemand_dast_validation — on-demand DAST validationrules:
# Равенство
- if: $CI_COMMIT_BRANCH == "main"
# Неравенство
- if: $CI_COMMIT_BRANCH != "develop"
# Регулярные выражения
- if: $CI_COMMIT_BRANCH =~ /^feature\/.+/
- if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+$/
# Логические операторы
- if: $CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push"
- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
# Проверка на существование
- if: $DEPLOY_TOKEN != null
# Вхождение подстроки
- if: $CI_COMMIT_MESSAGE =~ /hotfix/i| Значение | Описание |
|---|---|
on_success | Выполнять при успехе предыдущих stages (по умолчанию) |
on_failure | Выполнять при неудаче предыдущих stages |
always | Выполнять всегда |
manual | Требовать ручного запуска |
delayed | Выполнять с задержкой (требуется start_in) |
never | Не выполнять job |
deploy-production:
stage: deploy
script:
- ./deploy.sh production
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
start_in: 30 minutes # Автозапуск через 30 минут, если не запущен вручнуюneeds создаёт явные зависимости между jobs для DAG-пайплайнов.
stages:
- build
- test
- deploy
build:
stage: build
script:
- npm run build
test-unit:
stage: test
script:
- npm run test:unit
needs:
- build
test-integration:
stage: test
script:
- npm run test:integration
needs:
- build
deploy:
stage: deploy
script:
- ./deploy.sh
needs:
- test-unit
- test-integrationПреимущество перед stages:
needs: deploy ждёт завершения всех test jobsneeds: deploy запускается сразу после завершения test-unit и test-integrationbuild:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
deploy:
stage: deploy
script:
- ./deploy.sh
needs:
- job: build
artifacts: true # Скачать артефакты из buildbuild-frontend:
stage: build
script:
- npm run build:frontend
artifacts:
paths:
- dist/frontend/
build-backend:
stage: build
script:
- npm run build:backend
artifacts:
paths:
- dist/backend/
deploy:
stage: deploy
script:
- ./deploy.sh
needs:
- job: build-frontend
artifacts: true
- job: build-backend
artifacts: truedeploy:
stage: deploy
script:
- ./deploy.sh
needs:
- job: test-optional
optional: true # Продолжить даже если test-optional failed/skippedРазрешает продолжение пайплайна при ошибке job.
lint:
stage: lint
script:
- npm run lint
allow_failure: true # Пайплайн продолжится даже при ошибках линтераexperimental-test:
stage: test
script:
- npm run test:experimental
rules:
- if: $CI_COMMIT_BRANCH == "main"
allow_failure: true
- if: $CI_COMMIT_BRANCH
allow_failure: falsetest:
stage: test
script:
- npm test
parallel:
matrix:
- NODE_VERSION: [18, 20, 22]
allow_failure: truestages:
- lint
- build
- test
- deploy
variables:
NODE_VERSION: "20"
DOCKER_DRIVER: overlay2
.lint_template: &lint_template
stage: lint
image: node:${NODE_VERSION}-alpine
script:
- npm ci
- npm run lint
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
lint-frontend:
<<: *lint_template
script:
- cd frontend
- npm ci
- npm run lint
lint-backend:
<<: *lint_template
script:
- cd backend
- npm ci
- npm run lint
build:
stage: build
image: node:${NODE_VERSION}-alpine
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/
test:
stage: test
image: node:${NODE_VERSION}-alpine
script:
- npm ci
- npm test -- --coverage
needs:
- build
artifacts:
paths:
- coverage/
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
rules:
- if: $CI_COMMIT_BRANCH
deploy-staging:
stage: deploy
image: alpine:latest
script:
- apk add --no-cache curl
- ./deploy.sh staging
environment:
name: staging
url: https://staging.example.com
needs:
- test
rules:
- if: $CI_COMMIT_BRANCH == "develop"
when: on_success
deploy-production:
stage: deploy
image: alpine:latest
script:
- apk add --no-cache curl
- ./deploy.sh production
environment:
name: production
url: https://example.com
needs:
- test
rules:
- if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/
when: manualstages:
- test
- deploy
test:
stage: test
script:
- npm test
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
deploy-review:
stage: deploy
script:
- ./deploy-review.sh
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://$CI_COMMIT_REF_SLUG.example.com
on_stop: stop-review
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: on_success
stop-review:
stage: deploy
script:
- ./stop-review.sh
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manualВопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.