---
name: easypanel-deploy
description: Deploy completo e automatizado para EasyPanel com validação integrada, monitoring e safety net (auto-rollback) via API oficial.
disable-model-invocation: true
---

# EasyPanel Deploy

Deploy completo e automatizado para EasyPanel com validação integrada.

## Quando Usar

- Deploy completo de projecto
- Deploy com validação automática
- Deploy com monitoring
- Deploy com safety net (auto-rollback)
- Production deploys críticos

## Sintaxe

```bash
/easypanel-deploy [--skip-tests] [--force]
```

## Exemplos

```bash
# Deploy normal (com tests e validation)
/easypanel-deploy

# Deploy sem tests (CI/CD já rodou)
/easypanel-deploy --skip-tests

# Force deploy (ignorar warnings)
/easypanel-deploy --force
```

## Workflow Completo (9 Steps)

### 1. Pre-deploy Validation

```bash
/easypanel-validate
```

**Gates:**
- Score < 7/10 → **ABORT** (excepto --force)
- Critical issues → **ABORT**
- Se pass → Continue

### 2. Run Tests (se não --skip-tests)

```bash
npm test
```

**Gates:**
- Tests fail → **ABORT**
- No tests found → **WARNING** (continue)
- Tests pass → Continue

### 3. Build Local (test)

```bash
docker build --no-cache -t <project>:test .
```

**Checks:**
- Build completa sem erros
- Image size < 200MB (Node.js)
- EXPOSE port correcto

**Gates:**
- Build fail → **ABORT**
- Image size > 500MB → **WARNING** (continue com --force)

### 4. Git Check

```bash
git status
```

**Checks:**
- Uncommitted changes?
- Untracked files?

**Actions:**
- Se changes → **PROMPT**: "Commit agora? [y/N]"
- Se yes → `git add . && git commit -m "deploy: ..."`
- Se no → **ABORT**

### 5. Push to Gitea

```bash
git push origin main
```

**Actions:**
- Push commits
- Se CI/CD configurado → Aguardar webhook trigger
- Log commit SHA

### 6. Monitor EasyPanel Deploy

**Via API (preferido - sincroniza com GUI):**
```bash
# Obter token
TOKEN=$(cat /etc/easypanel/.api-token)

# Verificar estado do serviço
curl -s "http://localhost:3000/api/trpc/services.app.inspectService?input=$(echo -n '{"json":{"projectName":"PROJECT","serviceName":"SERVICE"}}' | jq -sRr @uri)" \
  -H "Authorization: Bearer $TOKEN"

# Listar todos os serviços do projecto
curl -s "http://localhost:3000/api/trpc/projects.inspectProject?input=$(echo -n '{"json":{"projectName":"PROJECT"}}' | jq -sRr @uri)" \
  -H "Authorization: Bearer $TOKEN"
```

**Via SSH (fallback):**
```bash
# Poll cada 10s (timeout 5min)
docker service ls | grep <service>
docker service ps <service>
```

**Timeline:**
- [00:00] Build started
- [01:30] Build complete
- [02:00] Container starting
- [02:15] Health check iniciado

### 7. Health Check (retry 5x, interval 10s)

```bash
curl -f https://<domain>/health
```

**Retry Logic:**
- Tentativa 1-5: aguardar 10s entre cada
- Se 200 OK → **SUCCESS**
- Se 5xx após 5 retries → **ROLLBACK**
- Se timeout → **ROLLBACK**

### 8. Metrics Validation

```bash
# Via docker stats ou EasyPanel API
docker stats <container> --no-stream
```

**Checks:**
- CPU < 80% (avg 60s)
- Memory < 80% limit
- No errors em logs (últimos 60s)

**Gates:**
- CPU > 90% → **WARNING** (potential issue)
- Memory > 90% → **WARNING** (OOM risk)
- Errors em logs → **WARNING** + report

### 9. Success Report

**Output:**
- Total deploy time
- Build time
- Image size
- Health status
- Metrics snapshot
- URLs (production, health, logs)

## Output Format (Success)

```
🚀 EasyPanel Deploy: <project-name>

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⏱️  TIMELINE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[00:00] ✅ Pre-deploy validation (score: 9.2/10)
[00:15] ✅ Tests passed (12/12, 2.3s)
[00:20] ✅ Local build (82MB, 1m 34s)
[00:25] ✅ Git push (commit: a3f5c21)
[01:55] ✅ EasyPanel build started
[03:42] ✅ Container started (dashboard-api-6f9d8)
[03:50] ✅ Health check 1/5: 200 OK
[03:52] ✅ Health check 5/5: 200 OK (stable)
[04:00] ✅ Metrics validated (CPU: 12%, RAM: 45MB/512MB)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ DEPLOY SUCCESS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📊 Metrics:
   - Total time: 4m 0s (vs ~60min manual, -93%)
   - Build time: 1m 34s
   - Image size: 82MB (-80% vs non-multi-stage)
   - Cold start: 2.1s
   - Memory usage: 45MB / 512MB (8.8%)
   - CPU usage: 12% (avg first 60s)

🌐 Endpoints:
   - Production: https://domain.descomplicar.pt
   - Health: https://domain.descomplicar.pt/health

📋 Logs:
   - EasyPanel: https://easy.descomplicar.pt/services/<service>/logs
   - Gitea: https://git.descomplicar.pt/org/repo/actions

🔔 Next Steps:
   1. Monitor uptime (first 24h critical)
   2. Check error rate (should be <1%)
   3. Load testing (optional, recommended)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

## Output Format (Failed)

```
❌ DEPLOY FAILED

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⏱️  TIMELINE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[00:00] ✅ Pre-deploy validation
[00:15] ✅ Tests passed
[00:20] ✅ Local build
[00:25] ✅ Git push
[01:55] ✅ EasyPanel build started
[03:42] ✅ Container started
[03:50] ❌ Health check 1/5: 502 Bad Gateway
[04:00] ❌ Health check 2/5: 502 Bad Gateway
[04:10] ❌ Health check 3/5: 502 Bad Gateway
[04:20] ❌ HEALTH CHECK FAILED (3/5 retries)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔴 ERROR DETAILS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Issue: Health endpoint not responding (502)
Likely cause: Port mismatch or app crash

