К концу этого туториала у вас будет полностью функциональный GitLab CI/CD конвейер, который автоматически тестирует ваш код, генерирует отчеты и развертывает в несколько окружений. За 75 минут вы построите production-ready workflow тестирования, который ловит баги рано и ускоряет ваш цикл релиза.

Что вы Построите

Вы создадите GitLab CI/CD конвейер, который:

  • Запускает unit, интеграционные и end-to-end тесты автоматически
  • Выполняет тесты параллельно через несколько этапов
  • Генерирует отчеты о покрытии кода и качестве
  • Развертывает в окружения staging и production
  • Реализует кэширование результатов тестов для более быстрых конвейеров
  • Отправляет уведомления в командные каналы при сбоях
  • Создает динамические тестовые окружения для каждого merge request

Это решает проблему узких мест ручного тестирования и несогласованных проверок качества, которые замедляют скорость разработки.

Цели Обучения

В этом туториале вы узнаете:

  • Как настроить .gitlab-ci.yml для workflows тестирования
  • Как реализовать многоэтапные конвейеры с зависимостями
  • Как использовать встроенный Docker registry GitLab для тестовых контейнеров
  • Как эффективно кэшировать результаты тестов и зависимости
  • Как реализовать параллельное выполнение тестов
  • Как защитить секреты с помощью переменных GitLab CI/CD

Оценка времени: 75-90 минут

Предварительные Требования

Требуемое ПО

Перед началом установите:

ИнструментВерсияНазначение
Git2.30+Контроль версий
Docker20.10+Container runtime
Node.js18.x+Тестовое окружение
Аккаунт GitLab-CI/CD платформа

Установка:

# macOS
brew install git docker node

# Linux (Ubuntu/Debian)
sudo apt update
sudo apt install git docker.io nodejs npm

# Windows (используя Chocolatey)
choco install git docker-desktop nodejs

Требуемые Знания

Вы должны быть знакомы с:

  • Базовыми операциями Git (commit, push, merge)
  • Основами синтаксиса YAML
  • Базовыми концепциями Docker
  • Не требуется: Продвинутые знания DevOps или Kubernetes

Требуемые Ресурсы

  • Аккаунт GitLab (бесплатный тариф подходит)
  • Репозиторий с существующими тестами
  • Аккаунт Docker Hub (опционально, для кастомных образов)

Шаг 1: Создайте Базовую Конфигурацию GitLab CI/CD

На этом шаге мы создадим основной файл .gitlab-ci.yml.

Создайте Конфигурацию Конвейера

В корне вашего репозитория создайте .gitlab-ci.yml:

# .gitlab-ci.yml
image: node:18-alpine

stages:
  - test
  - build
  - deploy

variables:
  npm_config_cache: "$CI_PROJECT_DIR/.npm"
  CYPRESS_CACHE_FOLDER: "$CI_PROJECT_DIR/.cypress"

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .npm
    - node_modules
    - .cypress

before_script:
  - npm ci --cache .npm --prefer-offline

unit-tests:
  stage: test
  script:
    - npm run test:unit
  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
  artifacts:
    when: always
    reports:
      junit: junit.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

Что это делает:

  • image: Использует базовый образ Node.js 18 Alpine (легковесный)
  • stages: Определяет фазы конвейера (test → build → deploy)
  • cache: Кэширует npm и Cypress для более быстрых запусков
  • before_script: Устанавливает зависимости перед каждым job’ом
  • coverage: Извлекает процент покрытия из вывода
  • artifacts: Сохраняет результаты тестов и отчеты о покрытии

Push и Запуск Конвейера

git add .gitlab-ci.yml
git commit -m "Add GitLab CI/CD pipeline"
git push origin main

Перейдите в CI/CD → Pipelines в GitLab. Вы должны увидеть:

✅ Pipeline #1234567 passed
   ✅ test stage
      ✅ unit-tests (42s)

Checkpoint: Теперь у вас есть автоматизированные unit-тесты, запускающиеся при каждом push.

Шаг 2: Добавьте Многоэтапный Конвейер Тестирования

Реализуйте Интеграционные и E2E Тесты

Расширьте .gitlab-ci.yml дополнительными этапами тестирования:

stages:
  - test
  - integration
  - e2e
  - build
  - deploy

# Unit тесты (из Шага 1)
unit-tests:
  stage: test
  script:
    - npm run test:unit
  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
  artifacts:
    when: always
    reports:
      junit: junit.xml

