Los pipelines de GitLab CI para Playwright requieren una decisión de diseño desde el principio: instalar los navegadores durante el pipeline o usar la imagen Docker oficial de Playwright. La imagen Docker es más rápida y evita el fallo más común, donde una incompatibilidad de versión entre el tag de la imagen y @playwright/test en package.json rompe el pipeline con un error executable doesn't exist. Esta guía cubre el .gitlab-ci.yml mínimo que funciona, la subida de artefactos, los secretos, el caché, el sharding paralelo y una configuración multi-entorno para staging y producción.
Prerequisitos
Necesitas un proyecto de Playwright funcionando localmente con npx playwright test, un repositorio en GitLab (gitlab.com o autoalojado), y un .gitlab-ci.yml que aún no existe o que estás ampliando.
El pipeline mínimo que funciona
Crea .gitlab-ci.yml en la raíz del proyecto:
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 daysSube este archivo y GitLab CI ejecutará los tests en cada commit.
Qué hace cada parte
image: mcr.microsoft.com/playwright:v1.44.0-jammy
Este es el contenedor Docker donde corre el pipeline. La imagen oficial de Playwright ya incluye Node.js, todas las dependencias del sistema para los navegadores y un entorno Linux.
El enfoque recomendado es este: sin instalación de navegadores en el pipeline.
Pinea la versión (v1.44.0, no latest) para que el pipeline no se rompa cuando Playwright publique una nueva versión. Actualízala manualmente cuando actualices Playwright en local.
npm ci vs. npm install
En CI usa siempre npm ci en lugar de npm install: instala exactamente lo que está en package-lock.json (determinista), es más rápido en entornos CI, y falla si package-lock.json no existe o es inconsistente.
artifacts
Playwright genera un reporte HTML en playwright-report/ después de cada ejecución. La sección artifacts le dice a GitLab que guarde esa carpeta para que puedas descargarla y verla.
when: always guarda los artefactos aunque los tests fallen, porque el reporte es más valioso precisamente cuando algo falla. expire_in: 7 days hace que GitLab elimine los artefactos automáticamente a los 7 días.
Para ver el reporte: GitLab CI → el pipeline → el job → "Download artifacts" → abre playwright-report/index.html.
Un pipeline más completo
Para proyectos reales, se necesita más estructura:
image: mcr.microsoft.com/playwright:v1.44.0-jammy
stages:
- test
variables:
npm_config_cache: "$CI_PROJECT_DIR/.npm"
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- .npm/
- node_modules/
playwright-tests:
stage: test
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 minutesvariables: define variables de entorno para el job. npm_config_cache le dice a npm qué directorio de caché usar.
cache: los módulos de Node se almacenan en caché entre ejecuciones del pipeline. La primera vez es lenta. Las siguientes son rápidas. La clave es el nombre de rama, así cada rama tiene su propio caché.
rules: controla cuándo se ejecuta el job. La configuración de arriba corre en merge requests (para ver los resultados antes de mergear) y en pushes a main (después de mergear).
--reporter=html,junit: genera el reporte HTML y el XML de JUnit. GitLab entiende el formato JUnit y muestra los resultados directamente en la UI del pipeline.
reports: junit: le indica a GitLab dónde está el XML de JUnit. GitLab muestra entonces una pestaña "Tests" en el pipeline con el estado de cada test.
Variables de entorno y secretos
Nunca pongas contraseñas ni claves de API en .gitlab-ci.yml. Usa las variables de CI/CD de GitLab:
Cómo configurarlas en GitLab
1. Project → Settings → CI/CD → Variables
2. Agrega: BASE_URL, ADMIN_EMAIL, ADMIN_PASSWORD, API_KEY
3. Marca las sensibles como "Masked" (no se muestran en los logs)
4. Marca las de entornos específicos como "Protected" (solo corren en ramas protegidas)
Cómo usarlas en el pipeline
playwright-tests:
script:
- npm ci
- npx playwright test
variables:
BASE_URL: $BASE_URL
ADMIN_EMAIL: $ADMIN_EMAILCómo usarlas en la config de Playwright
// playwright.config.ts
import dotenv from 'dotenv';
dotenv.config();
export default defineConfig({
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
},
});Las variables de CI/CD de GitLab están disponibles como variables de entorno en el job. process.env.BASE_URL funciona sin configuración adicional.
Ejecución paralela y sharding
Para suites grandes, ejecuta los tests en paralelo:
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 daysEsto crea 4 jobs paralelos, cada uno ejecutando el 25% de los tests. El tiempo total se divide aproximadamente por 4.
Para combinar los reportes HTML divididos necesitas el comando merge-reports de Playwright como paso adicional.
Modo headed para depuración
Por defecto, Playwright corre en modo headless en CI. Para depurar visualmente:
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 significa que el job no corre automáticamente. Lo activas desde la UI de GitLab cuando necesitas depurar.
Tests con resultados inestables
Playwright tiene lógica de reintentos integrada. Configúrala para CI:
// playwright.config.ts
export default defineConfig({
retries: process.env.CI ? 2 : 0,
});O en .gitlab-ci.yml, permitir que el job mismo reintente en caso de fallo:
playwright-tests:
retry:
max: 1
when:
- runner_system_failure
- stuck_or_timeout_failureEl retry a nivel de job (GitLab) es para fallos de infraestructura. El retry a nivel de test (config de Playwright) es para tests inestables. Los dos tienen su lugar.
Configuración con múltiples entornos
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.tuapp.com
rules:
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
playwright-production:
extends: .playwright-base
variables:
BASE_URL: https://tuapp.com
rules:
- if: $CI_COMMIT_BRANCH == "main"
environment:
name: productionLos tests de staging corren en la rama develop y en los merge requests. Los de producción solo cuando se mergea a main.
Problemas comunes y cómo resolverlos
Error "Executable doesn't exist"
No estás usando la imagen Docker de Playwright, o la versión no coincide. Usa mcr.microsoft.com/playwright:v1.44.0-jammy y asegúrate de que la versión sea exactamente la misma que @playwright/test en package.json.
Los tests tienen timeout en CI pero pasan en local
Las máquinas de CI son más lentas. Aumenta los timeouts en playwright.config.ts:
export default defineConfig({
timeout: 60000,
actionTimeout: 15000,
});"Cannot find module" en CI
Hay una dependencia que no está en package.json. Ejecuta npm install en local y confirma el package.json y package-lock.json actualizados.
Pipeline lento por la instalación de npm
Agrega caché (como en el ejemplo completo de arriba). La primera ejecución será lenta; las siguientes serán rápidas.
Checklist antes del primer push
- [ ]
.gitlab-ci.ymlestá en la raíz del proyecto - [ ] Se usa la imagen Docker de Playwright con versión pinada
- [ ]
npm ci(nonpm install) - [ ] Artefactos configurados para guardar
playwright-report/ - [ ] Los secretos están en variables de CI/CD de GitLab, no en el archivo YAML
- [ ]
retriesde Playwright configurado para el entorno CI - [ ]
timeoutdefinido enplaywright.config.ts