Merge branch 'development' into feature/bitacora-filtros-alineacion
This commit is contained in:
@@ -8,8 +8,6 @@ RUN apk update && apk add --no-cache ca-certificates wget && update-ca-certifica
|
||||
# Copiar package files
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
|
||||
|
||||
|
||||
# Instalar pnpm
|
||||
RUN npm config set strict-ssl false
|
||||
RUN npm install -g pnpm
|
||||
@@ -17,6 +15,10 @@ RUN npm install -g pnpm
|
||||
# Instalar dependencias
|
||||
RUN pnpm install
|
||||
|
||||
# Entrypoint (espera API backend en dev; no montar desde el host)
|
||||
COPY docker-entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
# Copiar código
|
||||
COPY . .
|
||||
|
||||
@@ -26,5 +28,7 @@ COPY . .
|
||||
# Exponer puerto
|
||||
EXPOSE 5173
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
# Comando por defecto (desarrollo)
|
||||
CMD ["pnpm", "run", "dev", "--", "--host", "0.0.0.0"]
|
||||
|
||||
@@ -39,6 +39,8 @@ FROM node:22-alpine AS runtime
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache wget
|
||||
|
||||
RUN npm config set strict-ssl false && \
|
||||
npm install -g pnpm
|
||||
|
||||
@@ -46,6 +48,9 @@ RUN npm config set strict-ssl false && \
|
||||
RUN addgroup -g 1001 -S nodejs
|
||||
RUN adduser -S svelte -u 1001
|
||||
|
||||
COPY docker-entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
# Copiar solo archivos necesarios para producción y aplicar propietario en la copia
|
||||
COPY --from=build --chown=svelte:nodejs /app/build ./build
|
||||
COPY --from=build --chown=svelte:nodejs /app/package.json ./
|
||||
@@ -65,5 +70,7 @@ ENV HOST=0.0.0.0
|
||||
# pero necesitamos valores por defecto para el build
|
||||
ENV INTERNAL_API_URL=http://backend:8000/api/
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
# Ejecutar aplicación con Node.js
|
||||
CMD ["pnpm", "start"]
|
||||
|
||||
44
frontend/docker-entrypoint.sh
Normal file
44
frontend/docker-entrypoint.sh
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Arranque del contenedor: opcionalmente espera al health del backend, luego ejecuta CMD (pnpm dev / start, …)
|
||||
|
||||
wait_for_backend() {
|
||||
local url=$1
|
||||
local max_attempts=30
|
||||
local attempt=1
|
||||
|
||||
echo "Esperando a que el backend esté disponible en ${url}..."
|
||||
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
# NOTA: usar la URL tal cual la pasa el caller. Antes esta función agregaba
|
||||
# un "/health" extra al final (resultando en /api/health/health → 404), lo
|
||||
# que provocaba que el entrypoint esperara 30 intentos en vano antes de
|
||||
# arrancar Vite, sumando ~90 s muertos al arranque del frontend.
|
||||
if wget -q -O /dev/null "${url}" 2>/dev/null; then
|
||||
echo "✓ Backend está listo"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Backend no está listo aún... (intento $attempt/$max_attempts)"
|
||||
attempt=$((attempt + 1))
|
||||
sleep 3
|
||||
done
|
||||
|
||||
echo "⚠ WARNING: Backend no estuvo disponible, continuando de todas formas"
|
||||
return 0
|
||||
}
|
||||
|
||||
# compose usa INTERNAL_API_URL; alias opcional BACKEND_INTERNAL_URL
|
||||
_api_base="${INTERNAL_API_URL:-${BACKEND_INTERNAL_URL:-http://backend:8000/api}}"
|
||||
_api_base="${_api_base%/}"
|
||||
wait_for_backend "${_api_base}/health"
|
||||
|
||||
# En desarrollo (volumen montado) reinstala deps si cambia package.json
|
||||
if [ "$NODE_ENV" = "development" ]; then
|
||||
echo "Instalando dependencias (development)..."
|
||||
CI=true pnpm install
|
||||
fi
|
||||
|
||||
echo "Iniciando: $*"
|
||||
exec "$@"
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineConfig } from '@playwright/test';
|
||||
import { fileURLToPath } from 'url';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
@@ -13,7 +13,7 @@ export default defineConfig({
|
||||
forbidOnly: inCI,
|
||||
timeout: 60000,
|
||||
use: {
|
||||
baseURL: 'http://localhost:5173',
|
||||
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'http://localhost:5173',
|
||||
// Sin display en agentes de integración: obligatorio headless
|
||||
headless: inCI ? true : false
|
||||
},
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
|
||||
describe('backend — health check', () => {
|
||||
// Solo en entorno con DNS `backend` (p. ej. red Docker) y con backend levantado; en Jenkins/CI se omite.
|
||||
const skipHttpIntegration = process.env.CI === 'true' || Boolean(process.env.JENKINS_URL)
|
||||
|
||||
describe.skipIf(skipHttpIntegration)('backend — health check', () => {
|
||||
|
||||
it('el backend esta corriendo y responde', async () => {
|
||||
const response = await fetch('http://backend:8000/api/health')
|
||||
|
||||
@@ -19,8 +19,9 @@ describe('getBackendAssetUrl', () => {
|
||||
expect(getBackendAssetUrl('/api/v1/items', 'http://localhost:8000/api')).toBe('http://localhost:8000/api/v1/items')
|
||||
})
|
||||
|
||||
it('construye URL completa para ruta normal', () => {
|
||||
expect(getBackendAssetUrl('/uploads/file.png', 'http://localhost:8000/api')).toBe('http://localhost:8000/api/uploads/file.png')
|
||||
})
|
||||
it('construye URL completa para ruta relativa (VITE_API_URL por defecto host:8000)', () => {
|
||||
// getBackendAssetUrl solo acepta path; la base sale de VITE o fallback http://localhost:8000
|
||||
expect(getBackendAssetUrl('/uploads/file.png')).toBe('http://localhost:8000/uploads/file.png')
|
||||
})
|
||||
|
||||
})
|
||||
@@ -11,7 +11,25 @@
|
||||
"strict": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowArbitraryExtensions": true
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"playwright.config.ts",
|
||||
"e2e/**/*.ts",
|
||||
"e2e/**/*.js",
|
||||
"vitest-setup-client.ts",
|
||||
"eslint.config.js",
|
||||
"./.svelte-kit/ambient.d.ts",
|
||||
"./.svelte-kit/non-ambient.d.ts",
|
||||
"./.svelte-kit/types/**/$types.d.ts",
|
||||
"./src/**/*.js",
|
||||
"./src/**/*.ts",
|
||||
"./src/**/*.svelte",
|
||||
"./tests/**/*.js",
|
||||
"./tests/**/*.ts",
|
||||
"./tests/**/*.svelte",
|
||||
"./vite.config.js",
|
||||
"./vite.config.ts"
|
||||
]
|
||||
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
||||
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
||||
//
|
||||
|
||||
@@ -3,12 +3,51 @@ import tailwindcss from '@tailwindcss/vite';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
|
||||
/* En CI, por defecto solo Node (evita Chromium). Con JENKINS_VITEST_FULL=1 o VITEST_FULL=1, también @vitest/browser. */
|
||||
const inCi = process.env.CI === 'true' || Boolean(process.env.JENKINS_URL);
|
||||
const vitestFull =
|
||||
process.env.VITEST_FULL === '1' || process.env.JENKINS_VITEST_FULL === '1';
|
||||
const skipBrowser = process.env.VITEST_NO_BROWSER === '1';
|
||||
const vitestNoBrowser = (inCi && !vitestFull) || skipBrowser;
|
||||
|
||||
const vitestServerProject = {
|
||||
extends: './vite.config.ts',
|
||||
test: {
|
||||
name: 'server' as const,
|
||||
environment: 'node' as const,
|
||||
include: ['src/**/*.{test,spec}.{js,ts}'],
|
||||
exclude: ['src/**/*.svelte.{test,spec}.{js,ts}'],
|
||||
},
|
||||
};
|
||||
|
||||
const vitestClientProject = {
|
||||
extends: './vite.config.ts',
|
||||
test: {
|
||||
name: 'client' as const,
|
||||
environment: 'browser' as const,
|
||||
browser: {
|
||||
enabled: true,
|
||||
provider: 'playwright' as const,
|
||||
instances: [{ browser: 'chromium' as const }],
|
||||
},
|
||||
include: ['src/**/*.svelte.{test,spec}.{js,ts}'],
|
||||
exclude: ['src/lib/server/**'],
|
||||
setupFiles: ['./vitest-setup-client.ts'],
|
||||
},
|
||||
};
|
||||
|
||||
export default defineConfig({
|
||||
server: {
|
||||
port: 5173, // fija el puerto
|
||||
host: true, // escucha en 0.0.0.0
|
||||
allowedHosts: [
|
||||
'anexo76-dev.aduanasoft.com',
|
||||
// Requeridos para dev local, healthcheck del contenedor y E2E (Playwright
|
||||
// con --network host apunta a 127.0.0.1:5173). Al definir allowedHosts,
|
||||
// Vite 5.1+ reemplaza el default ['.localhost'] y bloquea todo lo que no
|
||||
// esté aquí, devolviendo 403 "Blocked request".
|
||||
'127.0.0.1',
|
||||
'localhost',
|
||||
// 'otro-host.com' si necesitas más
|
||||
],
|
||||
proxy: {
|
||||
@@ -28,31 +67,8 @@ export default defineConfig({
|
||||
],
|
||||
test: {
|
||||
expect: { requireAssertions: true },
|
||||
projects: [
|
||||
{
|
||||
extends: './vite.config.ts',
|
||||
test: {
|
||||
name: 'client',
|
||||
environment: 'browser',
|
||||
browser: {
|
||||
enabled: true,
|
||||
provider: 'playwright',
|
||||
instances: [{ browser: 'chromium' }]
|
||||
},
|
||||
include: ['src/**/*.svelte.{test,spec}.{js,ts}'],
|
||||
exclude: ['src/lib/server/**'],
|
||||
setupFiles: ['./vitest-setup-client.ts']
|
||||
}
|
||||
},
|
||||
{
|
||||
extends: './vite.config.ts',
|
||||
test: {
|
||||
name: 'server',
|
||||
environment: 'node',
|
||||
include: ['src/**/*.{test,spec}.{js,ts}'],
|
||||
exclude: ['src/**/*.svelte.{test,spec}.{js,ts}']
|
||||
}
|
||||
}
|
||||
]
|
||||
projects: vitestNoBrowser
|
||||
? [vitestServerProject]
|
||||
: [vitestClientProject, vitestServerProject]
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user