⚙️ 3.9 · CI/CD con GitHub Actions: testing, build y deploy automatizado en cada commit

⏱ 4h 00min ⚡ 90 XP 🏅 Mid Junior 📖 Frontend Moderno y Proyecto Final
"Si tu deploy depende de un humano haciendo clic, tienes un problema de escala."

🎯 Objetivo del tema

Al terminar este tema serás capaz de: Al terminar este tema serás capaz de configurar pipelines de CI/CD con GitHub Actions: que tus tests se ejecuten automáticamente en cada push, que el build se valide, y que el deploy a Vercel/Netlify/Railway se haga sin intervención manual. Aprenderás workflows YAML, triggers, jobs, steps, secrets, matrices, badges, y el flujo profesional de integración continua. El resultado: cada commit a main es candidato a producción.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

🗺️ Mapa del tema

Imagina esto: haces push, esperas 2 minutos, abres tu app, y algo está roto. ¿Qué pasó? Alguien metió un bug. Pero tú no te enteraste hasta producción. Con CI/CD, ese escenario NO EXISTE: cada push dispara tests automáticos. Si algo se rompe, GitHub te avisa ANTES de hacer merge a main. Y cuando haces merge, el deploy es automático. Es la diferencia entre 'rezar para que no se rompa' y 'tener un seguro automático'. En este tema configuras un pipeline completo para tu Atlas Mundial.

1. Qué es CI/CD y por qué tu app lo necesita

Continuous Integration + Continuous Deployment: el flujo profesional.

2. GitHub Actions: workflows en YAML

La herramienta de CI/CD integrada en GitHub, gratis para repos públicos.

3. Triggers, jobs y steps: la anatomía de un workflow

eventos, jobs paralelos, steps con actions, contexto de ejecución.

4. Pipeline de testing automático en cada PR

Correr tests + coverage + lint automáticamente antes de mergear.

5. Deploy automático a Vercel/Netlify con secrets

Cómo proteger API keys y deployar con cada merge a main.

6. Badges, status checks y el flujo PR → review → merge → deploy

Cómo comunicar el estado de tu pipeline a tu equipo.

3.9.1 Qué es CI/CD y por qué tu app lo necesita

CI significa Continuous Integration (Integración Continua): cada vez que alguien hace push, se ejecutan los tests automáticamente. CD significa Continuous Deployment (Despliegue Continuo): si los tests pasan, el código se deploya a producción automáticamente. Es el flujo que usan Netflix, Google, Facebook, y todas las empresas de software modernas. Sin CI/CD, tu equipo acumula código sin probar durante semanas y el día del release es un desastre. Con CI/CD, cada cambio se prueba y deploya de forma aislada, reduciendo el riesgo 100x.

El antes y el después de CI/CD

  • ANTES de CI/CD: devs programan 2 semanas → merge conflictivo → deploy manual → algo se rompe → pánico a las 3am → hotfix urgente → bug nuevo.
  • DESPUÉS de CI/CD: dev hace push → tests automáticos en 3 min → si pasan, deploy a staging en 1 min → QA prueba → merge a main → deploy a producción en 2 min. Sin humanos involucrados en el deploy.
  • El secreto: cada commit es PEQUEÑO y se prueba AISLADAMENTE. Si falla, solo revientas ESE commit, no toda la release.
  • Las métricas mejoran: 95% menos bugs en producción, 10x más frecuencia de deploys, 50% menos tiempo de recuperación ante incidentes.
⭐ CI/CD: 1-2 días de setup, meses de ahorro: El ROI de CI/CD es INMEDIATO. La inversión: 1-2 días configurando el pipeline. El retorno: meses de tiempo ahorrado en deploys manuales, hotfixes, y bugs en producción. Empresas como Etsy pasaron de 1 deploy cada 2 semanas (con 40% de fallos) a 50 deploys por día (con 0.1% de fallos) solo con CI/CD bien implementado. No es un lujo: es el estándar de la industria. Si no tienes CI/CD, tu equipo está operando en modo artesanal.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.9.2 GitHub Actions: workflows en YAML

