@cleartrip/frontguard 0.1.7 → 0.1.9
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 +72 -40
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/bitbucket-pipelines.yml +45 -44
- package/templates/freekit-ci-setup.md +20 -0
package/dist/cli.js
CHANGED
|
@@ -2458,7 +2458,7 @@ export default defineConfig({
|
|
|
2458
2458
|
// },
|
|
2459
2459
|
|
|
2460
2460
|
// checks: {
|
|
2461
|
-
// bundle: {
|
|
2461
|
+
// bundle: { baselineRef: 'main', maxDeltaBytes: 50_000 }, // ref for git baseline file
|
|
2462
2462
|
// cycles: { enabled: true },
|
|
2463
2463
|
// deadCode: { enabled: true, gate: 'info' },
|
|
2464
2464
|
// // LLM: cloud keys in CI, or local Ollama (no API key) on dev/self-hosted runners:
|
|
@@ -2544,22 +2544,14 @@ function bitbucketDownloadsPageUrl() {
|
|
|
2544
2544
|
}
|
|
2545
2545
|
function formatBitbucketPrSnippet(report) {
|
|
2546
2546
|
const publicReport = process.env.FRONTGUARD_PUBLIC_REPORT_URL?.trim();
|
|
2547
|
+
const linkOnly = process.env.FRONTGUARD_BITBUCKET_COMMENT_LINK_ONLY === "1";
|
|
2548
|
+
if (linkOnly && publicReport) {
|
|
2549
|
+
return publicReport.endsWith("\n") ? publicReport : `${publicReport}
|
|
2550
|
+
`;
|
|
2551
|
+
}
|
|
2547
2552
|
const downloadsName = process.env.FRONTGUARD_REPORT_DOWNLOAD_NAME?.trim();
|
|
2548
2553
|
const downloadsPage = bitbucketDownloadsPageUrl();
|
|
2549
2554
|
const pipeline = bitbucketPipelineResultsUrl();
|
|
2550
|
-
let linkLine;
|
|
2551
|
-
if (publicReport) {
|
|
2552
|
-
linkLine = `**[Open full FrontGuard report (HTML)](${publicReport})** \u2014 interactive report in the browser (all findings).`;
|
|
2553
|
-
} else if (downloadsName && downloadsPage) {
|
|
2554
|
-
linkLine = `**[Repo Downloads](${downloadsPage})** \u2014 open \`${downloadsName}\` (uploaded by this pipeline). Download the file, then open it in a browser.`;
|
|
2555
|
-
} else if (pipeline) {
|
|
2556
|
-
linkLine = [
|
|
2557
|
-
`**[Open this pipeline run](${pipeline})** (Bitbucket login required).`,
|
|
2558
|
-
"On that page: open the **Artifacts** section \u2192 download **`frontguard-report.html`** \u2192 open the file in your browser to see the full interactive report."
|
|
2559
|
-
].join(" ");
|
|
2560
|
-
} else {
|
|
2561
|
-
linkLine = "_Run FrontGuard inside Bitbucket Pipelines so `BITBUCKET_REPO_FULL_NAME` and `BITBUCKET_BUILD_NUMBER` are set, or set `FRONTGUARD_PUBLIC_REPORT_URL` after uploading the HTML._";
|
|
2562
|
-
}
|
|
2563
2555
|
const { riskScore, results } = report;
|
|
2564
2556
|
const blocks = results.reduce(
|
|
2565
2557
|
(n3, r4) => n3 + r4.findings.filter((f4) => f4.severity === "block").length,
|
|
@@ -2569,25 +2561,48 @@ function formatBitbucketPrSnippet(report) {
|
|
|
2569
2561
|
(n3, r4) => n3 + r4.findings.filter((f4) => f4.severity === "warn").length,
|
|
2570
2562
|
0
|
|
2571
2563
|
);
|
|
2572
|
-
const
|
|
2573
|
-
"
|
|
2574
|
-
"",
|
|
2575
|
-
`**Risk:** ${riskScore} \xB7 **Blocking:** ${blocks} \xB7 **Warnings:** ${warns}`,
|
|
2564
|
+
const out = [
|
|
2565
|
+
"FrontGuard report (short summary)",
|
|
2576
2566
|
"",
|
|
2577
|
-
|
|
2578
|
-
""
|
|
2579
|
-
"| Check | Status |",
|
|
2580
|
-
"|:--|:--|"
|
|
2567
|
+
`Risk: ${riskScore} | Blocking: ${blocks} | Warnings: ${warns}`,
|
|
2568
|
+
""
|
|
2581
2569
|
];
|
|
2570
|
+
if (publicReport) {
|
|
2571
|
+
out.push("Full interactive report (open in browser):");
|
|
2572
|
+
out.push(publicReport);
|
|
2573
|
+
out.push("");
|
|
2574
|
+
} else if (downloadsName && downloadsPage) {
|
|
2575
|
+
out.push("HTML report is in Repository \u2192 Downloads. Open this page while logged in:");
|
|
2576
|
+
out.push(downloadsPage);
|
|
2577
|
+
out.push(`File name: ${downloadsName}`);
|
|
2578
|
+
out.push("Download the file, then open it in a browser.");
|
|
2579
|
+
out.push("");
|
|
2580
|
+
} else if (pipeline) {
|
|
2581
|
+
out.push(
|
|
2582
|
+
"There is no direct \u201CHTML URL\u201D for pipeline artifacts in Bitbucket. Use this pipeline run (log in), then Artifacts \u2192 frontguard-report.html:"
|
|
2583
|
+
);
|
|
2584
|
+
out.push(pipeline);
|
|
2585
|
+
out.push("");
|
|
2586
|
+
out.push(
|
|
2587
|
+
"Steps: open the link \u2192 scroll to Artifacts \u2192 download frontguard-report.html \u2192 open the file on your machine."
|
|
2588
|
+
);
|
|
2589
|
+
out.push("");
|
|
2590
|
+
} else {
|
|
2591
|
+
out.push(
|
|
2592
|
+
"Add a link: run FrontGuard inside Bitbucket Pipelines, or set FRONTGUARD_PUBLIC_REPORT_URL after uploading the HTML somewhere HTTPS."
|
|
2593
|
+
);
|
|
2594
|
+
out.push("");
|
|
2595
|
+
}
|
|
2596
|
+
out.push("Checks:");
|
|
2582
2597
|
for (const r4 of results) {
|
|
2583
|
-
const status = r4.skipped ? `
|
|
2584
|
-
|
|
2598
|
+
const status = r4.skipped ? `skipped (${r4.skipped.slice(0, 100)}${r4.skipped.length > 100 ? "\u2026" : ""})` : r4.findings.length === 0 ? "clean" : `${r4.findings.length} finding(s)`;
|
|
2599
|
+
out.push(`- ${r4.checkId}: ${status}`);
|
|
2585
2600
|
}
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2601
|
+
out.push("");
|
|
2602
|
+
out.push(
|
|
2603
|
+
"Do not paste the long frontguard-report.md into PR comments. Full text output is in that file / pipeline artifacts only."
|
|
2589
2604
|
);
|
|
2590
|
-
return
|
|
2605
|
+
return out.join("\n");
|
|
2591
2606
|
}
|
|
2592
2607
|
|
|
2593
2608
|
// src/ci/parse-ai-disclosure.ts
|
|
@@ -2687,10 +2702,10 @@ async function resolvePrNumber() {
|
|
|
2687
2702
|
const raw = process.env.FRONTGUARD_PR_NUMBER ?? process.env.PR_NUMBER;
|
|
2688
2703
|
const n3 = Number(raw);
|
|
2689
2704
|
if (Number.isFinite(n3) && n3 > 0) return n3;
|
|
2690
|
-
const
|
|
2691
|
-
if (!
|
|
2705
|
+
const path17 = process.env.GITHUB_EVENT_PATH;
|
|
2706
|
+
if (!path17) return null;
|
|
2692
2707
|
try {
|
|
2693
|
-
const payload = JSON.parse(await fs.readFile(
|
|
2708
|
+
const payload = JSON.parse(await fs.readFile(path17, "utf8"));
|
|
2694
2709
|
const num = payload.pull_request?.number;
|
|
2695
2710
|
return typeof num === "number" && num > 0 ? num : null;
|
|
2696
2711
|
} catch {
|
|
@@ -2829,7 +2844,7 @@ var defaultConfig = {
|
|
|
2829
2844
|
tsAnyDeltaToBlock: true
|
|
2830
2845
|
}
|
|
2831
2846
|
},
|
|
2832
|
-
prSize: { warnLines: 400, softBlockLines: 800 },
|
|
2847
|
+
prSize: { enabled: true, warnLines: 400, softBlockLines: 800 },
|
|
2833
2848
|
tsAnyDelta: {
|
|
2834
2849
|
enabled: true,
|
|
2835
2850
|
gate: "warn",
|
|
@@ -2837,24 +2852,25 @@ var defaultConfig = {
|
|
|
2837
2852
|
maxAdded: 0
|
|
2838
2853
|
},
|
|
2839
2854
|
cycles: {
|
|
2840
|
-
enabled:
|
|
2855
|
+
enabled: true,
|
|
2841
2856
|
gate: "warn",
|
|
2842
2857
|
entries: ["src"],
|
|
2843
2858
|
extraArgs: []
|
|
2844
2859
|
},
|
|
2845
2860
|
deadCode: {
|
|
2846
|
-
enabled:
|
|
2861
|
+
enabled: true,
|
|
2847
2862
|
gate: "info",
|
|
2848
2863
|
extraArgs: [],
|
|
2849
2864
|
maxReportLines: 80
|
|
2850
2865
|
},
|
|
2851
2866
|
bundle: {
|
|
2852
|
-
enabled:
|
|
2867
|
+
enabled: true,
|
|
2853
2868
|
gate: "warn",
|
|
2854
2869
|
runBuild: true,
|
|
2855
2870
|
buildCommand: "npm run build",
|
|
2856
2871
|
measureGlobs: ["dist/**/*", "build/static/**/*", ".next/static/**/*"],
|
|
2857
2872
|
baselinePath: ".frontguard/bundle-baseline.json",
|
|
2873
|
+
baselineRef: "main",
|
|
2858
2874
|
maxDeltaBytes: null,
|
|
2859
2875
|
maxTotalBytes: null
|
|
2860
2876
|
},
|
|
@@ -4149,6 +4165,14 @@ function sectionMentioned(body, hint) {
|
|
|
4149
4165
|
// src/checks/pr-size.ts
|
|
4150
4166
|
function runPrSize(config, pr) {
|
|
4151
4167
|
const t0 = performance.now();
|
|
4168
|
+
if (!config.checks.prSize.enabled) {
|
|
4169
|
+
return {
|
|
4170
|
+
checkId: "pr-size",
|
|
4171
|
+
findings: [],
|
|
4172
|
+
durationMs: 0,
|
|
4173
|
+
skipped: "disabled in config"
|
|
4174
|
+
};
|
|
4175
|
+
}
|
|
4152
4176
|
if (!pr) {
|
|
4153
4177
|
return {
|
|
4154
4178
|
checkId: "pr-size",
|
|
@@ -4574,7 +4598,7 @@ async function runBundle(cwd, config, stack) {
|
|
|
4574
4598
|
durationMs: Math.round(performance.now() - t0)
|
|
4575
4599
|
};
|
|
4576
4600
|
}
|
|
4577
|
-
const baseRef = await gitOkQuick(cwd) ? await resolveDiffBaseRef(cwd,
|
|
4601
|
+
const baseRef = await gitOkQuick(cwd) ? await resolveDiffBaseRef(cwd, cfg.baselineRef) : null;
|
|
4578
4602
|
const baseline = await readBaseline(cwd, cfg.baselinePath, baseRef);
|
|
4579
4603
|
const findings = [];
|
|
4580
4604
|
const infoLines = [
|
|
@@ -5097,7 +5121,6 @@ function buildHtmlReport(p2) {
|
|
|
5097
5121
|
.badges { margin-bottom: 1.25rem; display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
|
|
5098
5122
|
.badge { height: 28px; width: auto; max-width: 100%; image-rendering: crisp-edges; }
|
|
5099
5123
|
details { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 0.75rem; }
|
|
5100
|
-
details.open-default { border-color: #3d4f6a; }
|
|
5101
5124
|
summary {
|
|
5102
5125
|
cursor: pointer; padding: 0.65rem 1rem; font-weight: 600;
|
|
5103
5126
|
list-style: none; display: flex; align-items: center; gap: 0.5rem;
|
|
@@ -5162,12 +5185,12 @@ function buildHtmlReport(p2) {
|
|
|
5162
5185
|
<tbody>${checkRows}</tbody>
|
|
5163
5186
|
</table>
|
|
5164
5187
|
|
|
5165
|
-
<details
|
|
5188
|
+
<details>
|
|
5166
5189
|
<summary>Blocking (${blocks})</summary>
|
|
5167
5190
|
<div class="details-body">${blockingHtml}</div>
|
|
5168
5191
|
</details>
|
|
5169
5192
|
|
|
5170
|
-
<details
|
|
5193
|
+
<details>
|
|
5171
5194
|
<summary>Warnings (${warns})</summary>
|
|
5172
5195
|
<div class="details-body">${warningsHtml}</div>
|
|
5173
5196
|
</details>
|
|
@@ -5991,7 +6014,16 @@ async function runFrontGuard(opts) {
|
|
|
5991
6014
|
}
|
|
5992
6015
|
if (opts.prCommentOut) {
|
|
5993
6016
|
const snippet = formatBitbucketPrSnippet(report);
|
|
5994
|
-
|
|
6017
|
+
const abs = path4.isAbsolute(opts.prCommentOut) ? opts.prCommentOut : path4.join(opts.cwd, opts.prCommentOut);
|
|
6018
|
+
await fs.writeFile(abs, snippet, "utf8");
|
|
6019
|
+
g.stderr.write(
|
|
6020
|
+
`
|
|
6021
|
+
FrontGuard: wrote Bitbucket PR comment text to ${abs} (${snippet.length} bytes).
|
|
6022
|
+
Use ONLY this file in your POST \u2026/pullrequests/{id}/comments payload (content.raw).
|
|
6023
|
+
Do not post frontguard-report.md or captured stdout \u2014 that is the long markdown log.
|
|
6024
|
+
|
|
6025
|
+
`
|
|
6026
|
+
);
|
|
5995
6027
|
}
|
|
5996
6028
|
if (opts.markdown) {
|
|
5997
6029
|
g.stdout.write(report.markdown + "\n");
|