Nicholas Ceballos cb12d68fbe
CI Pipeline / HTML Lint (push) Successful in 7s
Deploy QA / Build and Push (push) Successful in 13s
CI Pipeline / Build Docker Image (push) Failing after 28m28s
CI Pipeline / Security Scan (push) Has been skipped
Deploy QA / Deploy to QA (push) Failing after 1s
CI Pipeline / Generate Summary (push) Failing after 0s
Deploy QA / Notification (push) Failing after 1s
build(docker): replace envsubst with sed, drop gettext
Replace nginx config environment variable substitution from envsubst to sed to eliminate the gettext package dependency, reducing the final container image size. Remove unused export statements from the docker-entrypoint.sh script.
2026-06-01 17:25:21 -06:00
2026-05-29 20:26:01 -06:00

CI/CD Multi-Environment Pipeline POC

Prueba de concepto de un pipeline CI/CD multi-ambiente con Gitea Actions, Docker y Nginx.

Arquitectura

                    feature/*
                       |
                      PR
                       |
                    ┌───┴───┐
                    │  dev  │ ──(push)──► CI Pipeline ──► Deploy QA
                    └───┬───┘           (lint, build,    (puerto 8081)
                        │                security scan)
                       PR                docker registry
                        │                    │
                    ┌───┴───┐                │
                    │staging│ ──(push)────────┼──► Deploy Staging
                    └───┬───┘                │    (puerto 8082)
                        │                    │
                       PR                    │
                        │                    │
                    ┌───┴───┐                │
                    │ main  │ ──(push)────────┴──► Deploy Production
                    └───────┘    (aprobación)      (puerto 8083)

Ambientes

Ambiente URL Puerto Rama Trigger
QA https://practicas.qa.kubistudio.cloud 8081 dev Push autom.
Staging https://practicas.staging.kubistudio.cloud 8082 staging Push autom.
Production https://practicas.prod.kubistudio.cloud 8083 main Push + aprob.

Configuración en Gitea

Secretos (Settings > Secrets)

Secreto Descripción
TOKEN Token de Gitea con permisos de escritura al registry
DEPLOY_SSH_KEY Clave SSH privada para acceder al servidor de deploy
DEPLOY_USERNAME Usuario SSH para conexión al servidor
DEPLOY_HOST Host/IP del servidor de deploy

Variables (Settings > Variables)

Variable Descripción Ejemplo
REGISTRY_URL URL del Gitea Container Registry git.kubistudio.cloud
IMAGE_NAME Nombre de la imagen en el registry kubistudio/cicd-multi-env-pipeline-poc

Flujo de Trabajo

  1. Crear rama feature/* desde dev
  2. Desarrollar y hacer commit
  3. Abrir PR a dev → CI ejecuta lint, build, security scan
  4. Merge a dev → CI + Deploy automático a QA
  5. PR de devstaging → Deploy automático a Staging
  6. PR de stagingmain → Requiere aprobación → Deploy a Producción

Ejecución Local

Con docker-compose

version: '3.8'

services:
  cicd-qa:
    build: .
    ports:
      - "8081:80"
    environment:
      APP_ENV: qa
      APP_VERSION: dev-local
      GIT_COMMIT: local
      GIT_BRANCH: dev
      BUILD_DATE: ${BUILD_DATE:-unknown}
      DEPLOY_TIME: ${DEPLOY_TIME:-unknown}
      BUILD_NUMBER: "0"

  cicd-staging:
    build: .
    ports:
      - "8082:80"
    environment:
      APP_ENV: staging
      APP_VERSION: staging-local
      GIT_COMMIT: local
      GIT_BRANCH: staging
      BUILD_DATE: ${BUILD_DATE:-unknown}
      DEPLOY_TIME: ${DEPLOY_TIME:-unknown}
      BUILD_NUMBER: "0"

  cicd-prod:
    build: .
    ports:
      - "8083:80"
    environment:
      APP_ENV: production
      APP_VERSION: 1.0.0
      DEPLOY_TIME: ${DEPLOY_TIME:-unknown}

Manual

# Build
docker build \
  --build-arg APP_VERSION=1.0.0 \
  --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  --build-arg GIT_COMMIT=$(git rev-parse --short HEAD) \
  --build-arg GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) \
  -t cicd-poc:latest .

# Run
docker run -d \
  --name cicd-qa \
  -p 8081:80 \
  -e APP_ENV=qa \
  -e APP_VERSION=dev-local \
  -e GIT_COMMIT=$(git rev-parse --short HEAD) \
  -e GIT_BRANCH=dev \
  -e BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  -e DEPLOY_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  -e BUILD_NUMBER="1" \
  cicd-poc:latest

# Test
curl http://localhost:8081/health

Variables de Entorno del Contenedor

Variable Obligatorio Default Descripción
APP_ENV No development Ambiente: qa, staging, production
APP_VERSION No 0.0.0 Versión de la aplicación
BUILD_DATE No (vacío) Fecha ISO del build
GIT_COMMIT No (vacío) SHA corto del commit
GIT_BRANCH No (vacío) Rama de git
DEPLOY_TIME No (vacío) Timestamp del deploy
BUILD_NUMBER No (vacío) Número de build de la pipeline

Rollback Manual

Production

ssh user@deploy-host

# Rollback a stable tag
docker stop cicd-prod && docker rm cicd-prod
docker run -d \
  --name cicd-prod \
  --restart unless-stopped \
  -p 8083:80 \
  -e APP_ENV=production \
  -e APP_VERSION=rollback \
  -e DEPLOY_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  registry-url/image-name:stable

# O con un SHA específico
docker run -d \
  --name cicd-prod \
  --restart unless-stopped \
  -p 8083:80 \
  -e APP_ENV=production \
  -e APP_VERSION=rollback \
  -e DEPLOY_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  registry-url/image-name:sha-SHA_DEL_COMMIT

QA / Staging

# QA
docker stop cicd-qa && docker rm cicd-qa
docker run -d --name cicd-qa -p 8081:80 ... registry-url/image-name:sha-SHA_ANTERIOR

# Staging
docker stop cicd-staging && docker rm cicd-staging
docker run -d --name cicd-staging -p 8082:80 ... registry-url/image-name:sha-SHA_ANTERIOR

Endpoints

Endpoint Descripción
/ Aplicación web
/health Health check (JSON)

Ejemplo /health

{
  "status": "ok",
  "env": "production",
  "version": "release-a1b2c3d",
  "timestamp": "2024-01-15T14:23:00+00:00"
}

Estructura del Proyecto

.
├── src/
│   └── index.html              # App web (UI completa self-contained)
├── .gitea/workflows/
│   ├── ci.yml                  # CI: lint + build + security scan
│   ├── deploy-qa.yml           # Deploy a QA (push a dev)
│   ├── deploy-staging.yml      # Deploy a Staging (push a staging)
│   └── deploy-prod.yml         # Deploy a Producción (push a main + aprobación)
├── docker-entrypoint.sh        # Entrypoint que genera env-config.js en runtime
├── Dockerfile                  # Multi-stage build
├── healthcheck.sh              # Script de health check
├── nginx.conf                  # Configuración de nginx
└── README.md                   # Este archivo
S
Description
CI/CD Multi-Environment Strategy (PoC)
Readme Unlicense 93 KiB
Languages
HTML 84.9%
Dockerfile 8.9%
Shell 6.2%