GitHub Actions es la herramienta de CI/CD INTEGRADA en GitHub. Es gratis para repos públicos (2000 min/mes) y tiene plan gratis para privados (con límites). Se configura con un archivo .github/workflows/ci.yml donde defines en YAML los eventos que disparan el workflow, los jobs, los steps, y las actions a usar. Es la opción #1 para aprender porque no necesitas otra cuenta, otra herramienta, ni otro login: ya estás en GitHub.

Anatomía básica de un workflow

# .github/workflows/ci.yml: el nombre del archivo puede ser cualquiera
# Convención: ci.yml, test.yml, deploy.yml, etc.

name: CI Pipeline    # nombre que aparece en la pestaña Actions de GitHub

# TRIGGERS: en QUÉ eventos se ejecuta este workflow
on:
  push:
    branches: [main, develop]   # cuando hay push a main o develop
  pull_request:
    branches: [main]            # cuando se abre/actualiza un PR a main
  # Otros triggers comunes:
  # schedule:                    # tareas programadas (cron)
  #   - cron: '0 2 * * *'        # todos los días a las 2am
  # workflow_dispatch:            # botón 'Run workflow' manual

# JOBS: grupos de steps que se ejecutan (pueden ser en paralelo)
jobs:
  # job 1: correr tests
  test:
    runs-on: ubuntu-latest     # sistema operativo del runner (ubuntu/windows/macos)
    # Opciones de runs-on: ubuntu-latest, windows-latest, macos-latest
    # También: ubuntu-22.04, self-hosted (tu propio runner)

    steps:
      # step 1: clonar el repo (casi siempre es el primero)
      - name: Checkout code
        uses: actions/checkout@v4   # 'uses' = usar una action de la marketplace

      # step 2: instalar Node.js 20
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'              # cache de dependencias para acelerar

      # step 3: instalar dependencias
      - name: Install dependencies
        run: npm ci                  # 'run' = ejecutar un comando shell
        # npm ci vs npm install: npm ci es más rápido y estricto (usa package-lock.json)

      # step 4: correr tests con coverage
      - name: Run tests
        run: npm run test:coverage

      # step 5: subir reporte de coverage a Codecov (opcional)
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          token: ${{ secrets.CODECOV_TOKEN }}   # secret (lo configuras en Settings > Secrets)
        if: always()    # 'if: always()' ejecuta este step incluso si los tests fallan

Workflow básico: test en cada PR a main

El job de build: validar que el bundle de producción compila

# Añadir este job al mismo workflow
  build:
    runs-on: ubuntu-latest
    needs: test                  # 'needs' = depende del job 'test' (se ejecuta DESPUÉS)

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build production bundle
        run: npm run build
        env:
          # Variables de entorno para el build (NO son secrets, son públicas)
          VITE_API_URL: https://api.miapp.com
          VITE_SUPABASE_URL: https://xxx.supabase.co

      # Subir el artefacto de build (opcional, útil para debuggear)
      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/
          retention-days: 7         # cuánto tiempo se guarda (max 90 días)

Job de build con Node 20 y caché de npm

⭐ GitHub Actions: 2000 min/mes gratis, suficiente para 90% de apps: GitHub Actions es BARATO y SUFICIENTE para el 90% de proyectos. 2000 min/mes gratis en repos públicos es ENORME (son 33 horas de CI al mes). En privados tienes 500 min/mes gratis. Si necesitas más, los planes empiezan en $4/mes por 3000 min. Es 10x más barato que CircleCI, Travis, o GitLab CI para el mismo uso. Y ya está integrado en tu repo: cero configuración de cuentas, tokens, o webhooks. Solo subes un YAML y funciona.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.9.3 Triggers, jobs y steps: la anatomía de un workflow

