Root cause: ffmpeg is absent in the prod worker, so vinpin.ocr cropScale silently returns the full 1600x900 frame — the tiny centered Rpartstore launch-error modal is illegible, so a DOWN Rpartstore is misread as a spinner and thrashes the seat. - Dockerfile: install ffmpeg so cropScale actually crops+3x-upscales (restores all clipped OCR: modal-crop error detect, Fiat modal, Renault header). - ensureRpartstore: gate the "already open" short-circuit on a CONTENT token (rpartstoreLoaded), not rpartstoreOpen which false-matches the flyout/title word "Rpartstore"; click the flyout entry when the submenu is up over the grid; keep a late open-window branch so a spinner/vehicle-page window still counts as present. - closeRpartstoreTab: never click windowClose(1298,14) (it hits the language selector and wedges the grid); gate the retry on a content token; Escape after. - cleanTeardown: dismiss any blocking modal BEFORE "Çıkış yap" so logout is a clean RDS log-off (not a dirty channel disconnect); recover a Disconnected dialog via disconnectedClose(953,505) + relaunch VINPIN app for a fresh grid. - Rpartstore-down cooldown (10m): a launch-error / repeated load-failure routes Renault decodes straight to Dialogys (skip reopening a down catalog); a confirmed load clears it. - ensureBrandGrid: dismiss a wedging launch-error modal + short-retry instead of burning the 84s dead-wait. - parseRenaultHeader: ignore the status-bar license-expiry date when reading the model year; sessionAlive matches RDST01/RDST02 (seat load-balances). - Keeps never-throw, VINPIN_DECODE_BUDGET_MS, sessionPoisoned, the acquire cap, spinner-guard, relogin-cap and the Fiat/Dialogys fallbacks intact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
86 lines
3.6 KiB
Docker
86 lines
3.6 KiB
Docker
# ── Stage 1: Base ──────────────────────────────────────
|
|
FROM node:22-alpine AS base
|
|
RUN corepack enable && corepack prepare pnpm@10.29.3 --activate
|
|
WORKDIR /app
|
|
|
|
# ── Stage 2: Dependencies ─────────────────────────────
|
|
FROM base AS deps
|
|
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
|
|
COPY apps/api/package.json apps/api/package.json
|
|
COPY apps/web/package.json apps/web/package.json
|
|
COPY packages/shared/package.json packages/shared/package.json
|
|
COPY packages/config/package.json packages/config/package.json
|
|
COPY packages/ui/package.json packages/ui/package.json
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
# ── Stage 3: Build ─────────────────────────────────────
|
|
FROM base AS build
|
|
COPY --from=deps /app/node_modules ./node_modules
|
|
COPY --from=deps /app/apps/api/node_modules ./apps/api/node_modules
|
|
COPY --from=deps /app/apps/web/node_modules ./apps/web/node_modules
|
|
COPY --from=deps /app/packages/shared/node_modules ./packages/shared/node_modules
|
|
COPY --from=deps /app/packages/config/node_modules ./packages/config/node_modules
|
|
COPY --from=deps /app/packages/ui/node_modules ./packages/ui/node_modules
|
|
COPY . .
|
|
|
|
# Vite env vars (baked at build time)
|
|
ARG VITE_FARO_ENABLED=false
|
|
ARG VITE_FARO_COLLECTOR_URL=
|
|
ARG VITE_POSTHOG_KEY=
|
|
ARG VITE_META_PIXEL_ID=
|
|
ARG VITE_CHATWOOT_BASE_URL=
|
|
ARG VITE_CHATWOOT_WEBSITE_TOKEN=
|
|
ARG VITE_GOOGLE_ADS_ID=
|
|
ARG VITE_GOOGLE_ADS_SIGNUP_LABEL=
|
|
|
|
RUN pnpm build
|
|
|
|
# ── Stage 4: Production ───────────────────────────────
|
|
FROM node:22-alpine AS production
|
|
|
|
# Chromium for Playwright (EMEX/PartsCatalogs). ffmpeg is required by the Vinpin
|
|
# OCR pipeline (vinpin.ocr cropScale): it crops+3x-upscales the tiny centered
|
|
# Rpartstore launch-error / decode-modal region so tesseract can read it. Without
|
|
# it cropScale silently returns the full 1600x900 frame and every clipped OCR
|
|
# degrades to an illegible full-frame 1x read (the DOWN-Rpartstore misclassify bug).
|
|
RUN apk add --no-cache chromium nss freetype harfbuzz ca-certificates ttf-freefont ffmpeg
|
|
ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium-browser
|
|
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy built artifacts
|
|
COPY --from=build /app/apps/api/dist ./apps/api/dist
|
|
COPY --from=build /app/apps/web/dist ./apps/web/dist
|
|
COPY --from=build /app/packages/shared/dist ./packages/shared/dist
|
|
COPY --from=build /app/packages/config/dist ./packages/config/dist
|
|
|
|
# Copy package files for production install
|
|
COPY --from=build /app/package.json ./
|
|
COPY --from=build /app/pnpm-lock.yaml ./
|
|
COPY --from=build /app/pnpm-workspace.yaml ./
|
|
COPY --from=build /app/apps/api/package.json ./apps/api/
|
|
COPY --from=build /app/apps/web/package.json ./apps/web/
|
|
COPY --from=build /app/packages/shared/package.json ./packages/shared/
|
|
COPY --from=build /app/packages/config/package.json ./packages/config/
|
|
COPY --from=build /app/packages/ui/package.json ./packages/ui/
|
|
|
|
# NestJS CLI config (needed for serve-static)
|
|
COPY --from=build /app/apps/api/nest-cli.json ./apps/api/
|
|
|
|
# Drizzle migrations + startup wrapper
|
|
COPY --from=build /app/apps/api/drizzle ./apps/api/drizzle
|
|
COPY --from=build /app/apps/api/start.sh ./apps/api/start.sh
|
|
|
|
# Runtime scripts (EMEX VIN scraper, etc.) loaded by EmexService via require()
|
|
COPY --from=build /app/scripts ./scripts
|
|
|
|
RUN corepack enable && corepack prepare pnpm@10.29.3 --activate \
|
|
&& pnpm install --frozen-lockfile --prod \
|
|
&& pnpm store prune
|
|
|
|
ENV NODE_ENV=production
|
|
EXPOSE 4000
|
|
|
|
CMD ["./apps/api/start.sh"]
|