diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..efde022 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,54 @@ +name: deploy-analiticaNucleo + +on: + push: + branches: [ master ] + +jobs: + #───────────────── deploy ───────────────── + deploy: + runs-on: docker + env: + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }} + steps: + - uses: actions/checkout@v3 + + - name: Create .env file from secrets + run: | + cat > .env << EOF + SUPABASE_URL=${{ secrets.SUPABASE_URL }} + SUPABASE_ANON_KEY=${{ secrets.SUPABASE_ANON_KEY }} + EOF + + - name: Ensure external docker network exists + run: | + docker network inspect principal >/dev/null 2>&1 || docker network create principal + + - name: Stop existing analiticaNucleo stack + run: docker compose -f docker-compose.yml --project-name analiticaNucleo down || true + + - name: Pull latest images (if any) + run: docker compose -f docker-compose.yml pull || true + + - name: Build and start analiticaNucleo stack + run: docker compose -f docker-compose.yml --project-name analiticaNucleo up -d --build --remove-orphans + + - name: Wait for service to be ready + run: | + echo "Waiting for Nuxt app to start..." + sleep 10 + docker compose -f docker-compose.yml --project-name analiticaNucleo logs --tail=30 nuxt-app + + - name: Show service status + run: docker compose -f docker-compose.yml --project-name analiticaNucleo ps + + - name: Show recent logs + run: docker compose -f docker-compose.yml --project-name analiticaNucleo logs --tail=50 + + - name: Test service health + run: | + echo "Checking container health..." + CID=$(docker compose -f docker-compose.yml --project-name analiticaNucleo ps -q nuxt-app) + echo "Container: $CID" + docker inspect "$CID" --format '{{.State.Status}}' || true diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5cc72d6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +# Build stage +FROM node:22-alpine AS builder + +WORKDIR /app + +# Copy package files +COPY nuxt4-app/package*.json ./ + +# Install dependencies +RUN npm ci --prefer-offline --no-audit + +# Copy app source +COPY nuxt4-app/ ./ + +# Build the application +RUN npm run build + +# Production stage +FROM node:22-alpine + +WORKDIR /app + +# Copy built application from builder +COPY --from=builder /app/.output /app/.output + +# Expose port (internal, no published externally) +EXPOSE 3000 + +ENV NODE_ENV=production +ENV HOST=0.0.0.0 +ENV PORT=3000 + +# Start the application +CMD ["node", ".output/server/index.mjs"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ae1764a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +version: '3.8' + +services: + nuxt-app: + build: + context: . + dockerfile: Dockerfile + container_name: analiticaNucleo-nuxt-app + restart: unless-stopped + environment: + - NODE_ENV=production + - SUPABASE_URL=${SUPABASE_URL} + - SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY} + - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL} + - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY} + networks: + - principal + labels: + - "traefik.enable=true" + - "traefik.http.routers.analiticaNucleo.rule=Host(`analitica.nucleoriofrio.com`)" + - "traefik.http.routers.analiticaNucleo.entrypoints=websecure" + - "traefik.http.routers.analiticaNucleo.tls=true" + - "traefik.http.routers.analiticaNucleo.tls.certresolver=letsencrypt" + - "traefik.http.services.analiticaNucleo.loadbalancer.server.port=3000" + - "traefik.docker.network=principal" + +networks: + principal: + external: true diff --git a/nuxt4-app/app/components/DateRangeSelector.vue b/nuxt4-app/app/components/DateRangeSelector.vue index 9ed89b7..6930921 100644 --- a/nuxt4-app/app/components/DateRangeSelector.vue +++ b/nuxt4-app/app/components/DateRangeSelector.vue @@ -26,11 +26,11 @@
- +
- +
@@ -138,7 +138,7 @@ function setToday() { // Watch para aplicar el preset cuando cambia (incluyendo el valor inicial) watch(() => props.selectedPreset, (newPreset) => { - if (newPreset && newPreset !== 'custom' && newPreset !== '') { + if (newPreset !== '' && newPreset !== 'custom') { selectPreset(newPreset) } }, { immediate: true }) diff --git a/nuxt4-app/app/components/MetadatosCard.vue b/nuxt4-app/app/components/MetadatosCard.vue index c57c33a..0bea18e 100644 --- a/nuxt4-app/app/components/MetadatosCard.vue +++ b/nuxt4-app/app/components/MetadatosCard.vue @@ -6,7 +6,7 @@ compact && tableStore?.isStale ? 'bg-yellow-500/10 border-l-4 !border-l-yellow-500' : '' ]" @click="toggleCompact" - :ui="compact ? { body: { padding: '0' }, header: { padding: 'px-3 py-2' }, footer: { padding: '0' } } : {}" + :ui="compact ? { body: 'p-0', header: 'px-3 py-2', footer: 'p-0' } : {}" >