Un workflow de GitHub Actions tiene 3 niveles: TRIGGERS (cuándo se ejecuta), JOBS (qué se ejecuta en paralelo), y STEPS (cómo se ejecuta cada job). Los jobs pueden depender entre sí (needs), pueden correr en paralelo, en diferentes OS, y pueden tener una matriz de versiones. Es como Lego: combinas estos elementos para construir tu pipeline perfecto.

Triggers: los 10 más usados

  • on: push → cuando se hace push a cualquier branch.
  • on: push.branches: [main] → solo a main (ahorra minutos de CI).
  • on: pull_request → cuando se abre/actualiza un PR.
  • on: pull_request.target: main → PRs que apuntan a main.
  • on: workflow_dispatch → botón 'Run workflow' manual desde la UI.
  • on: schedule → tareas programadas con cron (ej: nightly builds).
  • on: release → cuando se publica un release.
  • on: issues → cuando se abre/cierra/etiqueta un issue.
  • on: workflow_call → para reutilizar este workflow desde otros.
  • on: push.paths: ['src/**'] → solo si cambian archivos en src/.

Matriz: testear en múltiples versiones/OS

# Matrix: ejecutar el MISMO job en múltiples combinaciones
# Útil para testear en Node 18, 20, 22 y Ubuntu, Windows, macOS
jobs:
  test:
    runs-on: ${{ matrix.os }}      # OS viene de la matriz
    strategy:
      fail-fast: false             # NO cancelar los demás si uno falla
      matrix:
        node-version: [18, 20, 22]  # 3 versiones de Node
        os: [ubuntu-latest, windows-latest, macos-latest]  # 3 OS
        # Total: 9 combinaciones (3 x 3) en paralelo

    steps:
      - uses: actions/checkout@v4

      - name: Use Node.js ${{ matrix.node-version }} on ${{ matrix.os }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

      - run: npm ci
      - run: npm test
        env:
          CI: true                  # flag para que los tests sepan que están en CI

Matrix strategy: 9 combinaciones en paralelo

⭐ Matrix: más confianza, menos tiempo: El matrix strategy es BRILLANTE para asegurarte de que tu código funciona en múltiples entornos. Si tienes una app de Node, la matriz Node 18+20+22 x Ubuntu+Windows+macOS = 9 jobs en paralelo que se ejecutan en ~3 minutos. Es el doble de confianza por la mitad del tiempo que tardarías testeando secuencialmente. Y si uno falla (ej: Windows + Node 22), sabes EXACTAMENTE dónde está el problema. La regla: si tu app tiene usuarios en múltiples OS o tu equipo usa múltiples versiones, usa matriz. Si solo es Node 20 en Ubuntu, no vale la pena.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.9.4 Pipeline de testing automático en cada PR

El pipeline de testing es el CORAZÓN de CI/CD. En cada Pull Request, GitHub Actions debe correr: lint (calidad de código), tests unit, tests de integración, build, y mostrar el reporte. Si algo falla, el PR no se puede mergear. Es la red de seguridad que evita que bugs lleguen a main. Configurarlo toma 30 minutos y te ahorra meses de bugs en producción.

Pipeline completo de testing en cada PR

# .github/workflows/ci.yml: pipeline profesional
name: CI Pipeline

on:
  pull_request:
    branches: [main, develop]
  push:
    branches: [main, develop]

jobs:
  # JOB 1: Lint (calidad de código)
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20', cache: 'npm' }
      - run: npm ci
      - name: ESLint
        run: npm run lint
      - name: Prettier check
        run: npm run format:check

  # JOB 2: Tests + coverage (paralelo a lint)
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20', cache: 'npm' }
      - run: npm ci
      - name: Run tests with coverage
        run: npm run test:coverage
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with: { token: ${{ secrets.CODECOV_TOKEN }} }
      - name: Archive coverage report
        uses: actions/upload-artifact@v4
        with:
          name: coverage-report
          path: coverage/
          retention-days: 7

  # JOB 3: Build (depende de lint y test)
  build:
    runs-on: ubuntu-latest
    needs: [lint, test]   # espera a que ambos pasen
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20', cache: 'npm' }
      - run: npm ci
      - name: Build production bundle
        run: npm run build
        env:
          VITE_API_URL: https://api.miapp.com
      - name: Check bundle size
        run: |
          echo 'Bundle size:'
          du -sh dist/
          # Fallar si el bundle es mayor a 2MB
          SIZE=$(du -sm dist/ | cut -f1)
          if [ $SIZE -gt 2 ]; then
            echo 'Bundle too large!'
            exit 1
          fi

  # JOB 4: Status check (verifica que TODOS pasaron)
  all-checks-passed:
    runs-on: ubuntu-latest
    needs: [lint, test, build]
    if: success()          # solo si los anteriores pasaron
    steps:
      - run: echo 'All checks passed! Ready to merge.'

Pipeline completo: lint, test, build, status check

⭐ Branch protection: disciplina automática: Configurar branch protection en GitHub es el COMPLEMENTO del pipeline: en Settings > Branches > Branch protection rules, marca 'Require status checks to pass before merging' y selecciona los jobs que creaste. Ahora NINGÚN PR se puede mergear si los tests fallan, aunque el reviewer diga 'OK'. Es la regla que evita el clásico 'mergea rápido que luego lo arreglo' (que nunca se arregla). Es la diferencia entre 'esperar que el equipo sea disciplinado' y 'tener disciplina automática'.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.9.5 Deploy automático a Vercel/Netlify con secrets

El deploy automático es la segunda parte de CD (Continuous Deployment). Una vez que los tests pasan y haces merge a main, tu app se deploya automáticamente. Vercel, Netlify, y Railway tienen GitHub Actions oficiales, o puedes usar su integración nativa con GitHub (más fácil). Lo crítico: proteger las API keys y secrets con GitHub Secrets, NUNCA en el código.

Opción 1: Integración nativa (más fácil)

  • Vercel: ve a vercel.com, conecta tu repo de GitHub, cada push a main se deploya automáticamente. Sin configurar Actions.
  • Netlify: igual, ve a netlify.com, conecta tu repo, cada push a main = deploy automático.
  • Railway: para backend, ve a railway.app, conecta tu repo, cada push a main = deploy del backend.
  • Ventaja: cero configuración. Desventaja: menos control sobre CUÁNDO deployear.

Opción 2: GitHub Actions con Vercel CLI (más control)

# .github/workflows/deploy.yml: deploy manual con Actions
name: Deploy to Vercel

on:
  push:
    branches: [main]    # solo en merge a main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with: { node-version: '20', cache: 'npm' }

      - run: npm ci

      - name: Install Vercel CLI
        run: npm install -g vercel@latest

      - name: Pull Vercel environment
        run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
        env:
            VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
            VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

      - name: Build project
        run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}

      - name: Deploy to Vercel
        run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}

      # Si quieres notificar a Slack/Discord/email:
      - name: Notify deploy success
        if: success()
        run: |
          curl -X POST ${{ secrets.DISCORD_WEBHOOK_URL }} \
            -H 'Content-Type: application/json' \
            -d '{"content": "✅ Deploy a producción exitoso: ${{ github.sha }}"}'

      - name: Notify deploy failure
        if: failure()
        run: |
          curl -X POST ${{ secrets.DISCORD_WEBHOOK_URL }} \
            -H 'Content-Type: application/json' \
            -d '{"content": "❌ Deploy FALLÓ en commit ${{ github.sha }}"}'

