@cleartrip/frontguard 0.2.5 → 0.2.6

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/cli.js CHANGED
@@ -7,9 +7,10 @@ import { WriteStream } from 'tty';
7
7
  import path5, { sep, normalize, delimiter, resolve, dirname } from 'path';
8
8
  import fs from 'fs/promises';
9
9
  import { pathToFileURL, fileURLToPath } from 'url';
10
- import { execFileSync, spawn } from 'child_process';
10
+ import { tmpdir } from 'os';
11
+ import fs2, { existsSync, statSync, readFileSync } from 'fs';
12
+ import { spawn, execFileSync } from 'child_process';
11
13
  import { createRequire } from 'module';
12
- import fs2 from 'fs';
13
14
  import { pipeline } from 'stream/promises';
14
15
  import { PassThrough } from 'stream';
15
16
  import fg from 'fast-glob';
@@ -2496,9 +2497,23 @@ async function initFrontGuard(cwd) {
2496
2497
  await fs.writeFile(tplPr, PR_TEMPLATE, "utf8");
2497
2498
  }
2498
2499
  }
2499
-
2500
- // src/ci/bitbucket-pr-snippet.ts
2500
+ var MAX_PNG_BYTES_FOR_EMBED = 22e4;
2501
2501
  function checksImageMarkdown() {
2502
+ const embedPath = process.env.FRONTGUARD_EMBED_CHECKS_PNG_PATH?.trim();
2503
+ if (embedPath) {
2504
+ try {
2505
+ if (!existsSync(embedPath)) return null;
2506
+ const st = statSync(embedPath);
2507
+ if (!st.isFile() || st.size > MAX_PNG_BYTES_FOR_EMBED) return null;
2508
+ const buf = readFileSync(embedPath);
2509
+ const b64 = buf.toString("base64");
2510
+ const md = `![FrontGuard \u2014 checks summary](data:image/png;base64,${b64})`;
2511
+ if (md.length > 45e4) return null;
2512
+ return md;
2513
+ } catch {
2514
+ return null;
2515
+ }
2516
+ }
2502
2517
  const u4 = process.env.FRONTGUARD_CHECKS_IMAGE_URL?.trim();
2503
2518
  if (!u4) return null;
2504
2519
  return `![FrontGuard \u2014 checks summary](${u4})`;
@@ -5532,6 +5547,30 @@ function applyAiAssistedEscalation(results, pr, config) {
5532
5547
  }
5533
5548
  }
5534
5549
  }
5550
+ var PLAYWRIGHT = "playwright@1.49.1";
5551
+ function runCmd(command, args) {
5552
+ return new Promise((resolve, reject) => {
5553
+ const p2 = spawn(command, args, { stdio: "inherit", env: process.env });
5554
+ p2.on("error", reject);
5555
+ p2.on("close", (code) => {
5556
+ if (code === 0) resolve();
5557
+ else reject(new Error(`${command} exited with code ${code}`));
5558
+ });
5559
+ });
5560
+ }
5561
+ async function runChecksHtmlToPng(htmlPath, pngPath) {
5562
+ const fileUrl = pathToFileURL(htmlPath).href;
5563
+ const npx = process.platform === "win32" ? "npx.cmd" : "npx";
5564
+ await runCmd(npx, ["-y", PLAYWRIGHT, "install", "chromium"]);
5565
+ await runCmd(npx, [
5566
+ "-y",
5567
+ PLAYWRIGHT,
5568
+ "screenshot",
5569
+ fileUrl,
5570
+ pngPath,
5571
+ "--viewport-size=920,1000"
5572
+ ]);
5573
+ }
5535
5574
 
5536
5575
  // src/report/builder.ts
5537
5576
  var import_picocolors = __toESM(require_picocolors());
@@ -6915,26 +6954,53 @@ async function runFrontGuard(opts) {
6915
6954
  llmAppendix,
6916
6955
  cwd: opts.cwd,
6917
6956
  emitHtml: Boolean(opts.htmlOut),
6918
- emitChecksSnapshot: Boolean(opts.checksSnapshotOut)
6957
+ emitChecksSnapshot: Boolean(opts.checksSnapshotOut || opts.checksPngOut)
6919
6958
  });
6920
6959
  if (opts.htmlOut && report.html) {
6921
6960
  await fs.writeFile(opts.htmlOut, report.html, "utf8");
6922
6961
  }
