From eeb0920afdd55a9110db18e2c103b32b4a62f948 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Sat, 11 Apr 2026 21:55:24 +0200 Subject: [PATCH] chore: stabilize deployment and resolve asset 404s --- .gitea/workflows/deploy.yml | 50 +++++++++++++++++++++++++++++++++++-- apps/web/next.config.mjs | 12 +++++++++ docker-compose.yml | 2 +- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 3bb19b2..235eefb 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -418,14 +418,60 @@ jobs: if: always() run: docker builder prune -f --filter "until=1h" - # (JOB 5: Post-Deploy Verification was removed to reduce pipeline noise) + # ────────────────────────────────────────────────────────────────────────────── + # JOB 5: Post-Deploy Verification + # ────────────────────────────────────────────────────────────────────────────── + post_deploy_checks: + name: 🩺 Smoke Test + needs: [prepare, deploy] + runs-on: docker + if: needs.deploy.result == 'success' + container: + image: alpine:latest + steps: + - name: 🌐 Check Production URL + shell: sh + run: | + # Wait longer (up to 2 minutes) for Next.js to fully prime + COUNT=0 + MAX=24 + URL="${{ needs.prepare.outputs.next_public_url }}" + + echo "Verifying $URL is responsive..." + while [ $COUNT -lt $MAX ]; do + STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$URL/" || echo "000") + if [ "$STATUS" = "200" ]; then + echo "✅ Site is UP (200 OK)" + break + fi + echo "⏳ Wait for 200 OK (Status: $STATUS)..." + sleep 5 + COUNT=$((COUNT + 1)) + done + + if [ "$STATUS" != "200" ]; then + echo "❌ Site failed smoke test after 2 minutes! (Status: $STATUS)" + exit 1 + fi + + - name: 🌐 Check Case Study Assets + shell: sh + run: | + URL="${{ needs.prepare.outputs.next_public_url }}/case-studies/klz-cables" + echo "Verifying case study $URL..." + STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$URL") + if [ "$STATUS" != "200" ]; then + echo "❌ Case study page failed! (Status: $STATUS)" + exit 1 + fi + echo "✅ Case study page is UP" # ────────────────────────────────────────────────────────────────────────────── # JOB 6: Notifications # ────────────────────────────────────────────────────────────────────────────── notifications: name: 🔔 Notify - needs: [prepare, deploy] + needs: [prepare, deploy, post_deploy_checks] if: always() runs-on: docker container: diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index c5e6389..db42184 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -41,6 +41,18 @@ const nextConfig = { return [ // Umami proxy rewrite handled in app/stats/api/send/route.ts // Sentry relay handled in app/errors/api/relay/route.ts + { + source: '/assets/:path*', + destination: '/showcase/klz-cables.com/assets/:path*', + }, + { + source: '/wp-content/:path*', + destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-content/:path*', + }, + { + source: '/wp-includes/:path*', + destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-includes/:path*', + }, ]; }, async redirects() { diff --git a/docker-compose.yml b/docker-compose.yml index 84e6e17..d4329dc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,7 +26,7 @@ services: - "caddy.reverse_proxy={{upstreams 3000}}" # Public Router (Whitelist for OG Images, Sitemaps, Health) - - 'traefik.http.routers.${PROJECT_NAME}-public.rule=(${TRAEFIK_HOST_RULE:-Host("${TRAEFIK_HOST:-mintel.localhost}")}) && (PathPrefix("/health") || PathPrefix("/api/health") || PathPrefix("/sitemap.xml") || PathPrefix("/robots.txt") || PathPrefix("/manifest.webmanifest") || PathPrefix("/api/og") || PathRegexp(".*opengraph-image.*") || PathRegexp(".*sitemap.*"))' + - 'traefik.http.routers.${PROJECT_NAME}-public.rule=(${TRAEFIK_HOST_RULE:-Host("${TRAEFIK_HOST:-mintel.localhost}")}) && (PathPrefix("/health") || PathPrefix("/api/health") || PathPrefix("/sitemap.xml") || PathPrefix("/robots.txt") || PathPrefix("/manifest.webmanifest") || PathPrefix("/api/og") || PathPrefix("/assets") || PathPrefix("/wp-content") || PathPrefix("/wp-includes") || PathPrefix("/showcase") || PathRegexp(".*opengraph-image.*") || PathRegexp(".*sitemap.*"))' - "traefik.http.routers.${PROJECT_NAME}-public.entrypoints=${TRAEFIK_ENTRYPOINT:-web}" - "traefik.http.routers.${PROJECT_NAME}-public.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-}" - "traefik.http.routers.${PROJECT_NAME}-public.tls=${TRAEFIK_TLS:-false}"