fix(emex): ship runtime scripts/ in prod image and forward chromium executable path
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
EMEX-decoded vehicles surfaced empty category pages on prod because two runtime prerequisites were absent from the production image: 1. `scripts/emex-vin-scraper.js` was never copied — the build stage's `COPY . .` brings it in but the production stage only cherry-picks `apps/api/dist`, `drizzle`, and `start.sh`. Every EMEX leaf hit therefore failed with "Scraper file not found at: /app/scripts/…" and the category page rendered "Bu kategori icin parca bulunamadi." 2. `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium-browser` was exported in the Dockerfile but never reached `chromium.launch()` — that env var is consumed by `playwright install`, not at runtime. Playwright fell back to its bundled headless-shell cache path (`/root/.cache/ms-playwright/chromium_headless_shell-*/…`) which does not exist on the alpine image, so even with the scraper file present the browser pool init would have kept failing. Fix: - Dockerfile: `COPY --from=build /app/scripts ./scripts`. - `emex.browser.ts` + `parts-catalogs-auth.service.ts`: read `process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` and pass it as `executablePath` to `chromium.launch()` when set. Verified on prod container: `ls /app/scripts` → missing pre-fix; the binary at `/usr/bin/chromium-browser` exists, so the env-var hand-off will resolve cleanly once the new image lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -165,6 +165,12 @@ export class EmexBrowserService implements OnModuleInit, OnModuleDestroy {
|
||||
// Dynamic import — playwright is a devDependency
|
||||
const { chromium } = await import("playwright");
|
||||
|
||||
// PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH only influences `playwright install`;
|
||||
// chromium.launch() at runtime ignores it unless we forward it explicitly.
|
||||
// Alpine images don't ship the bundled chromium-headless-shell that
|
||||
// Playwright otherwise looks for under /root/.cache/ms-playwright/, so
|
||||
// without this hand-off the production container fails with
|
||||
// "Executable doesn't exist at …chrome-headless-shell".
|
||||
const launchOptions: Record<string, unknown> = {
|
||||
headless: true,
|
||||
args: [
|
||||
@@ -175,6 +181,8 @@ export class EmexBrowserService implements OnModuleInit, OnModuleDestroy {
|
||||
"--disable-gpu",
|
||||
],
|
||||
};
|
||||
const executablePath = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH;
|
||||
if (executablePath) launchOptions.executablePath = executablePath;
|
||||
|
||||
if (this.useProxy) {
|
||||
const port = this.randomProxyPort();
|
||||
|
||||
@@ -615,7 +615,10 @@ export class PartsCatalogsAuthService implements OnModuleInit, OnModuleDestroy {
|
||||
private async _doLaunch(): Promise<void> {
|
||||
const { chromium } = await import("playwright");
|
||||
|
||||
this.browser = await chromium.launch({
|
||||
// See emex.browser.ts:_doLaunch — PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH is
|
||||
// a `playwright install` knob, not a launch knob, so forward it manually
|
||||
// for Alpine production where the bundled headless shell isn't installed.
|
||||
const launchOptions: Record<string, unknown> = {
|
||||
headless: true,
|
||||
args: [
|
||||
"--no-sandbox",
|
||||
@@ -624,7 +627,11 @@ export class PartsCatalogsAuthService implements OnModuleInit, OnModuleDestroy {
|
||||
"--disable-accelerated-2d-canvas",
|
||||
"--disable-gpu",
|
||||
],
|
||||
});
|
||||
};
|
||||
const executablePath = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH;
|
||||
if (executablePath) launchOptions.executablePath = executablePath;
|
||||
|
||||
this.browser = await chromium.launch(launchOptions);
|
||||
|
||||
this.browser.on("disconnected", () => {
|
||||
this.logger.warn("Browser disconnected — will relaunch on next request");
|
||||
|
||||
Reference in New Issue
Block a user