Deploy a Vercel con notificaciones a Discord

Cómo configurar GitHub Secrets (NUNCA hardcodear API keys)

# Paso 1: ve a tu repo en GitHub > Settings > Secrets and variables > Actions
# Paso 2: 'New repository secret'
# Paso 3: añade los secrets:

# Para Vercel:
#   VERCEL_TOKEN: tu token de Vercel (Settings > Tokens en vercel.com)
#   VERCEL_ORG_ID: el ID de tu org (Project Settings > General)
#   VERCEL_PROJECT_ID: el ID de tu proyecto (Project Settings > General)

# Para Supabase:
#   SUPABASE_URL: la URL de tu proyecto
#   SUPABASE_ANON_KEY: la key pública (anon)
#   SUPABASE_SERVICE_KEY: la key de servicio (SOLO en backend, NUNCA en frontend)

# Para Codecov:
#   CODECOV_TOKEN: el token de codecov.io

# Para Discord/Slack:
#   DISCORD_WEBHOOK_URL: la URL del webhook de tu canal

# En el código, los usas con ${{ secrets.NOMBRE }}:
#   env:
#     API_KEY: ${{ secrets.API_KEY }}

# IMPORTANTE:
#   - NUNCA hagas commit de API keys al repo (aunque sea privado)
#   - NUNCA imprimas secrets en logs (GitHub los enmascara automáticamente, pero no confíes)
#   - Para keys SECRETAS (OpenAI, Stripe, AWS), usa backend con .env
#   - Rota secrets cada 3-6 meses

