Saltar a contenido

⚠ Vigencia por confirmar. Esta guía se solapa con CI/CD con runners self-hosted y con Despliegue de EcommerceV2Backend, y contradice a la primera respecto de dónde van las SSH keys del runner (acá: directorio de trabajo del runner; allá: ~/.ssh del usuario del servicio). Confirmar cuál aplica antes de seguirla.

Guía de Despliegue Automatizado

Este documento describe el setup completo de CI/CD para desplegar Medusa en staging y producción mediante GitHub Actions con runners self-hosted.

Arquitectura

Push a rama
    ↓
├─ staging: Auto-deploy a servidor de staging
│   └─ Runner self-hosted en servidor de staging
│   └─ Ejecuta ./deploy.sh con tag staging-*
│
└─ main: Deploy a producción CON APROBACIÓN
    └─ Requiere aprobación en GitHub
    └─ Runner self-hosted en servidor de producción
    └─ Ejecuta ./deploy.sh con tag sha-*

Prerrequisitos

  • GitHub repository: CompulandiaTI/EcommerceV2Backend
  • Servidor de staging con Docker instalado
  • Servidor de producción con Docker instalado
  • Acceso administrativo a ambos servidores
  • Acceso a la configuración del repositorio en GitHub

Paso 1: Configurar Runners Self-Hosted

Los runners permiten que GitHub Actions ejecute jobs en tus servidores privados (sin exponer credenciales).

1.1 En el servidor de STAGING

# 1. Crear directorio de trabajo
mkdir -p /opt/github-runner-staging
cd /opt/github-runner-staging

# 2. Descargar el runner (usa la versión más reciente desde GitHub)
curl -o actions-runner-linux-x64.tar.gz -L https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gz
tar xzf ./actions-runner-linux-x64.tar.gz
rm actions-runner-linux-x64.tar.gz

# 3. En GitHub: Settings → Actions → Runners → New runner self-hosted
#    Selecciona: Linux, x64
#    Copia el token de configuración (válido 1 hora)

# 4. Ejecutar configuración (pega el token de GitHub)
./config.sh --url https://github.com/CompulandiaTI/EcommerceV2Backend --token <PASTE_TOKEN_HERE>
# Preguntas:
#   - name: staging
#   - work folder: _work
#   - labels: staging (importante: label debe coincidir con runs-on: [self-hosted, staging])

# 5. Instalar como servicio systemd (para que arranque automáticamente)
sudo ./svc.sh install
sudo systemctl start actions-runner
sudo systemctl enable actions-runner

# 6. Verificar que está corriendo
sudo systemctl status actions-runner

1.2 En el servidor de PRODUCCIÓN

Repite lo anterior pero: - Directorio: /opt/github-runner-production - Name: production - Labels: production - Los comandos systemd son iguales

Después de configurar, ambos runners aparecerán en GitHub → Settings → Actions → Runners como "Idle" y green.

Paso 2: Configurar SSH para Git (Deploy Keys)

El runner necesita poder hacer git fetch del repositorio para actualizar archivos de despliegue.

En ambos servidores:

# IMPORTANTE: La SSH key debe estar en el WORKING DIRECTORY del runner,
# NO en /home/username/.ssh/
# El runner en staging corre desde: /opt/github-runner-staging
# El runner en producción corre desde: /opt/github-runner-production

# 1. Generar SSH key en el directorio de trabajo del runner
# Reemplaza RUNNER_DIR según tu servidor (staging o producción)
RUNNER_DIR=/opt/github-runner-staging
USER=_svc_actions_staging

sudo mkdir -p $RUNNER_DIR/.ssh
sudo ssh-keygen -t rsa -f $RUNNER_DIR/.ssh/id_rsa -N "" -C "$USER@runner"

# 2. Permisos correctos
sudo chown -R $USER:$USER $RUNNER_DIR/.ssh
sudo chmod 700 $RUNNER_DIR/.ssh
sudo chmod 600 $RUNNER_DIR/.ssh/id_rsa

# 3. Copiar la public key
sudo cat $RUNNER_DIR/.ssh/id_rsa.pub

En GitHub:

  1. Ir a repo → Settings → Deploy Keys
  2. Click "Add deploy key"
  3. Title: staging-runner (o production-runner)
  4. Key: (pega el contenido de id_rsa.pub)
  5. ✅ Allow write access (si el runner necesita hacer push)
  6. Click "Add key"

Verificar:

# En el servidor, probar que SSH funciona
RUNNER_DIR=/opt/github-runner-staging
USER=_svc_actions_staging

# Test 1: Autenticación SSH
sudo -u $USER ssh -T git@github.com
# Debería responder: "Hi CompulandiaTI/EcommerceV2Backend! You've successfully authenticated..."

# Test 2: Git clone
sudo -u $USER git clone git@github.com:CompulandiaTI/EcommerceV2Backend.git /tmp/test-clone
rm -rf /tmp/test-clone
# Debería clonar sin pedir contraseña

Paso 3: Autenticar Acceso a GHCR (Image Registry)

El servidor necesita poder hacer pull de la imagen privada en GHCR.

En ambos servidores:

# 1. Crear un Personal Access Token (PAT) en GitHub
#    GitHub → Settings → Developer settings → Personal access tokens (classic)
#    Permisos: read:packages
#    Copia el token (ej. ghp_xxxxx...)

