@reddoorla/maintenance 0.10.4 → 0.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -397,6 +397,32 @@ async function readSiteConfig(sitePath) {
397
397
  return out;
398
398
  }
399
399
 
400
+ // src/util/free-port.ts
401
+ import { createServer } from "net";
402
+ async function findFreePort() {
403
+ return new Promise((resolve, reject) => {
404
+ const server = createServer();
405
+ server.unref();
406
+ server.on("error", reject);
407
+ server.listen(0, "127.0.0.1", () => {
408
+ const addr = server.address();
409
+ if (typeof addr === "object" && addr) {
410
+ const port = addr.port;
411
+ server.close(() => resolve(port));
412
+ } else {
413
+ server.close();
414
+ reject(new Error("findFreePort: could not determine assigned port from socket"));
415
+ }
416
+ });
417
+ });
418
+ }
419
+ function withFreePort(url, port) {
420
+ const u = new URL(url);
421
+ u.hostname = "localhost";
422
+ u.port = String(port);
423
+ return u.toString();
424
+ }
425
+
400
426
  // src/audits/lighthouse.ts
401
427
  async function readJsonMaybe(path) {
402
428
  try {
@@ -437,13 +463,19 @@ async function lighthouseAudit(ctx) {
437
463
  const site = ctx.site;
438
464
  const label = siteLabel(site);
439
465
  const siteCfg = await readSiteConfig(site.path);
440
- const resolvedConfig = siteCfg.lighthouseUrl ? {
466
+ const port = await findFreePort();
467
+ const baseUrl = siteCfg.lighthouseUrl ?? lighthouseConfig.ci.collect.url[0];
468
+ const resolvedConfig = {
441
469
  ...lighthouseConfig,
442
470
  ci: {
443
471
  ...lighthouseConfig.ci,
444
- collect: { ...lighthouseConfig.ci.collect, url: [siteCfg.lighthouseUrl] }
472
+ collect: {
473
+ ...lighthouseConfig.ci.collect,
474
+ url: [withFreePort(baseUrl, port)],
475
+ startServerCommand: `npm run vite:dev -- --port ${port} --strictPort`
476
+ }
445
477
  }
446
- } : lighthouseConfig;
478
+ };
447
479
  const configDir = await mkdtemp(join4(tmpdir(), "reddoor-lhci-"));
448
480
  const configPath = join4(configDir, "lighthouserc.json");
449
481
  await writeFile(configPath, JSON.stringify(resolvedConfig), "utf-8");
@@ -554,6 +586,32 @@ async function readJsonMaybe2(path) {
554
586
  return null;
555
587
  }
556
588
  }
589
+ function buildPlaywrightConfig(port) {
590
+ return `import { defineConfig } from "@playwright/test";
591
+
592
+ export default defineConfig({
593
+ testDir: ".",
594
+ testMatch: /.*\\.spec\\.ts$/,
595
+ fullyParallel: true,
596
+ forbidOnly: !!process.env.CI,
597
+ retries: process.env.CI ? 2 : 0,
598
+ reporter: process.env.CI ? "github" : "list",
599
+ use: {
600
+ baseURL: "http://localhost:${port}",
601
+ trace: "on-first-retry",
602
+ },
603
+ webServer: {
604
+ // --strictPort: refuse to bump to a different port if ours is taken,
605
+ // so the audit fails loudly instead of probing a zombie.
606
+ // reuseExistingServer:false: never reuse \u2014 we control the lifecycle.
607
+ command: "npm run vite:dev -- --port ${port} --strictPort",
608
+ url: "http://localhost:${port}/dev/a11y-fixtures",
609
+ reuseExistingServer: false,
610
+ timeout: 120_000,
611
+ },
612
+ });
613
+ `;
614
+ }
557
615
  function buildSpec() {
558
616
  return `import { test, expect } from "@playwright/test";
559
617
  import AxeBuilder from "@axe-core/playwright";
@@ -607,19 +665,26 @@ async function a11yAudit(ctx) {
607
665
  const specDir = await mkdtemp2(join5(tmpdir2(), "reddoor-a11y-spec-"));
608
666
  const specPath = join5(specDir, "a11y.spec.ts");
609
667
  await writeFile2(specPath, buildSpec(), "utf-8");
668
+ const port = await findFreePort();
669
+ const configPath = join5(specDir, "playwright.config.ts");
670
+ await writeFile2(configPath, buildPlaywrightConfig(port), "utf-8");
610
671
  const resultsPath = join5(site.path, RESULTS_REL);
611
672
  await rm2(join5(site.path, ".reddoor-a11y"), { recursive: true, force: true });
612
673
  let raw;
613
674
  try {
614
- raw = await spawn2("npx", ["--yes", "playwright", "test", "--reporter=line", specPath], {
615
- cwd: site.path,
616
- env: { ...process.env, REDDOOR_A11Y_OUTPUT: resultsPath },
617
- // playwright on a cold tree downloads Chrome, boots the site's dev
618
- // server, and runs axe over every configured route. The shared 30 s
619
- // default in runAudits is fine for deps/lint/security but starves
620
- // playwright (mirrors the lighthouse fix shipped earlier).
621
- timeoutMs: 5 * 6e4
622
- });
675
+ raw = await spawn2(
676
+ "npx",
677
+ ["--yes", "playwright", "test", `--config=${configPath}`, "--reporter=line", specPath],
678
+ {
679
+ cwd: site.path,
680
+ env: { ...process.env, REDDOOR_A11Y_OUTPUT: resultsPath },
681
+ // playwright on a cold tree downloads Chrome, boots the site's dev
682
+ // server, and runs axe over every configured route. The shared 30 s
683
+ // default in runAudits is fine for deps/lint/security but starves
684
+ // playwright (mirrors the lighthouse fix shipped earlier).
685
+ timeoutMs: 5 * 6e4
686
+ }
687
+ );
623
688
  } catch (err) {
624
689
  await rm2(specDir, { recursive: true, force: true });
625
690
  const e = err;