Compare commits

...

57 Commits

Author SHA1 Message Date
8101756638 Merge branch 'backup-ci-cd-attempts'
Some checks failed
Optimized Build and Deploy / remote-build-and-deploy (push) Failing after 1m25s
# Conflicts:
#	Backend/GestionIntegral.Api/Dockerfile
#	Backend/GestionIntegral.Api/appsettings.json
#	Frontend/Dockerfile
2025-06-26 23:21:05 -03:00
b66d00c92d Retry 2309
Some checks failed
Optimized Build and Deploy / remote-build-and-deploy (push) Failing after 1m19s
2025-06-26 23:09:33 -03:00
72c2f7ee31 Retry 2244
Some checks failed
Optimized Build and Deploy / remote-build-and-deploy (push) Failing after 1m25s
2025-06-26 22:44:44 -03:00
1456ccd723 Retry 2239
Some checks failed
Optimized Build and Deploy / remote-build-and-deploy (push) Failing after 1m40s
2025-06-26 22:39:09 -03:00
229f657685 Retry 2221
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 1m59s
2025-06-26 22:21:47 -03:00
13ab496727 Retry 2211
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 4m31s
2025-06-26 22:11:59 -03:00
5adc1e6d46 Se realiza fix y se añade depuración al deply
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 1m55s
2025-06-26 21:55:46 -03:00
1ec21741cc Retry Secret JWT Key
Some checks failed
Optimized Build and Deploy / remote-build-and-deploy (push) Failing after 4m10s
2025-06-26 21:46:57 -03:00
b33dd4f94f Cambio por host 2025-06-16 19:06:11 -03:00
ba9bef2364 Cambio de imagen kaniko 2025-06-16 18:58:49 -03:00
856d7ac5c1 Retest 2025-06-16 18:52:48 -03:00
d8dc41222c Fix yml 2025-06-16 18:50:31 -03:00
a434640456 Test con Kaniko 2025-06-16 18:44:51 -03:00
fcc2b90f15 Added: privileged: true 2025-06-16 18:28:08 -03:00
0d7614ef4c Webhook gitea Enable. 2025-06-16 18:21:59 -03:00
ae54ef3fe5 Retry 1807 2025-06-16 18:07:22 -03:00
c361842a91 Retry 1806 2025-06-16 18:06:14 -03:00
de079d8bd4 Cabio de Variable por valor directo. 2025-06-16 13:12:14 -03:00
401e61e0eb Se añade la URL del registro al nombre del repo 2025-06-16 13:02:38 -03:00
4b208793ce Todos los registros de contenedores (Docker Hub, Gitea, etc.) exigen que los nombres de las imágenes de Docker estén en minúsculas. El pipeline está intentando crear una imagen llamada dmolinari/GestionIntegralWeb-backend, pero la parte GestionIntegralWeb contiene mayúsculas.
Esto ocurre porque la variable de Drone ${DRONE_REPO_NAME} toma el nombre directamente de Gitea, que en este caso es GestionIntegralWeb. La sintaxis es: ${VARIABLE,,}.
2025-06-16 12:57:22 -03:00
d60dd8dc9f Linter: duplicate step name 2025-06-16 12:49:35 -03:00
8156df9f90 Fix indentación. Y Trusted en Drone. 2025-06-16 12:48:22 -03:00
55ca8bffa7 Prueba: Usar el Socket de Docker del Host 2025-06-16 12:41:32 -03:00
02265a46e7 Cambio de enfoque. Parametro para MTU (Maximum Transmission Unit) añadidos. 2025-06-16 12:18:21 -03:00
767cd081dc Se agregan daemon_dns para poder resolver los dominios de nuget desde los contenedores de despliegue. 2025-06-16 12:05:49 -03:00
97b6a9241f Se agregan debug-network para verificar valores. 2025-06-16 11:57:42 -03:00
b68ac1fed1 Test Webhook 2025-06-16 03:07:17 -03:00
2e83c2e373 Retry 0142 2025-06-16 01:42:57 -03:00
1e8d5fd308 Forzar la network. 2025-06-16 01:34:16 -03:00
a1dfd0d089 Fix: Configure docker plugin for insecure registry 2025-06-16 01:30:15 -03:00
eff65921e6 Nuevo test 2025-06-15 23:10:37 -03:00
b3de8dba3a Retry mil 2025-06-15 23:06:51 -03:00
f62fc4b507 Va 2025-06-15 22:57:24 -03:00
66686fc548 Retry yml 2025-06-15 22:52:26 -03:00
c0900e07e6 Fix problema de indentación. 2025-06-15 22:46:25 -03:00
a63b40471b Retry .drone.yml 2025-06-15 22:42:58 -03:00
12decefc1b Fix de yml para Drone. 2025-06-15 22:38:22 -03:00
bb79ccf64c Cambio de Enfoque para CI/CD. Se intenta uso de Drone. 2025-06-15 22:18:23 -03:00
b3e70a3988 Nuevo 2025-06-15 21:29:03 -03:00
55640c394f A ver... 2025-06-15 21:15:41 -03:00
338cd8579f Final? 2025-06-15 19:46:31 -03:00
69620c5607 Este 2025-06-15 19:40:15 -03:00
8ba18ed687 Va 2025-06-15 19:18:13 -03:00
30570beaca Reversion 1.24.0 2025-06-15 19:00:31 -03:00
db10fa0254 Test con Gitea 1.21.11 2025-06-15 12:16:46 -03:00
1d664672b2 No puede resolver gitea. Debe usar el secreto REGISTRY_URL. 2025-06-15 11:28:46 -03:00
969c78a567 Sin sh-runner. 2025-06-15 11:22:02 -03:00
0b884197fb Reversión antes de cambio de foco. 2025-06-15 11:19:21 -03:00
0d2c30ad94 Test con sh-runner 2025-06-15 11:01:10 -03:00
f1591bd572 Reversión 3 2025-06-15 10:39:12 -03:00
24e4769f78 Fix 2025-06-15 10:32:18 -03:00
76d48cc310 Reversión 2. 2025-06-15 10:26:55 -03:00
b072e31385 Nuevo testeo de CI/CD. 2025-06-15 04:06:27 -03:00
65be2bcbaa Reversión. 2025-06-14 23:45:47 -03:00
0fb3cb7aef Reseteo de estado por fallas del deply. 2025-06-14 23:13:05 -03:00
541625bf66 fix: Run jobs on runner host to resolve network issues 2025-06-14 23:01:28 -03:00
cbe313b59d Ajustes de CI/CD. 2025-06-14 22:11:02 -03:00
6 changed files with 142 additions and 23 deletions