6923
- if (opts.checksSnapshotOut && report.checksSnapshotHtml) {
6924
- const snapPath = path5.isAbsolute(opts.checksSnapshotOut) ? opts.checksSnapshotOut : path5.join(opts.cwd, opts.checksSnapshotOut);
6925
- await fs.writeFile(snapPath, report.checksSnapshotHtml, "utf8");
6926
- const fileUrl = pathToFileURL(snapPath).href;
6927
- g.stderr.write(
6928
- `
6929
- FrontGuard: wrote checks snapshot HTML to ${snapPath} (screenshot this file for PR comments).
6930
- Example: npx playwright screenshot "${fileUrl}" frontguard-checks.png
6931
- Host the PNG at an HTTPS URL, then set FRONTGUARD_CHECKS_IMAGE_URL before generating the PR comment.
6962
+ let embedPngPath = null;
6963
+ let tmpDir = null;
6964
+ let htmlForPng;
6965
+ if ((opts.checksSnapshotOut || opts.checksPngOut) && report.checksSnapshotHtml) {
6966
+ if (opts.checksSnapshotOut) {
6967
+ const snapPath = path5.isAbsolute(opts.checksSnapshotOut) ? opts.checksSnapshotOut : path5.join(opts.cwd, opts.checksSnapshotOut);
6968
+ await fs.writeFile(snapPath, report.checksSnapshotHtml, "utf8");
6969
+ htmlForPng = snapPath;
6970
+ g.stderr.write(`
6971
+ FrontGuard: wrote checks snapshot HTML to ${snapPath}
6972
+ `);
6973
+ }
6974
+ if (opts.checksPngOut) {
6975
+ if (!htmlForPng) {
6976
+ tmpDir = await fs.mkdtemp(path5.join(tmpdir(), "fg-checks-"));
6977
+ htmlForPng = path5.join(tmpDir, "checks.html");
6978
+ await fs.writeFile(htmlForPng, report.checksSnapshotHtml, "utf8");
6979
+ }
6980
+ const pngAbs = path5.isAbsolute(opts.checksPngOut) ? opts.checksPngOut : path5.join(opts.cwd, opts.checksPngOut);
6981
+ await runChecksHtmlToPng(htmlForPng, pngAbs);
6982
+ embedPngPath = pngAbs;
6983
+ g.stderr.write(`FrontGuard: wrote checks PNG to ${pngAbs} (Playwright via npx).
6984
+
6985
+ `);
6986
+ if (tmpDir) {
6987
+ await fs.rm(tmpDir, { recursive: true, force: true });
6988
+ tmpDir = null;
6989
+ }
6990
+ } else if (opts.checksSnapshotOut && htmlForPng) {
6991
+ g.stderr.write(
6992
+ ` Tip: add --checksPngOut checks.png to render this HTML to PNG with Playwright (npx).
6932
6993
 
6933
6994
  `
6934
- );
6995
+ );
6996
+ }
6935
6997
  }
6936
6998
  if (opts.prCommentOut) {
6999
+ if (embedPngPath) {
7000
+ g.env.FRONTGUARD_EMBED_CHECKS_PNG_PATH = embedPngPath;
7001
+ }
6937
7002
  const snippet = formatBitbucketPrSnippet(report);
7003
+ delete g.env.FRONTGUARD_EMBED_CHECKS_PNG_PATH;
6938
7004
  const abs = path5.isAbsolute(opts.prCommentOut) ? opts.prCommentOut : path5.join(opts.cwd, opts.prCommentOut);
6939
7005
  await fs.writeFile(abs, snippet, "utf8");
6940
7006
  g.stderr.write(
@@ -6942,7 +7008,7 @@ FrontGuard: wrote checks snapshot HTML to ${snapPath} (screenshot this file for
6942
7008
  FrontGuard: wrote Bitbucket PR comment text to ${abs} (${snippet.length} bytes).
6943
7009
  Use ONLY this file in your POST \u2026/pullrequests/{id}/comments payload (content.raw).
6944
7010
  Do not post frontguard-report.md or captured stdout \u2014 that is the long markdown log.
6945
- Optional: set FRONTGUARD_CHECKS_IMAGE_URL so the comment includes a checks summary image.
7011
+ With --checksPngOut, the PNG is inlined (small files only) or set FRONTGUARD_CHECKS_IMAGE_URL.
6946
7012
 
6947
7013
  `
6948
7014
  );
@@ -6997,7 +7063,11 @@ var run = defineCommand({
6997
7063
  },
6998
7064
  checksSnapshotOut: {
6999
7065
  type: "string",
7000
- description: "Write HTML with only the Checks table (screenshot \u2192 PNG \u2192 FRONTGUARD_CHECKS_IMAGE_URL in PR comment)"
7066
+ description: "Write HTML with only the Checks table (for screenshots / PR comments)"
7067
+ },
7068
+ checksPngOut: {
7069
+ type: "string",
7070
+ description: "Write PNG of the checks table via Playwright (npx). Pair with --checksSnapshotOut or use alone"
7001
7071
  },
7002
7072
  prCommentOut: {
7003
7073
  type: "string",
@@ -7012,6 +7082,7 @@ var run = defineCommand({
7012
7082
  append: typeof args.append === "string" ? args.append : null,
7013
7083
  htmlOut: typeof args.htmlOut === "string" ? args.htmlOut : null,
7014
7084
  checksSnapshotOut: typeof args.checksSnapshotOut === "string" ? args.checksSnapshotOut : null,
7085
+ checksPngOut: typeof args.checksPngOut === "string" ? args.checksPngOut : null,
7015
7086
  prCommentOut: typeof args.prCommentOut === "string" ? args.prCommentOut : null
7016
7087
  });
7017
7088
  }