first commit
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
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}`);
|
||||
Reference in New Issue
Block a user