# 2. En el servidor, hacer login a GHCR
echo "ghp_xxxxx..." | docker login ghcr.io -u TU_USUARIO_GITHUB --password-stdin

# Esto guarda las credenciales en ~/.docker/config.json
# Verificar: docker logout ghcr.io && docker login ghcr.io (debería funcionar sin pedir token)

Paso 3: Configurar GitHub Environment (Producción con Aprobación)

En GitHub, los "environments" permiten requerir aprobación antes de ejecutar ciertos jobs.

En GitHub: 1. Ir a repo → Settings → Environments 2. Click "New environment" 3. Nombre: production 4. Click "Add protection rules" (opcional, pero recomendado) - ✅ Require reviewers: Selecciona quién puede aprobar (ej. tu usuario o equipo) - ✅ Restrict deployments to deployment branches: main (solo desde main se despliega) - Save

A partir de ahora, cuando un workflow intente acceder al environment production, requerirá aprobación de una de las personas configuradas.

Paso 4: El Workflow en Acción

Ahora el setup está listo. Así funciona:

Push a staging:

git push origin staging

En GitHub → Actions → Workflows: 1. Build corre en GitHub runners → publica imagen con tags staging-latest y staging-sha-abc123 2. Deploy-staging corre automáticamente en el runner de staging - Ejecuta ./deploy.sh con MEDUSA_TAG=staging-sha-abc123 - Hace pg_dump previo - Publica la imagen - Verifica health check - Si falla, auto-rollback a versión anterior

Push a main:

git push origin main

En GitHub → Actions → Workflows: 1. Build corre en GitHub runners → publica imagen con tags latest y sha-abc123 2. Deploy-prod espera aprobación: - En GitHub UI: Actions → Workflow run → "Review deployments" - Aprueba o rechaza - Si aprueba: corre en runner de producción - Ejecuta ./deploy.sh con MEDUSA_TAG=sha-abc123 - Hace pg_dump + deploy + health check + rollback si falla

Paso 5: Verificar que Funciona

Prueba 1: Verificar runners registrados

En GitHub → Settings → Actions → Runners: - Debes ver dos runners: staging y production (ambos "Idle" en verde)

Prueba 2: Primer push a staging

# En development local
git checkout staging
git pull
# Hacer un cambio trivial (ej. comentario en README)
git add .
git commit -m "test: verificar workflow"
git push origin staging

En GitHub → Actions: - El workflow "Build, Test & Deploy" debería ejecutarse - "Build" completa ✅ - "Deploy-staging" ejecuta automáticamente ✅ - Revisar logs para confirmar que ./deploy.sh corrió

Si pasa health check:

✅ Despliegue OK (tag: staging-sha-abc123)

Prueba 3: Push a main (requiere aprobación)

git checkout main
git pull
git merge staging
git push origin main

En GitHub → Actions: - "Build" completa ✅ - "Deploy-prod" se queda en "waiting" (amarillo) - Click en el workflow → "Review deployments" - Selecciona "production" environment - Click "Approve" - El job se ejecuta en el runner de producción

Paso 6: Rollback Manual

Si necesitas revertir a una versión anterior (sin esperar a un nuevo push):

# En el servidor de producción
MEDUSA_TAG=staging-sha-abc123 ./deploy.sh

Los tags disponibles están en GHCR (GitHub → repo → Packages).

Operación Normal

Deploy a staging:

git push origin staging  # Auto-deploy, sin aprobación

Deploy a producción:

git checkout main
git merge staging           # Fusiona cambios probados de staging
git push origin main        # Dispara workflow
# En GitHub UI: aprueba el deployment

Solución de Problemas

Runner no se conecta a GitHub

# En el servidor, revisar logs
sudo journalctl -u actions-runner -f

# Reiniciar el runner
sudo systemctl restart actions-runner

Deploy falla con "permission denied" al ejecutar ./deploy.sh

# En el servidor, asegurar que deploy.sh es ejecutable
chmod +x /path/to/repo/deploy.sh

docker login falla en el runner

  • El runner corre como usuario específico. Verifica que ese usuario pueda acceder a ~/.docker/config.json
  • O ejecuta docker login como el mismo usuario que corre el runner:
    sudo -u _svc_actions docker login ghcr.io  # si el runner corre como _svc_actions
    

No ve el runner en GitHub

  • Verifica que la URL del repo sea correcta (https://github.com/CompulandiaTI/EcommerceV2Backend)
  • Revisa que el token no haya expirado (válido 1 hora durante config)
  • Rerun ./config.sh con un token nuevo

Archivos clave

  • .github/workflows/build-deploy.yml — El workflow completo
  • deploy.sh — Script de despliegue en cada servidor
  • docker-compose.yml — Parametrizado con ${MEDUSA_TAG}
  • Dockerfile — Multi-stage, genera imagen para GHCR

Convenciones de Tags en GHCR

Tag Rama Cuándo
staging-latest staging Última versión en staging
staging-sha-abc123 staging Commit específico en staging
latest main Última versión en producción
sha-abc123 main Commit específico en producción

Ejemplo de rollback manual:

# Revertir a un commit anterior
MEDUSA_TAG=sha-def456 ./deploy.sh


¿Preguntas o aclaraciones necesarias?