82
.drone.yml Normal file
View File

@@ -0,0 +1,82 @@
kind: pipeline
type: docker
name: Build y Deploy
trigger:
branch:
- main
event:
- push
steps:
- name: build-and-publish-backend
image: plugins/kaniko
settings:
repo: host.docker.internal:5000/${DRONE_REPO_OWNER}/${DRONE_REPO_NAME,,}-backend
tags:
- latest
- ${DRONE_COMMIT_SHA:0:8}
dockerfile: Backend/GestionIntegral.Api/Dockerfile
context: .
username:
from_secret: GITEA_USER
password:
from_secret: ACTIONS_PAT
insecure: true
- name: build-and-publish-frontend
image: plugins/kaniko
settings:
repo: host.docker.internal:5000/${DRONE_REPO_OWNER}/${DRONE_REPO_NAME,,}-frontend
tags:
- latest
- ${DRONE_COMMIT_SHA:0:8}
dockerfile: Frontend/Dockerfile
context: .
username:
from_secret: GITEA_USER
password:
from_secret: ACTIONS_PAT
insecure: true
depends_on:
- build-and-publish-backend
- name: deploy-to-production
image: alpine:latest
environment:
SSH_KEY:
from_secret: PROD_SERVER_SSH_KEY
PROD_HOST:
from_secret: PROD_SERVER_HOST
PROD_USER:
from_secret: PROD_SERVER_USER
DB_PASSWORD:
from_secret: DB_SA_PASSWORD_SECRET
JWT_KEY:
from_secret: JWT_KEY_SECRET
REGISTRY:
from_secret: REGISTRY_URL
GITEA_USER:
from_secret: GITEA_USER
GITEA_PAT:
from_secret: ACTIONS_PAT
commands:
- apk add --no-cache openssh-client
- mkdir -p ~/.ssh
- echo "$SSH_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H $PROD_HOST >> ~/.ssh/known_hosts
- |
ssh $PROD_USER@$PROD_HOST << 'EOF'
echo "--- CONECTADO AL SERVIDOR DE PRODUCCIÓN ---"
cd /opt/gestion-integral
export DB_SA_PASSWORD="${DB_PASSWORD}"
export JWT_KEY="${JWT_KEY}"
docker login ${REGISTRY} -u ${GITEA_USER} -p ${GITEA_PAT}
docker compose pull
docker compose up -d
docker image prune -af
echo "--- DESPLIEGUE COMPLETADO ---"
EOF
depends_on:
- build-and-publish-frontend

