@code-pushup/coverage-plugin 0.35.0 → 0.42.0
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/bin.js +455 -104
- package/index.js +438 -93
- package/package.json +4 -4
- package/src/lib/config.d.ts +2 -2
package/bin.js
CHANGED
|
@@ -3,8 +3,300 @@ import chalk5 from "chalk";
|
|
|
3
3
|
import { writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname } from "node:path";
|
|
5
5
|
|
|
6
|
-
// packages/
|
|
7
|
-
|
|
6
|
+
// packages/utils/src/lib/text-formats/constants.ts
|
|
7
|
+
var NEW_LINE = "\n";
|
|
8
|
+
var TAB = " ";
|
|
9
|
+
|
|
10
|
+
// packages/utils/src/lib/text-formats/html/details.ts
|
|
11
|
+
function details(title, content, cfg = { open: false }) {
|
|
12
|
+
return `<details${cfg.open ? " open" : ""}>${NEW_LINE}<summary>${title}</summary>${NEW_LINE}${// ⚠️ The blank line is needed to ensure Markdown in content is rendered correctly.
|
|
13
|
+
NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
|
|
14
|
+
// ⚠️ The blank line ensure Markdown in content is rendered correctly.
|
|
15
|
+
NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
|
|
16
|
+
NEW_LINE}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// packages/utils/src/lib/text-formats/html/font-style.ts
|
|
20
|
+
var boldElement = "b";
|
|
21
|
+
function bold(text) {
|
|
22
|
+
return `<${boldElement}>${text}</${boldElement}>`;
|
|
23
|
+
}
|
|
24
|
+
var italicElement = "i";
|
|
25
|
+
function italic(text) {
|
|
26
|
+
return `<${italicElement}>${text}</${italicElement}>`;
|
|
27
|
+
}
|
|
28
|
+
var codeElement = "code";
|
|
29
|
+
function code(text) {
|
|
30
|
+
return `<${codeElement}>${text}</${codeElement}>`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// packages/utils/src/lib/text-formats/html/link.ts
|
|
34
|
+
function link(href, text) {
|
|
35
|
+
return `<a href="${href}">${text || href}"</a>`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// packages/utils/src/lib/transform.ts
|
|
39
|
+
import { platform } from "node:os";
|
|
40
|
+
function toUnixNewlines(text) {
|
|
41
|
+
return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
|
|
42
|
+
}
|
|
43
|
+
function capitalize(text) {
|
|
44
|
+
return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
|
|
45
|
+
1
|
|
46
|
+
)}`;
|
|
47
|
+
}
|
|
48
|
+
function toNumberPrecision(value, decimalPlaces) {
|
|
49
|
+
return Number(
|
|
50
|
+
`${Math.round(
|
|
51
|
+
Number.parseFloat(`${value}e${decimalPlaces}`)
|
|
52
|
+
)}e-${decimalPlaces}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
function toOrdinal(value) {
|
|
56
|
+
if (value % 10 === 1 && value % 100 !== 11) {
|
|
57
|
+
return `${value}st`;
|
|
58
|
+
}
|
|
59
|
+
if (value % 10 === 2 && value % 100 !== 12) {
|
|
60
|
+
return `${value}nd`;
|
|
61
|
+
}
|
|
62
|
+
if (value % 10 === 3 && value % 100 !== 13) {
|
|
63
|
+
return `${value}rd`;
|
|
64
|
+
}
|
|
65
|
+
return `${value}th`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// packages/utils/src/lib/table.ts
|
|
69
|
+
function rowToStringArray({ rows, columns = [] }) {
|
|
70
|
+
if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
|
|
71
|
+
throw new TypeError(
|
|
72
|
+
"Column can`t be object when rows are primitive values"
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return rows.map((row) => {
|
|
76
|
+
if (Array.isArray(row)) {
|
|
77
|
+
return row.map(String);
|
|
78
|
+
}
|
|
79
|
+
const objectRow = row;
|
|
80
|
+
if (columns.length === 0 || typeof columns.at(0) === "string") {
|
|
81
|
+
return Object.values(objectRow).map(String);
|
|
82
|
+
}
|
|
83
|
+
return columns.map(
|
|
84
|
+
({ key }) => String(objectRow[key])
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function columnsToStringArray({ rows, columns = [] }) {
|
|
89
|
+
const firstRow = rows.at(0);
|
|
90
|
+
const primitiveRows = Array.isArray(firstRow);
|
|
91
|
+
if (typeof columns.at(0) === "string" && !primitiveRows) {
|
|
92
|
+
throw new Error("invalid union type. Caught by model parsing.");
|
|
93
|
+
}
|
|
94
|
+
if (columns.length === 0) {
|
|
95
|
+
if (Array.isArray(firstRow)) {
|
|
96
|
+
return firstRow.map((_, idx) => String(idx));
|
|
97
|
+
}
|
|
98
|
+
return Object.keys(firstRow);
|
|
99
|
+
}
|
|
100
|
+
if (typeof columns.at(0) === "string") {
|
|
101
|
+
return columns.map(String);
|
|
102
|
+
}
|
|
103
|
+
const cols = columns;
|
|
104
|
+
return cols.map(({ label, key }) => label ?? capitalize(key));
|
|
105
|
+
}
|
|
106
|
+
function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
|
|
107
|
+
const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
|
|
108
|
+
if (typeof column === "string") {
|
|
109
|
+
return column;
|
|
110
|
+
} else if (typeof column === "object") {
|
|
111
|
+
return column.align ?? "center";
|
|
112
|
+
} else {
|
|
113
|
+
return "center";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function getColumnAlignmentForIndex(targetIdx, columns = []) {
|
|
117
|
+
const column = columns.at(targetIdx);
|
|
118
|
+
if (column == null) {
|
|
119
|
+
return "center";
|
|
120
|
+
} else if (typeof column === "string") {
|
|
121
|
+
return column;
|
|
122
|
+
} else if (typeof column === "object") {
|
|
123
|
+
return column.align ?? "center";
|
|
124
|
+
} else {
|
|
125
|
+
return "center";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function getColumnAlignments({
|
|
129
|
+
rows,
|
|
130
|
+
columns = []
|
|
131
|
+
}) {
|
|
132
|
+
if (rows.at(0) == null) {
|
|
133
|
+
throw new Error("first row can`t be undefined.");
|
|
134
|
+
}
|
|
135
|
+
if (Array.isArray(rows.at(0))) {
|
|
136
|
+
const firstPrimitiveRow = rows.at(0);
|
|
137
|
+
return Array.from({ length: firstPrimitiveRow.length }).map(
|
|
138
|
+
(_, idx) => getColumnAlignmentForIndex(idx, columns)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const firstObject = rows.at(0);
|
|
142
|
+
return Object.keys(firstObject).map(
|
|
143
|
+
(key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// packages/utils/src/lib/text-formats/html/table.ts
|
|
148
|
+
function wrap(elem, content) {
|
|
149
|
+
return `<${elem}>${content}</${elem}>${NEW_LINE}`;
|
|
150
|
+
}
|
|
151
|
+
function wrapRow(content) {
|
|
152
|
+
const elem = "tr";
|
|
153
|
+
return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
|
|
154
|
+
}
|
|
155
|
+
function table(tableData) {
|
|
156
|
+
if (tableData.rows.length === 0) {
|
|
157
|
+
throw new Error("Data can't be empty");
|
|
158
|
+
}
|
|
159
|
+
const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
|
|
160
|
+
const tableHeaderRow = wrapRow(tableHeaderCols);
|
|
161
|
+
const tableBody = rowToStringArray(tableData).map((arr) => {
|
|
162
|
+
const columns = arr.map((s) => wrap("td", s)).join("");
|
|
163
|
+
return wrapRow(columns);
|
|
164
|
+
}).join("");
|
|
165
|
+
return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// packages/utils/src/lib/text-formats/md/font-style.ts
|
|
169
|
+
var boldWrap = "**";
|
|
170
|
+
function bold2(text) {
|
|
171
|
+
return `${boldWrap}${text}${boldWrap}`;
|
|
172
|
+
}
|
|
173
|
+
var italicWrap = "_";
|
|
174
|
+
function italic2(text) {
|
|
175
|
+
return `${italicWrap}${text}${italicWrap}`;
|
|
176
|
+
}
|
|
177
|
+
var strikeThroughWrap = "~";
|
|
178
|
+
function strikeThrough(text) {
|
|
179
|
+
return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
|
|
180
|
+
}
|
|
181
|
+
var codeWrap = "`";
|
|
182
|
+
function code2(text) {
|
|
183
|
+
return `${codeWrap}${text}${codeWrap}`;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// packages/utils/src/lib/text-formats/md/headline.ts
|
|
187
|
+
function headline(text, hierarchy = 1) {
|
|
188
|
+
return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
|
|
189
|
+
}
|
|
190
|
+
function h(text, hierarchy = 1) {
|
|
191
|
+
return headline(text, hierarchy);
|
|
192
|
+
}
|
|
193
|
+
function h1(text) {
|
|
194
|
+
return headline(text, 1);
|
|
195
|
+
}
|
|
196
|
+
function h2(text) {
|
|
197
|
+
return headline(text, 2);
|
|
198
|
+
}
|
|
199
|
+
function h3(text) {
|
|
200
|
+
return headline(text, 3);
|
|
201
|
+
}
|
|
202
|
+
function h4(text) {
|
|
203
|
+
return headline(text, 4);
|
|
204
|
+
}
|
|
205
|
+
function h5(text) {
|
|
206
|
+
return headline(text, 5);
|
|
207
|
+
}
|
|
208
|
+
function h6(text) {
|
|
209
|
+
return headline(text, 6);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// packages/utils/src/lib/text-formats/md/image.ts
|
|
213
|
+
function image(src, alt) {
|
|
214
|
+
return ``;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// packages/utils/src/lib/text-formats/md/link.ts
|
|
218
|
+
function link2(href, text) {
|
|
219
|
+
return `[${text || href}](${href})`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// packages/utils/src/lib/text-formats/md/list.ts
|
|
223
|
+
function li(text, order = "unordered") {
|
|
224
|
+
const style = order === "unordered" ? "-" : "- [ ]";
|
|
225
|
+
return `${style} ${text}`;
|
|
226
|
+
}
|
|
227
|
+
function indentation(text, level = 1) {
|
|
228
|
+
return `${TAB.repeat(level)}${text}`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// packages/utils/src/lib/text-formats/md/paragraphs.ts
|
|
232
|
+
function paragraphs(...sections) {
|
|
233
|
+
return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// packages/utils/src/lib/text-formats/md/section.ts
|
|
237
|
+
function section(...contents) {
|
|
238
|
+
return `${lines(...contents)}${NEW_LINE}`;
|
|
239
|
+
}
|
|
240
|
+
function lines(...contents) {
|
|
241
|
+
return `${contents.filter(Boolean).join(NEW_LINE)}`;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// packages/utils/src/lib/text-formats/md/table.ts
|
|
245
|
+
var alignString = /* @__PURE__ */ new Map([
|
|
246
|
+
["left", ":--"],
|
|
247
|
+
["center", ":--:"],
|
|
248
|
+
["right", "--:"]
|
|
249
|
+
]);
|
|
250
|
+
function tableRow(rows) {
|
|
251
|
+
return `|${rows.join("|")}|`;
|
|
252
|
+
}
|
|
253
|
+
function table2(data) {
|
|
254
|
+
if (data.rows.length === 0) {
|
|
255
|
+
throw new Error("Data can't be empty");
|
|
256
|
+
}
|
|
257
|
+
const alignmentRow = getColumnAlignments(data).map(
|
|
258
|
+
(s) => alignString.get(s) ?? String(alignString.get("center"))
|
|
259
|
+
);
|
|
260
|
+
return section(
|
|
261
|
+
`${lines(
|
|
262
|
+
tableRow(columnsToStringArray(data)),
|
|
263
|
+
tableRow(alignmentRow),
|
|
264
|
+
...rowToStringArray(data).map(tableRow)
|
|
265
|
+
)}`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// packages/utils/src/lib/text-formats/index.ts
|
|
270
|
+
var md = {
|
|
271
|
+
bold: bold2,
|
|
272
|
+
italic: italic2,
|
|
273
|
+
strikeThrough,
|
|
274
|
+
code: code2,
|
|
275
|
+
link: link2,
|
|
276
|
+
image,
|
|
277
|
+
headline,
|
|
278
|
+
h,
|
|
279
|
+
h1,
|
|
280
|
+
h2,
|
|
281
|
+
h3,
|
|
282
|
+
h4,
|
|
283
|
+
h5,
|
|
284
|
+
h6,
|
|
285
|
+
indentation,
|
|
286
|
+
lines,
|
|
287
|
+
li,
|
|
288
|
+
section,
|
|
289
|
+
paragraphs,
|
|
290
|
+
table: table2
|
|
291
|
+
};
|
|
292
|
+
var html = {
|
|
293
|
+
bold,
|
|
294
|
+
italic,
|
|
295
|
+
code,
|
|
296
|
+
link,
|
|
297
|
+
details,
|
|
298
|
+
table
|
|
299
|
+
};
|
|
8
300
|
|
|
9
301
|
// packages/models/src/lib/implementation/schemas.ts
|
|
10
302
|
import { MATERIAL_ICONS } from "vscode-material-icons";
|
|
@@ -71,6 +363,7 @@ function missingRefsForCategoriesErrorMsg(categories, plugins) {
|
|
|
71
363
|
}
|
|
72
364
|
|
|
73
365
|
// packages/models/src/lib/implementation/schemas.ts
|
|
366
|
+
var primitiveValueSchema = z.union([z.string(), z.number()]);
|
|
74
367
|
function executionMetaSchema(options = {
|
|
75
368
|
descriptionDate: "Execution start date and time",
|
|
76
369
|
descriptionDuration: "Execution duration in ms"
|
|
@@ -162,6 +455,7 @@ function hasNonZeroWeightedRef(refs) {
|
|
|
162
455
|
}
|
|
163
456
|
|
|
164
457
|
// packages/models/src/lib/audit.ts
|
|
458
|
+
import { z as z2 } from "zod";
|
|
165
459
|
var auditSchema = z2.object({
|
|
166
460
|
slug: slugSchema.describe("ID (unique within plugin)")
|
|
167
461
|
}).merge(
|
|
@@ -191,7 +485,7 @@ function getDuplicateSlugsInAudits(audits) {
|
|
|
191
485
|
}
|
|
192
486
|
|
|
193
487
|
// packages/models/src/lib/audit-output.ts
|
|
194
|
-
import { z as
|
|
488
|
+
import { z as z5 } from "zod";
|
|
195
489
|
|
|
196
490
|
// packages/models/src/lib/issue.ts
|
|
197
491
|
import { z as z3 } from "zod";
|
|
@@ -222,16 +516,61 @@ var issueSchema = z3.object(
|
|
|
222
516
|
{ description: "Issue information" }
|
|
223
517
|
);
|
|
224
518
|
|
|
519
|
+
// packages/models/src/lib/table.ts
|
|
520
|
+
import { z as z4 } from "zod";
|
|
521
|
+
var tableAlignmentSchema = z4.enum(["left", "center", "right"], {
|
|
522
|
+
description: "Cell alignment"
|
|
523
|
+
});
|
|
524
|
+
var tableColumnObjectSchema = z4.object({
|
|
525
|
+
key: z4.string(),
|
|
526
|
+
label: z4.string().optional(),
|
|
527
|
+
align: tableAlignmentSchema.optional()
|
|
528
|
+
});
|
|
529
|
+
var tableRowObjectSchema = z4.record(primitiveValueSchema, {
|
|
530
|
+
description: "Object row"
|
|
531
|
+
});
|
|
532
|
+
var tableRowPrimitiveSchema = z4.array(primitiveValueSchema, {
|
|
533
|
+
description: "Primitive row"
|
|
534
|
+
});
|
|
535
|
+
var tableSharedSchema = z4.object({
|
|
536
|
+
title: z4.string().optional().describe("Display title for table")
|
|
537
|
+
});
|
|
538
|
+
var tablePrimitiveSchema = tableSharedSchema.merge(
|
|
539
|
+
z4.object(
|
|
540
|
+
{
|
|
541
|
+
columns: z4.array(tableAlignmentSchema).optional(),
|
|
542
|
+
rows: z4.array(tableRowPrimitiveSchema)
|
|
543
|
+
},
|
|
544
|
+
{ description: "Table with primitive rows and optional alignment columns" }
|
|
545
|
+
)
|
|
546
|
+
);
|
|
547
|
+
var tableObjectSchema = tableSharedSchema.merge(
|
|
548
|
+
z4.object(
|
|
549
|
+
{
|
|
550
|
+
columns: z4.union([
|
|
551
|
+
z4.array(tableAlignmentSchema),
|
|
552
|
+
z4.array(tableColumnObjectSchema)
|
|
553
|
+
]).optional(),
|
|
554
|
+
rows: z4.array(tableRowObjectSchema)
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
description: "Table with object rows and optional alignment or object columns"
|
|
558
|
+
}
|
|
559
|
+
)
|
|
560
|
+
);
|
|
561
|
+
var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
|
|
562
|
+
|
|
225
563
|
// packages/models/src/lib/audit-output.ts
|
|
226
564
|
var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
|
|
227
|
-
var auditDisplayValueSchema =
|
|
228
|
-
var auditDetailsSchema =
|
|
565
|
+
var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
|
|
566
|
+
var auditDetailsSchema = z5.object(
|
|
229
567
|
{
|
|
230
|
-
issues:
|
|
568
|
+
issues: z5.array(issueSchema, { description: "List of findings" }).optional(),
|
|
569
|
+
table: tableSchema("Table of related findings").optional()
|
|
231
570
|
},
|
|
232
571
|
{ description: "Detailed information" }
|
|
233
572
|
);
|
|
234
|
-
var auditOutputSchema =
|
|
573
|
+
var auditOutputSchema = z5.object(
|
|
235
574
|
{
|
|
236
575
|
slug: slugSchema.describe("Reference to audit"),
|
|
237
576
|
displayValue: auditDisplayValueSchema,
|
|
@@ -241,7 +580,7 @@ var auditOutputSchema = z4.object(
|
|
|
241
580
|
},
|
|
242
581
|
{ description: "Audit information" }
|
|
243
582
|
);
|
|
244
|
-
var auditOutputsSchema =
|
|
583
|
+
var auditOutputsSchema = z5.array(auditOutputSchema, {
|
|
245
584
|
description: "List of JSON formatted audit output emitted by the runner process of a plugin"
|
|
246
585
|
}).refine(
|
|
247
586
|
(audits) => !getDuplicateSlugsInAudits2(audits),
|
|
@@ -258,13 +597,13 @@ function getDuplicateSlugsInAudits2(audits) {
|
|
|
258
597
|
}
|
|
259
598
|
|
|
260
599
|
// packages/models/src/lib/category-config.ts
|
|
261
|
-
import { z as
|
|
600
|
+
import { z as z6 } from "zod";
|
|
262
601
|
var categoryRefSchema = weightedRefSchema(
|
|
263
602
|
"Weighted references to audits and/or groups for the category",
|
|
264
603
|
"Slug of an audit or group (depending on `type`)"
|
|
265
604
|
).merge(
|
|
266
|
-
|
|
267
|
-
type:
|
|
605
|
+
z6.object({
|
|
606
|
+
type: z6.enum(["audit", "group"], {
|
|
268
607
|
description: "Discriminant for reference kind, affects where `slug` is looked up"
|
|
269
608
|
}),
|
|
270
609
|
plugin: slugSchema.describe(
|
|
@@ -285,8 +624,8 @@ var categoryConfigSchema = scorableSchema(
|
|
|
285
624
|
description: "Meta info for category"
|
|
286
625
|
})
|
|
287
626
|
).merge(
|
|
288
|
-
|
|
289
|
-
isBinary:
|
|
627
|
+
z6.object({
|
|
628
|
+
isBinary: z6.boolean({
|
|
290
629
|
description: 'Is this a binary category (i.e. only a perfect score considered a "pass")?'
|
|
291
630
|
}).optional()
|
|
292
631
|
})
|
|
@@ -302,7 +641,7 @@ function getDuplicateRefsInCategoryMetrics(metrics) {
|
|
|
302
641
|
metrics.map(({ slug, type, plugin }) => `${type} :: ${plugin} / ${slug}`)
|
|
303
642
|
);
|
|
304
643
|
}
|
|
305
|
-
var categoriesSchema =
|
|
644
|
+
var categoriesSchema = z6.array(categoryConfigSchema, {
|
|
306
645
|
description: "Categorization of individual audits"
|
|
307
646
|
}).refine(
|
|
308
647
|
(categoryCfg) => !getDuplicateSlugCategories(categoryCfg),
|
|
@@ -321,18 +660,18 @@ function getDuplicateSlugCategories(categories) {
|
|
|
321
660
|
}
|
|
322
661
|
|
|
323
662
|
// packages/models/src/lib/commit.ts
|
|
324
|
-
import { z as
|
|
325
|
-
var commitSchema =
|
|
663
|
+
import { z as z7 } from "zod";
|
|
664
|
+
var commitSchema = z7.object(
|
|
326
665
|
{
|
|
327
|
-
hash:
|
|
666
|
+
hash: z7.string({ description: "Commit SHA (full)" }).regex(
|
|
328
667
|
/^[\da-f]{40}$/,
|
|
329
668
|
"Commit SHA should be a 40-character hexadecimal string"
|
|
330
669
|
),
|
|
331
|
-
message:
|
|
332
|
-
date:
|
|
670
|
+
message: z7.string({ description: "Commit message" }),
|
|
671
|
+
date: z7.coerce.date({
|
|
333
672
|
description: "Date and time when commit was authored"
|
|
334
673
|
}),
|
|
335
|
-
author:
|
|
674
|
+
author: z7.string({
|
|
336
675
|
description: "Commit author name"
|
|
337
676
|
}).trim()
|
|
338
677
|
},
|
|
@@ -340,22 +679,22 @@ var commitSchema = z6.object(
|
|
|
340
679
|
);
|
|
341
680
|
|
|
342
681
|
// packages/models/src/lib/core-config.ts
|
|
343
|
-
import { z as
|
|
682
|
+
import { z as z13 } from "zod";
|
|
344
683
|
|
|
345
684
|
// packages/models/src/lib/persist-config.ts
|
|
346
|
-
import { z as
|
|
347
|
-
var formatSchema =
|
|
348
|
-
var persistConfigSchema =
|
|
685
|
+
import { z as z8 } from "zod";
|
|
686
|
+
var formatSchema = z8.enum(["json", "md"]);
|
|
687
|
+
var persistConfigSchema = z8.object({
|
|
349
688
|
outputDir: filePathSchema.describe("Artifacts folder").optional(),
|
|
350
689
|
filename: fileNameSchema.describe("Artifacts file name (without extension)").optional(),
|
|
351
|
-
format:
|
|
690
|
+
format: z8.array(formatSchema).optional()
|
|
352
691
|
});
|
|
353
692
|
|
|
354
693
|
// packages/models/src/lib/plugin-config.ts
|
|
355
|
-
import { z as
|
|
694
|
+
import { z as z11 } from "zod";
|
|
356
695
|
|
|
357
696
|
// packages/models/src/lib/group.ts
|
|
358
|
-
import { z as
|
|
697
|
+
import { z as z9 } from "zod";
|
|
359
698
|
var groupRefSchema = weightedRefSchema(
|
|
360
699
|
"Weighted reference to a group",
|
|
361
700
|
"Reference slug to a group within this plugin (e.g. 'max-lines')"
|
|
@@ -372,7 +711,7 @@ var groupSchema = scorableSchema(
|
|
|
372
711
|
getDuplicateRefsInGroups,
|
|
373
712
|
duplicateRefsInGroupsErrorMsg
|
|
374
713
|
).merge(groupMetaSchema);
|
|
375
|
-
var groupsSchema =
|
|
714
|
+
var groupsSchema = z9.array(groupSchema, {
|
|
376
715
|
description: "List of groups"
|
|
377
716
|
}).optional().refine(
|
|
378
717
|
(groups) => !getDuplicateSlugsInGroups(groups),
|
|
@@ -400,14 +739,14 @@ function getDuplicateSlugsInGroups(groups) {
|
|
|
400
739
|
}
|
|
401
740
|
|
|
402
741
|
// packages/models/src/lib/runner-config.ts
|
|
403
|
-
import { z as
|
|
404
|
-
var outputTransformSchema =
|
|
405
|
-
var runnerConfigSchema =
|
|
742
|
+
import { z as z10 } from "zod";
|
|
743
|
+
var outputTransformSchema = z10.function().args(z10.unknown()).returns(z10.union([auditOutputsSchema, z10.promise(auditOutputsSchema)]));
|
|
744
|
+
var runnerConfigSchema = z10.object(
|
|
406
745
|
{
|
|
407
|
-
command:
|
|
746
|
+
command: z10.string({
|
|
408
747
|
description: "Shell command to execute"
|
|
409
748
|
}),
|
|
410
|
-
args:
|
|
749
|
+
args: z10.array(z10.string({ description: "Command arguments" })).optional(),
|
|
411
750
|
outputFile: filePathSchema.describe("Output path"),
|
|
412
751
|
outputTransform: outputTransformSchema.optional()
|
|
413
752
|
},
|
|
@@ -415,8 +754,8 @@ var runnerConfigSchema = z9.object(
|
|
|
415
754
|
description: "How to execute runner"
|
|
416
755
|
}
|
|
417
756
|
);
|
|
418
|
-
var onProgressSchema =
|
|
419
|
-
var runnerFunctionSchema =
|
|
757
|
+
var onProgressSchema = z10.function().args(z10.unknown()).returns(z10.void());
|
|
758
|
+
var runnerFunctionSchema = z10.function().args(onProgressSchema.optional()).returns(z10.union([auditOutputsSchema, z10.promise(auditOutputsSchema)]));
|
|
420
759
|
|
|
421
760
|
// packages/models/src/lib/plugin-config.ts
|
|
422
761
|
var pluginMetaSchema = packageVersionSchema().merge(
|
|
@@ -427,13 +766,13 @@ var pluginMetaSchema = packageVersionSchema().merge(
|
|
|
427
766
|
description: "Plugin metadata"
|
|
428
767
|
})
|
|
429
768
|
).merge(
|
|
430
|
-
|
|
769
|
+
z11.object({
|
|
431
770
|
slug: slugSchema.describe("Unique plugin slug within core config"),
|
|
432
771
|
icon: materialIconSchema
|
|
433
772
|
})
|
|
434
773
|
);
|
|
435
|
-
var pluginDataSchema =
|
|
436
|
-
runner:
|
|
774
|
+
var pluginDataSchema = z11.object({
|
|
775
|
+
runner: z11.union([runnerConfigSchema, runnerFunctionSchema]),
|
|
437
776
|
audits: pluginAuditsSchema,
|
|
438
777
|
groups: groupsSchema
|
|
439
778
|
});
|
|
@@ -459,22 +798,22 @@ function getMissingRefsFromGroups(pluginCfg) {
|
|
|
459
798
|
}
|
|
460
799
|
|
|
461
800
|
// packages/models/src/lib/upload-config.ts
|
|
462
|
-
import { z as
|
|
463
|
-
var uploadConfigSchema =
|
|
801
|
+
import { z as z12 } from "zod";
|
|
802
|
+
var uploadConfigSchema = z12.object({
|
|
464
803
|
server: urlSchema.describe("URL of deployed portal API"),
|
|
465
|
-
apiKey:
|
|
804
|
+
apiKey: z12.string({
|
|
466
805
|
description: "API key with write access to portal (use `process.env` for security)"
|
|
467
806
|
}),
|
|
468
807
|
organization: slugSchema.describe(
|
|
469
808
|
"Organization slug from Code PushUp portal"
|
|
470
809
|
),
|
|
471
810
|
project: slugSchema.describe("Project slug from Code PushUp portal"),
|
|
472
|
-
timeout:
|
|
811
|
+
timeout: z12.number({ description: "Request timeout in minutes (default is 5)" }).positive().int().optional()
|
|
473
812
|
});
|
|
474
813
|
|
|
475
814
|
// packages/models/src/lib/core-config.ts
|
|
476
|
-
var unrefinedCoreConfigSchema =
|
|
477
|
-
plugins:
|
|
815
|
+
var unrefinedCoreConfigSchema = z13.object({
|
|
816
|
+
plugins: z13.array(pluginConfigSchema, {
|
|
478
817
|
description: "List of plugins to be used (official, community-provided, or custom)"
|
|
479
818
|
}).min(1),
|
|
480
819
|
/** portal configuration for persisting results */
|
|
@@ -497,7 +836,7 @@ function refineCoreConfig(schema) {
|
|
|
497
836
|
}
|
|
498
837
|
|
|
499
838
|
// packages/models/src/lib/report.ts
|
|
500
|
-
import { z as
|
|
839
|
+
import { z as z14 } from "zod";
|
|
501
840
|
var auditReportSchema = auditSchema.merge(auditOutputSchema);
|
|
502
841
|
var pluginReportSchema = pluginMetaSchema.merge(
|
|
503
842
|
executionMetaSchema({
|
|
@@ -505,9 +844,9 @@ var pluginReportSchema = pluginMetaSchema.merge(
|
|
|
505
844
|
descriptionDuration: "Duration of the plugin run in ms"
|
|
506
845
|
})
|
|
507
846
|
).merge(
|
|
508
|
-
|
|
509
|
-
audits:
|
|
510
|
-
groups:
|
|
847
|
+
z14.object({
|
|
848
|
+
audits: z14.array(auditReportSchema).min(1),
|
|
849
|
+
groups: z14.array(groupSchema).optional()
|
|
511
850
|
})
|
|
512
851
|
).refine(
|
|
513
852
|
(pluginReport) => !getMissingRefsFromGroups2(pluginReport.audits, pluginReport.groups ?? []),
|
|
@@ -541,10 +880,10 @@ var reportSchema = packageVersionSchema({
|
|
|
541
880
|
descriptionDuration: "Duration of the collect run in ms"
|
|
542
881
|
})
|
|
543
882
|
).merge(
|
|
544
|
-
|
|
883
|
+
z14.object(
|
|
545
884
|
{
|
|
546
|
-
categories:
|
|
547
|
-
plugins:
|
|
885
|
+
categories: z14.array(categoryConfigSchema),
|
|
886
|
+
plugins: z14.array(pluginReportSchema).min(1),
|
|
548
887
|
commit: commitSchema.describe("Git commit for which report was collected").nullable()
|
|
549
888
|
},
|
|
550
889
|
{ description: "Collect output data" }
|
|
@@ -560,36 +899,40 @@ var reportSchema = packageVersionSchema({
|
|
|
560
899
|
);
|
|
561
900
|
|
|
562
901
|
// packages/models/src/lib/reports-diff.ts
|
|
563
|
-
import { z as
|
|
902
|
+
import { z as z15 } from "zod";
|
|
564
903
|
function makeComparisonSchema(schema) {
|
|
565
904
|
const sharedDescription = schema.description || "Result";
|
|
566
|
-
return
|
|
905
|
+
return z15.object({
|
|
567
906
|
before: schema.describe(`${sharedDescription} (source commit)`),
|
|
568
907
|
after: schema.describe(`${sharedDescription} (target commit)`)
|
|
569
908
|
});
|
|
570
909
|
}
|
|
571
910
|
function makeArraysComparisonSchema(diffSchema, resultSchema, description) {
|
|
572
|
-
return
|
|
911
|
+
return z15.object(
|
|
573
912
|
{
|
|
574
|
-
changed:
|
|
575
|
-
unchanged:
|
|
576
|
-
added:
|
|
577
|
-
removed:
|
|
913
|
+
changed: z15.array(diffSchema),
|
|
914
|
+
unchanged: z15.array(resultSchema),
|
|
915
|
+
added: z15.array(resultSchema),
|
|
916
|
+
removed: z15.array(resultSchema)
|
|
578
917
|
},
|
|
579
918
|
{ description }
|
|
580
919
|
);
|
|
581
920
|
}
|
|
582
|
-
var scorableMetaSchema =
|
|
921
|
+
var scorableMetaSchema = z15.object({
|
|
922
|
+
slug: slugSchema,
|
|
923
|
+
title: titleSchema,
|
|
924
|
+
docsUrl: docsUrlSchema
|
|
925
|
+
});
|
|
583
926
|
var scorableWithPluginMetaSchema = scorableMetaSchema.merge(
|
|
584
|
-
|
|
585
|
-
plugin: pluginMetaSchema.pick({ slug: true, title: true }).describe("Plugin which defines it")
|
|
927
|
+
z15.object({
|
|
928
|
+
plugin: pluginMetaSchema.pick({ slug: true, title: true, docsUrl: true }).describe("Plugin which defines it")
|
|
586
929
|
})
|
|
587
930
|
);
|
|
588
931
|
var scorableDiffSchema = scorableMetaSchema.merge(
|
|
589
|
-
|
|
932
|
+
z15.object({
|
|
590
933
|
scores: makeComparisonSchema(scoreSchema).merge(
|
|
591
|
-
|
|
592
|
-
diff:
|
|
934
|
+
z15.object({
|
|
935
|
+
diff: z15.number().min(-1).max(1).describe("Score change (`scores.after - scores.before`)")
|
|
593
936
|
})
|
|
594
937
|
).describe("Score comparison")
|
|
595
938
|
})
|
|
@@ -600,10 +943,10 @@ var scorableWithPluginDiffSchema = scorableDiffSchema.merge(
|
|
|
600
943
|
var categoryDiffSchema = scorableDiffSchema;
|
|
601
944
|
var groupDiffSchema = scorableWithPluginDiffSchema;
|
|
602
945
|
var auditDiffSchema = scorableWithPluginDiffSchema.merge(
|
|
603
|
-
|
|
946
|
+
z15.object({
|
|
604
947
|
values: makeComparisonSchema(auditValueSchema).merge(
|
|
605
|
-
|
|
606
|
-
diff:
|
|
948
|
+
z15.object({
|
|
949
|
+
diff: z15.number().int().describe("Value change (`values.after - values.before`)")
|
|
607
950
|
})
|
|
608
951
|
).describe("Audit `value` comparison"),
|
|
609
952
|
displayValues: makeComparisonSchema(auditDisplayValueSchema).describe(
|
|
@@ -612,15 +955,15 @@ var auditDiffSchema = scorableWithPluginDiffSchema.merge(
|
|
|
612
955
|
})
|
|
613
956
|
);
|
|
614
957
|
var categoryResultSchema = scorableMetaSchema.merge(
|
|
615
|
-
|
|
958
|
+
z15.object({ score: scoreSchema })
|
|
616
959
|
);
|
|
617
960
|
var groupResultSchema = scorableWithPluginMetaSchema.merge(
|
|
618
|
-
|
|
961
|
+
z15.object({ score: scoreSchema })
|
|
619
962
|
);
|
|
620
963
|
var auditResultSchema = scorableWithPluginMetaSchema.merge(
|
|
621
964
|
auditOutputSchema.pick({ score: true, value: true, displayValue: true })
|
|
622
965
|
);
|
|
623
|
-
var reportsDiffSchema =
|
|
966
|
+
var reportsDiffSchema = z15.object({
|
|
624
967
|
commits: makeComparisonSchema(commitSchema).nullable().describe("Commits identifying compared reports"),
|
|
625
968
|
categories: makeArraysComparisonSchema(
|
|
626
969
|
categoryDiffSchema,
|
|
@@ -704,7 +1047,7 @@ async function ensureDirectoryExists(baseDir) {
|
|
|
704
1047
|
await mkdir(baseDir, { recursive: true });
|
|
705
1048
|
return;
|
|
706
1049
|
} catch (error) {
|
|
707
|
-
ui().logger.
|
|
1050
|
+
ui().logger.info(error.message);
|
|
708
1051
|
if (error.code !== "EEXIST") {
|
|
709
1052
|
throw error;
|
|
710
1053
|
}
|
|
@@ -715,6 +1058,7 @@ function pluginWorkDir(slug) {
|
|
|
715
1058
|
}
|
|
716
1059
|
|
|
717
1060
|
// packages/utils/src/lib/reports/utils.ts
|
|
1061
|
+
var { image: image2, bold: boldMd } = md;
|
|
718
1062
|
function calcDuration(start, stop) {
|
|
719
1063
|
return Math.round((stop ?? performance.now()) - start);
|
|
720
1064
|
}
|
|
@@ -750,13 +1094,13 @@ function executeProcess(cfg) {
|
|
|
750
1094
|
process2.on("error", (err) => {
|
|
751
1095
|
stderr += err.toString();
|
|
752
1096
|
});
|
|
753
|
-
process2.on("close", (
|
|
1097
|
+
process2.on("close", (code3) => {
|
|
754
1098
|
const timings = { date, duration: calcDuration(start) };
|
|
755
|
-
if (
|
|
1099
|
+
if (code3 === 0 || ignoreExitCode) {
|
|
756
1100
|
onComplete?.();
|
|
757
|
-
resolve({ code, stdout, stderr, ...timings });
|
|
1101
|
+
resolve({ code: code3, stdout, stderr, ...timings });
|
|
758
1102
|
} else {
|
|
759
|
-
const errorMsg = new ProcessError({ code, stdout, stderr, ...timings });
|
|
1103
|
+
const errorMsg = new ProcessError({ code: code3, stdout, stderr, ...timings });
|
|
760
1104
|
onError?.(errorMsg);
|
|
761
1105
|
reject(errorMsg);
|
|
762
1106
|
}
|
|
@@ -764,38 +1108,42 @@ function executeProcess(cfg) {
|
|
|
764
1108
|
});
|
|
765
1109
|
}
|
|
766
1110
|
|
|
767
|
-
// packages/utils/src/lib/git.ts
|
|
1111
|
+
// packages/utils/src/lib/git/git.ts
|
|
768
1112
|
import { simpleGit } from "simple-git";
|
|
769
1113
|
|
|
770
|
-
// packages/utils/src/lib/
|
|
771
|
-
import {
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
}
|
|
775
|
-
function toNumberPrecision(value, decimalPlaces) {
|
|
776
|
-
return Number(
|
|
777
|
-
`${Math.round(
|
|
778
|
-
Number.parseFloat(`${value}e${decimalPlaces}`)
|
|
779
|
-
)}e-${decimalPlaces}`
|
|
780
|
-
);
|
|
781
|
-
}
|
|
782
|
-
function toOrdinal(value) {
|
|
783
|
-
if (value % 10 === 1 && value % 100 !== 11) {
|
|
784
|
-
return `${value}st`;
|
|
785
|
-
}
|
|
786
|
-
if (value % 10 === 2 && value % 100 !== 12) {
|
|
787
|
-
return `${value}nd`;
|
|
788
|
-
}
|
|
789
|
-
if (value % 10 === 3 && value % 100 !== 13) {
|
|
790
|
-
return `${value}rd`;
|
|
791
|
-
}
|
|
792
|
-
return `${value}th`;
|
|
793
|
-
}
|
|
1114
|
+
// packages/utils/src/lib/git/git.commits-and-tags.ts
|
|
1115
|
+
import { simpleGit as simpleGit2 } from "simple-git";
|
|
1116
|
+
|
|
1117
|
+
// packages/utils/src/lib/semver.ts
|
|
1118
|
+
import { rcompare, valid } from "semver";
|
|
794
1119
|
|
|
795
1120
|
// packages/utils/src/lib/progress.ts
|
|
796
1121
|
import chalk3 from "chalk";
|
|
797
1122
|
import { MultiProgressBars } from "multi-progress-bars";
|
|
798
1123
|
|
|
1124
|
+
// packages/utils/src/lib/reports/formatting.ts
|
|
1125
|
+
var { headline: headline2, lines: lines2, link: link3, section: section2, table: table3 } = md;
|
|
1126
|
+
|
|
1127
|
+
// packages/utils/src/lib/reports/generate-md-report-categoy-section.ts
|
|
1128
|
+
var { link: link4, section: section3, h2: h22, lines: lines3, li: li2, bold: boldMd2, h3: h32, indentation: indentation2 } = md;
|
|
1129
|
+
|
|
1130
|
+
// packages/utils/src/lib/reports/generate-md-report.ts
|
|
1131
|
+
var { h1: h12, h2: h23, h3: h33, lines: lines4, link: link5, section: section4, code: codeMd } = md;
|
|
1132
|
+
var { bold: boldHtml, details: details2 } = html;
|
|
1133
|
+
|
|
1134
|
+
// packages/utils/src/lib/reports/generate-md-reports-diff.ts
|
|
1135
|
+
var {
|
|
1136
|
+
h1: h13,
|
|
1137
|
+
h2: h24,
|
|
1138
|
+
lines: lines5,
|
|
1139
|
+
link: link6,
|
|
1140
|
+
bold: boldMd3,
|
|
1141
|
+
italic: italicMd,
|
|
1142
|
+
table: table4,
|
|
1143
|
+
section: section5
|
|
1144
|
+
} = md;
|
|
1145
|
+
var { details: details3 } = html;
|
|
1146
|
+
|
|
799
1147
|
// packages/utils/src/lib/reports/log-stdout-summary.ts
|
|
800
1148
|
import chalk4 from "chalk";
|
|
801
1149
|
|
|
@@ -822,10 +1170,13 @@ function calculateCoverage(hit, found) {
|
|
|
822
1170
|
return found > 0 ? hit / found : 1;
|
|
823
1171
|
}
|
|
824
1172
|
function mergeConsecutiveNumbers(numberArr) {
|
|
825
|
-
return [...numberArr].sort().reduce((acc, currValue) => {
|
|
1173
|
+
return [...numberArr].sort((a, b) => a - b).reduce((acc, currValue) => {
|
|
826
1174
|
const prevValue = acc.at(-1);
|
|
827
1175
|
if (prevValue != null && (prevValue.start === currValue - 1 || prevValue.end === currValue - 1)) {
|
|
828
|
-
return [
|
|
1176
|
+
return [
|
|
1177
|
+
...acc.slice(0, -1),
|
|
1178
|
+
{ start: prevValue.start, end: currValue }
|
|
1179
|
+
];
|
|
829
1180
|
}
|
|
830
1181
|
return [...acc, { start: currValue }];
|
|
831
1182
|
}, []);
|
|
@@ -850,8 +1201,8 @@ function lcovReportToFunctionStat(record) {
|
|
|
850
1201
|
}
|
|
851
1202
|
function lcovReportToLineStat(record) {
|
|
852
1203
|
const missingCoverage = record.lines.hit < record.lines.found;
|
|
853
|
-
const
|
|
854
|
-
const linePositions = mergeConsecutiveNumbers(
|
|
1204
|
+
const lines6 = missingCoverage ? record.lines.details.filter((detail) => !detail.hit).map((detail) => detail.line) : [];
|
|
1205
|
+
const linePositions = mergeConsecutiveNumbers(lines6);
|
|
855
1206
|
return {
|
|
856
1207
|
totalFound: record.lines.found,
|
|
857
1208
|
totalHit: record.lines.hit,
|