¡Lánzate al pipeline de CI/CD: tu primer paso concreto hoy!
CI CD Pipeline: lo esencial en un artículo — código real, diagramas y pasos concretos, extractos de un curso de 20 lecciones.
La mejor forma de aprender CI CD Pipeline es practicando. Este artículo te da un empujón con extractos prácticos extraídos de un curso de 20 lecciones — lo suficiente para obtener un primer resultado hoy mismo.
- Introducción a CICD
- Integración Continua
- Calidad del Código
- Optimización del Pipeline
- Despliegue Continuo
Cobertura de código y umbrales de calidad
Capítulo 02 • Lección 03 • Duración : 45 min
- Comprender qué es la cobertura de código y sus límites
- Medir la cobertura con las herramientas estándar (pytest-cov, jest, JaCoCo)
- Definir umbrales inteligentes (línea, rama, mutación)
- Bloquear un PR si la cobertura baja
- Visualizar los informes en Codecov o SonarQube
1. ¿Qué es la cobertura de código?
La cobertura de código mide el porcentaje de líneas (o de ramas, condiciones, funciones) ejecutadas por tus pruebas automatizadas.
| Tipo | Medida | Ejemplo |
|---|---|---|
| Line Coverage | % de líneas ejecutadas | 80 % = 80 líneas de 100 son alcanzadas |
| Branch Coverage | % de ramas condicionales probadas | if/else, switch — ambos caminos deben pasar |
| Function Coverage | % de funciones llamadas | ¿Todas las funciones exportadas están probadas? |
| Statement Coverage | % de instrucciones ejecutadas | Cercano a line coverage |
| Mutation Coverage | % de mutaciones detectadas por las pruebas | Más fiable pero costoso (mutation testing) |
El 100 % de cobertura NO significa 100 % de calidad. Se puede tener 100 % de líneas ejecutadas sin verificar los resultados. assert es igual de importante que ejecutar el código.
2. Cobertura en Python con pytest-cov
pip install pytest pytest-cov # Ejecutar las pruebas con coverage pytest --cov=mon_module --cov-report=term --cov-report=html # Salida por consola : # Name Stmts Miss Cover # ------------------------------------- # mon_module.py 50 5 90% # ------------------------------------- # TOTAL 50 5 90% # Informe HTML interactivo en htmlcov/index.html
Configuración vía pyproject.toml
[tool.pytest.ini_options]
addopts = "--cov=src --cov-report=term-missing --cov-report=xml --cov-fail-under=80"
[tool.coverage.run]
source = ["src"]
omit = [
"*/tests/*",
"*/migrations/*",
"*/__init__.py"
]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]
fail_under = 80
show_missing = true3. Cobertura en JavaScript con Jest
npm install --save-dev jest
# package.json
{
"scripts": {
"test": "jest",
"test:coverage": "jest --coverage"
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,ts}",
"!src/**/*.d.ts",
"!src/index.ts"
],
"coverageThreshold": {
"global": {
"branches": 75,
"functions": 80,
"lines": 80,
"statements": 80
}
},
"coverageReporters": ["text", "lcov", "html", "cobertura"]
}
}
# Ejecutar
npm run test:coverage
# Si no se alcanza el umbral :
# Jest: "global" coverage threshold for lines (80%) not met: 73.5%
# → Build FALLA4. Cobertura en Java con JaCoCo
<!-- pom.xml -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals><goal>prepare-agent</goal></goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals><goal>report</goal></goals>
</execution>
<execution>
<id>jacoco-check</id>
<goals><goal>check</goal></goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
mvn clean test
# Informe en target/site/jacoco/index.html5. Definir umbrales inteligentes
| Tipo de proyecto | Umbral recomendado |
|---|---|
| Critical (banking, healthcare, aerospace) | 90-95 % |
| SaaS / Web app production | 80-85 % |
| Backend API | 75-85 % |
| Frontend (UI logic) | 60-70 % |
| Prototype / MVP | 40-60 % |
| Script utilitario | 0-30 % (a menudo innecesario) |
En lugar de un umbral absoluto, exija que la cobertura no baje respecto a la rama main. Codecov y SonarQube lo hacen de forma nativa.
6. Integración GitHub Actions
name: CI with Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install
run: pip install -e ".[dev]"
- name: Tests + coverage
run: pytest --cov --cov-report=xml --cov-report=term --cov-fail-under=80
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true7. Codecov : visualizar y comparar
codecov.yml para personalizar
coverage:
status:
project:
default:
target: 80%
threshold: 1%
patch:
default:
target: 90%
threshold: 5%
comment:
layout: "header, diff, flags, files"
behavior: default
require_changes: false
ignore:
- "tests/**"
- "**/__init__.py"
- "migrations/**"Gestión de artifacts y registries
Capítulo 03 • Lección 03 • Duración : 45 min
- Comprender qué es un artifact y un registry
- Almacenar y compartir artifacts (zip, jar, wheel) en GitHub Actions
- Enviar imágenes Docker a Docker Hub, GHCR, AWS ECR
- Gestionar el versionado semántico de los artifacts
- Establecer reglas de retención para evitar la explosión de costes
1. ¿Qué es un artifact?
Un artifact es cualquier archivo producido por un build y destinado a ser utilizado más tarde :
| Tipo de artifact | Ejemplo | Registry típico |
|---|---|---|
| Image container | devforge-api:1.2.3 (Docker) | Docker Hub, GHCR, ECR, Quay |
| Package Python | my-lib-1.0.0.whl | PyPI, AWS CodeArtifact, GitHub Packages |
| Package npm | my-lib-1.0.0.tgz | npm registry, GitHub Packages |
| JAR Java | my-app-1.0.jar | Maven Central, Nexus, JFrog Artifactory |
| Binario compilado | my-cli-linux-amd64 | GitHub Releases, S3 |
| Helm chart | my-chart-1.0.0.tgz | ChartMuseum, OCI registries |
| Fichero ZIP genérico | build-output.zip | GitHub Actions Artifacts, S3 |
2. Artifacts GitHub Actions (intra-workflow)
Subir un artifact
- name: Build wheel
run: python -m build
- name: Upload wheel as artifact
uses: actions/upload-artifact@v4
with:
name: python-wheel
path: dist/*.whl
retention-days: 30Descargar en un job siguiente
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download wheel
uses: actions/download-artifact@v4
with:
name: python-wheel
path: ./dist
- name: Install
run: pip install dist/*.whlLos artifacts de GitHub son gratuitos hasta 500 MB por repo público, y expiran por defecto después de 90 días.
3. Container registries comparados
| Registry | Coste | Ventajas | Inconvenientes |
|---|---|---|---|
| Docker Hub | Gratis (público) / 5 $/user (privado) | El más popular, amplio ecosistema | Rate limits en los pulls |
| GHCR (GitHub) | Gratis (público) / incluido en GitHub | Integración nativa con GitHub | Menos conocido |
| AWS ECR | 0.10 $/Go/mes | Seguridad IAM, escaneo automático, integrado con ECS/EKS | Específico de región |
| GCR / Artifact Registry | 0.10 $/Go/mes | Integrado con GCP, multi-formato | Lock-in GCP |
| Azure ACR | Basic 5 $/mes | Integrado con Azure | Lock-in Azure |
| Quay.io | Gratis (público) / de pago (privado) | Fuerte detector de vulnerabilidades | Menos soporte |
| Harbor (self-hosted) | Gratis (pero ops) | Sin dependencia externa, control total | Hay que mantenerlo uno mismo |
4. Push hacia Docker Hub desde GitHub Actions
- name: Login Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
myuser/myapp:latest
myuser/myapp:${{ github.sha }}
myuser/myapp:${{ github.ref_name }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max5. Push hacia GHCR (GitHub Container Registry)
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}GHCR no requiere ningún secret adicional : el GITHUB_TOKEN autogenerado es suficiente.
6. Push hacia AWS ECR
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecr
aws-region: eu-west-3
- name: Login to ECR
id: ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: |
${{ steps.ecr.outputs.registry }}/myapp:latest
${{ steps.ecr.outputs.registry }}/myapp:${{ github.sha }}7. Versionado semántico de las imágenes
Convención SemVer : MAJOR.MINOR.PATCH
| Tag | Cuándo usarlo |
|---|---|
1.2.3 | Versión exacta inmutable (producción estricta) |
1.2 | Último parche de la menor 1.2 |
1 | Última menor de la mayor 1 |
latest | La más reciente (¡evitar en prod!) |
sha-abc1234 | Tag basado en el commit de Git |
main / develop | Última de la rama |
pr-42 | Específico de una Pull Request |
v1.2.3-rc.1 | Release candidate |
Con docker/metadata-action
- name: Generate tags
id: meta
uses: docker/metadata-action@v5
with:
images: myuser/myapp
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix=sha-,format=short
type=raw,value=latest,enable={{is_default_branch}}
# Salida automática según el contexto :
# - en main : latest, sha-abc1234, main
# - en tag v1.2.3 : 1.2.3, 1.2, 1, sha-abc1234
# - en PR #42 : pr-42, sha-abc1234Capítulo 00.1 — Filosofía CI/CD : ¿Por qué automatizar?
1. El mundo antes de CI/CD — La «Integration Hell»
Antes de adoptar las prácticas CI/CD, los equipos de desarrollo trabajaban en silos durante semanas o meses en ramas separadas. Cuando intentaban integrar su código, el resultado solía ser catastrófico. A este fenómeno se le llamaba Integration Hell (infierno de la integración).
🔴 Antes de CI/CD
🟢 Con CI/CD
2. El coste del bug — La regla del «Shift Left»
El principio «Shift Left» (desplazar a la izquierda) significa que hay que detectar y corregir los problemas lo antes posible en el ciclo de desarrollo. Cuanto más tarde se detecta un bug, más caro resulta corregirlo.
CI/CD permite detectar los problemas desde el commit, reduciendo drásticamente el coste de corrección. Las pruebas automatizadas, el análisis estático del código y los escaneos de seguridad se ejecutan en cada push, mucho antes de que el código llegue a producción.
3. Los tres pilares : CI, CD (Entrega) y CD (Despliegue)
🔵 CI — Integración Continua
Los desarrolladores integran su código en una rama común varias veces al día. En cada integración se lanza un pipeline automatizado : compilación, pruebas unitarias, análisis de código.
Objetivo : detectar conflictos y bugs rápidamente.
🟡 CD — Entrega Continua
El código siempre está en un estado desplegable. Tras la CI, el pipeline prepara automáticamente una release (paquete, imagen Docker) lista para desplegarse en cualquier entorno.
Objetivo : poder desplegar en cualquier momento, con aprobación humana posible.
🟢 CD — Despliegue Continuo
Todo commit que pasa las pruebas se despliega automáticamente en producción, sin intervención humana. Es el nivel máximo de automatización, utilizado por Netflix, Amazon, Google.
Objetivo : eliminar cualquier retraso entre el código y el valor para el usuario.
| Práctica | Frecuencia de despliegue | Aprobación humana | Nivel de confianza requerido |
|---|---|---|---|
| Manual | Trimestral / Anual | Siempre | Bajo (proceso) |
| CI solamente | Semanal / Mensual | Siempre | Medio (pruebas básicas) |
| CI + CD Entrega | Diaria / Semanal | Opcional | Alto (pruebas completas) |
| CI + CD Despliegue | Varias veces/día | Nunca | Muy alto (pruebas + monitorización) |
4. El pipeline CI/CD — Vista general
Un pipeline CI/CD es una cadena de pasos automatizados que transforma un commit de código en una aplicación desplegada en producción.
| Paso | Descripción | Herramientas habituales | Duración típica |
|---|---|---|---|
| Code | El desarrollador sube código a Git | Git, GitHub, GitLab | — |
| Build | Compilación, resolución de dependencias | Maven, npm, Gradle, Docker | 1–5 min |
| Test unitario | Pruebas rápidas a nivel de funciones | JUnit, Jest, pytest | 1–3 min |
| Análisis de calidad | Cobertura de código, linting, seguridad | SonarQube, ESLint, Snyk | 2–5 min |
| Package | Creación de un artifact desplegable | Docker, JAR, ZIP, Helm | 2–10 min |
| Test de integración | Pruebas en un entorno completo | Postman, Cypress, k6 | 5–15 min |
| Deploy Staging | Despliegue en entorno de pruebas | Kubernetes, ECS, Heroku | 2–5 min |
| Deploy Prod | Despliegue en producción | Rolling, Blue/Green, Canary | 2–10 min |
| Monitor | Vigilancia y alertas post-despliegue | Prometheus, Grafana, Datadog | Continuo |
5. Las métricas DORA — Medir el rendimiento DevOps
El proyecto DORA (DevOps Research and Assessment) identificó cuatro métricas clave que miden la eficacia de una organización DevOps. Estas métricas permiten situar a tu equipo y definir objetivos de mejora.
📈 Deployment Frequency
Este artículo cubre los extractos más útiles — el curso completo CI CD Pipeline (7 capítulos, 20 lecciones, ejercicios corregidos y proyecto final) te lleva hasta el final.
./acceder-al-curso-completo curso gratuito : Dominar Claude CodeFAQ
¿Cuánto tiempo se tarda en aprender CI CD Pipeline?
¿Se necesitan requisitos previos?
¿Por dónde empezar de forma concreta?
📬 ¿Quieres recibir este tipo de guía cada semana? Suscríbete gratis — código real, cero paja.