Compare commits
28 Commits
77c5f5419f
...
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 |
@@ -52,14 +52,37 @@ jobs:
|
|||||||
run: npm run test:run
|
run: npm run test:run
|
||||||
working-directory: Frontend
|
working-directory: Frontend
|
||||||
|
|
||||||
# Docker build job (depends on backend and frontend builds)
|
|
||||||
docker-build:
|
docker-build:
|
||||||
needs: [backend-build, frontend-build]
|
needs: [backend-build, frontend-build]
|
||||||
runs-on: ubuntu-latest
|
runs-on: docker
|
||||||
if: github.ref == 'refs/heads/main'
|
if: github.ref == 'refs/heads/main'
|
||||||
|
env:
|
||||||
|
DOCKER_API_VERSION: "1.41"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
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
|
- name: Build Docker images
|
||||||
run: docker-compose build
|
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
|
||||||
@@ -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
|
||||||
|
|||||||
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.
|
||||||
|
|
||||||
|
---
|
||||||
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;
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { AuthProvider } from '../useAuth';
|
import { AuthProvider } from '../useAuth';
|
||||||
import { useAuth } from '../useAuth';
|
import { useAuth } from '../useAuth';
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
// Test component that uses useAuth hook
|
// Test component that uses useAuth hook
|
||||||
const TestComponent = () => {
|
const TestComponent = () => {
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|
||||||
|
|||||||
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,13 +37,17 @@ 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:
|
||||||
- backend
|
- backend
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
sqlserver_data:
|
sqlserver_data:
|
||||||
Reference in New Issue
Block a user