# Интеграционные тесты
integration-tests:
  stage: integration
  services:
    - postgres:15-alpine
    - redis:7-alpine
  variables:
    POSTGRES_DB: testdb
    POSTGRES_USER: test
    POSTGRES_PASSWORD: testpass
    DATABASE_URL: "postgresql://test:testpass@postgres:5432/testdb"
    REDIS_URL: "redis://redis:6379"
  script:
    - npm run db:migrate
    - npm run test:integration
  artifacts:
    when: always
    reports:
      junit: test-results/integration-junit.xml

# E2E тесты с Playwright
e2e-tests:
  stage: e2e
  image: mcr.microsoft.com/playwright:v1.40.0-focal
  script:
    - npm ci
    - npm run build
    - npx playwright test
  artifacts:
    when: always
    paths:
      - playwright-report/
      - test-results/
    expire_in: 30 days

Что нового:

  • services: Поднимает PostgreSQL и Redis для интеграционных тестов
  • variables: Конфигурация тестов, специфичная для окружения
  • npm run db:migrate: Подготавливает схему БД перед тестами
  • Кастомный образ: Использует официальный Docker-образ Playwright для E2E тестов
  • expire_in: Артефакты автоматически удаляются через 30 дней

Checkpoint: Многоэтапный конвейер теперь запускает unit, интеграционные и E2E тесты последовательно.

Шаг 3: Реализуйте Параллельное Выполнение Тестов

Разделите Тесты на Несколько Job’ов

Для более быстрой обратной связи запускайте тесты параллельно:

unit-tests:
  stage: test
  parallel: 4
  script:
    - npm run test:unit -- --shard=${CI_NODE_INDEX}/${CI_NODE_TOTAL}
  artifacts:
    when: always
    reports:
      junit: junit-${CI_NODE_INDEX}.xml

e2e-tests:
  stage: e2e
  image: mcr.microsoft.com/playwright:v1.40.0-focal
  parallel:
    matrix:
      - BROWSER: [chromium, firefox, webkit]
  script:
    - npm ci
    - npx playwright test --project=$BROWSER
  artifacts:
    when: always
    paths:
      - playwright-report-$BROWSER/
    reports:
      junit: test-results/junit-$BROWSER.xml

Как работает параллельное выполнение:

  • parallel: 4: Разделяет unit-тесты на 4 конкурентных job’а
  • CI_NODE_INDEX/CI_NODE_TOTAL: Встроенные переменные для шардирования
  • Матричная стратегия: Запускает E2E тесты в 3 браузерах одновременно
  • Динамические имена артефактов: Каждый параллельный job загружает отдельные результаты

Прирост производительности:

  • Unit-тесты: 2м 40с → 40с (4x ускорение)
  • E2E тесты: 5м 30с → 2м 10с (3x ускорение параллельно)

Шаг 4: Добавьте Сканирование Качества Кода и Безопасности

Интегрируйте GitLab Code Quality

Добавьте проверки качества в ваш конвейер:

include:
  - template: Code-Quality.gitlab-ci.yml
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml

stages:
  - test
  - integration
  - e2e
  - quality
  - security
  - build
  - deploy

code_quality:
  stage: quality
  artifacts:
    reports:
      codequality: gl-code-quality-report.json

sast:
  stage: security

dependency_scanning:
  stage: security

Что это добавляет:

  • Code Quality: Анализирует код на сложность, дублирование и поддерживаемость
  • SAST: Static Application Security Testing для уязвимостей
  • Dependency Scanning: Проверяет известные проблемы безопасности в зависимостях
  • Виджеты merge request: Результаты появляются непосредственно в интерфейсе MR

Шаг 5: Реализуйте Динамические Тестовые Окружения

Создайте Review Apps для Каждого MR

Добавьте динамические окружения для ручного QA-тестирования:

deploy-review:
  stage: deploy
  image: alpine:latest
  script:
    - apk add --no-cache curl
    - |
      curl --request POST \
        --header "PRIVATE-TOKEN: $DEPLOY_TOKEN" \
        --data "environment=review-$CI_COMMIT_REF_SLUG" \
        "https://api.your-platform.com/deploy"
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://review-$CI_COMMIT_REF_SLUG.your-app.com
    on_stop: stop-review
  only:
    - merge_requests

stop-review:
  stage: deploy
  script:
    - echo "Остановка review окружения"
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    action: stop
  when: manual
  only:
    - merge_requests

Шаг 6: Добавьте Уведомления и Мониторинг

Настройте Slack Уведомления

