Пайплайны GitLab CI для Playwright требуют одного дизайнерского решения с самого начала: устанавливать браузеры во время пайплайна или использовать официальный Docker-образ Playwright. Вариант с Docker-образом быстрее и избавляет от самой частой причины отказа: несовпадения версий между тегом образа и @playwright/test в package.json, из-за которого пайплайн падает с ошибкой executable doesn't exist. В этом гайде: минимальный рабочий .gitlab-ci.yml, загрузка артефактов, секреты, кэширование, параллельное шардирование и мультиокружная настройка для staging и production.
Предварительные требования
- Playwright-проект работает локально через
npx playwright test - Репозиторий GitLab (gitlab.com или self-hosted)
.gitlab-ci.ymlещё не существует (или добавляешь в него)
Минимальный рабочий пайплайн
Создаёшь .gitlab-ci.yml в корне проекта:
image: mcr.microsoft.com/playwright:v1.44.0-jammy
stages:
- test
playwright-tests:
stage: test
script:
- npm ci
- npx playwright test
artifacts:
when: always
paths:
- playwright-report/
expire_in: 7 daysВсё. Пушишь этот файл и GitLab CI запускает тесты на каждый коммит.
Разберём что делает каждая часть.
Объяснение строка за строкой
image: mcr.microsoft.com/playwright:v1.44.0-jammy
Docker-контейнер внутри которого выполняется пайплайн. Официальный Docker-образ Playwright включает Node.js, все предустановленные зависимости браузеров и Linux-окружение.
Это рекомендуемый подход: установка браузеров в пайплайне не нужна.
Фиксируй версию (v1.44.0, не latest) чтобы пайплайн не ломался при выходе новой версии Playwright. Обновляй вручную когда обновляешь Playwright локально.
npm ci vs. npm install
В CI всегда используй npm ci вместо npm install: npm ci устанавливает ровно то что в package-lock.json (детерминировано), работает быстрее в CI-окружениях и падает если package-lock.json отсутствует или не согласован.
artifacts
Playwright генерирует HTML-отчёт в playwright-report/ после каждого запуска. Секция artifacts говорит GitLab сохранить эту папку чтобы её можно было скачать и просмотреть.
when: always сохраняет артефакты даже при падении тестов: отчёт нужен именно когда тесты упали. expire_in: 7 days говорит GitLab автоматически удалять артефакты через 7 дней.
Просмотр отчёта: GitLab CI → пайплайн → джоба → «Download artifacts» → открываешь playwright-report/index.html.
Более полный пайплайн
Для реальных проектов нужна бо́льшая структура:
image: mcr.microsoft.com/playwright:v1.44.0-jammy
stages:
- test
variables:
# Кэш node_modules между запусками для скорости
npm_config_cache: "$CI_PROJECT_DIR/.npm"
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- .npm/
- node_modules/
playwright-tests:
stage: test
# Запуск на merge request-ах и основной ветке
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"
script:
- npm ci
- npx playwright test --reporter=html,junit
artifacts:
when: always
paths:
- playwright-report/
- test-results/
reports:
junit: test-results/results.xml
expire_in: 7 days
# Таймаут всей джобы
timeout: 20 minutesЧто добавилось
variables: переменные окружения для джобы. npm_config_cache говорит npm использовать конкретную директорию кэша.
cache: Node-модули кэшируются между запусками пайплайна. Первый запуск медленный (скачивает всё). Последующие быстрые (читает из кэша). Ключ: имя ветки, у разных веток отдельные кэши.
rules: контролирует когда запускается джоба. Конфиг выше запускается на merge request-ах (видишь результаты тестов до мёрджа) и на пушах в main (после мёрджа).
--reporter=html,junit: генерирует и HTML-отчёт, и JUnit XML. Формат JUnit понимает GitLab и отображает результаты тестов прямо в UI пайплайна.
reports: junit: говорит GitLab где находится JUnit XML. GitLab показывает вкладку «Tests» в пайплайне с pass/fail по каждому тесту.
Использование переменных окружения (секреты)
Никогда не помещай пароли или API-ключи в .gitlab-ci.yml. Используй переменные GitLab CI/CD:
Настройка переменных в GitLab
1. Project → Settings → CI/CD → Variables
2. Добавляешь: BASE_URL, ADMIN_EMAIL, ADMIN_PASSWORD, API_KEY
3. Чувствительные помечаешь как «Masked» (скрыты в логах)
4. Специфичные для окружения помечаешь как «Protected» (только на защищённых ветках)
Использование в пайплайне
playwright-tests:
script:
- npm ci
- npx playwright test
variables:
BASE_URL: $BASE_URL # Из переменных GitLab CI
ADMIN_EMAIL: $ADMIN_EMAIL # Из переменных GitLab CIИспользование в конфиге Playwright
// playwright.config.ts
import dotenv from 'dotenv';
dotenv.config();
export default defineConfig({
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
},
});Переменные GitLab CI доступны как переменные окружения в джобе: process.env.BASE_URL работает.
Параллельное выполнение и шардирование
Для больших тест-сьютов запускаешь тесты параллельно:
playwright-tests:
stage: test
parallel:
matrix:
- SHARD: ["1/4", "2/4", "3/4", "4/4"]
script:
- npm ci
- npx playwright test --shard=$SHARD
artifacts:
when: always
paths:
- playwright-report/
expire_in: 7 daysСоздаётся 4 параллельных джобы, каждая запускает 25% тестов. Общее время тестирования делится примерно на 4.
Объединение разбитых HTML-отчётов требует дополнительных шагов (команда merge-reports в Playwright).
Запуск в headed-режиме (для отладки)
По умолчанию Playwright запускается headless в CI. Если нужна визуальная отладка:
playwright-debug:
stage: test
script:
- npm ci
- npx playwright test --headed --video=on
when: manual # Запускается только вручную
artifacts:
when: always
paths:
- test-results/ # Видео сохраняются здесь
expire_in: 1 daywhen: manual означает: джоба не запускается автоматически, запускаешь её вручную из UI GitLab когда нужна отладка.
Работа с флакующими тестами
Playwright имеет встроенную логику повторных попыток. Настройка для CI:
// playwright.config.ts
export default defineConfig({
retries: process.env.CI ? 2 : 0, // 2 повтора только в CI
});Или в .gitlab-ci.yml разрешить самой джобе повторяться при падении:
playwright-tests:
retry:
max: 1 # Повторить всю джобу один раз при падении
when:
- runner_system_failure
- stuck_or_timeout_failureПовтор на уровне джобы (GitLab) предназначен для инфраструктурных сбоев. Повтор на уровне теста (конфиг Playwright) для флакующих тестов. Используй оба.
Полный пример с несколькими окружениями
image: mcr.microsoft.com/playwright:v1.44.0-jammy
stages:
- test
.playwright-base:
script:
- npm ci
- npx playwright test --reporter=html,junit
artifacts:
when: always
paths:
- playwright-report/
reports:
junit: test-results/results.xml
expire_in: 7 days
timeout: 20 minutes
playwright-staging:
extends: .playwright-base
variables:
BASE_URL: https://staging.yourapp.com
rules:
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
playwright-production:
extends: .playwright-base
variables:
BASE_URL: https://yourapp.com
rules:
- if: $CI_COMMIT_BRANCH == "main"
environment:
name: productionStaging-тесты запускаются на ветке develop и MR-ах, production-тесты только при мёрдже в main.
Диагностика частых проблем
Ошибка «Executable doesn't exist»
Не используешь Docker-образ Playwright или версия не та. Держись mcr.microsoft.com/playwright:v1.44.0-jammy и версия должна точно совпадать с версией @playwright/test.
Тесты падают по таймауту в CI, но проходят локально
CI-машины медленнее. Увеличивай таймауты в playwright.config.ts:
export default defineConfig({
timeout: 60000, // 60с на тест (вместо дефолтных 30с)
actionTimeout: 15000, // 15с на действие
});«Cannot find module» в CI
Зависимость отсутствует в package.json. Запускаешь npm install локально и коммитишь обновлённые package.json и package-lock.json.
Пайплайн медленный из-за npm install
Добавляй кэширование (показано в полном примере выше). Первый запуск медленный, последующие быстрые.
Чеклист перед первым запуском
- [ ]
.gitlab-ci.ymlнаходится в корне проекта - [ ] Используется Docker-образ Playwright с зафиксированной версией
- [ ]
npm ci(неnpm install) - [ ] Артефакты настроены для сохранения
playwright-report/ - [ ] Секреты в переменных GitLab CI, не в YAML-файле
- [ ]
retriesв Playwright настроены для CI-окружения - [ ]
timeoutзадан вplaywright.config.ts(CI-машины медленнее)
После этой настройки каждый пуш в репозиторий будет автоматически запускать тест-сьют и делать результаты доступными в просмотрщике пайплайна GitLab.