Configuración correcta de GitHub Secrets

⭐ Secrets > variables de entorno para credenciales: GitHub Secrets son la forma SEGURA de manejar credenciales en CI/CD. A diferencia de las variables de entorno normales (que cualquiera puede ver en los logs), los secrets están encriptados, solo se exponen a Actions específicas, y se enmascaran automáticamente en logs (aparecen como ***). La regla de oro: NUNCA hardcodear una API key en el código o en un .env commiteado. SIEMPRE usar secrets de GitHub (o equivalente en GitLab, Bitbucket). Si tu key termina en un commit, aunque lo borres, queda en el historial de Git para siempre: rótala inmediatamente.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.9.6 Badges, status checks y el flujo PR → review → merge → deploy

El flujo profesional de CI/CD termina con badges en tu README que muestran el estado de tu pipeline, y un flujo claro: PR → review → status checks pasan → merge a main → deploy automático. Es la última pieza del puzzle: comunicar a tu equipo (y al mundo) que tu código está saludable.

Badges en el README: estado del pipeline a la vista

# README.md: añade badges al inicio

<p align="center">
  <!-- Badge de build status (pasa o falla) -->
  <img src="https://github.com/username/repo/actions/workflows/ci.yml/badge.svg" alt="Build Status">

  <!-- Badge de coverage -->
  <img src="https://codecov.io/gh/username/repo/branch/main/graph/badge.svg" alt="Coverage">

  <!-- Badge de licencia -->
  <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License">

  <!-- Badge de versión -->
  <img src="https://img.shields.io/github/v/release/username/repo" alt="Release">

  <!-- Badge de Lighthouse score -->
  <img src="https://img.shields.io/badge/Lighthouse-95%2B-success" alt="Lighthouse">
</p>

# Los badges usan Shields.io o servicios similares (codecov.io, github.com)
# Se actualizan automáticamente según el estado real de tu pipeline.
# Si un badge está rojo, sabes que algo está mal sin abrir GitHub.

# El flujo profesional completo:
# 1. Dev crea branch: git checkout -b feature/login
# 2. Dev hace commits y push: git push origin feature/login
# 3. Dev abre PR en GitHub: 'feature/login' → 'main'
# 4. CI se dispara automáticamente: corre lint + tests + build
# 5. Si CI pasa, badges en verde. Si falla, badges en rojo.
# 6. Reviewer revisa el código y aprueba (o pide cambios)
# 7. Branch protection verifica: tests pasan + review aprobado → permite merge
# 8. Dev mergea: 'Squash and merge' (1 commit limpio)
# 9. Deploy automático a producción (Vercel/Railway)
# 10. Notificación a Slack/Discord: '✅ Deploy a producción exitoso'
# 11. Monitoring (Sentry, LogRocket) verifica que no hay errores