Logs (last 20 lines):
  > Error: listen EADDRINUSE: address already in use :::8080
  > at Server.setupListenHandle [as _listen2]

Root cause detected: App listening on port 8080, Traefik expects 3000

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔄 AUTO-ROLLBACK
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[04:25] ⏪ Rolling back to previous version (commit: 7d3a1f2)
[04:30] ✅ Rollback complete
[04:35] ✅ Health check: 200 OK (service restored)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🛠️  RECOMMENDED FIXES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1. Update Dockerfile EXPOSE: Change 8080 → 3000
   OR
2. Update docker-compose.yml Traefik label:
   traefik.http.services.X.loadbalancer.server.port=8080

3. Test fix locally: docker build && docker run
4. Commit fix + redeploy: /easypanel-deploy

🔍 Troubleshooting:
   /easypanel-troubleshoot <service-name>
```

## Auto-Rollback Logic

**Trigger Conditions:**
- Health check fails 3/5 times
- Container crashes dentro de 60s
- Metrics críticos (CPU > 95%, Memory OOM)

**Rollback Actions:**
1. Identificar último commit estável (health OK)
2. `git revert` ou `git checkout`
3. Force push para trigger redeploy
4. Aguardar health check OK
5. Report success/fail

## Flags

### --skip-tests

```bash
/easypanel-deploy --skip-tests
```

**Quando usar:**
- CI/CD já executou tests
- Tests demoram muito (>5min)
- Deploy de hotfix urgente

### --force

```bash
/easypanel-deploy --force
```

**Quando usar:**
- Ignorar validation warnings
- Deploy apesar de score < 7/10
- Override safety checks

**⚠️ ATENÇÃO:** Usar apenas se souber o que está a fazer.

## Integration com CI/CD

O deploy automatico via Gitea Actions usa o webhook do EasyPanel (nao esta skill directamente).
Cada servico tem um `deploymentUrl` unico (visivel em `inspectService`).

```yaml
# .gitea/workflows/deploy.yml
steps:
  - name: Trigger EasyPanel Deploy
    run: |
      curl -s -X POST "${{ secrets.EASYPANEL_DEPLOY_URL }}"
    # EASYPANEL_DEPLOY_URL = http://IP:3000/api/deploy/<service-token>
```

Ver skill `/easypanel-cicd` para configuracao completa de CI/CD com Gitea Actions.

## API Endpoints Usados

Ver skill `/easypanel-api` para documentação completa.

| Acção | Endpoint | Verificado |
|-------|----------|:----------:|
| Deploy serviço | `POST services.app.deployService` | Sim |
| Estado serviço | `GET services.app.inspectService` | Sim |
| Parar serviço | `POST services.app.stopService` | Sim |
| Iniciar serviço | `POST services.app.startService` | Sim |
| Reiniciar serviço | `POST services.app.restartService` | Sim |
| Logs serviço | `GET logs.getServiceLogs` | Sim |

**Endpoints que NAO existem:** `redeployService` — usar `deployService` para re-deploy.

## MCPs Necessários

- ✅ `ssh-unified` - Acesso ao servidor para executar comandos API
- ✅ `gitea` - Git operations e push

## Tools Necessários

```bash
# Git
git status
git add .
git commit
git push

# Docker
docker build
docker stats

# Curl
curl -f https://domain/health
```

## Metrics Tracking

Após deploy, gravar métricas:

```sql
INSERT INTO tblskill_metrics (
  skill_name, duration_ms, success,
  build_time_ms, image_size_mb, deploy_time_ms,
  health_check_status, cpu_avg, ram_mb
) VALUES (
  '/easypanel-deploy', DURATION, SUCCESS,
  BUILD_TIME, IMAGE_SIZE, DEPLOY_TIME,
  'ok', CPU, RAM
);
```

## Checklist Execução

- [ ] Executar /easypanel-validate
- [ ] Check score >= 7/10
- [ ] Run tests (se não --skip-tests)
- [ ] Build local test
- [ ] Verificar uncommitted changes
- [ ] Push to Gitea
- [ ] Monitor build EasyPanel
- [ ] Health check (5 retries)
- [ ] Validate metrics (CPU, RAM)
- [ ] Report success ou trigger rollback
- [ ] Log metrics

---

**Versão:** 1.0.0 | **Autor:** Descomplicar® | **Data:** 2026-02-04

## Metadata (Desk CRM Task #65)

```
Tarefa: SKL: /easypanel-deploy - Automated Deploy + Validation
Milestone: 294 (Skills Claude Code)
Tags: skill(79), stackworkflow(75), claude-code(81), activo(116)
Responsáveis: Emanuel(1), AikTop(25)
Status: 4 (Em progresso) → 5 (Concluído)
```

---

**/** @author Descomplicar® | @link descomplicar.pt | @copyright 2026 **/
---

## Healing Log

Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.

```jsonl
{"date":"","issue":"","fix":"","source":"user|auto"}
```

*Adicionar nova linha após cada erro corrigido.*
