Compare commits
38 Commits
08cd32ba85
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 840ef44670 | |||
| 42cb6e0d67 | |||
| 6de2518a72 | |||
| 6a4b16bb8b | |||
| f70ecaeeb5 | |||
| 8459327d8b | |||
| 29b497468e | |||
| c33b186098 | |||
| 56e7b8b0a8 | |||
| 11638026d9 | |||
| e3db9eb87f | |||
| 3a85201154 | |||
| 865cf9b3e8 | |||
| eb5f04e5e2 | |||
| ca15833526 | |||
| 67b56c1c9b | |||
| ed7586f950 | |||
| 361be0eb9e | |||
| 667b01c2a0 | |||
| d3e77ad9a5 | |||
| fd52352b21 | |||
| 86a4b7cc1d | |||
| 5fed217818 | |||
| 03c2cbf90b | |||
| 2061ea5c0e | |||
| 8729de88a7 | |||
| caf6d492ca | |||
| 653d3e7670 | |||
| 77c5f5419f | |||
| 86e656d593 | |||
| afac617b3f | |||
| 1585339dee | |||
| 39469ad121 | |||
| f8e5060278 | |||
| d7481323f9 | |||
| c91ee30c1b | |||
| 552d1305f8 | |||
| 48aaaa798c |
2
.gga
2
.gga
@@ -34,7 +34,7 @@ EXCLUDE_PATTERNS="*.test.ts,*.spec.ts,*.test.tsx,*.spec.tsx,*.d.ts"
|
|||||||
|
|
||||||
# File containing code review rules
|
# File containing code review rules
|
||||||
# Default: AGENTS.md
|
# Default: AGENTS.md
|
||||||
RULES_FILE="AGENTS.md"
|
RULES_FILE="AGENT.md"
|
||||||
|
|
||||||
# Strict mode: fail if AI response is ambiguous
|
# Strict mode: fail if AI response is ambiguous
|
||||||
# Default: true
|
# Default: true
|
||||||
|
|||||||
29
.gitea/ISSUE_TEMPLATE/bug_report.md
Normal file
29
.gitea/ISSUE_TEMPLATE/bug_report.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
about: Reportar un bug o problema
|
||||||
|
title: "[BUG] "
|
||||||
|
labels: bug
|
||||||
|
---
|
||||||
|
|
||||||
|
## Descripción del Bug
|
||||||
|
Descripción clara del problema.
|
||||||
|
|
||||||
|
## Pasos para Reproducir
|
||||||
|
1. Ir a '...'
|
||||||
|
2. Hacer click en '...'
|
||||||
|
3. Ver error
|
||||||
|
|
||||||
|
## Comportamiento Esperado
|
||||||
|
Describir lo que debería pasar.
|
||||||
|
|
||||||
|
## Comportamiento Actual
|
||||||
|
Describir lo que realmente pasa.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
Si aplica, agregar screenshots.
|
||||||
|
|
||||||
|
## Entorno
|
||||||
|
- OS: [ej. Windows 11]
|
||||||
|
- Browser: [ej. Chrome 120]
|
||||||
|
- .NET Version: [ej. 10.0]
|
||||||
|
- Node Version: [ej. 22.x]
|
||||||
24
.gitea/ISSUE_TEMPLATE/feature_request.md
Normal file
24
.gitea/ISSUE_TEMPLATE/feature_request.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Feature Request
|
||||||
|
about: Solicitar una nueva funcionalidad
|
||||||
|
title: "[FEATURE] "
|
||||||
|
labels: feature
|
||||||
|
---
|
||||||
|
|
||||||
|
## Descripción de la Feature
|
||||||
|
Descripción clara de lo que se quiere.
|
||||||
|
|
||||||
|
## Problema que Resuelve
|
||||||
|
¿Qué problema tiene el usuario actualmente?
|
||||||
|
|
||||||
|
## Solución Propuesta
|
||||||
|
Describir la solución deseada.
|
||||||
|
|
||||||
|
## Alternativas Consideradas
|
||||||
|
Otras soluciones que se consideraron.
|
||||||
|
|
||||||
|
## Área
|
||||||
|
- [ ] Backend
|
||||||
|
- [ ] Frontend
|
||||||
|
- [ ] DevOps
|
||||||
|
- [ ] Base de Datos
|
||||||
21
.gitea/ISSUE_TEMPLATE/task.md
Normal file
21
.gitea/ISSUE_TEMPLATE/task.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: Technical Task
|
||||||
|
about: Tarea técnica o refactor
|
||||||
|
title: "[TASK] "
|
||||||
|
labels: task
|
||||||
|
---
|
||||||
|
|
||||||
|
## Descripción
|
||||||
|
Descripción de la tarea técnica.
|
||||||
|
|
||||||
|
## Objetivo
|
||||||
|
Qué se quiere lograr.
|
||||||
|
|
||||||
|
## Alcance
|
||||||
|
- [ ] Archivos/carpetas afectados
|
||||||
|
- [ ] Dependencias
|
||||||
|
- [ ] Tests necesarios
|
||||||
|
|
||||||
|
## Criterios de Aceptación
|
||||||
|
- [ ] Criterio 1
|
||||||
|
- [ ] Criterio 2
|
||||||
21
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
21
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
## Descripción
|
||||||
|
Breve descripción de los cambios.
|
||||||
|
|
||||||
|
## Tipo de Cambio
|
||||||
|
- [ ] Bug fix (change that fixes an issue)
|
||||||
|
- [ ] New feature (change that adds functionality)
|
||||||
|
- [ ] Breaking change (change that would cause existing functionality to not work as expected)
|
||||||
|
- [ ] Documentation update
|
||||||
|
|
||||||
|
## Issue Relacionada
|
||||||
|
Closes #
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
- [ ] Mi código sigue las convenciones del proyecto (AGENT.md)
|
||||||
|
- [ ] He hecho self-review de mi código
|
||||||
|
- [ ] He agregado tests que prueban mi cambio (si aplica)
|
||||||
|
- [ ] Los tests pasan localmente
|
||||||
|
- [ ] He actualizado la documentación (si aplica)
|
||||||
|
|
||||||
|
## Screenshots (si aplica)
|
||||||
|
Agregar screenshots de los cambios visuales.
|
||||||
88
.gitea/workflows/ci.yml
Normal file
88
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
name: CI/CD Pipeline
|
||||||
|
|
||||||
|
# Triggers: push to main and pull requests to main
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Backend build job
|
||||||
|
backend-build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup .NET 10
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
with:
|
||||||
|
dotnet-version: 10.x
|
||||||
|
|
||||||
|
- name: Restore dependencies
|
||||||
|
run: dotnet restore Backend/PruebaGentle.slnx
|
||||||
|
|
||||||
|
- name: Build backend
|
||||||
|
run: dotnet build Backend/PruebaGentle.slnx --configuration Release
|
||||||
|
|
||||||
|
# Frontend build job
|
||||||
|
frontend-build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js 22
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22.x
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
working-directory: Frontend
|
||||||
|
|
||||||
|
- name: Build frontend
|
||||||
|
run: npm run build
|
||||||
|
working-directory: Frontend
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm run test:run
|
||||||
|
working-directory: Frontend
|
||||||
|
|
||||||
|
docker-build:
|
||||||
|
needs: [backend-build, frontend-build]
|
||||||
|
runs-on: docker
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
env:
|
||||||
|
DOCKER_API_VERSION: "1.41"
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Login to Gitea Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: repo.eldiaservicios.com
|
||||||
|
username: dmolinari
|
||||||
|
password: ${{ secrets.TOKEN_REGISTRY }}
|
||||||
|
|
||||||
|
- name: Build Docker images
|
||||||
|
run: docker compose build
|
||||||
|
|
||||||
|
- name: Tag versioned images
|
||||||
|
run: |
|
||||||
|
docker tag repo.eldiaservicios.com/dmolinari/pruebagentle/backend:latest repo.eldiaservicios.com/dmolinari/pruebagentle/backend:${{ github.run_number }}
|
||||||
|
docker tag repo.eldiaservicios.com/dmolinari/pruebagentle/frontend:latest repo.eldiaservicios.com/dmolinari/pruebagentle/frontend:${{ github.run_number }}
|
||||||
|
|
||||||
|
- name: Push to registry
|
||||||
|
run: |
|
||||||
|
docker compose push
|
||||||
|
docker push repo.eldiaservicios.com/dmolinari/pruebagentle/backend:${{ github.run_number }}
|
||||||
|
docker push repo.eldiaservicios.com/dmolinari/pruebagentle/frontend:${{ github.run_number }}
|
||||||
|
|
||||||
|
- name: Clean up old images
|
||||||
|
run: |
|
||||||
|
docker images --format '{{.Repository}}:{{.Tag}}' | grep 'repo.eldiaservicios.com/dmolinari/pruebagentle' | tail -n +3 | xargs -r docker rmi || true
|
||||||
38
AGENT.md
38
AGENT.md
@@ -2,6 +2,33 @@
|
|||||||
|
|
||||||
> **IMPORTANTE:** El idioma oficial de este proyecto es el ESPAÑOL. Todas las respuestas, explicaciones, comentarios de código y logs deben ser exclusivamente en español.
|
> **IMPORTANTE:** El idioma oficial de este proyecto es el ESPAÑOL. Todas las respuestas, explicaciones, comentarios de código y logs deben ser exclusivamente en español.
|
||||||
|
|
||||||
|
## 🚨 REGLA DE ORO: DELEGAR SIEMPRE
|
||||||
|
|
||||||
|
**NUNCA escribas código inline como orquestador.** Tu rol es COORDINAR, no ejecutar.
|
||||||
|
|
||||||
|
### Auto-pregunta ANTES de cada acción:
|
||||||
|
> *"¿Esto infla mi contexto sin necesidad?"*
|
||||||
|
> - Si SÍ → **DELEGA** a sub-agente
|
||||||
|
> - Si NO → hazlo inline
|
||||||
|
|
||||||
|
### DELEGAR (siempre):
|
||||||
|
- ❌ Escribir o editar CUALQUIER archivo de código
|
||||||
|
- ❌ Leer 4+ archivos para entender
|
||||||
|
- ❌ Ejecutar tests, builds, installs
|
||||||
|
- ❌ Crear branches, commits complejos
|
||||||
|
- ❌ Cualquier tarea de implementación
|
||||||
|
|
||||||
|
### INLINE (solo esto):
|
||||||
|
- ✅ git status / diff / log (solo lectura)
|
||||||
|
- ✅ Leer 1-3 archivos para DECIDIR (no para escribir)
|
||||||
|
- ✅ mem_search / mem_save
|
||||||
|
- ✅ Responder al usuario / hacer preguntas
|
||||||
|
|
||||||
|
### Anti-patrones que NUNCA debes repetir:
|
||||||
|
1. Leer archivos como "preparación" y luego editarlos → DELEGA la lectura + edición juntos
|
||||||
|
2. Escribir un fix "rápido" de 2 líneas → DELEGA igual
|
||||||
|
3. Ejecutar `npm run build` o `dotnet build` → DELEGA
|
||||||
|
|
||||||
Este proyecto utiliza C# (.NET Web API), React (TypeScript + Vite + Tailwind CSS), SQL Server, Docker y Gitea.
|
Este proyecto utiliza C# (.NET Web API), React (TypeScript + Vite + Tailwind CSS), SQL Server, Docker y Gitea.
|
||||||
DEBES cumplir estrictamente estas reglas en TODAS las fases del SDD (Spec, Design, Apply, Verify).
|
DEBES cumplir estrictamente estas reglas en TODAS las fases del SDD (Spec, Design, Apply, Verify).
|
||||||
|
|
||||||
@@ -63,3 +90,14 @@ Para cualquier aprobación, pregunta o decisión que requieras del usuario, DEBE
|
|||||||
1. Pasa tu pregunta SIEMPRE entre comillas dobles.
|
1. Pasa tu pregunta SIEMPRE entre comillas dobles.
|
||||||
2. Al ejecutar este comando, la terminal se pausará automáticamente (pueden ser minutos u horas). NO ENTRES EN PÁNICO, solo espera.
|
2. Al ejecutar este comando, la terminal se pausará automáticamente (pueden ser minutos u horas). NO ENTRES EN PÁNICO, solo espera.
|
||||||
3. Cuando el comando termine, capturará la salida estándar (stdout) donde estará la respuesta exacta del usuario. Usa esa respuesta para continuar tu trabajo.
|
3. Cuando el comando termine, capturará la salida estándar (stdout) donde estará la respuesta exacta del usuario. Usa esa respuesta para continuar tu trabajo.
|
||||||
|
|
||||||
|
### 🔄 Protocolo Post-Reinicio (OBLIGATORIO)
|
||||||
|
|
||||||
|
Si OpenCode se reinició:
|
||||||
|
|
||||||
|
1. **PRIMERA ACCIÓN**: Buscar en engram `mem_search(query: "remote-communication-protocol")`
|
||||||
|
2. **Si el usuario está EN EL CHAT** (mensajes directos en esta ventana):
|
||||||
|
- Continuar normalmente, NO enviar Telegram
|
||||||
|
3. **Si el usuario NO está** (último mensaje fue "salgo de la pc" o "modo remoto"):
|
||||||
|
- Ejecutar: `node E:/telegram-mcp/index.js "Reinicio completado. Estoy de vuelta y a la espera de tu mensaje."`
|
||||||
|
- Esperar respuesta antes de continuar
|
||||||
@@ -4,12 +4,12 @@ EXPOSE 8080
|
|||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY PruebaGentle.Core/PruebaGentle.Core.csproj PruebaGentle.Core/
|
COPY Backend/PruebaGentle.Core/PruebaGentle.Core.csproj Backend/PruebaGentle.Core/
|
||||||
COPY PruebaGentle.Infrastructure/PruebaGentle.Infrastructure.csproj PruebaGentle.Infrastructure/
|
COPY Backend/PruebaGentle.Infrastructure/PruebaGentle.Infrastructure.csproj Backend/PruebaGentle.Infrastructure/
|
||||||
COPY PruebaGentle.API/PruebaGentle.API.csproj PruebaGentle.API/
|
COPY Backend/PruebaGentle.API/PruebaGentle.API.csproj Backend/PruebaGentle.API/
|
||||||
RUN dotnet restore PruebaGentle.API/PruebaGentle.API.csproj
|
RUN dotnet restore Backend/PruebaGentle.API/PruebaGentle.API.csproj
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR /src/PruebaGentle.API
|
WORKDIR /src/Backend/PruebaGentle.API
|
||||||
RUN dotnet build -c Release -o /app/build
|
RUN dotnet build -c Release -o /app/build
|
||||||
|
|
||||||
FROM build AS publish
|
FROM build AS publish
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "Server=localhost;Database=PruebaGentle;User Id=sa;Password=YourStrong@Password123;TrustServerCertificate=true;"
|
"DefaultConnection": "Server=localhost;Database=Desarrollo;User Id=desarrollo;Password=desarrollo2026;TrustServerCertificate=true;"
|
||||||
},
|
},
|
||||||
"JwtSettings": {
|
"JwtSettings": {
|
||||||
"Secret": "ThisIsA32CharacterLongSecretKey!!",
|
"Secret": "ThisIsA32CharacterLongSecretKey!!",
|
||||||
|
|||||||
167
Bitacora-CICD-Gitea.md
Normal file
167
Bitacora-CICD-Gitea.md
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# 📖 Bitácora de Configuración CI/CD en Gitea
|
||||||
|
|
||||||
|
## Fase 1: Configuración del Gitea Act-Runner
|
||||||
|
**Objetivo:** Levantar el contenedor que ejecutará los pipelines de Gitea (el "runner").
|
||||||
|
|
||||||
|
* **Problema 1:** El contenedor del runner no iniciaba y arrojaba el error `accepts at most 0 arg(s), received 1`.
|
||||||
|
* **Causa:** Un espacio en blanco después de la coma en la variable de entorno `GITEA_RUNNER_LABELS` que Bash interpretaba como un argumento adicional.
|
||||||
|
* **Solución:** Eliminar el espacio y encerrar toda la declaración entre comillas dobles en el `docker-compose.yml` de Gitea:
|
||||||
|
`- "GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:18-bullseye,docker:docker://repo.eldiaservicios.com/dmolinari/act-runner:latest"`
|
||||||
|
|
||||||
|
## Fase 2: Preparación del Proyecto y Docker Compose
|
||||||
|
**Objetivo:** Que el código fuente (Backend y Frontend) se construya correctamente dentro de Docker.
|
||||||
|
|
||||||
|
* **Problema 2:** Error al construir la imagen del backend: `ERROR: "/PruebaGentle.API.csproj" not found`.
|
||||||
|
* **Causa:** El "contexto" de construcción (`context`) estaba mal referenciado; Docker buscaba el archivo en la raíz cuando en realidad estaba dentro de la carpeta `Backend/`.
|
||||||
|
* **Solución:** Se ajustó el `docker-compose.yml` del proyecto definiendo explícitamente los contextos (`context: ./Backend` y `context: ./Frontend`).
|
||||||
|
|
||||||
|
* **Problema 3:** Gitea no mostraba los paquetes en la pestaña "Paquetes" del repositorio.
|
||||||
|
* **Causa:** Las imágenes no tenían metadatos que le dijeran a Gitea a qué repositorio pertenecían.
|
||||||
|
* **Solución:** Se agregaron etiquetas OCI (`labels`) al `docker-compose.yml` del proyecto.
|
||||||
|
|
||||||
|
* **Problema 4:** Docker Compose no sabía cómo llamar a las imágenes, dando errores al intentar etiquetarlas con `docker tag backend`.
|
||||||
|
* **Solución:** Declarar el nombre exacto de la imagen en la propiedad `image:` de cada servicio.
|
||||||
|
|
||||||
|
**✅ Resultado final de `docker-compose.yml` (Proyecto):**
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
image: repo.eldiaservicios.com/dmolinari/pruebagentle/backend:latest
|
||||||
|
build:
|
||||||
|
context: ./Backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
labels:
|
||||||
|
- "org.opencontainers.image.source=https://repo.eldiaservicios.com/dmolinari/PruebaGentle"
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
image: repo.eldiaservicios.com/dmolinari/pruebagentle/frontend:latest
|
||||||
|
build:
|
||||||
|
context: ./Frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
labels:
|
||||||
|
- "org.opencontainers.image.source=https://repo.eldiaservicios.com/dmolinari/PruebaGentle"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fase 3: Solución de Problemas en el Pipeline (Errores de Gitea Actions)
|
||||||
|
**Objetivo:** Que el Action compile, inicie sesión y suba las imágenes a Gitea Registry.
|
||||||
|
|
||||||
|
* **Problema 5:** Error `client version 1.52 is too new. Maximum supported API version is 1.41`.
|
||||||
|
* **Causa:** El Docker Engine del servidor host es más antiguo que el cliente instalado en el runner. Las variables de entorno del `Dockerfile` se borraban al iniciar el job.
|
||||||
|
* **Solución:** Forzar la compatibilidad inyectando `env: DOCKER_API_VERSION: "1.41"` directamente a nivel del Job en el archivo `ci.yml`.
|
||||||
|
|
||||||
|
* **Problema 6:** Errores de Autenticación (`unauthorized`, `cannot perform an interactive login from a non TTY device` y `Password required`).
|
||||||
|
* **Causa:** Faltaba el paso para iniciar sesión en el Registry. Al intentar pasarlo por consola, si una variable estaba vacía, Docker pedía la clave por teclado, colgando el proceso (non TTY). Además, el token por defecto de Gitea no tenía permisos de escritura para paquetes.
|
||||||
|
* **Solución:**
|
||||||
|
1. Se generó un **Token de Acceso Personal (PAT)** desde el perfil del usuario con permisos de lectura/escritura en *Packages*.
|
||||||
|
2. Se guardó este token en **Configuración del Repositorio -> Acciones -> Secretos** bajo el nombre `TOKEN_REGISTRY`.
|
||||||
|
3. Se implementó la acción oficial `docker/login-action@v3` para manejar el login de forma segura.
|
||||||
|
|
||||||
|
* **Problema 7:** Las imágenes subidas sobreescribían el historial (todo era `latest`).
|
||||||
|
* **Causa:** La etiqueta `latest` reemplaza a la anterior sin guardar historial.
|
||||||
|
* **Solución:** Implementar doble etiquetado. Subir `:latest` (para producción) y subir `:${{ github.run_number }}` (para mantener un registro de versiones atado a la ejecución del Action).
|
||||||
|
|
||||||
|
## Fase 4: El Archivo Pipeline Final (`ci.yml`)
|
||||||
|
Este es el archivo definitivo, pulido y profesional que logró integrar todo el proceso:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: CI/CD Pipeline
|
||||||
|
|
||||||
|
# Triggers: push to main and pull requests to main
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Backend build job
|
||||||
|
backend-build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup .NET 10
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
with:
|
||||||
|
dotnet-version: 10.x
|
||||||
|
|
||||||
|
- name: Restore dependencies
|
||||||
|
run: dotnet restore Backend/PruebaGentle.slnx
|
||||||
|
|
||||||
|
- name: Build backend
|
||||||
|
run: dotnet build Backend/PruebaGentle.slnx --configuration Release
|
||||||
|
|
||||||
|
# Frontend build job
|
||||||
|
frontend-build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js 22
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22.x
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
working-directory: Frontend
|
||||||
|
|
||||||
|
- name: Build frontend
|
||||||
|
run: npm run build
|
||||||
|
working-directory: Frontend
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm run test:run
|
||||||
|
working-directory: Frontend
|
||||||
|
|
||||||
|
docker-build:
|
||||||
|
needs: [backend-build, frontend-build]
|
||||||
|
runs-on: docker
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
env:
|
||||||
|
DOCKER_API_VERSION: "1.41"
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Login to Gitea Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: repo.eldiaservicios.com
|
||||||
|
username: dmolinari
|
||||||
|
password: ${{ secrets.TOKEN_REGISTRY }}
|
||||||
|
|
||||||
|
- name: Build Docker images
|
||||||
|
run: docker compose build
|
||||||
|
|
||||||
|
- name: Tag versioned images
|
||||||
|
run: |
|
||||||
|
docker tag repo.eldiaservicios.com/dmolinari/pruebagentle/backend:latest repo.eldiaservicios.com/dmolinari/pruebagentle/backend:${{ github.run_number }}
|
||||||
|
docker tag repo.eldiaservicios.com/dmolinari/pruebagentle/frontend:latest repo.eldiaservicios.com/dmolinari/pruebagentle/frontend:${{ github.run_number }}
|
||||||
|
|
||||||
|
- name: Push to registry
|
||||||
|
run: |
|
||||||
|
docker compose push
|
||||||
|
docker push repo.eldiaservicios.com/dmolinari/pruebagentle/backend:${{ github.run_number }}
|
||||||
|
docker push repo.eldiaservicios.com/dmolinari/pruebagentle/frontend:${{ github.run_number }}
|
||||||
|
|
||||||
|
- name: Clean up old images
|
||||||
|
run: |
|
||||||
|
docker images --format '{{.Repository}}:{{.Tag}}' | grep 'repo.eldiaservicios.com/dmolinari/pruebagentle' | tail -n +3 | xargs -r docker rmi || true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fase 5: Mantenimiento y Retención del Servidor
|
||||||
|
**Objetivo:** Evitar que el disco del servidor colapse por acumular cientos de versiones de imágenes.
|
||||||
|
|
||||||
|
* **Acción tomada:** Se configuró una regla de limpieza automática desde la cuenta de **Administrador del sitio** de Gitea (`/admin/packages`).
|
||||||
|
* **Regla implementada:**
|
||||||
|
* Tipo: `Container`
|
||||||
|
* Mantener el más reciente: `5 versiones por paquete` (Esto actúa como escudo de seguridad mínimo).
|
||||||
|
* Eliminar versiones anteriores a: `X días` (Para limpiar la basura antigua periódicamente).
|
||||||
|
* **Aclaración de Interfaz:** Se aprendió que Gitea agrupa los paquetes en la vista del repositorio (hay que hacer clic para ver las versiones), mientras que en la vista de administración muestra todas las etiquetas desagrupadas.
|
||||||
|
|
||||||
|
---
|
||||||
@@ -1 +1 @@
|
|||||||
VITE_API_URL=http://localhost:5000/api
|
VITE_API_URL=http://localhost:5082/api
|
||||||
|
|||||||
1146
Frontend/package-lock.json
generated
1146
Frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,9 @@
|
|||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"test": "vitest",
|
||||||
|
"test:run": "vitest run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
@@ -17,6 +19,9 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.4",
|
"@eslint/js": "^9.39.4",
|
||||||
"@tailwindcss/vite": "^4.2.2",
|
"@tailwindcss/vite": "^4.2.2",
|
||||||
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
|
"@testing-library/react": "^16.3.2",
|
||||||
|
"@testing-library/user-event": "^14.6.1",
|
||||||
"@types/node": "^24.12.0",
|
"@types/node": "^24.12.0",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
@@ -25,9 +30,11 @@
|
|||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.5.2",
|
"eslint-plugin-react-refresh": "^0.5.2",
|
||||||
"globals": "^17.4.0",
|
"globals": "^17.4.0",
|
||||||
|
"jsdom": "^29.0.1",
|
||||||
"tailwindcss": "^4.2.2",
|
"tailwindcss": "^4.2.2",
|
||||||
"typescript": "~5.9.3",
|
"typescript": "~5.9.3",
|
||||||
"typescript-eslint": "^8.57.0",
|
"typescript-eslint": "^8.57.0",
|
||||||
"vite": "^8.0.1"
|
"vite": "^8.0.1",
|
||||||
|
"vitest": "^4.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
Frontend/src/components/TestEcosistemaComponent.tsx
Normal file
21
Frontend/src/components/TestEcosistemaComponent.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const TestEcosistemaComponent: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>Test Ecosistema OpenCode</h2>
|
||||||
|
<p>Componente creado para completar la fase apply del flujo SDD</p>
|
||||||
|
<ul>
|
||||||
|
<li>MCP engram: ✅ Funcional</li>
|
||||||
|
<li>MCP mssql: ❌ Sin conexión</li>
|
||||||
|
<li>MCP convention-checker: ✅ Funcional</li>
|
||||||
|
<li>MCP release-mcp: ✅ Funcional</li>
|
||||||
|
<li>MCP coordinator-mcp: ✅ Funcional</li>
|
||||||
|
<li>MCP context7: ✅ Funcional</li>
|
||||||
|
<li>MCP sdd-mcp: ⚠️ Parcial/Stub</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TestEcosistemaComponent;
|
||||||
32
Frontend/src/hooks/__tests__/useAuth.test.tsx
Normal file
32
Frontend/src/hooks/__tests__/useAuth.test.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { AuthProvider } from '../useAuth';
|
||||||
|
import { useAuth } from '../useAuth';
|
||||||
|
|
||||||
|
// Test component that uses useAuth hook
|
||||||
|
const TestComponent = () => {
|
||||||
|
const auth = useAuth();
|
||||||
|
return <div data-testid="auth-user">{auth.user?.username ?? 'null'}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('useAuth hook', () => {
|
||||||
|
test('throws error when used outside AuthProvider', () => {
|
||||||
|
// Render component without AuthProvider wrapper
|
||||||
|
const renderTestComponent = () => render(<TestComponent />);
|
||||||
|
|
||||||
|
// Expect it to throw an error
|
||||||
|
expect(renderTestComponent).toThrow('useAuth must be used within an AuthProvider');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('provides context through AuthProvider', () => {
|
||||||
|
// Render component with AuthProvider wrapper
|
||||||
|
render(
|
||||||
|
<AuthProvider>
|
||||||
|
<TestComponent />
|
||||||
|
</AuthProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should initially show null since no user is set
|
||||||
|
const authContextElement = screen.getByTestId('auth-user');
|
||||||
|
expect(authContextElement).toHaveTextContent('null');
|
||||||
|
});
|
||||||
|
});
|
||||||
2
Frontend/src/test/setup.ts
Normal file
2
Frontend/src/test/setup.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Setup file for Vitest with React Testing Library
|
||||||
|
import '@testing-library/jest-dom'
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"types": ["vite/client"],
|
"types": ["vite/client", "vitest/globals"],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
/* Bundler mode */
|
/* Bundler mode */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vitest/config'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
import tailwindcss from '@tailwindcss/vite'
|
import tailwindcss from '@tailwindcss/vite'
|
||||||
|
|
||||||
@@ -8,9 +8,14 @@ export default defineConfig({
|
|||||||
port: 8181,
|
port: 8181,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://localhost:5000',
|
target: 'http://localhost:5082',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: './src/test/setup.ts',
|
||||||
|
globals: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
41
README.md
Normal file
41
README.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# PruebaGentle
|
||||||
|
|
||||||
|
Proyecto de prueba con backend .NET y frontend React.
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
- **Backend**: .NET 10 + Dapper + SQL Server
|
||||||
|
- **Frontend**: React 19 + Vite + Tailwind CSS
|
||||||
|
- **Database**: SQL Server (Docker)
|
||||||
|
- **CI/CD**: Gitea Actions
|
||||||
|
|
||||||
|
## Desarrollo Local
|
||||||
|
|
||||||
|
### Requisitos
|
||||||
|
- .NET 10 SDK
|
||||||
|
- Node.js 22+
|
||||||
|
- Docker Desktop
|
||||||
|
|
||||||
|
### Comandos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Frontend
|
||||||
|
cd Frontend
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Backend
|
||||||
|
cd Backend
|
||||||
|
dotnet restore
|
||||||
|
dotnet run
|
||||||
|
|
||||||
|
# Docker (todo)
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pipeline
|
||||||
|
|
||||||
|
El pipeline de CI/CD corre en Gitea Actions y construye:
|
||||||
|
1. Backend (.NET)
|
||||||
|
2. Frontend (React + Vite)
|
||||||
|
3. Imágenes Docker (push al registry de Gitea)
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
sqlserver:
|
sqlserver:
|
||||||
image: mcr.microsoft.com/mssql/server:2022-latest
|
image: mcr.microsoft.com/mssql/server:2022-latest
|
||||||
@@ -20,9 +18,13 @@ services:
|
|||||||
start_period: 30s
|
start_period: 30s
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
|
# 1. AÑADIMOS EL NOMBRE DE LA IMAGEN AQUÍ
|
||||||
|
image: repo.eldiaservicios.com/dmolinari/pruebagentle/backend:latest
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Backend/Dockerfile
|
dockerfile: Backend/Dockerfile
|
||||||
|
labels:
|
||||||
|
- "org.opencontainers.image.source=https://repo.eldiaservicios.com/dmolinari/PruebaGentle"
|
||||||
ports:
|
ports:
|
||||||
- "5000:8080"
|
- "5000:8080"
|
||||||
environment:
|
environment:
|
||||||
@@ -35,9 +37,13 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
|
# 2. AÑADIMOS EL NOMBRE DE LA IMAGEN AQUÍ
|
||||||
|
image: repo.eldiaservicios.com/dmolinari/pruebagentle/frontend:latest
|
||||||
build:
|
build:
|
||||||
context: ./Frontend
|
context: ./Frontend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
labels:
|
||||||
|
- "org.opencontainers.image.source=https://repo.eldiaservicios.com/dmolinari/PruebaGentle"
|
||||||
ports:
|
ports:
|
||||||
- "8181:80"
|
- "8181:80"
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
Reference in New Issue
Block a user