# Tiempo total: 5-10 minutos desde el push hasta producción.

Badges en README + flujo PR → review → merge → deploy

⭐ El estándar de la industria: PR + CI + CD: El flujo PR + branch protection + CI + CD es el ESTÁNDAR de la industria. Si tu equipo no lo usa, está operando en modo artesanal: merges riesgosos, deploys manuales a las 3am, bugs en producción. La inversión de tiempo es 1-2 días para configurar todo (Actions, secrets, branch protection, badges). El retorno es ANUAL: menos bugs, menos hotfixes, menos tiempo invertido en deploys. Empresas como GitHub, Vercel, y Stripe deployan 50-100 veces al día con este flujo. No es magia, es automatización disciplinada.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

📚 Contenido ampliado

Material adicional, referencias externas verificadas y ejemplos extendidos.

🤖 AI Mission

La IA no configura tu pipeline: te ayuda a entenderlo.

Misión: Toma tu app Atlas Mundial y configura un pipeline de CI/CD completo con GitHub Actions. Pipeline debe incluir: lint, tests, build, deploy a Vercel, y badges en el README. Configura branch protection en main para requerir CI + review antes de mergear. Pídele a la IA: 'Tengo este workflow de GitHub Actions. ¿Qué optimizaciones me recomiendas para que corra más rápido y use menos minutos?' Anota en tu cuaderno: 3 cosas que descubristas al configurar el pipeline.

Pasos sugeridos

  1. Crea .github/workflows/ci.yml con 3 jobs: lint, test, build.
  2. Configura: on: pull_request (a main) + on: push (a main).
  3. Job lint: npm run lint y npm run format:check.
  4. Job test: usa tu script npm run test:coverage.
  5. Job build: necesita [lint, test] y corre npm run build.
  6. Configura branch protection en main: requiere status checks (lint, test, build) + 1 review.
  7. Crea un PR de prueba (cambia el README). Verifica que CI se dispara y los 3 jobs pasan.
  8. Si tienes Vercel/Netlify: conecta tu repo. Si no, añade un job de deploy manual.
  9. Configura GitHub Secrets: VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID.
  10. Añade badge al README: ![CI](https://github.com/USER/REPO/actions/workflows/ci.yml/badge.svg).
  11. Haz un cambio pequeño, abre PR, verifica que CI corre y aparece el badge en verde.
  12. Pídele a la IA optimizaciones (caché de npm, matrix, etc.). Aplica 2-3.
  13. Haz commit: 'ci: pipeline completo con GitHub Actions, branch protection configurado'.

📓 Entregable: Captura del PR con los 3 jobs en verde, badge en el README, captura de la branch protection rule, código del workflow YAML, y media página de cuaderno con tus 3 descubrimientos.

🚫 Errores típicos de razonamiento

Error 1: No configurar branch protection (los merges pasan aunque los tests fallen).
Por qué: Si tu workflow de CI corre tests pero NO configuras branch protection en main, los devs pueden mergear PRs con tests en rojo ('luego lo arreglo'). Es el clásico 'later is never'. La solución: Settings > Branches > Branch protection rules > Require status checks to pass before merging. Ahora el botón de merge está GRIS hasta que CI pase. Es la disciplina automática que tu equipo necesita.
Error 2: Hardcodear API keys en el código o en archivos .env commiteados.
Por qué: Si haces commit de una API key (aunque sea en .env), queda en el historial de Git PARA SIEMPRE, aunque borres el archivo. Cualquiera con acceso al repo puede verla. Y si la key es de un servicio de pago (OpenAI, AWS, Stripe), te pueden hacer cargos fraudulentos. La solución: SIEMPRE usar GitHub Secrets para keys en CI/CD, y dotenv + .gitignore para desarrollo local. Si ya commiteaste una key, rótala INMEDIATAMENTE y limpia el historial con git filter-branch.
Error 3: Correr CI en cada commit a cualquier branch (gasta minutos innecesarios).
Por qué: Si configuras on: push sin branches, CI corre también en commits a branches de prueba, gastando minutos innecesarios (2000 min/mes se acaban rápido). La regla: corre CI solo en PRs a main y pushes a main/develop. Para branches de feature, CI corre automáticamente con el PR. Configura: on: pull_request: branches: [main] + on: push: branches: [main, develop]. Te ahorra 50-70% de minutos.
Error 4: No usar caché de dependencias (npm install tarda 2 min cada vez).
Por qué: Sin caché, cada job de CI descarga TODAS las dependencias desde cero (2-3 min). Con caché, las dependencias se guardan entre runs (30 seg). En un pipeline de 10 jobs por día, ahorras 15 min. La configuración: actions/setup-node@v4 con with: cache: 'npm' automáticamente usa el caché. O manual: uses: actions/cache@v4 con path: ~/.npm, key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}. Es un cambio de 1 línea que ahorra horas al mes.
Error 5: Imprimir secrets en los logs de CI (aunque GitHub los enmascare).
Por qué: GitHub enmascara secrets automáticamente en logs (aparecen como ***), pero hay formas de 'escapar' la máscara: si concatenas el secret con otra string, o lo pasas a un comando que lo imprime de otra forma, puede quedar visible. La regla: NUNCA uses echo ${{ secrets.X }}, ni en curl, ni en printf. Si necesitas usar un secret en un comando, pásalo como env var (env: API_KEY: ${{ secrets.X }}) y úsalo como $API_KEY. Los logs de GitHub saben enmascarar env vars.

