Skip to content

Commit 64d8fc7

Browse files
committed
chore: update dist
Signed-off-by: Avish Jha <avish.j@protonmail.com>
1 parent 91d352b commit 64d8fc7

2 files changed

Lines changed: 222 additions & 26 deletions

File tree

dist/report.js

Lines changed: 220 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23625,6 +23625,22 @@ var METRIC_KEYS = [
2362523625
"speed-index",
2362623626
"interactive"
2362723627
];
23628+
var METRIC_DISPLAY_NAMES = {
23629+
"first-contentful-paint": "First Contentful Paint",
23630+
"largest-contentful-paint": "Largest Contentful Paint",
23631+
"cumulative-layout-shift": "Cumulative Layout Shift",
23632+
"total-blocking-time": "Total Blocking Time",
23633+
"speed-index": "Speed Index",
23634+
"interactive": "Time to Interactive"
23635+
};
23636+
var METRIC_SHORT_NAMES = {
23637+
"first-contentful-paint": "FCP",
23638+
"largest-contentful-paint": "LCP",
23639+
"cumulative-layout-shift": "CLS",
23640+
"total-blocking-time": "TBT",
23641+
"speed-index": "SI",
23642+
"interactive": "TTI"
23643+
};
2362823644

2362923645
// src/utils.ts
2363023646
function isPathSafe(inputPath) {
@@ -23669,6 +23685,15 @@ function buildRegressionsList(regressions) {
2366923685
md += "\n";
2367023686
return md;
2367123687
}
23688+
function fmtMetricValue(key, value) {
23689+
if (key === "cumulative-layout-shift") {
23690+
return value.toFixed(3);
23691+
}
23692+
if (key === "total-blocking-time") {
23693+
return `${Math.round(value)}ms`;
23694+
}
23695+
return `${(value / 1e3).toFixed(2)}s`;
23696+
}
2367223697

2367323698
// src/lhr.ts
2367423699
function warn(message) {
@@ -23901,14 +23926,35 @@ function buildIssueBody(analysis, consecutiveFailLimit) {
2390123926
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2390223927
const branch = process.env.GITHUB_REF?.replace("refs/heads/", "") ?? "unknown";
2390323928
const commit = process.env.GITHUB_SHA?.substring(0, 7) ?? "unknown";
23904-
let body = `## Lighthouse Performance Alert
23929+
const failedUrls = analysis.urls.filter((u) => !u.passed);
23930+
const failingProfiles = failedUrls.flatMap((u) => u.profiles.filter((p) => !p.passed));
23931+
const totalProfiles = analysis.urls.reduce((s, u) => s + u.profiles.length, 0);
23932+
const totalErrors = failingProfiles.reduce(
23933+
(s, p) => s + countAssertionLevels(filterFailedAssertions(p.assertions)).errors,
23934+
0
23935+
);
23936+
const totalWarnings = failingProfiles.reduce(
23937+
(s, p) => s + countAssertionLevels(filterFailedAssertions(p.assertions)).warnings,
23938+
0
23939+
);
23940+
const totalRegressions = failingProfiles.reduce((s, p) => s + p.regressions.length, 0);
23941+
let body = `## \u{1F534} Lighthouse Performance Alert
2390523942

2390623943
`;
23907-
body += `**Timestamp:** ${timestamp}
23944+
const parts = [];
23945+
if (totalErrors > 0) parts.push(`${totalErrors} error${pl(totalErrors)}`);
23946+
if (totalWarnings > 0) parts.push(`${totalWarnings} warning${pl(totalWarnings)}`);
23947+
if (totalRegressions > 0) parts.push(`${totalRegressions} regression${pl(totalRegressions)}`);
23948+
body += `> **${analysis.urls.length} URL${pl(analysis.urls.length)}** across `;
23949+
body += `**${totalProfiles} profile${pl(totalProfiles)}** \u2014 `;
23950+
body += `**${failingProfiles.length} failing** \xB7 ${parts.join(" \xB7 ")}
23951+
2390823952
`;
23909-
body += `**Branch:** ${branch}
23953+
body += buildStatusMatrix(analysis);
23954+
body += `\`${branch}\` \xB7 \`${commit}\` \xB7 ${fmtDate(timestamp)}
23955+
2391023956
`;
23911-
body += `**Commit:** ${commit}
23957+
body += `---
2391223958

2391323959
`;
2391423960
for (const url of analysis.urls) {
@@ -23918,35 +23964,166 @@ function buildIssueBody(analysis, consecutiveFailLimit) {
2391823964
`;
2391923965
for (const pr of url.profiles) {
2392023966
if (pr.passed) continue;
23921-
body += `#### ${pr.profile}
23967+
body += buildProfileSection(pr, consecutiveFailLimit);
23968+
}
23969+
}
23970+
body += `---
2392223971

2392323972
`;
23924-
if (pr.reportLink) {
23925-
body += `[View report](${pr.reportLink})
23926-
23973+
const runCount = failingProfiles[0]?.runMetrics?.length;
23974+
body += `<sub>\u{1F916} Auto-managed by AutoLighthouse`;
23975+
if (runCount && runCount > 1) body += ` \xB7 ${runCount} runs per profile`;
23976+
body += `</sub>`;
23977+
return body;
23978+
}
23979+
function pl(n) {
23980+
return n !== 1 ? "s" : "";
23981+
}
23982+
function fmtDate(iso) {
23983+
const d = new Date(iso);
23984+
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
23985+
const hh = String(d.getUTCHours()).padStart(2, "0");
23986+
const mm = String(d.getUTCMinutes()).padStart(2, "0");
23987+
return `${months[d.getUTCMonth()]} ${d.getUTCDate()}, ${d.getUTCFullYear()} ${hh}:${mm} UTC`;
23988+
}
23989+
function profileStatusIcon(pr) {
23990+
const failures = filterFailedAssertions(pr.assertions);
23991+
const { errors } = countAssertionLevels(failures);
23992+
if (errors > 0) return "\u{1F534}";
23993+
if (failures.length > 0) return "\u{1F7E1}";
23994+
if (pr.regressions.length > 0) return "\u{1F4C9}";
23995+
return "\u{1F7E2}";
23996+
}
23997+
function buildStatusMatrix(analysis) {
23998+
const profileSet = /* @__PURE__ */ new Set();
23999+
for (const url of analysis.urls) {
24000+
for (const p of url.profiles) profileSet.add(p.profile);
24001+
}
24002+
const profiles = Array.from(profileSet);
24003+
if (profiles.length === 0) return "";
24004+
const icons = { desktop: "\u{1F5A5}\uFE0F", mobile: "\u{1F4F1}", tablet: "\u{1F4F1}" };
24005+
let md = `| URL |`;
24006+
for (const p of profiles) md += ` ${icons[p] ?? ""} ${p} |`;
24007+
md += `
24008+
|-----|`;
24009+
for (const _ of profiles) md += `:---:|`;
24010+
md += `
2392724011
`;
24012+
for (const url of analysis.urls) {
24013+
md += `| \`${url.pathname}\` |`;
24014+
for (const name of profiles) {
24015+
const pr = url.profiles.find((p) => p.profile === name);
24016+
if (!pr) {
24017+
md += ` \u2014 |`;
24018+
continue;
2392824019
}
23929-
const failures = filterFailedAssertions(pr.assertions);
23930-
if (failures.length > 0) {
23931-
const { errors, warnings } = countAssertionLevels(failures);
23932-
body += `**Assertion Failures:** ${errors} error(s), ${warnings} warning(s)
24020+
md += ` ${profileStatusIcon(pr)} |`;
24021+
}
24022+
md += `
24023+
`;
24024+
}
24025+
md += `
24026+
`;
24027+
return md;
24028+
}
24029+
function buildProfileSection(pr, consecutiveFailLimit) {
24030+
const icon = profileStatusIcon(pr);
24031+
let md = `<details open>
24032+
<summary><b>${icon} ${pr.profile}</b>`;
24033+
const failures = filterFailedAssertions(pr.assertions);
24034+
if (failures.length > 0) {
24035+
const { errors, warnings } = countAssertionLevels(failures);
24036+
const counts = [];
24037+
if (errors > 0) counts.push(`${errors} error${pl(errors)}`);
24038+
if (warnings > 0) counts.push(`${warnings} warning${pl(warnings)}`);
24039+
md += ` \xB7 ${counts.join(", ")}`;
24040+
}
24041+
if (pr.regressions.length > 0) {
24042+
md += ` \xB7 ${pr.regressions.length} regression${pl(pr.regressions.length)}`;
24043+
}
24044+
if (pr.reportLink) {
24045+
md += ` \xB7 <a href="${pr.reportLink}">View Report \u2197</a>`;
24046+
}
24047+
md += `</summary>
2393324048

2393424049
`;
23935-
body += buildAssertionTable(failures);
23936-
}
23937-
if (pr.regressions.length > 0) {
23938-
body += buildRegressionsList(pr.regressions);
23939-
}
23940-
if (pr.consecutiveFailures >= consecutiveFailLimit) {
23941-
body += `\u26A0\uFE0F **Persistent failure** \u2014 ${pr.consecutiveFailures} consecutive runs
24050+
if (failures.length > 0) {
24051+
md += `**Assertion Failures**
2394224052

2394324053
`;
24054+
md += `| Audit | Level | Actual | Threshold |
24055+
`;
24056+
md += `|-------|-------|--------|----------|
24057+
`;
24058+
for (const a of failures) {
24059+
const lvl = a.level === "error" ? "\u{1F534} error" : "\u{1F7E1} warn";
24060+
md += `| ${a.auditId} | ${lvl} | ${a.actual ?? "\u2014"} | ${a.operator ?? ""} ${a.expected ?? "\u2014"} |
24061+
`;
24062+
}
24063+
md += "\n";
24064+
}
24065+
if (pr.regressions.length > 0) {
24066+
md += buildRegressionsList(pr.regressions);
24067+
}
24068+
const runs = pr.runMetrics;
24069+
if (runs && runs.length > 0) {
24070+
md += buildMetricsTable(pr.metrics, runs);
24071+
}
24072+
if (pr.consecutiveFailures >= consecutiveFailLimit) {
24073+
md += `> \u26A0\uFE0F **Persistent failure** \u2014 ${pr.consecutiveFailures} consecutive runs
24074+
24075+
`;
24076+
}
24077+
md += `</details>
24078+
24079+
`;
24080+
return md;
24081+
}
24082+
function buildMetricsTable(median, runs) {
24083+
let md = `**Core Web Vitals** _(median of ${runs.length} run${pl(runs.length)})_
24084+
24085+
`;
24086+
md += `| Metric | Median | Range |
24087+
`;
24088+
md += `|--------|-------:|------:|
24089+
`;
24090+
for (const key of METRIC_KEYS) {
24091+
const medVal = median[key];
24092+
if (medVal === void 0) continue;
24093+
const sorted = runs.map((r) => r[key]).filter((v) => v !== void 0).sort((a, b) => a - b);
24094+
if (sorted.length === 0) continue;
24095+
const range = `${fmtMetricValue(key, sorted[0])} \u2013 ${fmtMetricValue(key, sorted[sorted.length - 1])}`;
24096+
md += `| ${METRIC_DISPLAY_NAMES[key]} | ${fmtMetricValue(key, medVal)} | ${range} |
24097+
`;
24098+
}
24099+
md += "\n";
24100+
if (runs.length > 1) {
24101+
md += `<details>
24102+
<summary>\u{1F4CA} Individual runs (${runs.length})</summary>
24103+
24104+
`;
24105+
md += `| # |`;
24106+
for (const key of METRIC_KEYS) md += ` ${METRIC_SHORT_NAMES[key]} |`;
24107+
md += `
24108+
|---|`;
24109+
for (const _ of METRIC_KEYS) md += `---:|`;
24110+
md += `
24111+
`;
24112+
for (let i = 0; i < runs.length; i++) {
24113+
md += `| ${i + 1} |`;
24114+
for (const key of METRIC_KEYS) {
24115+
const v = runs[i][key];
24116+
md += ` ${v !== void 0 ? fmtMetricValue(key, v) : "\u2014"} |`;
2394424117
}
24118+
md += `
24119+
`;
2394524120
}
24121+
md += `
24122+
</details>
24123+
24124+
`;
2394624125
}
23947-
body += `---
23948-
_This issue is auto-managed by AutoLighthouse._`;
23949-
return body;
24126+
return md;
2395024127
}
2395124128
async function manageIssue(octokit, analysis, consecutiveFailLimit) {
2395224129
const existingIssue = await findOpenIssue(octokit);
@@ -24081,16 +24258,25 @@ async function run() {
2408124258
const raw = [];
2408224259
for (const artifact of artifacts) {
2408324260
const failedAssertions = artifact.assertions.filter((a) => !a.passed);
24261+
const lhrsByUrl = /* @__PURE__ */ new Map();
2408424262
for (const lhrPath of artifact.lhrPaths) {
2408524263
const lhr = parseLhr(lhrPath);
2408624264
if (!lhr) continue;
2408724265
const url = extractUrl(lhr);
2408824266
if (!url) continue;
24089-
const pathname = extractPathname(url);
2409024267
const metrics = extractMetrics(lhr);
24268+
let entry = lhrsByUrl.get(url);
24269+
if (!entry) {
24270+
entry = { pathname: extractPathname(url), allMetrics: [] };
24271+
lhrsByUrl.set(url, entry);
24272+
}
24273+
entry.allMetrics.push(metrics);
24274+
}
24275+
for (const [url, { pathname, allMetrics }] of lhrsByUrl) {
24276+
const metrics = medianMetrics(allMetrics);
2409124277
const urlAssertions = failedAssertions.filter((a) => !a.url || a.url === url);
2409224278
const reportLink = artifact.links[url] ?? void 0;
24093-
raw.push({ profile: artifact.profile, url, pathname, metrics, assertions: urlAssertions, reportLink });
24279+
raw.push({ profile: artifact.profile, url, pathname, metrics, runMetrics: allMetrics, assertions: urlAssertions, reportLink });
2409424280
}
2409524281
}
2409624282
const urlMap = /* @__PURE__ */ new Map();
@@ -24119,6 +24305,7 @@ async function run() {
2411924305
const profileResult = {
2412024306
profile: r.profile,
2412124307
metrics: r.metrics,
24308+
runMetrics: r.runMetrics,
2412224309
regressions,
2412324310
assertions: r.assertions,
2412424311
consecutiveFailures: newConsecutive,
@@ -24186,6 +24373,15 @@ async function run() {
2418624373
}
2418724374
}
2418824375
}
24376+
function medianMetrics(allMetrics) {
24377+
if (allMetrics.length === 1) return allMetrics[0];
24378+
const result = {};
24379+
for (const key of METRIC_KEYS) {
24380+
const values = allMetrics.map((m) => m[key]).filter((v) => v !== void 0).sort((a, b) => a - b);
24381+
result[key] = values.length > 0 ? values[Math.floor(values.length / 2)] : void 0;
24382+
}
24383+
return result;
24384+
}
2418924385
function extractPathname(url) {
2419024386
try {
2419124387
return new URL(url).pathname || "/";

dist/report.js.map

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)