98 lines
3.2 KiB
JavaScript
98 lines
3.2 KiB
JavaScript
import { readFileSync, existsSync, writeFileSync } from "node:fs";
|
|
import path from "node:path";
|
|
import { globSync } from "glob";
|
|
|
|
const base = process.argv[2] ?? ".";
|
|
const outFile = process.argv[3] ?? "pr-quality-body.md";
|
|
|
|
function readJson(p) {
|
|
return JSON.parse(readFileSync(p, "utf8"));
|
|
}
|
|
|
|
const lines = [];
|
|
|
|
const covPath = path.join(base, "coverage", "coverage-summary.json");
|
|
if (existsSync(covPath)) {
|
|
const c = readJson(covPath);
|
|
const t = c.total;
|
|
lines.push("## Couverture (packages métier Vitest)");
|
|
lines.push(
|
|
`| Métrique | % |`,
|
|
`|----------|---|`,
|
|
`| Lignes | ${t.lines.pct.toFixed(2)} |`,
|
|
`| Branches | ${t.branches.pct.toFixed(2)} |`,
|
|
`| Fonctions | ${t.functions.pct.toFixed(2)} |`,
|
|
""
|
|
);
|
|
} else {
|
|
lines.push("## Couverture", "_Résumé indisponible (fichier coverage-summary manquant)._", "", "");
|
|
}
|
|
|
|
const a11yPath = path.join(base, "e2e", "a11y-summary.json");
|
|
if (existsSync(a11yPath)) {
|
|
const a = readJson(a11yPath);
|
|
lines.push("## Accessibilité (Axe / Playwright)");
|
|
lines.push(`- Violations : **${a.axeViolationCount}**`);
|
|
if (a.axeViolationIds?.length) lines.push(`- Ids : ${a.axeViolationIds.join(", ")}`);
|
|
lines.push("");
|
|
} else {
|
|
lines.push("## Accessibilité", "_Résumé Axe indisponible._", "", "");
|
|
}
|
|
|
|
const perfPath = path.join(base, "e2e", "perf-summary.json");
|
|
if (existsSync(perfPath)) {
|
|
const p = readJson(perfPath);
|
|
lines.push("## Performance (timings navigation)");
|
|
lines.push("```json");
|
|
lines.push(JSON.stringify(p.navigationTiming ?? p, null, 2));
|
|
lines.push("```", "");
|
|
}
|
|
|
|
const auditPath = path.join(base, "audit.json");
|
|
if (existsSync(auditPath)) {
|
|
const audit = readJson(auditPath);
|
|
const vulns = audit.vulnerabilities ?? {};
|
|
const metaV = audit.metadata?.vulnerabilities;
|
|
lines.push("## Sécurité (npm audit)");
|
|
if (metaV) {
|
|
lines.push(
|
|
`- Agrégat : critical ${metaV.critical}, high ${metaV.high}, moderate ${metaV.moderate}, low ${metaV.low}, info ${metaV.info}, total ${metaV.total}`
|
|
);
|
|
} else {
|
|
let high = 0;
|
|
let critical = 0;
|
|
for (const v of Object.values(vulns)) {
|
|
if (v.severity === "high") high++;
|
|
if (v.severity === "critical") critical++;
|
|
}
|
|
lines.push(`- Critical : ${critical}, High : ${high}`);
|
|
}
|
|
lines.push(`- Détail des paquets affectés : ${Object.keys(vulns).length}`, "");
|
|
} else {
|
|
lines.push("## Sécurité", "_npm audit non disponible._", "", "");
|
|
}
|
|
|
|
const lhr = globSync(path.join(base, "lhci", "**", "lhr-*.json").replace(/\\/g, "/"))[0];
|
|
if (lhr && existsSync(lhr)) {
|
|
const rep = readJson(lhr);
|
|
const cats = rep.categories ?? {};
|
|
const score = (c) => (c?.score != null ? Math.round(c.score * 100) : "n/a");
|
|
lines.push("## Lighthouse / SEO");
|
|
lines.push(
|
|
`| Catégorie | Score |`,
|
|
`|-----------|-------|`,
|
|
`| Performance | ${score(cats.performance)} |`,
|
|
`| Accessibilité | ${score(cats.accessibility)} |`,
|
|
`| Bonnes pratiques | ${score(cats["best-practices"])} |`,
|
|
`| SEO | ${score(cats.seo)} |`,
|
|
""
|
|
);
|
|
} else {
|
|
lines.push("## Lighthouse / SEO", "_Rapport LHCI indisponible._", "", "");
|
|
}
|
|
|
|
lines.push("---", "_Rapport généré par CI Ben-to._");
|
|
|
|
writeFileSync(outFile, lines.join("\n"), "utf8");
|
|
console.log(`Wrote ${outFile}`);
|