Visión General de GitLab CI
GitLab CI/CD está integrado directamente en GitLab — sin plugins, sin servicio separado, sin configuración adicional. Cada repositorio de GitLab puede usar CI/CD agregando un archivo .gitlab-ci.yml a la raíz del repositorio. GitLab detecta este archivo automáticamente y ejecuta el pipeline.
Para ingenieros QA, GitLab CI ofrece varias ventajas: reportes de tests nativos en merge requests, registro de contenedores integrado, gestión de entornos y review apps para testing de despliegues.
Estructura de .gitlab-ci.yml
Pipeline Básico
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
Conceptos Clave
| Concepto | Descripción |
|---|---|
| stages | Lista ordenada de fases del pipeline; jobs en la misma etapa se ejecutan en paralelo |
| image | Imagen Docker para el entorno del job |
| script | Comandos shell a ejecutar |
| artifacts | Archivos a preservar entre etapas o después del pipeline |
| rules | Condiciones que controlan cuándo se ejecuta un job |
| needs | Dependencias directas entre jobs (salta el orden de etapas) |
| services | Contenedores Docker adicionales (bases de datos, APIs) para el job |
Services: Dependencias de Test
Los services de GitLab CI levantan contenedores Docker junto a tu job. Esto es perfecto para tests de integración:
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
Los contenedores de servicio son accesibles por sus nombres alias (db, cache) como hostnames dentro del job.
Pipelines de Merge Request
GitLab puede ejecutar pipelines específicamente para merge requests, mostrando resultados directamente en el 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
Los resultados de tests de los reportes JUnit aparecen como una pestaña “Tests” en el merge request, mostrando conteos de éxitos/fallos y detalles de tests individuales.
Jobs Paralelos y Matrix
Keyword Parallel
Divide un job entre múltiples runners automáticamente:
e2e-tests:
stage: test
parallel: 4
script:
- npx playwright test --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
GitLab establece CI_NODE_INDEX (1-4) y CI_NODE_TOTAL (4) automáticamente, habilitando test sharding sin configuración manual.
Estrategia 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
Caché
Cachea dependencias entre ejecuciones del pipeline para acelerar builds:
default:
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
policy: pull-push
Gestión de Entornos
Los entornos de GitLab te permiten rastrear despliegues y conectarlos con testing:
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
Ejercicio: Diseña un Pipeline de GitLab CI
Crea un .gitlab-ci.yml para una aplicación web con:
- Etapa build con instalación de dependencias
- Etapa test con tests unitarios, integración (necesita PostgreSQL) y E2E en paralelo
- Deploy a staging en rama main
- Smoke tests después del despliegue a staging
- Reportes de tests visibles en merge requests
Solución
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
| Funcionalidad | GitLab CI | GitHub Actions | Jenkins |
|---|---|---|---|
| Archivo config | .gitlab-ci.yml | .github/workflows/*.yml | Jenkinsfile |
| Reportes de tests | Nativos en MR | Vía acciones terceros | Vía plugins |
| Container registry | Integrado | GitHub Packages | Externo |
| Services | Docker services nativos | Service containers | Plugin Docker |
| Parallel/Matrix | parallel + matrix | strategy.matrix | Scripted pipeline |
| Entornos | Integrados con tracking | Feature Environments | Setup manual |
| Review Apps | Integradas | Vía acciones custom | Setup manual |
| Self-hosted | GitLab Runner | Self-hosted runners | Funcionalidad core |
Mejores Prácticas para QA
Siempre usa
artifacts:reports:junitpara obtener resultados de tests en merge requests. Esta es una de las funcionalidades más fuertes de GitLab CI para visibilidad de QA.Usa
needsen lugar de ordenamiento por etapas cuando sea posible. La keywordneedspermite que los jobs inicien tan pronto como sus dependencias terminen.Configura
artifacts: when: alwaysen jobs de test. Sin esto, los reportes y capturas de pantalla se pierden cuando los tests fallan.Usa
parallelpara suites de tests grandes. La keyword parallel integrada conCI_NODE_INDEX/CI_NODE_TOTALhace el sharding trivial.Aprovecha services para tests de integración. Iniciar PostgreSQL, Redis u otras dependencias como services es más simple y rápido que instalarlas en el job.
Usa rules en lugar de only/except. La keyword
ruleses más poderosa y el enfoque recomendado para controlar cuándo se ejecutan los jobs.