Обзор GitLab CI

GitLab CI/CD встроен непосредственно в GitLab — без плагинов, без отдельного сервиса, без дополнительной настройки. Каждый репозиторий GitLab может использовать CI/CD, добавив файл .gitlab-ci.yml в корень репозитория. GitLab обнаруживает этот файл автоматически и запускает пайплайн.

Для QA-инженеров GitLab CI предлагает ряд преимуществ: нативные тестовые отчёты в merge requests, встроенный реестр контейнеров, управление окружениями и review apps для тестирования деплоев.

Структура .gitlab-ci.yml

Базовый пайплайн

stages:
  - build
  - test
  - deploy

install:
  stage: build
  image: node:20
  script:
    - npm ci
  artifacts:
    paths:
      - node_modules/
    expire_in: 1 hour

unit-tests:
  stage: test
  image: node:20
  script:
    - npm run test:unit -- --ci --coverage
  artifacts:
    reports:
      junit: junit-results.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'

e2e-tests:
  stage: test
  image: mcr.microsoft.com/playwright:v1.40.0-focal
  script:
    - npm ci
    - npx playwright test
  artifacts:
    when: always
    paths:
      - playwright-report/
      - test-results/
    reports:
      junit: test-results/junit.xml
    expire_in: 7 days

Ключевые концепции

КонцепцияОписание
stagesУпорядоченный список фаз пайплайна; jobs на одном этапе выполняются параллельно
imageDocker-образ для окружения job
scriptShell-команды для выполнения
artifactsФайлы для сохранения между этапами или после пайплайна
rulesУсловия, управляющие запуском job
needsПрямые зависимости между jobs (пропуск порядка этапов)
servicesДополнительные Docker-контейнеры (БД, API) для job

Services: зависимости для тестов

Services GitLab CI запускают Docker-контейнеры рядом с вашим job. Это идеально для интеграционного тестирования:

integration-tests:
  stage: test
  image: node:20
  services:
    - name: postgres:15
      alias: db
    - name: redis:7
      alias: cache
  variables:
    POSTGRES_DB: test_db
    POSTGRES_USER: test_user
    POSTGRES_PASSWORD: test_pass
    DATABASE_URL: "postgresql://test_user:test_pass@db:5432/test_db"
    REDIS_URL: "redis://cache:6379"
  script:
    - npm ci
    - npm run test:integration

Контейнеры сервисов доступны по именам-алиасам (db, cache) как хостнеймы внутри job.

Пайплайны для Merge Request

GitLab может запускать пайплайны специально для merge requests, отображая результаты прямо в MR:

e2e-tests:
  stage: test
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"
  script:
    - npx playwright test
  artifacts:
    reports:
      junit: test-results/junit.xml

Результаты тестов из JUnit-отчётов отображаются как вкладка «Tests» в merge request, показывая количество успешных/упавших и детали отдельных тестов.

Параллельные и matrix jobs

Ключевое слово parallel

Разделите job между несколькими runners автоматически:

e2e-tests:
  stage: test
  parallel: 4
  script:
    - npx playwright test --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL

GitLab автоматически устанавливает CI_NODE_INDEX (1-4) и CI_NODE_TOTAL (4), что позволяет шардировать тесты без ручной настройки.

Matrix-стратегия

e2e-tests:
  stage: test
  parallel:
    matrix:
      - BROWSER: [chromium, firefox, webkit]
  image: mcr.microsoft.com/playwright:v1.40.0-focal
  script:
    - npx playwright test --project=$BROWSER

Кэширование

Кэшируйте зависимости между запусками пайплайна для ускорения сборок:

default:
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/
    policy: pull-push

Управление окружениями

Окружения GitLab позволяют отслеживать деплои и связывать их с тестированием:

deploy-staging:
  stage: deploy
  script:
    - ./deploy.sh staging
  environment:
    name: staging
    url: https://staging.example.com

smoke-tests:
  stage: test
  needs: [deploy-staging]
  script:
    - npx playwright test --config=smoke.config.ts
  environment:
    name: staging
    action: verify

Упражнение: Спроектируйте пайплайн GitLab CI

Создайте .gitlab-ci.yml для веб-приложения с:

  • Этапом build с установкой зависимостей
  • Этапом test с unit, интеграционными (нужен PostgreSQL) и E2E-тестами параллельно
  • Деплоем в staging на ветке main
  • Smoke-тестами после деплоя в staging
  • Тестовыми отчётами, видимыми в merge requests
Решение
stages:
  - build
  - test
  - deploy
  - verify

default:
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/

install:
  stage: build
  image: node:20
  script:
    - npm ci
  artifacts:
    paths:
      - node_modules/
    expire_in: 1 hour

unit-tests:
  stage: test
  image: node:20
  needs: [install]
  script:
    - npm run test:unit -- --ci --coverage
  artifacts:
    reports:
      junit: junit-results.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'

integration-tests:
  stage: test
  image: node:20
  needs: [install]
  services:
    - name: postgres:15
      alias: db
  variables:
    POSTGRES_DB: test_db
    POSTGRES_USER: test
    POSTGRES_PASSWORD: test
    DATABASE_URL: "postgresql://test:test@db:5432/test_db"
  script:
    - npm run test:integration
  artifacts:
    reports:
      junit: integration-results.xml

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

deploy-staging:
  stage: deploy
  image: alpine:latest
  needs: [unit-tests, integration-tests, e2e-tests]
  script:
    - ./scripts/deploy-staging.sh
  environment:
    name: staging
    url: https://staging.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

smoke-tests:
  stage: verify
  image: mcr.microsoft.com/playwright:v1.40.0-focal
  needs: [deploy-staging]
  script:
    - npm ci
    - npx playwright test --config=smoke.config.ts
  environment:
    name: staging
    action: verify
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

GitLab CI vs GitHub Actions vs Jenkins

ВозможностьGitLab CIGitHub ActionsJenkins
Конфигурационный файл.gitlab-ci.yml.github/workflows/*.ymlJenkinsfile
Отчёты о тестахНативные в MRЧерез сторонние actionsЧерез плагины
Реестр контейнеровВстроенныйGitHub PackagesВнешний
ServicesНативные Docker servicesService containersПлагин Docker
Parallel/Matrixparallel + matrixstrategy.matrixScripted pipeline
ОкруженияВстроенные с трекингомFeature EnvironmentsРучная настройка
Review AppsВстроенныеЧерез custom actionsРучная настройка
Self-hostedGitLab RunnerSelf-hosted runnersОсновная функциональность

Лучшие практики для QA

  1. Всегда используйте artifacts:reports:junit для получения результатов тестов в merge requests. Это одна из сильнейших функций GitLab CI для видимости QA.

  2. Используйте needs вместо порядка этапов где возможно. Ключевое слово needs позволяет jobs начинаться сразу после завершения их зависимостей.

  3. Устанавливайте artifacts: when: always на тестовых jobs. Без этого отчёты тестов и скриншоты теряются при падении тестов.

  4. Используйте parallel для больших тестовых наборов. Встроенное ключевое слово parallel с CI_NODE_INDEX/CI_NODE_TOTAL делает шардинг тривиальным.

  5. Используйте services для интеграционных тестов. Запуск PostgreSQL, Redis или других зависимостей как services проще и быстрее, чем их установка в job.

  6. Используйте rules вместо only/except. Ключевое слово rules мощнее и является рекомендованным подходом для управления запуском jobs.