1. El repositorio como fuente de la verdad
En un proyecto profesional, todo lo necesario para construir y desplegar la aplicación vive en el repositorio de Git: el código, el Dockerfile, la configuración del servidor, los scripts de base de datos y la documentación. Nada importante debería existir solo en el servidor o en el portátil de alguien. Así, cualquier cambio queda registrado (quién, cuándo y por qué), se puede revisar antes de aplicarlo y se puede deshacer.
Un flujo de trabajo con ramas
Hay muchas formas de organizar las ramas, pero la mayoría de equipos usan alguna variante de este flujo, conocido como GitHub Flow o desarrollo basado en el tronco: la rama main siempre está lista para desplegar, y cada cambio se hace en una rama corta que se integra mediante una pull request revisada por otra persona y comprobada automáticamente.
1git switch -c feat/filtro-categorias # rama para el cambio
2git add . && git commit -m "feat(web): filtro por categoría"
3git push -u origin feat/filtro-categorias # y se abre la pull request
4# … revisión, pruebas automáticas en verde, fusión en main …
5git switch main && git pull
6git tag -a v1.5.0 -m "Versión 1.5.0" # marcar la versión publicada
7git push origin v1.5.0Versiones con significado
El versionado semántico da significado a los números de versión MAYOR.MENOR.PARCHE: se sube el parche al corregir errores sin cambiar nada más, el menor al añadir funciones compatibles con lo anterior y el mayor cuando hay cambios incompatibles. Si además los mensajes de commit siguen la convención Conventional Commits (feat:, fix:, docs:, y ! para lo incompatible), la siguiente versión y el registro de cambios se pueden generar automáticamente, que es justo lo que harás en los retos.
2. Documentar para el que viene detrás
La documentación de una aplicación web no es un documento de Word que se entrega al final y nadie abre. Es un conjunto de piezas pequeñas, vivas y cerca del código, que responden a preguntas concretas de personas concretas. Y quien más la necesita suele ser tu yo de dentro de seis meses.
| Documento | Responde a | Formato habitual |
|---|---|---|
| README.md | ¿Qué es esto y cómo lo arranco en mi equipo? | Markdown en la raíz del repositorio |
| Guía de despliegue | ¿Cómo se despliega, se configura y se vuelve atrás? | Markdown en docs/ o un wiki |
| Documentación de la API | ¿Qué rutas hay y qué devuelven? | OpenAPI generado o escrito a mano |
| Comentarios de documentación | ¿Qué hace esta clase o función y cómo se usa? | Javadoc, phpDocumentor, JSDoc |
| Registro de cambios | ¿Qué ha cambiado en cada versión? | CHANGELOG.md, generado desde los commits |
| Decisiones de arquitectura | ¿Por qué se eligió esto y no aquello? | ADR: documentos cortos numerados |
1/**
2 * Calcula el precio final de una línea de pedido.
3 *
4 * @param float $precio Precio unitario sin IVA.
5 * @param int $cantidad Unidades (mayor que 0).
6 * @param float $descuento Descuento entre 0 y 1.
7 * @return float Importe con IVA redondeado a 2 decimales.
8 * @throws InvalidArgumentException Si la cantidad no es positiva.
9 */
10function importeLinea(float $precio, int $cantidad, float $descuento = 0): float { /* … */ }Herramientas como phpDocumentor, Javadoc o TypeDoc convierten esos comentarios en una web de documentación, y generadores de sitios como MkDocs o Docusaurus publican las guías escritas en Markdown. Lo importante es que la documentación se actualice en la misma pull request que el código que describe.
3. Integración y despliegue continuos
La integración continua (CI) consiste en que cada cambio que se sube al repositorio se construya y se pruebe automáticamente, para detectar los errores en minutos y no el día antes de la entrega. La entrega continua deja cada versión preparada para desplegarse con un botón, y el despliegue continuo va un paso más allá: si todo está en verde, se publica sola.
Un pipeline es una cadena de montaje con controles de calidad
1name: CI/CD
2on:
3 push: { branches: [main] }
4 pull_request:
5
6jobs:
7 pruebas:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v4
11 - uses: actions/setup-node@v4
12 with: { node-version: 22, cache: npm }
13 - run: npm ci
14 - run: npm run lint
15 - run: npm test
16
17 desplegar:
18 needs: pruebas # solo si las pruebas pasan
19 if: github.ref == 'refs/heads/main' # y solo desde main
20 runs-on: ubuntu-latest
21 environment: produccion # puede exigir aprobación manual
22 steps:
23 - uses: actions/checkout@v4
24 - run: docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .
25 - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
26 - run: docker push ghcr.io/${{ github.repository }}:${{ github.sha }}
27 - run: ssh despliegue@servidor "./desplegar.sh ${{ github.sha }}" # clave SSH en los secretos- Los secretos (claves SSH, contraseñas) se guardan en el gestor de secretos de la plataforma, nunca en el fichero del pipeline.
- Pipelines rápidos: usar caché de dependencias y ejecutar en paralelo lo que se pueda. Si tarda media hora, nadie esperará a que termine.
- Rojo significa parar: un pipeline que falla se arregla antes de seguir añadiendo cambios.
| Plataforma | Dónde se configura |
|---|---|
| GitHub Actions | .github/workflows/*.yml |
| GitLab CI/CD | .gitlab-ci.yml |
| Jenkins | Jenkinsfile (muy usado en empresas con servidores propios) |
| Vercel, Netlify, Render | Despliegue automático al conectar el repositorio |
4. Después del despliegue: observar
Desplegar no es el final. Hay que saber si la aplicación funciona bien para los usuarios reales, y enterarse de los problemas antes que ellos. Para eso se combinan tres fuentes de información:
- Registros: qué ha pasado, petición a petición, centralizados para poder buscar (Loki, ELK).
- Métricas: números en el tiempo, como peticiones por segundo, errores o uso de memoria (Prometheus y Grafana).
- Alertas: avisos automáticos cuando algo se sale de lo normal, y comprobaciones externas de disponibilidad (Uptime Kuma, UptimeRobot).
Las copias de seguridad también se despliegan
5. Retos
Dos piezas de cualquier sistema de publicación automática: calcular la siguiente versión semántica y generar el registro de cambios a partir de los mensajes de commit.
Retos de Bash en el IDE
Escribe el script y pulsa Ejecutar tests: se ejecuta en un Linux real con Bash y se prueba con varios casos, algunos ocultos.
Cada línea es «versión tipo», donde la versión es MAYOR.MENOR.PARCHE y el tipo es major, minor o patch. Escribe la siguiente versión: major sube el primero y pone los otros a 0; minor sube el segundo y pone a 0 el parche; patch sube el último. Si la versión no tiene el formato correcto o el tipo no es válido, escribe «Versión no válida».
La entrada son mensajes de commit con el formato de Conventional Commits («tipo(ámbito)!: descripción», con ámbito y ! opcionales). Genera un changelog con las secciones «## Cambios incompatibles» (commits con !), «## Novedades» (feat) y «## Correcciones» (fix), en ese orden, cada una con líneas «- descripción» en el orden original y omitiendo las secciones vacías. Los demás tipos (docs, chore, test…) se ignoran salvo que lleven !. Termina con una línea en blanco y «Siguiente versión: major», «minor», «patch» o «ninguna».