-
Notifications
You must be signed in to change notification settings - Fork 1
CI CD Pipeline
Anderson Fabian Garcia Nieto edited this page Jul 9, 2026
·
4 revisions
Linker1 implementa un pipeline de integración y despliegue continuo completo, compuesto por tres workflows de GitHub Actions que cubren desde la compilación hasta el rollback automático en producción.
┌──────────────────────────────────────┐
│ CÓDIGO EN GITHUB │
└──────────────┬───────────────────────┘
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
push a DEV/main push tag v*.*.* push a main
pull_request workflow_dispatch
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ ci.yml │ │ release.yml │ │ pipeline.yml │
│ (CI Gate) │ │ (Release) │ │ (CD Pipeline) │
└──────────────┘ └──────────────┘ └──────────────────┘
Trigger: push o PR a
DEV,mainomaster
Propósito: Validar la calidad del código antes de merge
Build ──▶ Tests ──▶ Package ──▶ Summary
│ Smoke Test
│ │
│ API Tests (Live)
│ │
└───▶ Publish GitHub Package
- Checkout del repositorio
- Setup de JDK 21 (Temurin) con caché de Maven
- Compilación de fuentes:
mvn -B -ntp compile
- Ejecución de tests unitarios:
mvn -B -ntp test -
Verificación de cobertura con JaCoCo:
mvn -B -ntp verify -DskipTests- Umbral de cobertura: 100% de líneas (configurado en
pom.xml, excluyendoMain.class)
- Umbral de cobertura: 100% de líneas (configurado en
- Upload del reporte de cobertura como artefacto
- Generación del fat JAR:
mvn -B -ntp package -DskipTests - Inclusión del launcher script (
scripts/linker1) - Upload del artefacto
linker1-jar
- Descarga y verificación del artefacto empaquetado
- Confirma que el JAR y el launcher existen y son ejecutables
- Inicia la aplicación real con el JAR empaquetado
- Espera hasta 20 segundos por el startup
-
Validaciones funcionales contra
http://localhost:8080:-
GET /→ 200 (página principal) -
GET /app.js→ 200 (JavaScript) -
GET /styles.css→ 200 (CSS) -
POST /linkcon URL → crea link + verifica redirección 301 -
POST /linkcon alias → crea alias + verifica redirección 301 -
POST /linkcon alias duplicado → verifica conflicto 409 -
GET /does-not-exist→ 404
-
- Solo en push (no en PRs)
- Ejecuta la colección de Postman/Newman contra la instancia de producción:
https://1.n-la-c.app - Genera y sube reporte JUnit XML
- Solo tras smoke test + API tests exitosos
- Genera versión única con metadata de CI:
1.0-ci.{RUN_NUMBER}.{RUN_ATTEMPT}.{SHA:7} - Publica en GitHub Packages (Maven registry)
Trigger: push a
mainoworkflow_dispatch
Propósito: Despliegue automatizado a producción con rollback
Build ──▶ Deploy to Production ──▶ Validate Production
│ │
│ ┌───────────────┘
│ │ (si alguno falla)
│ ▼
└──▶ Rollback (automático)
- Compila y empaqueta el JAR (
linker-appartifact) - Independiente del
ci.yml(los artefactos deupload-artifactno cruzan entre workflows)
-
Environment:
prod(scoping de secrets/variables) - Mecanismo: OCI Bastion (SSH tunnel gestionado, sin IP pública)
-
Acción:
co-eiv-devsecops/material-curso/actions/oci-bastion-deploy@main
Proceso de despliegue remoto:
- Secrets se transportan en base64 para evitar inyección de shell
- Valores se decodifican y escapan para systemd (
%→%%,"→\") - JAR se copia a
/opt/linker1/linker1.jar - Se genera/actualiza la unidad systemd (
linker1.service) systemctl daemon-reload && systemctl restart linker1.service-
Verificación post-deploy:
-
systemctl is-active linker1.service✓ -
curl localhost:8080/→ 200 ✓ -
curl localhost:8080/healthz→ status (informativo)
-
- Smoke test de solo lectura contra
https://1.n-la-c.app - Verifica assets estáticos y respuesta 404 para rutas inexistentes
- Se ejecuta solo si
deploy-prodovalidate-prodfallan (if: failure()) - Identifica el tag SemVer previo al actual
- Descarga el JAR del release previo desde GitHub Releases
- Lo despliega vía Bastion con el mismo mecanismo
- Verifica que el servicio responde 200 post-rollback
Trigger: push de tag
v*.*.*oworkflow_dispatch
Propósito: Publicar releases oficiales
Checkout ──▶ Resolve Tag ──▶ Verify Quality Gates ──▶ Build Package ──▶ Publish GitHub Release
-
Validación del tag: formato SemVer estricto (
vMAJOR.MINOR.PATCH) -
Quality gates:
mvn -B -ntp clean verify(incluye tests + cobertura) -
Build del paquete:
mvn -B -ntp package -DskipTests -
Publicación: GitHub Release con:
-
linker1-1.0-jar-with-dependencies.jar(artefacto ejecutable) -
linker1(launcher script) - Release notes auto-generados por GitHub
-
┌─────────────────────────────────────────────────────────────────────────────────┐
│ │
│ Developer │
│ │ │
│ ├─── feature/* branch │
│ │ │ │
│ │ ▼ │
│ │ Pull Request → DEV │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────── ci.yml ─────────────┐ │
│ │ │ Build → Test → Package → Smoke │ ← Branch protection: requiere │
│ │ │ │ │ CI verde + 1 approval │
│ │ │ Coverage ≥ 100% │ │
│ │ └─────────────────────────────────┘ │
│ │ │ │
│ │ ▼ (merge aprobado) │
│ │ │
│ ├─── Pull Request → main │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────── ci.yml ─────────────┐ │
│ │ │ Build → Test → Package → Smoke │ │
│ │ │ + API Tests + Publish Pkg │ │
│ │ └─────────────────────────────────┘ │
│ │ │ │
│ │ ▼ (merge a main) │
│ │ │
│ │ ┌──────── pipeline.yml ───────────┐ │
│ │ │ Build → Deploy Prod │ │
│ │ │ │ │ │
│ │ │ ▼ │ │
│ │ │ Validate Prod │ │
│ │ │ │ │ │
│ │ │ (falla?) → Rollback │ │
│ │ └─────────────────────────────────┘ │
│ │ │
│ └─── git tag v1.x.x + push │
│ │ │
│ ▼ │
│ ┌──────── release.yml ────────────┐ │
│ │ Verify → Build → GitHub Release │ │
│ └─────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
| Característica | Detalle |
|---|---|
| Concurrency groups |
ci-${{ github.ref }} con cancel-in-progress: true — un push nuevo cancela la ejecución anterior |
| Maven cache |
cache: maven en setup-java acelera builds subsecuentes |
| Batch mode |
mvn -B -ntp — sin output interactivo ni transfer progress |
| Artefactos entre jobs |
upload-artifact / download-artifact pasan el JAR entre jobs |
| Nombre | Tipo | Nivel | Propósito |
|---|---|---|---|
LD_SDK_KEY |
Secret | Repo | LaunchDarkly SDK key |
GITHUB_TOKEN |
Secret | Auto | Autenticación para GitHub Packages |
DEPLOYMENT_PRIVATE_KEY |
Secret | Repo | SSH key para deploy vía Bastion |
DEPLOYMENT_PUBLIC_KEY |
Secret | Repo | Matching public key |
OCI_CLI_* |
Secrets | Repo/Org | Autenticación OCI CLI |
OCI_BASTION_OCID |
Variable | Org | ID del Bastion |
OCI_INSTANCE_OCID |
Variable | Repo | ID de la VM de producción |
OTEL_EXPORTER_OTLP_* |
Variable/Secret | Repo | Configuración de Grafana Cloud |
MYSQL_* |
Variable/Secret | Repo | Conexión MySQL para healthcheck |