fix(project-manager): remover Dify KB das descriptions, marcar nota TODO
Dify foi removido 06-03-2026. Skills brainstorm/discover ainda referenciam-no no corpo. Bump v1.2 + nota top-of-file. Reescrita workflow para próxima sessão. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,359 @@
|
||||
---
|
||||
name: easypanel-cicd
|
||||
description: Configuracao de CI/CD com Gitea Actions para auto-deploy no EasyPanel via webhook — setup de workflows, secrets e validacao.
|
||||
---
|
||||
|
||||
# /easypanel-cicd - CI/CD Gitea Actions para EasyPanel
|
||||
|
||||
Configuracao completa de pipelines CI/CD que ligam repositorios Gitea ao EasyPanel para auto-deploy.
|
||||
|
||||
---
|
||||
|
||||
## Quando usar
|
||||
|
||||
- Configurar auto-deploy de um repositorio Gitea para EasyPanel
|
||||
- Criar workflow Gitea Actions com testes + deploy
|
||||
- Obter e configurar webhook URL de um servico
|
||||
- Diagnosticar pipelines CI/CD falhados
|
||||
- Adicionar CI/CD a projectos existentes no EasyPanel
|
||||
|
||||
## Quando nao usar
|
||||
|
||||
- Para deploy manual (usar `/easypanel-deploy`)
|
||||
- Para scaffold de projecto novo (usar `/easypanel-init`)
|
||||
- Para troubleshooting de containers (usar `/easypanel-troubleshoot`)
|
||||
|
||||
---
|
||||
|
||||
## Sintaxe
|
||||
|
||||
```bash
|
||||
/easypanel-cicd <repo-name> # Setup completo (workflow + secrets + webhook)
|
||||
/easypanel-cicd <repo-name> --webhook-only # Apenas obter/configurar webhook
|
||||
/easypanel-cicd <repo-name> --diagnose # Diagnosticar pipeline falhado
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura
|
||||
|
||||
```
|
||||
Gitea (push main) --> Gitea Actions Runner --> Testes + Build --> Webhook POST --> EasyPanel Redeploy
|
||||
(3 runners activos) (deploy URL) (build + container)
|
||||
```
|
||||
|
||||
**Componentes:**
|
||||
- **Gitea Actions Runners:** 3 replicas activas (`descomplicar_gitea-runner`)
|
||||
- **Webhook URL:** Cada servico EasyPanel tem `deploymentUrl` unico
|
||||
- **Formato:** `http://<IP>:3000/api/deploy/<service-token>`
|
||||
|
||||
---
|
||||
|
||||
## Workflow completo
|
||||
|
||||
### 1. Obter webhook URL do servico
|
||||
|
||||
```bash
|
||||
TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
|
||||
# Via inspectService — campo deploymentUrl
|
||||
INPUT='{"json":{"projectName":"descomplicar","serviceName":"SERVICE_NAME"}}'
|
||||
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$INPUT'))")
|
||||
curl -s "http://localhost:3000/api/trpc/services.app.inspectService?input=$ENCODED" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['result']['data']['json']['deploymentUrl'])"
|
||||
```
|
||||
|
||||
**Formato da URL:** `http://178.63.18.51:3000/api/deploy/<service-token>`
|
||||
|
||||
**Nota:** O token e unico por servico e nao expira. Nao confundir com o API token geral.
|
||||
|
||||
### 2. Configurar secret no repositorio Gitea
|
||||
|
||||
Via MCP Gitea:
|
||||
```
|
||||
mcp__gitea__upsert_repo_action_secret({
|
||||
owner: "ealmeida",
|
||||
repo: "REPO_NAME",
|
||||
secretname: "EASYPANEL_DEPLOY_URL",
|
||||
body: { data: "http://178.63.18.51:3000/api/deploy/<service-token>" }
|
||||
})
|
||||
```
|
||||
|
||||
Secrets adicionais recomendados:
|
||||
- `EASYPANEL_DEPLOY_URL` — webhook URL (obrigatorio)
|
||||
- `DEPLOY_DOMAIN` — dominio do servico (opcional, para health check)
|
||||
|
||||
### 3. Criar workflow Gitea Actions
|
||||
|
||||
Criar `.gitea/workflows/deploy.yml` no repositorio:
|
||||
|
||||
#### Template basico (apenas deploy)
|
||||
|
||||
```yaml
|
||||
name: Deploy to EasyPanel
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger EasyPanel Deploy
|
||||
run: |
|
||||
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${{ secrets.EASYPANEL_DEPLOY_URL }}")
|
||||
if [ "$RESPONSE" != "200" ]; then
|
||||
echo "Deploy trigger failed with HTTP $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo "Deploy triggered successfully"
|
||||
```
|
||||
|
||||
#### Template completo (testes + build + deploy + health check)
|
||||
|
||||
```yaml
|
||||
name: CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint --if-present
|
||||
|
||||
- name: Test
|
||||
run: npm test --if-present
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
deploy:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
||||
steps:
|
||||
- name: Trigger EasyPanel Deploy
|
||||
run: |
|
||||
echo "Triggering deploy..."
|
||||
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${{ secrets.EASYPANEL_DEPLOY_URL }}")
|
||||
if [ "$RESPONSE" != "200" ]; then
|
||||
echo "Deploy trigger failed with HTTP $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo "Deploy triggered (HTTP $RESPONSE)"
|
||||
|
||||
- name: Wait for deployment
|
||||
run: sleep 120
|
||||
|
||||
- name: Health check
|
||||
if: ${{ secrets.DEPLOY_DOMAIN != '' }}
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://${{ secrets.DEPLOY_DOMAIN }}/health" || echo "000")
|
||||
echo "Health check $i/5: HTTP $STATUS"
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
echo "Service healthy"
|
||||
exit 0
|
||||
fi
|
||||
sleep 15
|
||||
done
|
||||
echo "Health check failed after 5 attempts"
|
||||
exit 1
|
||||
```
|
||||
|
||||
#### Template Python
|
||||
|
||||
```yaml
|
||||
name: CI/CD Pipeline (Python)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- run: pip install -r requirements.txt
|
||||
- run: python -m pytest --if-present
|
||||
|
||||
deploy:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
steps:
|
||||
- name: Trigger EasyPanel Deploy
|
||||
run: |
|
||||
curl -sf -X POST "${{ secrets.EASYPANEL_DEPLOY_URL }}" || exit 1
|
||||
```
|
||||
|
||||
### 4. Commit e push
|
||||
|
||||
```bash
|
||||
git add .gitea/workflows/deploy.yml
|
||||
git commit -m "ci: add Gitea Actions deploy pipeline"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### 5. Validar pipeline
|
||||
|
||||
```bash
|
||||
# Via MCP Gitea — verificar runs
|
||||
mcp__gitea__list_repo_action_runs({
|
||||
owner: "ealmeida",
|
||||
repo: "REPO_NAME",
|
||||
limit: 5
|
||||
})
|
||||
```
|
||||
|
||||
Ou verificar logs:
|
||||
```bash
|
||||
mcp__gitea__list_repo_action_run_jobs({
|
||||
owner: "ealmeida",
|
||||
repo: "REPO_NAME",
|
||||
run_id: RUN_ID
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Diagnostico (--diagnose)
|
||||
|
||||
### Pipeline nao dispara
|
||||
|
||||
1. Verificar se o ficheiro esta em `.gitea/workflows/` (nao `.github/workflows/`)
|
||||
2. Verificar se o branch e `main` (ou o configurado no `on.push.branches`)
|
||||
3. Verificar se os runners estao activos:
|
||||
```bash
|
||||
docker service ls | grep gitea-runner
|
||||
# Esperado: 3/3 replicas
|
||||
```
|
||||
|
||||
### Webhook falha (HTTP != 200)
|
||||
|
||||
1. Verificar se o `deploymentUrl` esta correcto (servico pode ter sido recriado)
|
||||
2. Verificar se o EasyPanel esta acessivel internamente:
|
||||
```bash
|
||||
curl -s http://localhost:3000/api/trpc/projects.listProjects -H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
3. Verificar se o token do servico nao mudou (re-obter via inspectService)
|
||||
|
||||
### Build falha no EasyPanel
|
||||
|
||||
1. Verificar Dockerfile:
|
||||
```bash
|
||||
/easypanel-validate
|
||||
```
|
||||
2. Verificar logs do build:
|
||||
```bash
|
||||
/easypanel-troubleshoot SERVICE_NAME
|
||||
```
|
||||
|
||||
### Testes falham no runner
|
||||
|
||||
1. Verificar logs do job:
|
||||
```bash
|
||||
mcp__gitea__get_repo_action_job_log_preview({
|
||||
owner: "ealmeida",
|
||||
repo: "REPO_NAME",
|
||||
job_id: JOB_ID
|
||||
})
|
||||
```
|
||||
2. Verificar se dependencias estao no `package.json`/`requirements.txt`
|
||||
3. Verificar se env vars de teste estao configuradas
|
||||
|
||||
---
|
||||
|
||||
## Servicos com CI/CD activo (inventario)
|
||||
|
||||
Para listar todos os servicos com source git (candidatos a CI/CD):
|
||||
|
||||
```bash
|
||||
TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
curl -s "http://localhost:3000/api/trpc/projects.listProjectsAndServices" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
| python3 -c "
|
||||
import sys,json
|
||||
d=json.load(sys.stdin)['result']['data']['json']
|
||||
for s in d.get('services',[]):
|
||||
src=s.get('source',{}) or {}
|
||||
if src.get('type')=='git' and s.get('type')=='app':
|
||||
repo=src.get('repo','').split('@')[-1] if '@' in src.get('repo','') else src.get('repo','')
|
||||
print(f\"{s['projectName']}/{s['name']} | repo={repo} | ref={src.get('ref','?')}\")
|
||||
"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checklist de execucao
|
||||
|
||||
- [ ] Identificar servico EasyPanel alvo (projectName + serviceName)
|
||||
- [ ] Obter deploymentUrl via inspectService (SSH ao servidor easy)
|
||||
- [ ] Criar secret EASYPANEL_DEPLOY_URL no repo Gitea (via MCP)
|
||||
- [ ] Criar secret DEPLOY_DOMAIN no repo Gitea (opcional, para health check)
|
||||
- [ ] Criar `.gitea/workflows/deploy.yml` com template adequado
|
||||
- [ ] Commit e push do workflow
|
||||
- [ ] Verificar que o primeiro run dispara (list_repo_action_runs)
|
||||
- [ ] Verificar que o deploy completa no EasyPanel
|
||||
- [ ] Health check do servico apos deploy
|
||||
|
||||
---
|
||||
|
||||
## MCPs necessarios
|
||||
|
||||
- `ssh-unified` — Acesso ao servidor easy para obter deploymentUrl
|
||||
- `gitea` — Criar secrets e verificar action runs
|
||||
|
||||
---
|
||||
|
||||
## Skills relacionadas
|
||||
|
||||
| Skill | Quando usar |
|
||||
|-------|-------------|
|
||||
| `/easypanel-deploy` | Deploy manual com validacao completa |
|
||||
| `/easypanel-validate` | Validar projecto antes de configurar CI/CD |
|
||||
| `/easypanel-init` | Scaffold novo projecto (ja inclui workflow template) |
|
||||
| `/easypanel-troubleshoot` | Diagnosticar deploy falhado |
|
||||
| `/easypanel-api` | Referencia API tRPC |
|
||||
|
||||
---
|
||||
|
||||
*Skill v1.0.0 | 24-03-2026 | Descomplicar(r)*
|
||||
|
||||
---
|
||||
|
||||
## 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.*
|
||||
Reference in New Issue
Block a user