🧪 Laboratorio práctico

Un pipeline automatizado es tu mejor seguro contra bugs en producción.

Laboratorio: Pipeline CI/CD completo para Atlas Mundial

Objetivo: Configurar un pipeline de CI/CD profesional para tu app Atlas Mundial con GitHub Actions. Debe incluir: lint, tests, build, deploy automático, branch protection, y badges. El resultado: cada commit a main se prueba y deploya sin intervención manual, y ningún PR con tests fallidos se puede mergear.

Pasos

  1. Crea .github/workflows/ci.yml con 4 jobs: lint, test, build, deploy.
  2. Job lint: setup-node v20 + cache npm + npm run lint + npm run format:check.
  3. Job test: setup-node + cache + npm ci + npm run test:coverage + upload a Codecov.
  4. Job build: needs [lint, test] + setup-node + npm run build.
  5. Job deploy: needs [build] + solo si branch es main + Vercel CLI deploy.
  6. Configura GitHub Secrets: VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID.
  7. Configura branch protection en main: requiere status checks (lint, test, build) + 1 review.
  8. Crea PR de prueba: cambia un texto del README. Verifica CI dispara.
  9. Verifica que los 4 jobs corren en paralelo donde corresponde.
  10. Verifica que el deploy job solo corre en push a main (no en PRs).
  11. Añade badges al README: build status, coverage, license, version.
  12. Si todo pasa, haz merge. Verifica que el deploy automático funcionó.
  13. Verifica en Vercel que la nueva versión está en producción.
  14. Haz un cambio que rompa los tests a propósito. Verifica que el PR no se puede mergear.
  15. Arregla el cambio. Verifica que CI vuelve a pasar.
  16. Pídele a la IA 2-3 optimizaciones al workflow. Aplica las más útiles.
  17. Haz commit: 'ci: pipeline CI/CD con GitHub Actions, deploy automático a Vercel'.

📓 Entregable: Captura del workflow corriendo con los 4 jobs en verde, badge en el README, captura de branch protection, captura del deploy en Vercel, código del workflow, y commit en Git.

📓 Tu cuaderno: Anota pseudocódigo, diagramas, errores que encontraste y respuestas a "explica sin código". La escritura manual refuerza tu razonamiento. Tu profesor puede pedirte que subas fotos de páginas específicas.