notify-failure:
  stage: .post
  image: curlimages/curl:latest
  script:
    - |
      curl -X POST $SLACK_WEBHOOK_URL \
        -H 'Content-Type: application/json' \
        -d '{
          "text": "❌ Конвейер упал для '"$CI_PROJECT_NAME"'"
        }'
  when: on_failure
  only:
    - main
    - develop

Настройте Slack Webhook

  1. Создайте Slack app на api.slack.com/apps
  2. Включите “Incoming Webhooks”
  3. Скопируйте URL webhook’а
  4. В GitLab: Settings → CI/CD → Variables
    • Key: SLACK_WEBHOOK_URL
    • Value: [вставьте URL webhook’а]

Шаг 7: Оптимизируйте Производительность Конвейера

Реализуйте Продвинутое Кэширование

Оптимизируйте стратегию кэширования:

cache:
  key:
    files:
      - package-lock.json
  paths:
    - .npm
    - node_modules
  policy: pull

.install_deps:
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - .npm
      - node_modules
    policy: pull-push

Улучшения кэширования:

  • Key по lockfile: Кэш инвалидируется только когда зависимости меняются
  • policy: pull: Большинство job’ов только читают кэш (быстрее)
  • policy: pull-push: Первый job обновляет кэш

Добавьте Правила Оптимизации Конвейера

Пропускайте ненужные job’ы:

unit-tests:
  stage: test
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
    - changes:
        - "src/**/*"
        - "tests/**/*"
        - package.json
      when: always
    - when: never

Прирост производительности:

  • Изменения только в документации: Конвейер пропущен (0с vs 3м)
  • Кэширование зависимостей: Время установки 2м → 15с
  • Умный пропуск job’ов: Средний конвейер 3м → 1м 30с

Устранение Неполадок

Проблема 1: Сервисы Не Подключаются

Симптомы:

Error: connect ECONNREFUSED 127.0.0.1:5432

Решение: Используйте alias сервиса как hostname:

integration-tests:
  services:
    - name: postgres:15-alpine
      alias: postgres
  variables:
    DATABASE_URL: "postgresql://test:testpass@postgres:5432/testdb"

Проблема 2: Таймаут Конвейера

Решение: Увеличьте таймаут job’а:

e2e-tests:
  timeout: 90 minutes

Проблема 3: Кэш Не Работает

Проверьте key кэша:

cache:
  key:
    files:
      - package-lock.json  # Убедитесь, что этот файл существует
  paths:
    - .npm
    - node_modules

Следующие Шаги

Поздравляем! Вы построили production-grade конвейер тестирования GitLab CI/CD. 🎉

Что вы Построили

Теперь у вас есть:

  • ✅ Многоэтапный конвейер с unit, интеграционными и E2E тестами
  • ✅ Параллельное выполнение тестов для более быстрой обратной связи
  • ✅ Сканирование качества кода и безопасности
  • ✅ Динамические review-окружения для каждого MR
  • ✅ Умное кэширование для оптимизированной производительности
  • ✅ Slack уведомления при сбоях

Прокачайте Навыки

Простые Улучшения (30 мин каждое)

  1. Добавьте Visual Regression Testing
  2. Включите Auto-Merge при Успехе

Промежуточные Улучшения (1-2 часа каждое)

  1. Реализуйте Dashboard Отчетов Тестов
  2. Добавьте Performance Testing

Продвинутые Улучшения (3+ часа)

  1. Мультипроектные Конвейеры
  2. Интеграция Kubernetes

Связанные Туториалы

Продолжайте обучение:

Заключение

Что вы Достигли

В этом туториале вы:

  1. ✅ Создали многоэтапный GitLab CI/CD конвейер
  2. ✅ Реализовали параллельное выполнение тестов для скорости
  3. ✅ Добавили сканирование качества кода и безопасности
  4. ✅ Настроили динамические review-окружения
  5. ✅ Настроили Slack уведомления
  6. ✅ Оптимизировали конвейер с умным кэшированием и правилами

Ключевые Выводы

  • GitLab CI/CD мощный: Встроенные функции ускоряют разработку
  • Параллельное выполнение важно: Стратегическая параллелизация сокращает время конвейера на 50-70%
  • Умное кэширование необходимо: Правильная конфигурация сокращает избыточную работу
  • Правила оптимизируют затраты: Пропускайте ненужные job’ы для экономии вычислительных ресурсов

Вопросы или отзывы? Оставьте комментарий!

Было полезно? Поделитесь с командой!