View File

@@ -26,7 +26,7 @@ jobs:
set -e
echo "--- INICIO DEL DESPLIEGUE OPTIMIZADO ---"
# 1. Preparar entorno
# 1. Preparar entorno (sin cambios)
TEMP_DIR=$(mktemp -d)
REPO_OWNER="dmolinari"
REPO_NAME="gestionintegralweb"
@@ -37,7 +37,7 @@ jobs:
cd "$TEMP_DIR"
git checkout "${{ gitea.sha }}"
# 2. Construcción paralela con Docker nativo (más rápido y fiable)
# 2. Construcción paralela (sin cambios)
build_image() {
local dockerfile=$1
local image_name=$2
@@ -55,18 +55,31 @@ jobs:
(build_image "Frontend/Dockerfile" "dmolinari/gestionintegralweb-frontend:latest" ".") &
wait
# 3. Despliegue con Docker Compose
cd /opt/gestion-integral
export DB_SA_PASSWORD='${{ secrets.DB_SA_PASSWORD_SECRET }}'
# Copiamos la versión actualizada del docker-compose.yml al directorio de despliegue.
echo "Copiando el archivo docker-compose.yml actualizado..."
cp "$TEMP_DIR/docker-compose.yml" /opt/gestion-integral/docker-compose.yml
echo "Recreando servicios..."
docker compose up -d --force-recreate
# (Opcional pero recomendado) Verificamos que el archivo se copió bien
echo "--- Verificando contenido del docker-compose.yml que se usará ---"
cat /opt/gestion-integral/docker-compose.yml | head -n 5
echo "------------------------------------------------------------------"
# 4. Limpieza
# 3. Crear/Actualizar los Docker Secrets (sin cambios)
# ... (tus comandos docker secret create) ...
printf "%s" '${{ secrets.JWT_KEY }}' | docker secret create jwt_key - 2>/dev/null || (printf "%s" '${{ secrets.JWT_KEY }}' | docker secret rm jwt_key && printf "%s" '${{ secrets.JWT_KEY }}' | docker secret create jwt_key -)
printf "%s" '${{ secrets.DB_SA_PASSWORD_SECRET }}' | docker secret create db_password - 2>/dev/null || (printf "%s" '${{ secrets.DB_SA_PASSWORD_SECRET }}' | docker secret rm db_password && printf "%s" '${{ secrets.DB_SA_PASSWORD_SECRET }}' | docker secret create db_password -)
# 4. Desplegar el Stack
echo "Desplegando el stack..."
docker stack deploy \
-c /opt/gestion-integral/docker-compose.yml \
--with-registry-auth \
gestion-integral
# 5. Limpieza (sin cambios)
echo "Realizando limpieza..."
rm -rf "$TEMP_DIR"
docker image prune -af --filter "until=24h"
echo "--- DESPLIEGUE COMPLETADO CON ÉXITO ---"
echo "Tiempo total: $(($SECONDS / 60)) minutos y $(($SECONDS % 60)) segundos"
EOSSH

View File

@@ -1,29 +1,37 @@
# --- Etapa 1: Build ---
# Usamos el SDK de .NET 9 (o el que corresponda) para compilar.
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
# Copia solo los archivos de proyecto primero para cachear dependencias
# Copiamos los archivos de proyecto (.sln y .csproj) y restauramos las dependencias.
# Esto es una optimización de caché de Docker.
COPY GestionIntegralWeb.sln .
COPY Backend/GestionIntegral.Api/GestionIntegral.Api.csproj Backend/GestionIntegral.Api/
# Restaura dependencias
# Restauramos los paquetes NuGet.
RUN dotnet restore "GestionIntegralWeb.sln"
# Copia el resto del código
# Copiamos todo el resto del código fuente.
COPY . .
# Construye el proyecto
# Nos movemos al directorio del proyecto y lo construimos en modo Release.
WORKDIR "/src/Backend/GestionIntegral.Api"
RUN dotnet build "GestionIntegral.Api.csproj" -c Release -o /app/build
# --- Etapa 2: Publish ---
# Publicamos la aplicación, lo que genera los artefactos listos para producción.
FROM build AS publish
RUN dotnet publish "GestionIntegral.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false
# --- Etapa 3: Final ---
# Usamos la imagen de runtime de ASP.NET, que es mucho más ligera que el SDK.
FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY --from=publish /app/publish .
# El puerto en el que la API escuchará DENTRO del contenedor.
# Usaremos 8080 para evitar conflictos si en el futuro corres algo en el puerto 80.
EXPOSE 8080
# El comando para iniciar la API cuando el contenedor arranque.
ENTRYPOINT ["dotnet", "GestionIntegral.Api.dll"]

View File

@@ -112,9 +112,18 @@ builder.Services.AddHealthChecks()
// --- Configuración de Autenticación JWT ---
var jwtSettings = builder.Configuration.GetSection("Jwt");
// Lee la RUTA al archivo del secreto desde la variable de entorno
var jwtKeyFilePath = builder.Configuration["JWT_KEY_FILE"];
// Si la ruta existe (estamos en Docker Swarm), lee el contenido del archivo.
// Si no, vuelve a buscar la variable de entorno (para desarrollo local).
var jwtKey = !string.IsNullOrEmpty(jwtKeyFilePath) && File.Exists(jwtKeyFilePath)
? File.ReadAllText(jwtKeyFilePath).Trim()
: builder.Configuration["JWT_KEY"] ?? throw new ArgumentNullException("JWT Key not configured");
// Le decimos que busque la clave JWT en la raíz de la configuración (donde están las variables de entorno).
// Si no la encuentra, como respaldo, busca en la sección "Jwt" del appsettings.
var jwtKey = builder.Configuration["JWT_KEY"] ?? jwtSettings["Key"] ?? throw new ArgumentNullException("JWT_KEY or Jwt:Key not configured");
//var jwtKey = builder.Configuration["JWT_KEY"] ?? /*jwtSettings["Key"] ??*/ throw new ArgumentNullException("JWT_KEY or Jwt:Key not configured");
var keyBytes = Encoding.ASCII.GetBytes(jwtKey);

View File

@@ -6,7 +6,7 @@
}
},
"Jwt": {
"Key": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2",
"Key": "",
"Issuer": "GestionIntegralApi",
"Audience": "GestionIntegralClient",
"DurationInHours": 8

View File

@@ -1,24 +1,31 @@
# --- Etapa 1: Build ---
# Usamos una imagen de Node.js para construir los archivos estáticos de React.
FROM node:20-alpine AS build
WORKDIR /app
# Copia solo dependencias primero para cachear
COPY Frontend/package.json Frontend/package-lock.json ./
RUN npm install --frozen-lockfile
# Copiamos los archivos de dependencias y las instalamos.
COPY package.json package-lock.json ./
RUN npm install
# Copia el resto del código
COPY Frontend/. .
# Copiamos el resto del código del frontend.
COPY . .
# Construye la aplicación
# Ejecutamos el script de build de Vite, que genera la carpeta 'dist'.
RUN npm run build
# --- Etapa 2: Serve ---
# Usamos una imagen de Nginx súper ligera para servir los archivos estáticos.
FROM nginx:stable-alpine
COPY Frontend/nginx.conf /etc/nginx/conf.d/default.conf
WORKDIR /usr/share/nginx/html
# Eliminamos el index.html por defecto de Nginx.
RUN rm -f index.html
# Copiamos los archivos construidos desde la etapa anterior a la carpeta que Nginx sirve.
COPY --from=build /app/dist .
# Nginx por defecto escucha en el puerto 80, así que lo exponemos.
EXPOSE 80
# Comando para iniciar Nginx. Esto asegura que se mantenga corriendo.
CMD ["nginx", "-g", "daemon off;"]