@code-pushup/core 0.39.0 → 0.42.1
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/index.js +923 -545
- package/package.json +5 -6
- package/src/index.d.ts +1 -1
- package/src/lib/history.d.ts +0 -42
- package/src/lib/normalize.d.ts +2 -1
package/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// packages/models/src/lib/audit.ts
|
|
2
|
-
import { z as z2 } from "zod";
|
|
3
|
-
|
|
4
1
|
// packages/models/src/lib/implementation/schemas.ts
|
|
5
2
|
import { MATERIAL_ICONS } from "vscode-material-icons";
|
|
6
3
|
import { z } from "zod";
|
|
@@ -66,6 +63,7 @@ function missingRefsForCategoriesErrorMsg(categories, plugins) {
|
|
|
66
63
|
}
|
|
67
64
|
|
|
68
65
|
// packages/models/src/lib/implementation/schemas.ts
|
|
66
|
+
var primitiveValueSchema = z.union([z.string(), z.number()]);
|
|
69
67
|
function executionMetaSchema(options = {
|
|
70
68
|
descriptionDate: "Execution start date and time",
|
|
71
69
|
descriptionDuration: "Execution duration in ms"
|
|
@@ -157,6 +155,7 @@ function hasNonZeroWeightedRef(refs) {
|
|
|
157
155
|
}
|
|
158
156
|
|
|
159
157
|
// packages/models/src/lib/audit.ts
|
|
158
|
+
import { z as z2 } from "zod";
|
|
160
159
|
var auditSchema = z2.object({
|
|
161
160
|
slug: slugSchema.describe("ID (unique within plugin)")
|
|
162
161
|
}).merge(
|
|
@@ -186,7 +185,7 @@ function getDuplicateSlugsInAudits(audits) {
|
|
|
186
185
|
}
|
|
187
186
|
|
|
188
187
|
// packages/models/src/lib/audit-output.ts
|
|
189
|
-
import { z as
|
|
188
|
+
import { z as z5 } from "zod";
|
|
190
189
|
|
|
191
190
|
// packages/models/src/lib/issue.ts
|
|
192
191
|
import { z as z3 } from "zod";
|
|
@@ -217,16 +216,61 @@ var issueSchema = z3.object(
|
|
|
217
216
|
{ description: "Issue information" }
|
|
218
217
|
);
|
|
219
218
|
|
|
219
|
+
// packages/models/src/lib/table.ts
|
|
220
|
+
import { z as z4 } from "zod";
|
|
221
|
+
var tableAlignmentSchema = z4.enum(["left", "center", "right"], {
|
|
222
|
+
description: "Cell alignment"
|
|
223
|
+
});
|
|
224
|
+
var tableColumnObjectSchema = z4.object({
|
|
225
|
+
key: z4.string(),
|
|
226
|
+
label: z4.string().optional(),
|
|
227
|
+
align: tableAlignmentSchema.optional()
|
|
228
|
+
});
|
|
229
|
+
var tableRowObjectSchema = z4.record(primitiveValueSchema, {
|
|
230
|
+
description: "Object row"
|
|
231
|
+
});
|
|
232
|
+
var tableRowPrimitiveSchema = z4.array(primitiveValueSchema, {
|
|
233
|
+
description: "Primitive row"
|
|
234
|
+
});
|
|
235
|
+
var tableSharedSchema = z4.object({
|
|
236
|
+
title: z4.string().optional().describe("Display title for table")
|
|
237
|
+
});
|
|
238
|
+
var tablePrimitiveSchema = tableSharedSchema.merge(
|
|
239
|
+
z4.object(
|
|
240
|
+
{
|
|
241
|
+
columns: z4.array(tableAlignmentSchema).optional(),
|
|
242
|
+
rows: z4.array(tableRowPrimitiveSchema)
|
|
243
|
+
},
|
|
244
|
+
{ description: "Table with primitive rows and optional alignment columns" }
|
|
245
|
+
)
|
|
246
|
+
);
|
|
247
|
+
var tableObjectSchema = tableSharedSchema.merge(
|
|
248
|
+
z4.object(
|
|
249
|
+
{
|
|
250
|
+
columns: z4.union([
|
|
251
|
+
z4.array(tableAlignmentSchema),
|
|
252
|
+
z4.array(tableColumnObjectSchema)
|
|
253
|
+
]).optional(),
|
|
254
|
+
rows: z4.array(tableRowObjectSchema)
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
description: "Table with object rows and optional alignment or object columns"
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
);
|
|
261
|
+
var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
|
|
262
|
+
|
|
220
263
|
// packages/models/src/lib/audit-output.ts
|
|
221
264
|
var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
|
|
222
|
-
var auditDisplayValueSchema =
|
|
223
|
-
var auditDetailsSchema =
|
|
265
|
+
var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
|
|
266
|
+
var auditDetailsSchema = z5.object(
|
|
224
267
|
{
|
|
225
|
-
issues:
|
|
268
|
+
issues: z5.array(issueSchema, { description: "List of findings" }).optional(),
|
|
269
|
+
table: tableSchema("Table of related findings").optional()
|
|
226
270
|
},
|
|
227
271
|
{ description: "Detailed information" }
|
|
228
272
|
);
|
|
229
|
-
var auditOutputSchema =
|
|
273
|
+
var auditOutputSchema = z5.object(
|
|
230
274
|
{
|
|
231
275
|
slug: slugSchema.describe("Reference to audit"),
|
|
232
276
|
displayValue: auditDisplayValueSchema,
|
|
@@ -236,7 +280,7 @@ var auditOutputSchema = z4.object(
|
|
|
236
280
|
},
|
|
237
281
|
{ description: "Audit information" }
|
|
238
282
|
);
|
|
239
|
-
var auditOutputsSchema =
|
|
283
|
+
var auditOutputsSchema = z5.array(auditOutputSchema, {
|
|
240
284
|
description: "List of JSON formatted audit output emitted by the runner process of a plugin"
|
|
241
285
|
}).refine(
|
|
242
286
|
(audits) => !getDuplicateSlugsInAudits2(audits),
|
|
@@ -253,13 +297,13 @@ function getDuplicateSlugsInAudits2(audits) {
|
|
|
253
297
|
}
|
|
254
298
|
|
|
255
299
|
// packages/models/src/lib/category-config.ts
|
|
256
|
-
import { z as
|
|
300
|
+
import { z as z6 } from "zod";
|
|
257
301
|
var categoryRefSchema = weightedRefSchema(
|
|
258
302
|
"Weighted references to audits and/or groups for the category",
|
|
259
303
|
"Slug of an audit or group (depending on `type`)"
|
|
260
304
|
).merge(
|
|
261
|
-
|
|
262
|
-
type:
|
|
305
|
+
z6.object({
|
|
306
|
+
type: z6.enum(["audit", "group"], {
|
|
263
307
|
description: "Discriminant for reference kind, affects where `slug` is looked up"
|
|
264
308
|
}),
|
|
265
309
|
plugin: slugSchema.describe(
|
|
@@ -280,8 +324,8 @@ var categoryConfigSchema = scorableSchema(
|
|
|
280
324
|
description: "Meta info for category"
|
|
281
325
|
})
|
|
282
326
|
).merge(
|
|
283
|
-
|
|
284
|
-
isBinary:
|
|
327
|
+
z6.object({
|
|
328
|
+
isBinary: z6.boolean({
|
|
285
329
|
description: 'Is this a binary category (i.e. only a perfect score considered a "pass")?'
|
|
286
330
|
}).optional()
|
|
287
331
|
})
|
|
@@ -297,7 +341,7 @@ function getDuplicateRefsInCategoryMetrics(metrics) {
|
|
|
297
341
|
metrics.map(({ slug, type, plugin }) => `${type} :: ${plugin} / ${slug}`)
|
|
298
342
|
);
|
|
299
343
|
}
|
|
300
|
-
var categoriesSchema =
|
|
344
|
+
var categoriesSchema = z6.array(categoryConfigSchema, {
|
|
301
345
|
description: "Categorization of individual audits"
|
|
302
346
|
}).refine(
|
|
303
347
|
(categoryCfg) => !getDuplicateSlugCategories(categoryCfg),
|
|
@@ -316,18 +360,18 @@ function getDuplicateSlugCategories(categories) {
|
|
|
316
360
|
}
|
|
317
361
|
|
|
318
362
|
// packages/models/src/lib/commit.ts
|
|
319
|
-
import { z as
|
|
320
|
-
var commitSchema =
|
|
363
|
+
import { z as z7 } from "zod";
|
|
364
|
+
var commitSchema = z7.object(
|
|
321
365
|
{
|
|
322
|
-
hash:
|
|
366
|
+
hash: z7.string({ description: "Commit SHA (full)" }).regex(
|
|
323
367
|
/^[\da-f]{40}$/,
|
|
324
368
|
"Commit SHA should be a 40-character hexadecimal string"
|
|
325
369
|
),
|
|
326
|
-
message:
|
|
327
|
-
date:
|
|
370
|
+
message: z7.string({ description: "Commit message" }),
|
|
371
|
+
date: z7.coerce.date({
|
|
328
372
|
description: "Date and time when commit was authored"
|
|
329
373
|
}),
|
|
330
|
-
author:
|
|
374
|
+
author: z7.string({
|
|
331
375
|
description: "Commit author name"
|
|
332
376
|
}).trim()
|
|
333
377
|
},
|
|
@@ -335,22 +379,22 @@ var commitSchema = z6.object(
|
|
|
335
379
|
);
|
|
336
380
|
|
|
337
381
|
// packages/models/src/lib/core-config.ts
|
|
338
|
-
import { z as
|
|
382
|
+
import { z as z13 } from "zod";
|
|
339
383
|
|
|
340
384
|
// packages/models/src/lib/persist-config.ts
|
|
341
|
-
import { z as
|
|
342
|
-
var formatSchema =
|
|
343
|
-
var persistConfigSchema =
|
|
385
|
+
import { z as z8 } from "zod";
|
|
386
|
+
var formatSchema = z8.enum(["json", "md"]);
|
|
387
|
+
var persistConfigSchema = z8.object({
|
|
344
388
|
outputDir: filePathSchema.describe("Artifacts folder").optional(),
|
|
345
389
|
filename: fileNameSchema.describe("Artifacts file name (without extension)").optional(),
|
|
346
|
-
format:
|
|
390
|
+
format: z8.array(formatSchema).optional()
|
|
347
391
|
});
|
|
348
392
|
|
|
349
393
|
// packages/models/src/lib/plugin-config.ts
|
|
350
|
-
import { z as
|
|
394
|
+
import { z as z11 } from "zod";
|
|
351
395
|
|
|
352
396
|
// packages/models/src/lib/group.ts
|
|
353
|
-
import { z as
|
|
397
|
+
import { z as z9 } from "zod";
|
|
354
398
|
var groupRefSchema = weightedRefSchema(
|
|
355
399
|
"Weighted reference to a group",
|
|
356
400
|
"Reference slug to a group within this plugin (e.g. 'max-lines')"
|
|
@@ -367,7 +411,7 @@ var groupSchema = scorableSchema(
|
|
|
367
411
|
getDuplicateRefsInGroups,
|
|
368
412
|
duplicateRefsInGroupsErrorMsg
|
|
369
413
|
).merge(groupMetaSchema);
|
|
370
|
-
var groupsSchema =
|
|
414
|
+
var groupsSchema = z9.array(groupSchema, {
|
|
371
415
|
description: "List of groups"
|
|
372
416
|
}).optional().refine(
|
|
373
417
|
(groups) => !getDuplicateSlugsInGroups(groups),
|
|
@@ -395,14 +439,14 @@ function getDuplicateSlugsInGroups(groups) {
|
|
|
395
439
|
}
|
|
396
440
|
|
|
397
441
|
// packages/models/src/lib/runner-config.ts
|
|
398
|
-
import { z as
|
|
399
|
-
var outputTransformSchema =
|
|
400
|
-
var runnerConfigSchema =
|
|
442
|
+
import { z as z10 } from "zod";
|
|
443
|
+
var outputTransformSchema = z10.function().args(z10.unknown()).returns(z10.union([auditOutputsSchema, z10.promise(auditOutputsSchema)]));
|
|
444
|
+
var runnerConfigSchema = z10.object(
|
|
401
445
|
{
|
|
402
|
-
command:
|
|
446
|
+
command: z10.string({
|
|
403
447
|
description: "Shell command to execute"
|
|
404
448
|
}),
|
|
405
|
-
args:
|
|
449
|
+
args: z10.array(z10.string({ description: "Command arguments" })).optional(),
|
|
406
450
|
outputFile: filePathSchema.describe("Output path"),
|
|
407
451
|
outputTransform: outputTransformSchema.optional()
|
|
408
452
|
},
|
|
@@ -410,8 +454,8 @@ var runnerConfigSchema = z9.object(
|
|
|
410
454
|
description: "How to execute runner"
|
|
411
455
|
}
|
|
412
456
|
);
|
|
413
|
-
var onProgressSchema =
|
|
414
|
-
var runnerFunctionSchema =
|
|
457
|
+
var onProgressSchema = z10.function().args(z10.unknown()).returns(z10.void());
|
|
458
|
+
var runnerFunctionSchema = z10.function().args(onProgressSchema.optional()).returns(z10.union([auditOutputsSchema, z10.promise(auditOutputsSchema)]));
|
|
415
459
|
|
|
416
460
|
// packages/models/src/lib/plugin-config.ts
|
|
417
461
|
var pluginMetaSchema = packageVersionSchema().merge(
|
|
@@ -422,13 +466,13 @@ var pluginMetaSchema = packageVersionSchema().merge(
|
|
|
422
466
|
description: "Plugin metadata"
|
|
423
467
|
})
|
|
424
468
|
).merge(
|
|
425
|
-
|
|
469
|
+
z11.object({
|
|
426
470
|
slug: slugSchema.describe("Unique plugin slug within core config"),
|
|
427
471
|
icon: materialIconSchema
|
|
428
472
|
})
|
|
429
473
|
);
|
|
430
|
-
var pluginDataSchema =
|
|
431
|
-
runner:
|
|
474
|
+
var pluginDataSchema = z11.object({
|
|
475
|
+
runner: z11.union([runnerConfigSchema, runnerFunctionSchema]),
|
|
432
476
|
audits: pluginAuditsSchema,
|
|
433
477
|
groups: groupsSchema
|
|
434
478
|
});
|
|
@@ -454,22 +498,22 @@ function getMissingRefsFromGroups(pluginCfg) {
|
|
|
454
498
|
}
|
|
455
499
|
|
|
456
500
|
// packages/models/src/lib/upload-config.ts
|
|
457
|
-
import { z as
|
|
458
|
-
var uploadConfigSchema =
|
|
501
|
+
import { z as z12 } from "zod";
|
|
502
|
+
var uploadConfigSchema = z12.object({
|
|
459
503
|
server: urlSchema.describe("URL of deployed portal API"),
|
|
460
|
-
apiKey:
|
|
504
|
+
apiKey: z12.string({
|
|
461
505
|
description: "API key with write access to portal (use `process.env` for security)"
|
|
462
506
|
}),
|
|
463
507
|
organization: slugSchema.describe(
|
|
464
508
|
"Organization slug from Code PushUp portal"
|
|
465
509
|
),
|
|
466
510
|
project: slugSchema.describe("Project slug from Code PushUp portal"),
|
|
467
|
-
timeout:
|
|
511
|
+
timeout: z12.number({ description: "Request timeout in minutes (default is 5)" }).positive().int().optional()
|
|
468
512
|
});
|
|
469
513
|
|
|
470
514
|
// packages/models/src/lib/core-config.ts
|
|
471
|
-
var unrefinedCoreConfigSchema =
|
|
472
|
-
plugins:
|
|
515
|
+
var unrefinedCoreConfigSchema = z13.object({
|
|
516
|
+
plugins: z13.array(pluginConfigSchema, {
|
|
473
517
|
description: "List of plugins to be used (official, community-provided, or custom)"
|
|
474
518
|
}).min(1),
|
|
475
519
|
/** portal configuration for persisting results */
|
|
@@ -496,7 +540,7 @@ var CONFIG_FILE_NAME = "code-pushup.config";
|
|
|
496
540
|
var SUPPORTED_CONFIG_FILE_FORMATS = ["ts", "mjs", "js"];
|
|
497
541
|
|
|
498
542
|
// packages/models/src/lib/report.ts
|
|
499
|
-
import { z as
|
|
543
|
+
import { z as z14 } from "zod";
|
|
500
544
|
var auditReportSchema = auditSchema.merge(auditOutputSchema);
|
|
501
545
|
var pluginReportSchema = pluginMetaSchema.merge(
|
|
502
546
|
executionMetaSchema({
|
|
@@ -504,9 +548,9 @@ var pluginReportSchema = pluginMetaSchema.merge(
|
|
|
504
548
|
descriptionDuration: "Duration of the plugin run in ms"
|
|
505
549
|
})
|
|
506
550
|
).merge(
|
|
507
|
-
|
|
508
|
-
audits:
|
|
509
|
-
groups:
|
|
551
|
+
z14.object({
|
|
552
|
+
audits: z14.array(auditReportSchema).min(1),
|
|
553
|
+
groups: z14.array(groupSchema).optional()
|
|
510
554
|
})
|
|
511
555
|
).refine(
|
|
512
556
|
(pluginReport) => !getMissingRefsFromGroups2(pluginReport.audits, pluginReport.groups ?? []),
|
|
@@ -540,10 +584,10 @@ var reportSchema = packageVersionSchema({
|
|
|
540
584
|
descriptionDuration: "Duration of the collect run in ms"
|
|
541
585
|
})
|
|
542
586
|
).merge(
|
|
543
|
-
|
|
587
|
+
z14.object(
|
|
544
588
|
{
|
|
545
|
-
categories:
|
|
546
|
-
plugins:
|
|
589
|
+
categories: z14.array(categoryConfigSchema),
|
|
590
|
+
plugins: z14.array(pluginReportSchema).min(1),
|
|
547
591
|
commit: commitSchema.describe("Git commit for which report was collected").nullable()
|
|
548
592
|
},
|
|
549
593
|
{ description: "Collect output data" }
|
|
@@ -559,40 +603,40 @@ var reportSchema = packageVersionSchema({
|
|
|
559
603
|
);
|
|
560
604
|
|
|
561
605
|
// packages/models/src/lib/reports-diff.ts
|
|
562
|
-
import { z as
|
|
606
|
+
import { z as z15 } from "zod";
|
|
563
607
|
function makeComparisonSchema(schema) {
|
|
564
608
|
const sharedDescription = schema.description || "Result";
|
|
565
|
-
return
|
|
609
|
+
return z15.object({
|
|
566
610
|
before: schema.describe(`${sharedDescription} (source commit)`),
|
|
567
611
|
after: schema.describe(`${sharedDescription} (target commit)`)
|
|
568
612
|
});
|
|
569
613
|
}
|
|
570
614
|
function makeArraysComparisonSchema(diffSchema, resultSchema, description) {
|
|
571
|
-
return
|
|
615
|
+
return z15.object(
|
|
572
616
|
{
|
|
573
|
-
changed:
|
|
574
|
-
unchanged:
|
|
575
|
-
added:
|
|
576
|
-
removed:
|
|
617
|
+
changed: z15.array(diffSchema),
|
|
618
|
+
unchanged: z15.array(resultSchema),
|
|
619
|
+
added: z15.array(resultSchema),
|
|
620
|
+
removed: z15.array(resultSchema)
|
|
577
621
|
},
|
|
578
622
|
{ description }
|
|
579
623
|
);
|
|
580
624
|
}
|
|
581
|
-
var scorableMetaSchema =
|
|
625
|
+
var scorableMetaSchema = z15.object({
|
|
582
626
|
slug: slugSchema,
|
|
583
627
|
title: titleSchema,
|
|
584
628
|
docsUrl: docsUrlSchema
|
|
585
629
|
});
|
|
586
630
|
var scorableWithPluginMetaSchema = scorableMetaSchema.merge(
|
|
587
|
-
|
|
631
|
+
z15.object({
|
|
588
632
|
plugin: pluginMetaSchema.pick({ slug: true, title: true, docsUrl: true }).describe("Plugin which defines it")
|
|
589
633
|
})
|
|
590
634
|
);
|
|
591
635
|
var scorableDiffSchema = scorableMetaSchema.merge(
|
|
592
|
-
|
|
636
|
+
z15.object({
|
|
593
637
|
scores: makeComparisonSchema(scoreSchema).merge(
|
|
594
|
-
|
|
595
|
-
diff:
|
|
638
|
+
z15.object({
|
|
639
|
+
diff: z15.number().min(-1).max(1).describe("Score change (`scores.after - scores.before`)")
|
|
596
640
|
})
|
|
597
641
|
).describe("Score comparison")
|
|
598
642
|
})
|
|
@@ -603,10 +647,10 @@ var scorableWithPluginDiffSchema = scorableDiffSchema.merge(
|
|
|
603
647
|
var categoryDiffSchema = scorableDiffSchema;
|
|
604
648
|
var groupDiffSchema = scorableWithPluginDiffSchema;
|
|
605
649
|
var auditDiffSchema = scorableWithPluginDiffSchema.merge(
|
|
606
|
-
|
|
650
|
+
z15.object({
|
|
607
651
|
values: makeComparisonSchema(auditValueSchema).merge(
|
|
608
|
-
|
|
609
|
-
diff:
|
|
652
|
+
z15.object({
|
|
653
|
+
diff: z15.number().int().describe("Value change (`values.after - values.before`)")
|
|
610
654
|
})
|
|
611
655
|
).describe("Audit `value` comparison"),
|
|
612
656
|
displayValues: makeComparisonSchema(auditDisplayValueSchema).describe(
|
|
@@ -615,15 +659,15 @@ var auditDiffSchema = scorableWithPluginDiffSchema.merge(
|
|
|
615
659
|
})
|
|
616
660
|
);
|
|
617
661
|
var categoryResultSchema = scorableMetaSchema.merge(
|
|
618
|
-
|
|
662
|
+
z15.object({ score: scoreSchema })
|
|
619
663
|
);
|
|
620
664
|
var groupResultSchema = scorableWithPluginMetaSchema.merge(
|
|
621
|
-
|
|
665
|
+
z15.object({ score: scoreSchema })
|
|
622
666
|
);
|
|
623
667
|
var auditResultSchema = scorableWithPluginMetaSchema.merge(
|
|
624
668
|
auditOutputSchema.pick({ score: true, value: true, displayValue: true })
|
|
625
669
|
);
|
|
626
|
-
var reportsDiffSchema =
|
|
670
|
+
var reportsDiffSchema = z15.object({
|
|
627
671
|
commits: makeComparisonSchema(commitSchema).nullable().describe("Commits identifying compared reports"),
|
|
628
672
|
categories: makeArraysComparisonSchema(
|
|
629
673
|
categoryDiffSchema,
|
|
@@ -652,6 +696,288 @@ var reportsDiffSchema = z14.object({
|
|
|
652
696
|
})
|
|
653
697
|
);
|
|
654
698
|
|
|
699
|
+
// packages/utils/src/lib/text-formats/constants.ts
|
|
700
|
+
var NEW_LINE = "\n";
|
|
701
|
+
var TAB = " ";
|
|
702
|
+
var SPACE = " ";
|
|
703
|
+
|
|
704
|
+
// packages/utils/src/lib/text-formats/html/details.ts
|
|
705
|
+
function details(title, content, cfg = { open: false }) {
|
|
706
|
+
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.
|
|
707
|
+
NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
|
|
708
|
+
// ⚠️ The blank line ensure Markdown in content is rendered correctly.
|
|
709
|
+
NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
|
|
710
|
+
NEW_LINE}`;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// packages/utils/src/lib/text-formats/html/font-style.ts
|
|
714
|
+
var boldElement = "b";
|
|
715
|
+
function bold(text) {
|
|
716
|
+
return `<${boldElement}>${text}</${boldElement}>`;
|
|
717
|
+
}
|
|
718
|
+
var italicElement = "i";
|
|
719
|
+
function italic(text) {
|
|
720
|
+
return `<${italicElement}>${text}</${italicElement}>`;
|
|
721
|
+
}
|
|
722
|
+
var codeElement = "code";
|
|
723
|
+
function code(text) {
|
|
724
|
+
return `<${codeElement}>${text}</${codeElement}>`;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// packages/utils/src/lib/text-formats/html/link.ts
|
|
728
|
+
function link(href, text) {
|
|
729
|
+
return `<a href="${href}">${text || href}"</a>`;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// packages/utils/src/lib/transform.ts
|
|
733
|
+
function objectToEntries(obj) {
|
|
734
|
+
return Object.entries(obj);
|
|
735
|
+
}
|
|
736
|
+
function deepClone(obj) {
|
|
737
|
+
return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
|
|
738
|
+
}
|
|
739
|
+
function toUnixPath(path) {
|
|
740
|
+
return path.replace(/\\/g, "/");
|
|
741
|
+
}
|
|
742
|
+
function capitalize(text) {
|
|
743
|
+
return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
|
|
744
|
+
1
|
|
745
|
+
)}`;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// packages/utils/src/lib/table.ts
|
|
749
|
+
function rowToStringArray({ rows, columns = [] }) {
|
|
750
|
+
if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
|
|
751
|
+
throw new TypeError(
|
|
752
|
+
"Column can`t be object when rows are primitive values"
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
return rows.map((row) => {
|
|
756
|
+
if (Array.isArray(row)) {
|
|
757
|
+
return row.map(String);
|
|
758
|
+
}
|
|
759
|
+
const objectRow = row;
|
|
760
|
+
if (columns.length === 0 || typeof columns.at(0) === "string") {
|
|
761
|
+
return Object.values(objectRow).map(String);
|
|
762
|
+
}
|
|
763
|
+
return columns.map(
|
|
764
|
+
({ key }) => String(objectRow[key])
|
|
765
|
+
);
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
function columnsToStringArray({ rows, columns = [] }) {
|
|
769
|
+
const firstRow = rows.at(0);
|
|
770
|
+
const primitiveRows = Array.isArray(firstRow);
|
|
771
|
+
if (typeof columns.at(0) === "string" && !primitiveRows) {
|
|
772
|
+
throw new Error("invalid union type. Caught by model parsing.");
|
|
773
|
+
}
|
|
774
|
+
if (columns.length === 0) {
|
|
775
|
+
if (Array.isArray(firstRow)) {
|
|
776
|
+
return firstRow.map((_, idx) => String(idx));
|
|
777
|
+
}
|
|
778
|
+
return Object.keys(firstRow);
|
|
779
|
+
}
|
|
780
|
+
if (typeof columns.at(0) === "string") {
|
|
781
|
+
return columns.map(String);
|
|
782
|
+
}
|
|
783
|
+
const cols = columns;
|
|
784
|
+
return cols.map(({ label, key }) => label ?? capitalize(key));
|
|
785
|
+
}
|
|
786
|
+
function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
|
|
787
|
+
const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
|
|
788
|
+
if (typeof column === "string") {
|
|
789
|
+
return column;
|
|
790
|
+
} else if (typeof column === "object") {
|
|
791
|
+
return column.align ?? "center";
|
|
792
|
+
} else {
|
|
793
|
+
return "center";
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
function getColumnAlignmentForIndex(targetIdx, columns = []) {
|
|
797
|
+
const column = columns.at(targetIdx);
|
|
798
|
+
if (column == null) {
|
|
799
|
+
return "center";
|
|
800
|
+
} else if (typeof column === "string") {
|
|
801
|
+
return column;
|
|
802
|
+
} else if (typeof column === "object") {
|
|
803
|
+
return column.align ?? "center";
|
|
804
|
+
} else {
|
|
805
|
+
return "center";
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
function getColumnAlignments({
|
|
809
|
+
rows,
|
|
810
|
+
columns = []
|
|
811
|
+
}) {
|
|
812
|
+
if (rows.at(0) == null) {
|
|
813
|
+
throw new Error("first row can`t be undefined.");
|
|
814
|
+
}
|
|
815
|
+
if (Array.isArray(rows.at(0))) {
|
|
816
|
+
const firstPrimitiveRow = rows.at(0);
|
|
817
|
+
return Array.from({ length: firstPrimitiveRow.length }).map(
|
|
818
|
+
(_, idx) => getColumnAlignmentForIndex(idx, columns)
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
const firstObject = rows.at(0);
|
|
822
|
+
return Object.keys(firstObject).map(
|
|
823
|
+
(key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// packages/utils/src/lib/text-formats/html/table.ts
|
|
828
|
+
function wrap(elem, content) {
|
|
829
|
+
return `<${elem}>${content}</${elem}>${NEW_LINE}`;
|
|
830
|
+
}
|
|
831
|
+
function wrapRow(content) {
|
|
832
|
+
const elem = "tr";
|
|
833
|
+
return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
|
|
834
|
+
}
|
|
835
|
+
function table(tableData) {
|
|
836
|
+
if (tableData.rows.length === 0) {
|
|
837
|
+
throw new Error("Data can't be empty");
|
|
838
|
+
}
|
|
839
|
+
const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
|
|
840
|
+
const tableHeaderRow = wrapRow(tableHeaderCols);
|
|
841
|
+
const tableBody = rowToStringArray(tableData).map((arr) => {
|
|
842
|
+
const columns = arr.map((s) => wrap("td", s)).join("");
|
|
843
|
+
return wrapRow(columns);
|
|
844
|
+
}).join("");
|
|
845
|
+
return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// packages/utils/src/lib/text-formats/md/font-style.ts
|
|
849
|
+
var boldWrap = "**";
|
|
850
|
+
function bold2(text) {
|
|
851
|
+
return `${boldWrap}${text}${boldWrap}`;
|
|
852
|
+
}
|
|
853
|
+
var italicWrap = "_";
|
|
854
|
+
function italic2(text) {
|
|
855
|
+
return `${italicWrap}${text}${italicWrap}`;
|
|
856
|
+
}
|
|
857
|
+
var strikeThroughWrap = "~";
|
|
858
|
+
function strikeThrough(text) {
|
|
859
|
+
return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
|
|
860
|
+
}
|
|
861
|
+
var codeWrap = "`";
|
|
862
|
+
function code2(text) {
|
|
863
|
+
return `${codeWrap}${text}${codeWrap}`;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// packages/utils/src/lib/text-formats/md/headline.ts
|
|
867
|
+
function headline(text, hierarchy = 1) {
|
|
868
|
+
return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
|
|
869
|
+
}
|
|
870
|
+
function h(text, hierarchy = 1) {
|
|
871
|
+
return headline(text, hierarchy);
|
|
872
|
+
}
|
|
873
|
+
function h1(text) {
|
|
874
|
+
return headline(text, 1);
|
|
875
|
+
}
|
|
876
|
+
function h2(text) {
|
|
877
|
+
return headline(text, 2);
|
|
878
|
+
}
|
|
879
|
+
function h3(text) {
|
|
880
|
+
return headline(text, 3);
|
|
881
|
+
}
|
|
882
|
+
function h4(text) {
|
|
883
|
+
return headline(text, 4);
|
|
884
|
+
}
|
|
885
|
+
function h5(text) {
|
|
886
|
+
return headline(text, 5);
|
|
887
|
+
}
|
|
888
|
+
function h6(text) {
|
|
889
|
+
return headline(text, 6);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// packages/utils/src/lib/text-formats/md/image.ts
|
|
893
|
+
function image(src, alt) {
|
|
894
|
+
return ``;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// packages/utils/src/lib/text-formats/md/link.ts
|
|
898
|
+
function link2(href, text) {
|
|
899
|
+
return `[${text || href}](${href})`;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// packages/utils/src/lib/text-formats/md/list.ts
|
|
903
|
+
function li(text, order = "unordered") {
|
|
904
|
+
const style = order === "unordered" ? "-" : "- [ ]";
|
|
905
|
+
return `${style} ${text}`;
|
|
906
|
+
}
|
|
907
|
+
function indentation(text, level = 1) {
|
|
908
|
+
return `${TAB.repeat(level)}${text}`;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// packages/utils/src/lib/text-formats/md/paragraphs.ts
|
|
912
|
+
function paragraphs(...sections) {
|
|
913
|
+
return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// packages/utils/src/lib/text-formats/md/section.ts
|
|
917
|
+
function section(...contents) {
|
|
918
|
+
return `${lines(...contents)}${NEW_LINE}`;
|
|
919
|
+
}
|
|
920
|
+
function lines(...contents) {
|
|
921
|
+
return `${contents.filter(Boolean).join(NEW_LINE)}`;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// packages/utils/src/lib/text-formats/md/table.ts
|
|
925
|
+
var alignString = /* @__PURE__ */ new Map([
|
|
926
|
+
["left", ":--"],
|
|
927
|
+
["center", ":--:"],
|
|
928
|
+
["right", "--:"]
|
|
929
|
+
]);
|
|
930
|
+
function tableRow(rows) {
|
|
931
|
+
return `|${rows.join("|")}|`;
|
|
932
|
+
}
|
|
933
|
+
function table2(data) {
|
|
934
|
+
if (data.rows.length === 0) {
|
|
935
|
+
throw new Error("Data can't be empty");
|
|
936
|
+
}
|
|
937
|
+
const alignmentRow = getColumnAlignments(data).map(
|
|
938
|
+
(s) => alignString.get(s) ?? String(alignString.get("center"))
|
|
939
|
+
);
|
|
940
|
+
return section(
|
|
941
|
+
`${lines(
|
|
942
|
+
tableRow(columnsToStringArray(data)),
|
|
943
|
+
tableRow(alignmentRow),
|
|
944
|
+
...rowToStringArray(data).map(tableRow)
|
|
945
|
+
)}`
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// packages/utils/src/lib/text-formats/index.ts
|
|
950
|
+
var md = {
|
|
951
|
+
bold: bold2,
|
|
952
|
+
italic: italic2,
|
|
953
|
+
strikeThrough,
|
|
954
|
+
code: code2,
|
|
955
|
+
link: link2,
|
|
956
|
+
image,
|
|
957
|
+
headline,
|
|
958
|
+
h,
|
|
959
|
+
h1,
|
|
960
|
+
h2,
|
|
961
|
+
h3,
|
|
962
|
+
h4,
|
|
963
|
+
h5,
|
|
964
|
+
h6,
|
|
965
|
+
indentation,
|
|
966
|
+
lines,
|
|
967
|
+
li,
|
|
968
|
+
section,
|
|
969
|
+
paragraphs,
|
|
970
|
+
table: table2
|
|
971
|
+
};
|
|
972
|
+
var html = {
|
|
973
|
+
bold,
|
|
974
|
+
italic,
|
|
975
|
+
code,
|
|
976
|
+
link,
|
|
977
|
+
details,
|
|
978
|
+
table
|
|
979
|
+
};
|
|
980
|
+
|
|
655
981
|
// packages/utils/src/lib/diff.ts
|
|
656
982
|
function matchArrayItemsByKey({
|
|
657
983
|
before,
|
|
@@ -769,40 +1095,48 @@ import chalk from "chalk";
|
|
|
769
1095
|
|
|
770
1096
|
// packages/utils/src/lib/reports/constants.ts
|
|
771
1097
|
var TERMINAL_WIDTH = 80;
|
|
772
|
-
var NEW_LINE = "\n";
|
|
773
1098
|
var SCORE_COLOR_RANGE = {
|
|
774
1099
|
GREEN_MIN: 0.9,
|
|
775
1100
|
YELLOW_MIN: 0.5
|
|
776
1101
|
};
|
|
1102
|
+
var CATEGORIES_TITLE = "\u{1F3F7} Categories";
|
|
777
1103
|
var FOOTER_PREFIX = "Made with \u2764 by";
|
|
778
1104
|
var CODE_PUSHUP_DOMAIN = "code-pushup.dev";
|
|
779
|
-
var README_LINK = "https://github.com/
|
|
1105
|
+
var README_LINK = "https://github.com/code-pushup/cli#readme";
|
|
780
1106
|
var reportHeadlineText = "Code PushUp Report";
|
|
781
1107
|
var reportOverviewTableHeaders = [
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
1108
|
+
{
|
|
1109
|
+
key: "category",
|
|
1110
|
+
label: "\u{1F3F7} Category",
|
|
1111
|
+
align: "left"
|
|
1112
|
+
},
|
|
1113
|
+
{
|
|
1114
|
+
key: "score",
|
|
1115
|
+
label: "\u2B50 Score"
|
|
1116
|
+
},
|
|
1117
|
+
{
|
|
1118
|
+
key: "audits",
|
|
1119
|
+
label: "\u{1F6E1} Audits"
|
|
1120
|
+
}
|
|
785
1121
|
];
|
|
786
1122
|
var reportRawOverviewTableHeaders = ["Category", "Score", "Audits"];
|
|
787
|
-
var
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
"Source file",
|
|
805
|
-
"Line(s)"
|
|
1123
|
+
var issuesTableHeadings = [
|
|
1124
|
+
{
|
|
1125
|
+
key: "severity",
|
|
1126
|
+
label: "Severity"
|
|
1127
|
+
},
|
|
1128
|
+
{
|
|
1129
|
+
key: "message",
|
|
1130
|
+
label: "Message"
|
|
1131
|
+
},
|
|
1132
|
+
{
|
|
1133
|
+
key: "file",
|
|
1134
|
+
label: "Source file"
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
key: "line",
|
|
1138
|
+
label: "Line(s)"
|
|
1139
|
+
}
|
|
806
1140
|
];
|
|
807
1141
|
|
|
808
1142
|
// packages/utils/src/lib/logging.ts
|
|
@@ -928,122 +1262,35 @@ async function importEsmModule(options) {
|
|
|
928
1262
|
return mod.default;
|
|
929
1263
|
}
|
|
930
1264
|
|
|
931
|
-
// packages/utils/src/lib/reports/md/details.ts
|
|
932
|
-
function details(title, content, cfg = { open: false }) {
|
|
933
|
-
return `<details${cfg.open ? " open" : ""}>
|
|
934
|
-
<summary>${title}</summary>
|
|
935
|
-
|
|
936
|
-
${content}
|
|
937
|
-
|
|
938
|
-
</details>
|
|
939
|
-
`;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
// packages/utils/src/lib/reports/md/font-style.ts
|
|
943
|
-
var stylesMap = {
|
|
944
|
-
i: "_",
|
|
945
|
-
// italic
|
|
946
|
-
b: "**",
|
|
947
|
-
// bold
|
|
948
|
-
s: "~",
|
|
949
|
-
// strike through
|
|
950
|
-
c: "`"
|
|
951
|
-
// code
|
|
952
|
-
};
|
|
953
|
-
function style(text, styles = ["b"]) {
|
|
954
|
-
return styles.reduce((t, s) => `${stylesMap[s]}${t}${stylesMap[s]}`, text);
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
// packages/utils/src/lib/reports/md/headline.ts
|
|
958
|
-
function headline(text, hierarchy = 1) {
|
|
959
|
-
return `${"#".repeat(hierarchy)} ${text}`;
|
|
960
|
-
}
|
|
961
|
-
function h1(text) {
|
|
962
|
-
return headline(text, 1);
|
|
963
|
-
}
|
|
964
|
-
function h2(text) {
|
|
965
|
-
return headline(text, 2);
|
|
966
|
-
}
|
|
967
|
-
function h3(text) {
|
|
968
|
-
return headline(text, 3);
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
// packages/utils/src/lib/reports/md/image.ts
|
|
972
|
-
function image(src, alt) {
|
|
973
|
-
return ``;
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
// packages/utils/src/lib/reports/md/link.ts
|
|
977
|
-
function link(href, text) {
|
|
978
|
-
return `[${text || href}](${href})`;
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
// packages/utils/src/lib/reports/md/list.ts
|
|
982
|
-
function li(text, order = "unordered") {
|
|
983
|
-
const style2 = order === "unordered" ? "-" : "- [ ]";
|
|
984
|
-
return `${style2} ${text}`;
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
// packages/utils/src/lib/reports/md/paragraphs.ts
|
|
988
|
-
function paragraphs(...sections) {
|
|
989
|
-
return sections.filter(Boolean).join("\n\n");
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
// packages/utils/src/lib/reports/md/table.ts
|
|
993
|
-
var alignString = /* @__PURE__ */ new Map([
|
|
994
|
-
["l", ":--"],
|
|
995
|
-
["c", ":--:"],
|
|
996
|
-
["r", "--:"]
|
|
997
|
-
]);
|
|
998
|
-
function tableMd(data, align) {
|
|
999
|
-
if (data.length === 0) {
|
|
1000
|
-
throw new Error("Data can't be empty");
|
|
1001
|
-
}
|
|
1002
|
-
const alignmentSetting = align ?? data[0]?.map(() => "c");
|
|
1003
|
-
const tableContent = data.map((arr) => `|${arr.join("|")}|`);
|
|
1004
|
-
const alignmentRow = `|${alignmentSetting?.map((s) => alignString.get(s)).join("|")}|`;
|
|
1005
|
-
return tableContent[0] + NEW_LINE + alignmentRow + NEW_LINE + tableContent.slice(1).join(NEW_LINE);
|
|
1006
|
-
}
|
|
1007
|
-
function tableHtml(data) {
|
|
1008
|
-
if (data.length === 0) {
|
|
1009
|
-
throw new Error("Data can't be empty");
|
|
1010
|
-
}
|
|
1011
|
-
const tableContent = data.map((arr, index) => {
|
|
1012
|
-
if (index === 0) {
|
|
1013
|
-
const headerRow = arr.map((s) => `<th>${s}</th>`).join("");
|
|
1014
|
-
return `<tr>${headerRow}</tr>`;
|
|
1015
|
-
}
|
|
1016
|
-
const row = arr.map((s) => `<td>${s}</td>`).join("");
|
|
1017
|
-
return `<tr>${row}</tr>`;
|
|
1018
|
-
});
|
|
1019
|
-
return `<table>${tableContent.join("")}</table>`;
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
1265
|
// packages/utils/src/lib/reports/utils.ts
|
|
1266
|
+
var { image: image2, bold: boldMd } = md;
|
|
1023
1267
|
function formatReportScore(score) {
|
|
1024
1268
|
return Math.round(score * 100).toString();
|
|
1025
1269
|
}
|
|
1026
1270
|
function formatScoreWithColor(score, options) {
|
|
1027
|
-
const styledNumber = options?.skipBold ? formatReportScore(score) :
|
|
1028
|
-
return `${
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1271
|
+
const styledNumber = options?.skipBold ? formatReportScore(score) : boldMd(formatReportScore(score));
|
|
1272
|
+
return `${scoreMarker(score)} ${styledNumber}`;
|
|
1273
|
+
}
|
|
1274
|
+
var MARKERS = {
|
|
1275
|
+
circle: {
|
|
1276
|
+
red: "\u{1F534}",
|
|
1277
|
+
yellow: "\u{1F7E1}",
|
|
1278
|
+
green: "\u{1F7E2}"
|
|
1279
|
+
},
|
|
1280
|
+
square: {
|
|
1281
|
+
red: "\u{1F7E5}",
|
|
1282
|
+
yellow: "\u{1F7E8}",
|
|
1283
|
+
green: "\u{1F7E9}"
|
|
1036
1284
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
function getSquaredScoreMarker(score) {
|
|
1285
|
+
};
|
|
1286
|
+
function scoreMarker(score, markerType = "circle") {
|
|
1040
1287
|
if (score >= SCORE_COLOR_RANGE.GREEN_MIN) {
|
|
1041
|
-
return
|
|
1288
|
+
return MARKERS[markerType].green;
|
|
1042
1289
|
}
|
|
1043
1290
|
if (score >= SCORE_COLOR_RANGE.YELLOW_MIN) {
|
|
1044
|
-
return
|
|
1291
|
+
return MARKERS[markerType].yellow;
|
|
1045
1292
|
}
|
|
1046
|
-
return
|
|
1293
|
+
return MARKERS[markerType].red;
|
|
1047
1294
|
}
|
|
1048
1295
|
function getDiffMarker(diff) {
|
|
1049
1296
|
if (diff > 0) {
|
|
@@ -1059,7 +1306,7 @@ function colorByScoreDiff(text, diff) {
|
|
|
1059
1306
|
return shieldsBadge(text, color);
|
|
1060
1307
|
}
|
|
1061
1308
|
function shieldsBadge(text, color) {
|
|
1062
|
-
return
|
|
1309
|
+
return image2(
|
|
1063
1310
|
`https://img.shields.io/badge/${encodeURIComponent(text)}-${color}`,
|
|
1064
1311
|
text
|
|
1065
1312
|
);
|
|
@@ -1069,7 +1316,7 @@ function formatDiffNumber(diff) {
|
|
|
1069
1316
|
const sign = diff < 0 ? "\u2212" : "+";
|
|
1070
1317
|
return `${sign}${number}`;
|
|
1071
1318
|
}
|
|
1072
|
-
function
|
|
1319
|
+
function severityMarker(severity) {
|
|
1073
1320
|
if (severity === "error") {
|
|
1074
1321
|
return "\u{1F6A8}";
|
|
1075
1322
|
}
|
|
@@ -1260,13 +1507,13 @@ function executeProcess(cfg) {
|
|
|
1260
1507
|
process2.on("error", (err) => {
|
|
1261
1508
|
stderr += err.toString();
|
|
1262
1509
|
});
|
|
1263
|
-
process2.on("close", (
|
|
1510
|
+
process2.on("close", (code3) => {
|
|
1264
1511
|
const timings = { date, duration: calcDuration(start) };
|
|
1265
|
-
if (
|
|
1512
|
+
if (code3 === 0 || ignoreExitCode) {
|
|
1266
1513
|
onComplete?.();
|
|
1267
|
-
resolve({ code, stdout, stderr, ...timings });
|
|
1514
|
+
resolve({ code: code3, stdout, stderr, ...timings });
|
|
1268
1515
|
} else {
|
|
1269
|
-
const errorMsg = new ProcessError({ code, stdout, stderr, ...timings });
|
|
1516
|
+
const errorMsg = new ProcessError({ code: code3, stdout, stderr, ...timings });
|
|
1270
1517
|
onError?.(errorMsg);
|
|
1271
1518
|
reject(errorMsg);
|
|
1272
1519
|
}
|
|
@@ -1274,30 +1521,9 @@ function executeProcess(cfg) {
|
|
|
1274
1521
|
});
|
|
1275
1522
|
}
|
|
1276
1523
|
|
|
1277
|
-
// packages/utils/src/lib/git.ts
|
|
1524
|
+
// packages/utils/src/lib/git/git.ts
|
|
1278
1525
|
import { isAbsolute, join as join2, relative } from "node:path";
|
|
1279
1526
|
import { simpleGit } from "simple-git";
|
|
1280
|
-
|
|
1281
|
-
// packages/utils/src/lib/transform.ts
|
|
1282
|
-
function objectToEntries(obj) {
|
|
1283
|
-
return Object.entries(obj);
|
|
1284
|
-
}
|
|
1285
|
-
function deepClone(obj) {
|
|
1286
|
-
return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
|
|
1287
|
-
}
|
|
1288
|
-
function toUnixPath(path) {
|
|
1289
|
-
return path.replace(/\\/g, "/");
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
// packages/utils/src/lib/git.ts
|
|
1293
|
-
async function getLatestCommit(git = simpleGit()) {
|
|
1294
|
-
const log2 = await git.log({
|
|
1295
|
-
maxCount: 1,
|
|
1296
|
-
// git log -1 --pretty=format:"%H %s %an %aI" - See: https://git-scm.com/docs/pretty-formats
|
|
1297
|
-
format: { hash: "%H", message: "%s", author: "%an", date: "%aI" }
|
|
1298
|
-
});
|
|
1299
|
-
return commitSchema.parse(log2.latest);
|
|
1300
|
-
}
|
|
1301
1527
|
function getGitRoot(git = simpleGit()) {
|
|
1302
1528
|
return git.revparse("--show-toplevel");
|
|
1303
1529
|
}
|
|
@@ -1344,11 +1570,6 @@ async function guardAgainstLocalChanges(git = simpleGit()) {
|
|
|
1344
1570
|
throw new GitStatusError(status);
|
|
1345
1571
|
}
|
|
1346
1572
|
}
|
|
1347
|
-
async function getCurrentBranchOrTag(git = simpleGit()) {
|
|
1348
|
-
return await git.branch().then((r) => r.current) || // If no current branch, try to get the tag
|
|
1349
|
-
// @TODO use simple git
|
|
1350
|
-
await git.raw(["describe", "--tags", "--exact-match"]).then((out) => out.trim());
|
|
1351
|
-
}
|
|
1352
1573
|
async function safeCheckout(branchOrHash, forceCleanStatus = false, git = simpleGit()) {
|
|
1353
1574
|
if (forceCleanStatus) {
|
|
1354
1575
|
await git.raw(["reset", "--hard"]);
|
|
@@ -1359,6 +1580,27 @@ async function safeCheckout(branchOrHash, forceCleanStatus = false, git = simple
|
|
|
1359
1580
|
await git.checkout(branchOrHash);
|
|
1360
1581
|
}
|
|
1361
1582
|
|
|
1583
|
+
// packages/utils/src/lib/git/git.commits-and-tags.ts
|
|
1584
|
+
import { simpleGit as simpleGit2 } from "simple-git";
|
|
1585
|
+
|
|
1586
|
+
// packages/utils/src/lib/semver.ts
|
|
1587
|
+
import { rcompare, valid } from "semver";
|
|
1588
|
+
|
|
1589
|
+
// packages/utils/src/lib/git/git.commits-and-tags.ts
|
|
1590
|
+
async function getLatestCommit(git = simpleGit2()) {
|
|
1591
|
+
const log2 = await git.log({
|
|
1592
|
+
maxCount: 1,
|
|
1593
|
+
// git log -1 --pretty=format:"%H %s %an %aI" - See: https://git-scm.com/docs/pretty-formats
|
|
1594
|
+
format: { hash: "%H", message: "%s", author: "%an", date: "%aI" }
|
|
1595
|
+
});
|
|
1596
|
+
return commitSchema.parse(log2.latest);
|
|
1597
|
+
}
|
|
1598
|
+
async function getCurrentBranchOrTag(git = simpleGit2()) {
|
|
1599
|
+
return await git.branch().then((r) => r.current) || // If no current branch, try to get the tag
|
|
1600
|
+
// @TODO use simple git
|
|
1601
|
+
await git.raw(["describe", "--tags", "--exact-match"]).then((out) => out.trim());
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1362
1604
|
// packages/utils/src/lib/group-by-status.ts
|
|
1363
1605
|
function groupByStatus(results) {
|
|
1364
1606
|
return results.reduce(
|
|
@@ -1434,44 +1676,65 @@ function listAuditsFromAllPlugins(report) {
|
|
|
1434
1676
|
);
|
|
1435
1677
|
}
|
|
1436
1678
|
|
|
1437
|
-
// packages/utils/src/lib/reports/
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
`${FOOTER_PREFIX} ${link(README_LINK, "Code PushUp")}`
|
|
1679
|
+
// packages/utils/src/lib/reports/formatting.ts
|
|
1680
|
+
var { headline: headline2, lines: lines2, link: link3, section: section2, table: table3 } = md;
|
|
1681
|
+
function tableSection(tableData, options) {
|
|
1682
|
+
if (tableData.rows.length === 0) {
|
|
1683
|
+
return "";
|
|
1684
|
+
}
|
|
1685
|
+
const { level = 4 } = options ?? {};
|
|
1686
|
+
const render = (h7, l) => l === 0 ? h7 : headline2(h7, l);
|
|
1687
|
+
return lines2(
|
|
1688
|
+
tableData.title && render(tableData.title, level),
|
|
1689
|
+
table3(tableData)
|
|
1449
1690
|
);
|
|
1450
1691
|
}
|
|
1451
|
-
function
|
|
1452
|
-
|
|
1692
|
+
function metaDescription({
|
|
1693
|
+
docsUrl,
|
|
1694
|
+
description
|
|
1695
|
+
}) {
|
|
1696
|
+
if (docsUrl) {
|
|
1697
|
+
const docsLink = link3(docsUrl, "\u{1F4D6} Docs");
|
|
1698
|
+
if (!description) {
|
|
1699
|
+
return section2(docsLink);
|
|
1700
|
+
}
|
|
1701
|
+
const parsedDescription = description.toString().endsWith("```") ? `${description}${NEW_LINE + NEW_LINE}` : `${description}${SPACE}`;
|
|
1702
|
+
return section2(`${parsedDescription}${docsLink}`);
|
|
1703
|
+
}
|
|
1704
|
+
if (description && description.trim().length > 0) {
|
|
1705
|
+
return section2(description);
|
|
1706
|
+
}
|
|
1707
|
+
return "";
|
|
1453
1708
|
}
|
|
1454
|
-
|
|
1709
|
+
|
|
1710
|
+
// packages/utils/src/lib/reports/generate-md-report-categoy-section.ts
|
|
1711
|
+
var { link: link4, section: section3, h2: h22, lines: lines3, li: li2, bold: boldMd2, h3: h32, indentation: indentation2 } = md;
|
|
1712
|
+
function categoriesOverviewSection(report) {
|
|
1455
1713
|
const { categories, plugins } = report;
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1714
|
+
if (categories.length > 0 && plugins.length > 0) {
|
|
1715
|
+
const tableContent = {
|
|
1716
|
+
columns: reportOverviewTableHeaders,
|
|
1717
|
+
rows: categories.map(({ title, refs, score }) => ({
|
|
1718
|
+
// The heading "ID" is inferred from the heading text in Markdown.
|
|
1719
|
+
category: link4(`#${slugify(title)}`, title),
|
|
1720
|
+
score: `${scoreMarker(score)}${SPACE}${boldMd2(
|
|
1721
|
+
formatReportScore(score)
|
|
1722
|
+
)}`,
|
|
1723
|
+
audits: countCategoryAudits(refs, plugins).toString()
|
|
1724
|
+
}))
|
|
1725
|
+
};
|
|
1726
|
+
return tableSection(tableContent);
|
|
1727
|
+
}
|
|
1728
|
+
return "";
|
|
1465
1729
|
}
|
|
1466
|
-
function
|
|
1730
|
+
function categoriesDetailsSection(report) {
|
|
1467
1731
|
const { categories, plugins } = report;
|
|
1468
|
-
const categoryDetails = categories.
|
|
1469
|
-
const categoryTitle =
|
|
1470
|
-
const categoryScore = `${
|
|
1732
|
+
const categoryDetails = categories.flatMap((category) => {
|
|
1733
|
+
const categoryTitle = h32(category.title);
|
|
1734
|
+
const categoryScore = `${scoreMarker(
|
|
1471
1735
|
category.score
|
|
1472
|
-
)}
|
|
1473
|
-
const
|
|
1474
|
-
const categoryMDItems = category.refs.reduce((refAcc, ref) => {
|
|
1736
|
+
)}${SPACE}Score: ${boldMd2(formatReportScore(category.score))}`;
|
|
1737
|
+
const categoryMDItems = category.refs.map((ref) => {
|
|
1475
1738
|
if (ref.type === "group") {
|
|
1476
1739
|
const group = getSortableGroupByRef(ref, plugins);
|
|
1477
1740
|
const groupAudits = group.refs.map(
|
|
@@ -1481,151 +1744,240 @@ function reportToCategoriesSection(report) {
|
|
|
1481
1744
|
)
|
|
1482
1745
|
);
|
|
1483
1746
|
const pluginTitle = getPluginNameFromSlug(ref.plugin, plugins);
|
|
1484
|
-
|
|
1485
|
-
group,
|
|
1486
|
-
groupAudits,
|
|
1487
|
-
pluginTitle
|
|
1488
|
-
);
|
|
1489
|
-
return refAcc + mdGroupItem + NEW_LINE;
|
|
1747
|
+
return categoryGroupItem(group, groupAudits, pluginTitle);
|
|
1490
1748
|
} else {
|
|
1491
1749
|
const audit = getSortableAuditByRef(ref, plugins);
|
|
1492
1750
|
const pluginTitle = getPluginNameFromSlug(ref.plugin, plugins);
|
|
1493
|
-
|
|
1494
|
-
return refAcc + mdAuditItem + NEW_LINE;
|
|
1751
|
+
return categoryRef(audit, pluginTitle);
|
|
1495
1752
|
}
|
|
1496
|
-
}
|
|
1497
|
-
return
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1753
|
+
});
|
|
1754
|
+
return section3(
|
|
1755
|
+
categoryTitle,
|
|
1756
|
+
metaDescription(category),
|
|
1757
|
+
categoryScore,
|
|
1758
|
+
...categoryMDItems
|
|
1759
|
+
);
|
|
1760
|
+
});
|
|
1761
|
+
return lines3(h22(CATEGORIES_TITLE), ...categoryDetails);
|
|
1762
|
+
}
|
|
1763
|
+
function categoryRef({ title, score, value, displayValue }, pluginTitle) {
|
|
1764
|
+
const auditTitleAsLink = link4(
|
|
1765
|
+
`#${slugify(title)}-${slugify(pluginTitle)}`,
|
|
1766
|
+
title
|
|
1505
1767
|
);
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1768
|
+
const marker = scoreMarker(score, "square");
|
|
1769
|
+
return li2(
|
|
1770
|
+
`${marker}${SPACE}${auditTitleAsLink}${SPACE}(_${pluginTitle}_) - ${boldMd2(
|
|
1771
|
+
(displayValue || value).toString()
|
|
1772
|
+
)}`
|
|
1510
1773
|
);
|
|
1511
1774
|
}
|
|
1512
|
-
function
|
|
1513
|
-
const
|
|
1514
|
-
|
|
1515
|
-
`${getRoundScoreMarker(groupScore)} ${group.title} (_${pluginTitle}_)`
|
|
1775
|
+
function categoryGroupItem({ score = 0, title }, groupAudits, pluginTitle) {
|
|
1776
|
+
const groupTitle = li2(
|
|
1777
|
+
`${scoreMarker(score)}${SPACE}${title}${SPACE}(_${pluginTitle}_)`
|
|
1516
1778
|
);
|
|
1517
|
-
const auditTitles = groupAudits.
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
const auditsData = plugin.audits.reduce((auditAcc, audit) => {
|
|
1533
|
-
const auditTitle = `${audit.title} (${getPluginNameFromSlug(
|
|
1534
|
-
plugin.slug,
|
|
1535
|
-
report.plugins
|
|
1536
|
-
)})`;
|
|
1537
|
-
return auditAcc + h3(auditTitle) + NEW_LINE + NEW_LINE + reportToDetailsSection(audit) + NEW_LINE + NEW_LINE + getDocsAndDescription(audit);
|
|
1538
|
-
}, "");
|
|
1539
|
-
return pluginAcc + auditsData;
|
|
1540
|
-
}, "");
|
|
1541
|
-
return h2("\u{1F6E1}\uFE0F Audits") + NEW_LINE + NEW_LINE + auditsSection;
|
|
1542
|
-
}
|
|
1543
|
-
function reportToDetailsSection(audit) {
|
|
1544
|
-
const detailsTitle = `${getSquaredScoreMarker(audit.score)} ${getAuditResult(
|
|
1545
|
-
audit,
|
|
1546
|
-
true
|
|
1547
|
-
)} (score: ${formatReportScore(audit.score)})`;
|
|
1548
|
-
if (!audit.details?.issues.length) {
|
|
1549
|
-
return detailsTitle;
|
|
1550
|
-
}
|
|
1551
|
-
const detailsTableData = [
|
|
1552
|
-
detailsTableHeaders,
|
|
1553
|
-
...audit.details.issues.map((issue) => {
|
|
1554
|
-
const severity = `${getSeverityIcon(issue.severity)} <i>${issue.severity}</i>`;
|
|
1555
|
-
const message = issue.message;
|
|
1556
|
-
if (!issue.source) {
|
|
1557
|
-
return [severity, message, "", ""];
|
|
1558
|
-
}
|
|
1559
|
-
const file = `<code>${issue.source.file}</code>`;
|
|
1560
|
-
if (!issue.source.position) {
|
|
1561
|
-
return [severity, message, file, ""];
|
|
1562
|
-
}
|
|
1563
|
-
const { startLine, endLine } = issue.source.position;
|
|
1564
|
-
const line = `${startLine || ""}${endLine && startLine !== endLine ? `-${endLine}` : ""}`;
|
|
1565
|
-
return [severity, message, file, line];
|
|
1566
|
-
})
|
|
1567
|
-
];
|
|
1568
|
-
const detailsTable = `<h4>Issues</h4>${tableHtml(detailsTableData)}`;
|
|
1569
|
-
return details(detailsTitle, detailsTable);
|
|
1570
|
-
}
|
|
1571
|
-
function reportToAboutSection(report) {
|
|
1572
|
-
const date = formatDate(/* @__PURE__ */ new Date());
|
|
1573
|
-
const { duration, version: version2, commit, plugins, categories } = report;
|
|
1574
|
-
const commitInfo = commit ? `${commit.message} (${commit.hash})` : "N/A";
|
|
1575
|
-
const reportMetaTable = [
|
|
1576
|
-
reportMetaTableHeaders,
|
|
1577
|
-
[
|
|
1578
|
-
commitInfo,
|
|
1579
|
-
style(version2 || "", ["c"]),
|
|
1580
|
-
formatDuration(duration),
|
|
1581
|
-
plugins.length.toString(),
|
|
1582
|
-
categories.length.toString(),
|
|
1583
|
-
plugins.reduce((acc, { audits }) => acc + audits.length, 0).toString()
|
|
1584
|
-
]
|
|
1585
|
-
];
|
|
1586
|
-
const pluginMetaTable = [
|
|
1587
|
-
pluginMetaTableHeaders,
|
|
1588
|
-
...plugins.map((plugin) => [
|
|
1589
|
-
plugin.title,
|
|
1590
|
-
plugin.audits.length.toString(),
|
|
1591
|
-
style(plugin.version || "", ["c"]),
|
|
1592
|
-
formatDuration(plugin.duration)
|
|
1593
|
-
])
|
|
1594
|
-
];
|
|
1595
|
-
return (
|
|
1596
|
-
// eslint-disable-next-line prefer-template
|
|
1597
|
-
h2("About") + NEW_LINE + NEW_LINE + `Report was created by [Code PushUp](${README_LINK}) on ${date}.` + NEW_LINE + NEW_LINE + tableMd(reportMetaTable, ["l", "c", "c", "c", "c", "c"]) + NEW_LINE + NEW_LINE + "The following plugins were run:" + NEW_LINE + NEW_LINE + tableMd(pluginMetaTable, ["l", "c", "c", "c"])
|
|
1779
|
+
const auditTitles = groupAudits.map(
|
|
1780
|
+
({ title: auditTitle, score: auditScore, value, displayValue }) => {
|
|
1781
|
+
const auditTitleLink = link4(
|
|
1782
|
+
`#${slugify(auditTitle)}-${slugify(pluginTitle)}`,
|
|
1783
|
+
auditTitle
|
|
1784
|
+
);
|
|
1785
|
+
const marker = scoreMarker(auditScore, "square");
|
|
1786
|
+
return indentation2(
|
|
1787
|
+
li2(
|
|
1788
|
+
`${marker}${SPACE}${auditTitleLink} - ${boldMd2(
|
|
1789
|
+
String(displayValue ?? value)
|
|
1790
|
+
)}`
|
|
1791
|
+
)
|
|
1792
|
+
);
|
|
1793
|
+
}
|
|
1598
1794
|
);
|
|
1795
|
+
return lines3(groupTitle, ...auditTitles);
|
|
1599
1796
|
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1797
|
+
|
|
1798
|
+
// packages/utils/src/lib/reports/generate-md-report.ts
|
|
1799
|
+
var { h1: h12, h2: h23, h3: h33, lines: lines4, link: link5, section: section4, code: codeMd } = md;
|
|
1800
|
+
var { bold: boldHtml, details: details2 } = html;
|
|
1801
|
+
function auditDetailsAuditValue({
|
|
1802
|
+
score,
|
|
1803
|
+
value,
|
|
1804
|
+
displayValue
|
|
1603
1805
|
}) {
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1806
|
+
return `${scoreMarker(score, "square")} ${boldHtml(
|
|
1807
|
+
String(displayValue ?? value)
|
|
1808
|
+
)} (score: ${formatReportScore(score)})`;
|
|
1809
|
+
}
|
|
1810
|
+
function generateMdReport(report) {
|
|
1811
|
+
const printCategories = report.categories.length > 0;
|
|
1812
|
+
return lines4(
|
|
1813
|
+
h12(reportHeadlineText),
|
|
1814
|
+
printCategories ? categoriesOverviewSection(report) : "",
|
|
1815
|
+
printCategories ? categoriesDetailsSection(report) : "",
|
|
1816
|
+
auditsSection(report),
|
|
1817
|
+
aboutSection(report),
|
|
1818
|
+
`${FOOTER_PREFIX}${SPACE}${link5(README_LINK, "Code PushUp")}`
|
|
1819
|
+
);
|
|
1820
|
+
}
|
|
1821
|
+
function auditDetailsIssues(issues = []) {
|
|
1822
|
+
if (issues.length === 0) {
|
|
1823
|
+
return "";
|
|
1616
1824
|
}
|
|
1617
|
-
|
|
1825
|
+
const detailsTableData = {
|
|
1826
|
+
title: "Issues",
|
|
1827
|
+
columns: issuesTableHeadings,
|
|
1828
|
+
rows: issues.map(
|
|
1829
|
+
({ severity: severityVal, message, source: sourceVal }) => {
|
|
1830
|
+
const severity = `${severityMarker(severityVal)} <i>${severityVal}</i>`;
|
|
1831
|
+
if (!sourceVal) {
|
|
1832
|
+
return { severity, message, file: "", line: "" };
|
|
1833
|
+
}
|
|
1834
|
+
const file = `<code>${sourceVal.file}</code>`;
|
|
1835
|
+
if (!sourceVal.position) {
|
|
1836
|
+
return { severity, message, file, line: "" };
|
|
1837
|
+
}
|
|
1838
|
+
const { startLine, endLine } = sourceVal.position;
|
|
1839
|
+
const line = `${startLine || ""}${endLine && startLine !== endLine ? `-${endLine}` : ""}`;
|
|
1840
|
+
return { severity, message, file, line };
|
|
1841
|
+
}
|
|
1842
|
+
)
|
|
1843
|
+
};
|
|
1844
|
+
return tableSection(detailsTableData);
|
|
1845
|
+
}
|
|
1846
|
+
function auditDetails(audit) {
|
|
1847
|
+
const { table: table5, issues = [] } = audit.details ?? {};
|
|
1848
|
+
const detailsValue = auditDetailsAuditValue(audit);
|
|
1849
|
+
if (issues.length === 0 && table5 == null) {
|
|
1850
|
+
return section4(detailsValue);
|
|
1851
|
+
}
|
|
1852
|
+
const tableSectionContent = table5 == null ? "" : tableSection(table5);
|
|
1853
|
+
const issuesSectionContent = issues.length > 0 ? auditDetailsIssues(issues) : "";
|
|
1854
|
+
return details2(
|
|
1855
|
+
detailsValue,
|
|
1856
|
+
lines4(tableSectionContent, issuesSectionContent)
|
|
1857
|
+
);
|
|
1618
1858
|
}
|
|
1619
|
-
function
|
|
1620
|
-
|
|
1621
|
-
|
|
1859
|
+
function auditsSection({
|
|
1860
|
+
plugins
|
|
1861
|
+
}) {
|
|
1862
|
+
const content = plugins.flatMap(
|
|
1863
|
+
({ slug, audits }) => audits.flatMap((audit) => {
|
|
1864
|
+
const auditTitle = `${audit.title}${SPACE}(${getPluginNameFromSlug(
|
|
1865
|
+
slug,
|
|
1866
|
+
plugins
|
|
1867
|
+
)})`;
|
|
1868
|
+
const detailsContent = auditDetails(audit);
|
|
1869
|
+
const descriptionContent = metaDescription(audit);
|
|
1870
|
+
return [h33(auditTitle), detailsContent, descriptionContent];
|
|
1871
|
+
})
|
|
1872
|
+
);
|
|
1873
|
+
return section4(h23("\u{1F6E1}\uFE0F Audits"), ...content);
|
|
1874
|
+
}
|
|
1875
|
+
function aboutSection(report) {
|
|
1876
|
+
const { date, plugins } = report;
|
|
1877
|
+
const reportMetaTable = reportMetaData(report);
|
|
1878
|
+
const pluginMetaTable = reportPluginMeta({ plugins });
|
|
1879
|
+
return lines4(
|
|
1880
|
+
h23("About"),
|
|
1881
|
+
section4(
|
|
1882
|
+
`Report was created by [Code PushUp](${README_LINK}) on ${formatDate(
|
|
1883
|
+
new Date(date)
|
|
1884
|
+
)}.`
|
|
1885
|
+
),
|
|
1886
|
+
tableSection(pluginMetaTable),
|
|
1887
|
+
tableSection(reportMetaTable)
|
|
1888
|
+
);
|
|
1889
|
+
}
|
|
1890
|
+
function reportPluginMeta({ plugins }) {
|
|
1891
|
+
return {
|
|
1892
|
+
columns: [
|
|
1893
|
+
{
|
|
1894
|
+
key: "plugin",
|
|
1895
|
+
align: "left"
|
|
1896
|
+
},
|
|
1897
|
+
{
|
|
1898
|
+
key: "audits"
|
|
1899
|
+
},
|
|
1900
|
+
{
|
|
1901
|
+
key: "version"
|
|
1902
|
+
},
|
|
1903
|
+
{
|
|
1904
|
+
key: "duration"
|
|
1905
|
+
}
|
|
1906
|
+
],
|
|
1907
|
+
rows: plugins.map(
|
|
1908
|
+
({
|
|
1909
|
+
title: pluginTitle,
|
|
1910
|
+
audits,
|
|
1911
|
+
version: pluginVersion,
|
|
1912
|
+
duration: pluginDuration
|
|
1913
|
+
}) => ({
|
|
1914
|
+
plugin: pluginTitle,
|
|
1915
|
+
audits: audits.length.toString(),
|
|
1916
|
+
version: codeMd(pluginVersion || ""),
|
|
1917
|
+
duration: formatDuration(pluginDuration)
|
|
1918
|
+
})
|
|
1919
|
+
)
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1922
|
+
function reportMetaData({
|
|
1923
|
+
commit,
|
|
1924
|
+
version: version2,
|
|
1925
|
+
duration,
|
|
1926
|
+
plugins,
|
|
1927
|
+
categories
|
|
1928
|
+
}) {
|
|
1929
|
+
const commitInfo = commit ? `${commit.message}${SPACE}(${commit.hash})` : "N/A";
|
|
1930
|
+
return {
|
|
1931
|
+
columns: [
|
|
1932
|
+
{
|
|
1933
|
+
key: "commit",
|
|
1934
|
+
align: "left"
|
|
1935
|
+
},
|
|
1936
|
+
{
|
|
1937
|
+
key: "version"
|
|
1938
|
+
},
|
|
1939
|
+
{
|
|
1940
|
+
key: "duration"
|
|
1941
|
+
},
|
|
1942
|
+
{
|
|
1943
|
+
key: "plugins"
|
|
1944
|
+
},
|
|
1945
|
+
{
|
|
1946
|
+
key: "categories"
|
|
1947
|
+
},
|
|
1948
|
+
{
|
|
1949
|
+
key: "audits"
|
|
1950
|
+
}
|
|
1951
|
+
],
|
|
1952
|
+
rows: [
|
|
1953
|
+
{
|
|
1954
|
+
commit: commitInfo,
|
|
1955
|
+
version: codeMd(version2 || ""),
|
|
1956
|
+
duration: formatDuration(duration),
|
|
1957
|
+
plugins: plugins.length,
|
|
1958
|
+
categories: categories.length,
|
|
1959
|
+
audits: plugins.reduce((acc, { audits }) => acc + audits.length, 0).toString()
|
|
1960
|
+
}
|
|
1961
|
+
]
|
|
1962
|
+
};
|
|
1622
1963
|
}
|
|
1623
1964
|
|
|
1624
1965
|
// packages/utils/src/lib/reports/generate-md-reports-diff.ts
|
|
1966
|
+
var {
|
|
1967
|
+
h1: h13,
|
|
1968
|
+
h2: h24,
|
|
1969
|
+
lines: lines5,
|
|
1970
|
+
link: link6,
|
|
1971
|
+
bold: boldMd3,
|
|
1972
|
+
italic: italicMd,
|
|
1973
|
+
table: table4,
|
|
1974
|
+
section: section5
|
|
1975
|
+
} = md;
|
|
1976
|
+
var { details: details3 } = html;
|
|
1625
1977
|
var MAX_ROWS = 100;
|
|
1626
1978
|
function generateMdReportsDiff(diff) {
|
|
1627
|
-
return
|
|
1628
|
-
formatDiffHeaderSection(diff),
|
|
1979
|
+
return lines5(
|
|
1980
|
+
section5(formatDiffHeaderSection(diff)),
|
|
1629
1981
|
formatDiffCategoriesSection(diff),
|
|
1630
1982
|
formatDiffGroupsSection(diff),
|
|
1631
1983
|
formatDiffAuditsSection(diff)
|
|
@@ -1633,12 +1985,12 @@ function generateMdReportsDiff(diff) {
|
|
|
1633
1985
|
}
|
|
1634
1986
|
function formatDiffHeaderSection(diff) {
|
|
1635
1987
|
const outcomeTexts = {
|
|
1636
|
-
positive: `\u{1F973} Code PushUp report has ${
|
|
1637
|
-
negative: `\u{1F61F} Code PushUp report has ${
|
|
1638
|
-
mixed: `\u{1F928} Code PushUp report has both ${
|
|
1988
|
+
positive: `\u{1F973} Code PushUp report has ${boldMd3("improved")}`,
|
|
1989
|
+
negative: `\u{1F61F} Code PushUp report has ${boldMd3("regressed")}`,
|
|
1990
|
+
mixed: `\u{1F928} Code PushUp report has both ${boldMd3(
|
|
1639
1991
|
"improvements and regressions"
|
|
1640
1992
|
)}`,
|
|
1641
|
-
unchanged: `\u{1F610} Code PushUp report is ${
|
|
1993
|
+
unchanged: `\u{1F610} Code PushUp report is ${boldMd3("unchanged")}`
|
|
1642
1994
|
};
|
|
1643
1995
|
const outcome = mergeDiffOutcomes(
|
|
1644
1996
|
changesToDiffOutcomes([
|
|
@@ -1648,8 +2000,8 @@ function formatDiffHeaderSection(diff) {
|
|
|
1648
2000
|
])
|
|
1649
2001
|
);
|
|
1650
2002
|
const styleCommits = (commits) => `compared target commit ${commits.after.hash} with source commit ${commits.before.hash}`;
|
|
1651
|
-
return
|
|
1652
|
-
|
|
2003
|
+
return lines5(
|
|
2004
|
+
h13("Code PushUp"),
|
|
1653
2005
|
diff.commits ? `${outcomeTexts[outcome]} \u2013 ${styleCommits(diff.commits)}.` : `${outcomeTexts[outcome]}.`
|
|
1654
2006
|
);
|
|
1655
2007
|
}
|
|
@@ -1660,102 +2012,104 @@ function formatDiffCategoriesSection(diff) {
|
|
|
1660
2012
|
if (categoriesCount === 0) {
|
|
1661
2013
|
return "";
|
|
1662
2014
|
}
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
formatScoreWithColor(category.scores.
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
2015
|
+
const columns = [
|
|
2016
|
+
{ key: "category", label: "\u{1F3F7}\uFE0F Category", align: "left" },
|
|
2017
|
+
{ key: "after", label: hasChanges ? "\u2B50 Current score" : "\u2B50 Score" },
|
|
2018
|
+
{ key: "before", label: "\u2B50 Previous score" },
|
|
2019
|
+
{ key: "change", label: "\u{1F504} Score change" }
|
|
2020
|
+
];
|
|
2021
|
+
return lines5(
|
|
2022
|
+
h24("\u{1F3F7}\uFE0F Categories"),
|
|
2023
|
+
categoriesCount > 0 && table4({
|
|
2024
|
+
columns: hasChanges ? columns : columns.slice(0, 2),
|
|
2025
|
+
rows: [
|
|
2026
|
+
...sortChanges(changed).map((category) => ({
|
|
2027
|
+
category: formatTitle(category),
|
|
2028
|
+
after: formatScoreWithColor(category.scores.after),
|
|
2029
|
+
before: formatScoreWithColor(category.scores.before, {
|
|
2030
|
+
skipBold: true
|
|
2031
|
+
}),
|
|
2032
|
+
change: formatScoreChange(category.scores.diff)
|
|
2033
|
+
})),
|
|
2034
|
+
...added.map((category) => ({
|
|
2035
|
+
category: formatTitle(category),
|
|
2036
|
+
after: formatScoreWithColor(category.score),
|
|
2037
|
+
before: italicMd("n/a (\\*)"),
|
|
2038
|
+
change: italicMd("n/a (\\*)")
|
|
2039
|
+
})),
|
|
2040
|
+
...unchanged.map((category) => ({
|
|
2041
|
+
category: formatTitle(category),
|
|
2042
|
+
after: formatScoreWithColor(category.score),
|
|
2043
|
+
before: formatScoreWithColor(category.score, { skipBold: true }),
|
|
2044
|
+
change: "\u2013"
|
|
2045
|
+
}))
|
|
2046
|
+
].map(
|
|
2047
|
+
(row) => hasChanges ? row : { category: row.category, after: row.after }
|
|
2048
|
+
)
|
|
2049
|
+
}),
|
|
2050
|
+
added.length > 0 && section5(italicMd("(\\*) New category."))
|
|
1695
2051
|
);
|
|
1696
2052
|
}
|
|
1697
2053
|
function formatDiffGroupsSection(diff) {
|
|
1698
2054
|
if (diff.groups.changed.length + diff.groups.unchanged.length === 0) {
|
|
1699
2055
|
return "";
|
|
1700
2056
|
}
|
|
1701
|
-
return
|
|
1702
|
-
|
|
2057
|
+
return lines5(
|
|
2058
|
+
h24("\u{1F5C3}\uFE0F Groups"),
|
|
1703
2059
|
formatGroupsOrAuditsDetails("group", diff.groups, {
|
|
1704
|
-
|
|
1705
|
-
"\u{1F50C} Plugin",
|
|
1706
|
-
"\u{1F5C3}\uFE0F Group",
|
|
1707
|
-
"\u2B50 Current score",
|
|
1708
|
-
"\u2B50 Previous score",
|
|
1709
|
-
"\u{1F504} Score change"
|
|
2060
|
+
columns: [
|
|
2061
|
+
{ key: "plugin", label: "\u{1F50C} Plugin", align: "left" },
|
|
2062
|
+
{ key: "group", label: "\u{1F5C3}\uFE0F Group", align: "left" },
|
|
2063
|
+
{ key: "after", label: "\u2B50 Current score" },
|
|
2064
|
+
{ key: "before", label: "\u2B50 Previous score" },
|
|
2065
|
+
{ key: "change", label: "\u{1F504} Score change" }
|
|
1710
2066
|
],
|
|
1711
|
-
rows: sortChanges(diff.groups.changed).map((group) =>
|
|
1712
|
-
formatTitle(group.plugin),
|
|
1713
|
-
formatTitle(group),
|
|
1714
|
-
formatScoreWithColor(group.scores.after),
|
|
1715
|
-
formatScoreWithColor(group.scores.before, { skipBold: true }),
|
|
1716
|
-
formatScoreChange(group.scores.diff)
|
|
1717
|
-
|
|
1718
|
-
align: ["l", "l", "c", "c", "c"]
|
|
2067
|
+
rows: sortChanges(diff.groups.changed).map((group) => ({
|
|
2068
|
+
plugin: formatTitle(group.plugin),
|
|
2069
|
+
group: formatTitle(group),
|
|
2070
|
+
after: formatScoreWithColor(group.scores.after),
|
|
2071
|
+
before: formatScoreWithColor(group.scores.before, { skipBold: true }),
|
|
2072
|
+
change: formatScoreChange(group.scores.diff)
|
|
2073
|
+
}))
|
|
1719
2074
|
})
|
|
1720
2075
|
);
|
|
1721
2076
|
}
|
|
1722
2077
|
function formatDiffAuditsSection(diff) {
|
|
1723
|
-
return
|
|
1724
|
-
|
|
2078
|
+
return lines5(
|
|
2079
|
+
h24("\u{1F6E1}\uFE0F Audits"),
|
|
1725
2080
|
formatGroupsOrAuditsDetails("audit", diff.audits, {
|
|
1726
|
-
|
|
1727
|
-
"\u{1F50C} Plugin",
|
|
1728
|
-
"\u{1F6E1}\uFE0F Audit",
|
|
1729
|
-
"\u{1F4CF} Current value",
|
|
1730
|
-
"\u{1F4CF} Previous value",
|
|
1731
|
-
"\u{1F504} Value change"
|
|
2081
|
+
columns: [
|
|
2082
|
+
{ key: "plugin", label: "\u{1F50C} Plugin", align: "left" },
|
|
2083
|
+
{ key: "audit", label: "\u{1F6E1}\uFE0F Audit", align: "left" },
|
|
2084
|
+
{ key: "after", label: "\u{1F4CF} Current value" },
|
|
2085
|
+
{ key: "before", label: "\u{1F4CF} Previous value" },
|
|
2086
|
+
{ key: "change", label: "\u{1F504} Value change" }
|
|
1732
2087
|
],
|
|
1733
|
-
rows: sortChanges(diff.audits.changed).map((audit) =>
|
|
1734
|
-
formatTitle(audit.plugin),
|
|
1735
|
-
formatTitle(audit),
|
|
1736
|
-
`${
|
|
2088
|
+
rows: sortChanges(diff.audits.changed).map((audit) => ({
|
|
2089
|
+
plugin: formatTitle(audit.plugin),
|
|
2090
|
+
audit: formatTitle(audit),
|
|
2091
|
+
after: `${scoreMarker(audit.scores.after, "square")} ${boldMd3(
|
|
1737
2092
|
audit.displayValues.after || audit.values.after.toString()
|
|
1738
2093
|
)}`,
|
|
1739
|
-
`${
|
|
1740
|
-
formatValueChange(audit)
|
|
1741
|
-
|
|
1742
|
-
align: ["l", "l", "c", "c", "c"]
|
|
2094
|
+
before: `${scoreMarker(audit.scores.before, "square")} ${audit.displayValues.before || audit.values.before.toString()}`,
|
|
2095
|
+
change: formatValueChange(audit)
|
|
2096
|
+
}))
|
|
1743
2097
|
})
|
|
1744
2098
|
);
|
|
1745
2099
|
}
|
|
1746
|
-
function formatGroupsOrAuditsDetails(token, { changed, unchanged },
|
|
1747
|
-
return changed.length === 0 ? summarizeUnchanged(token, { changed, unchanged }) :
|
|
2100
|
+
function formatGroupsOrAuditsDetails(token, { changed, unchanged }, tableData) {
|
|
2101
|
+
return changed.length === 0 ? summarizeUnchanged(token, { changed, unchanged }) : details3(
|
|
1748
2102
|
summarizeDiffOutcomes(changesToDiffOutcomes(changed), token),
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
2103
|
+
lines5(
|
|
2104
|
+
table4({
|
|
2105
|
+
...tableData,
|
|
2106
|
+
rows: tableData.rows.slice(0, MAX_ROWS)
|
|
2107
|
+
// use never to avoid typing problem
|
|
2108
|
+
}),
|
|
2109
|
+
changed.length > MAX_ROWS && italicMd(
|
|
1755
2110
|
`Only the ${MAX_ROWS} most affected ${pluralize(
|
|
1756
2111
|
token
|
|
1757
|
-
)} are listed above for brevity
|
|
1758
|
-
["i"]
|
|
2112
|
+
)} are listed above for brevity.`
|
|
1759
2113
|
),
|
|
1760
2114
|
unchanged.length > 0 && summarizeUnchanged(token, { changed, unchanged })
|
|
1761
2115
|
)
|
|
@@ -1776,11 +2130,13 @@ function formatValueChange({
|
|
|
1776
2130
|
return colorByScoreDiff(`${marker} ${text}`, scores.diff);
|
|
1777
2131
|
}
|
|
1778
2132
|
function summarizeUnchanged(token, { changed, unchanged }) {
|
|
1779
|
-
return
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
2133
|
+
return section5(
|
|
2134
|
+
[
|
|
2135
|
+
changed.length > 0 ? pluralizeToken(`other ${token}`, unchanged.length) : `All of ${pluralizeToken(token, unchanged.length)}`,
|
|
2136
|
+
unchanged.length === 1 ? "is" : "are",
|
|
2137
|
+
"unchanged."
|
|
2138
|
+
].join(" ")
|
|
2139
|
+
);
|
|
1784
2140
|
}
|
|
1785
2141
|
function summarizeDiffOutcomes(outcomes, token) {
|
|
1786
2142
|
return objectToEntries(countDiffOutcomes(outcomes)).filter(
|
|
@@ -1805,7 +2161,7 @@ function formatTitle({
|
|
|
1805
2161
|
docsUrl
|
|
1806
2162
|
}) {
|
|
1807
2163
|
if (docsUrl) {
|
|
1808
|
-
return
|
|
2164
|
+
return link6(docsUrl, title);
|
|
1809
2165
|
}
|
|
1810
2166
|
return title;
|
|
1811
2167
|
}
|
|
@@ -1856,7 +2212,7 @@ function log(msg = "") {
|
|
|
1856
2212
|
}
|
|
1857
2213
|
function logStdoutSummary(report) {
|
|
1858
2214
|
const printCategories = report.categories.length > 0;
|
|
1859
|
-
log(
|
|
2215
|
+
log(reportToHeaderSection(report));
|
|
1860
2216
|
log();
|
|
1861
2217
|
logPlugins(report);
|
|
1862
2218
|
if (printCategories) {
|
|
@@ -1865,7 +2221,7 @@ function logStdoutSummary(report) {
|
|
|
1865
2221
|
log(`${FOOTER_PREFIX} ${CODE_PUSHUP_DOMAIN}`);
|
|
1866
2222
|
log();
|
|
1867
2223
|
}
|
|
1868
|
-
function
|
|
2224
|
+
function reportToHeaderSection(report) {
|
|
1869
2225
|
const { packageName, version: version2 } = report;
|
|
1870
2226
|
return `${chalk4.bold(reportHeadlineText)} - ${packageName}@${version2}`;
|
|
1871
2227
|
}
|
|
@@ -1905,16 +2261,16 @@ function logCategories({ categories, plugins }) {
|
|
|
1905
2261
|
applyScoreColor({ score }),
|
|
1906
2262
|
countCategoryAudits(refs, plugins)
|
|
1907
2263
|
]);
|
|
1908
|
-
const
|
|
1909
|
-
|
|
1910
|
-
|
|
2264
|
+
const table5 = ui().table();
|
|
2265
|
+
table5.columnWidths([TERMINAL_WIDTH - 9 - 10 - 4, 9, 10]);
|
|
2266
|
+
table5.head(
|
|
1911
2267
|
reportRawOverviewTableHeaders.map((heading, idx) => ({
|
|
1912
2268
|
content: chalk4.cyan(heading),
|
|
1913
2269
|
hAlign: hAlign(idx)
|
|
1914
2270
|
}))
|
|
1915
2271
|
);
|
|
1916
2272
|
rows.forEach(
|
|
1917
|
-
(row) =>
|
|
2273
|
+
(row) => table5.row(
|
|
1918
2274
|
row.map((content, idx) => ({
|
|
1919
2275
|
content: content.toString(),
|
|
1920
2276
|
hAlign: hAlign(idx)
|
|
@@ -1923,19 +2279,19 @@ function logCategories({ categories, plugins }) {
|
|
|
1923
2279
|
);
|
|
1924
2280
|
log(chalk4.magentaBright.bold("Categories"));
|
|
1925
2281
|
log();
|
|
1926
|
-
|
|
2282
|
+
table5.render();
|
|
1927
2283
|
log();
|
|
1928
2284
|
}
|
|
1929
2285
|
function applyScoreColor({ score, text }) {
|
|
1930
2286
|
const formattedScore = text ?? formatReportScore(score);
|
|
1931
|
-
const
|
|
2287
|
+
const style = text ? chalk4 : chalk4.bold;
|
|
1932
2288
|
if (score >= SCORE_COLOR_RANGE.GREEN_MIN) {
|
|
1933
|
-
return
|
|
2289
|
+
return style.green(formattedScore);
|
|
1934
2290
|
}
|
|
1935
2291
|
if (score >= SCORE_COLOR_RANGE.YELLOW_MIN) {
|
|
1936
|
-
return
|
|
2292
|
+
return style.yellow(formattedScore);
|
|
1937
2293
|
}
|
|
1938
|
-
return
|
|
2294
|
+
return style.red(formattedScore);
|
|
1939
2295
|
}
|
|
1940
2296
|
|
|
1941
2297
|
// packages/utils/src/lib/reports/scoring.ts
|
|
@@ -2097,12 +2453,22 @@ var verboseUtils = (verbose = false) => ({
|
|
|
2097
2453
|
|
|
2098
2454
|
// packages/core/package.json
|
|
2099
2455
|
var name = "@code-pushup/core";
|
|
2100
|
-
var version = "0.
|
|
2456
|
+
var version = "0.42.1";
|
|
2101
2457
|
|
|
2102
2458
|
// packages/core/src/lib/implementation/execute-plugin.ts
|
|
2103
2459
|
import chalk5 from "chalk";
|
|
2104
2460
|
|
|
2105
2461
|
// packages/core/src/lib/normalize.ts
|
|
2462
|
+
function normalizeIssue(issue, gitRoot) {
|
|
2463
|
+
const { source, ...issueWithoutSource } = issue;
|
|
2464
|
+
return source == null ? issue : {
|
|
2465
|
+
...issueWithoutSource,
|
|
2466
|
+
source: {
|
|
2467
|
+
...source,
|
|
2468
|
+
file: formatGitPath(source.file, gitRoot)
|
|
2469
|
+
}
|
|
2470
|
+
};
|
|
2471
|
+
}
|
|
2106
2472
|
async function normalizeAuditOutputs(audits) {
|
|
2107
2473
|
const gitRoot = await getGitRoot();
|
|
2108
2474
|
return audits.map((audit) => {
|
|
@@ -2114,13 +2480,7 @@ async function normalizeAuditOutputs(audits) {
|
|
|
2114
2480
|
details: {
|
|
2115
2481
|
...audit.details,
|
|
2116
2482
|
issues: audit.details.issues.map(
|
|
2117
|
-
(issue) => issue
|
|
2118
|
-
...issue,
|
|
2119
|
-
source: {
|
|
2120
|
-
...issue.source,
|
|
2121
|
-
file: formatGitPath(issue.source.file, gitRoot)
|
|
2122
|
-
}
|
|
2123
|
-
}
|
|
2483
|
+
(issue) => normalizeIssue(issue, gitRoot)
|
|
2124
2484
|
)
|
|
2125
2485
|
}
|
|
2126
2486
|
};
|
|
@@ -2158,7 +2518,11 @@ async function executeRunnerFunction(runner, onProgress) {
|
|
|
2158
2518
|
// packages/core/src/lib/implementation/execute-plugin.ts
|
|
2159
2519
|
var PluginOutputMissingAuditError = class extends Error {
|
|
2160
2520
|
constructor(auditSlug) {
|
|
2161
|
-
super(
|
|
2521
|
+
super(
|
|
2522
|
+
`Audit metadata not present in plugin config. Missing slug: ${chalk5.bold(
|
|
2523
|
+
auditSlug
|
|
2524
|
+
)}`
|
|
2525
|
+
);
|
|
2162
2526
|
}
|
|
2163
2527
|
};
|
|
2164
2528
|
async function executePlugin(pluginConfig, onProgress) {
|
|
@@ -2172,7 +2536,11 @@ async function executePlugin(pluginConfig, onProgress) {
|
|
|
2172
2536
|
} = pluginConfig;
|
|
2173
2537
|
const runnerResult = typeof runner === "object" ? await executeRunnerConfig(runner, onProgress) : await executeRunnerFunction(runner, onProgress);
|
|
2174
2538
|
const { audits: unvalidatedAuditOutputs, ...executionMeta } = runnerResult;
|
|
2175
|
-
const
|
|
2539
|
+
const result = auditOutputsSchema.safeParse(unvalidatedAuditOutputs);
|
|
2540
|
+
if (!result.success) {
|
|
2541
|
+
throw new Error(`Audit output is invalid: ${result.error.message}`);
|
|
2542
|
+
}
|
|
2543
|
+
const auditOutputs = result.data;
|
|
2176
2544
|
auditOutputsCorrelateWithPluginOutput(auditOutputs, pluginConfigAudits);
|
|
2177
2545
|
const normalizedAuditOutputs = await normalizeAuditOutputs(auditOutputs);
|
|
2178
2546
|
const auditReports = normalizedAuditOutputs.map(
|
|
@@ -2192,32 +2560,48 @@ async function executePlugin(pluginConfig, onProgress) {
|
|
|
2192
2560
|
...groups && { groups }
|
|
2193
2561
|
};
|
|
2194
2562
|
}
|
|
2563
|
+
var wrapProgress = async (pluginCfg, steps, progressBar) => {
|
|
2564
|
+
progressBar?.updateTitle(`Executing ${chalk5.bold(pluginCfg.title)}`);
|
|
2565
|
+
try {
|
|
2566
|
+
const pluginReport = await executePlugin(pluginCfg);
|
|
2567
|
+
progressBar?.incrementInSteps(steps);
|
|
2568
|
+
return pluginReport;
|
|
2569
|
+
} catch (error) {
|
|
2570
|
+
progressBar?.incrementInSteps(steps);
|
|
2571
|
+
throw new Error(
|
|
2572
|
+
error instanceof Error ? `- Plugin ${chalk5.bold(pluginCfg.title)} (${chalk5.bold(
|
|
2573
|
+
pluginCfg.slug
|
|
2574
|
+
)}) produced the following error:
|
|
2575
|
+
- ${error.message}` : String(error)
|
|
2576
|
+
);
|
|
2577
|
+
}
|
|
2578
|
+
};
|
|
2195
2579
|
async function executePlugins(plugins, options) {
|
|
2196
2580
|
const { progress = false } = options ?? {};
|
|
2197
2581
|
const progressBar = progress ? getProgressBar("Run plugins") : null;
|
|
2198
|
-
const pluginsResult = await plugins.reduce(
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
progressBar?.incrementInSteps(plugins.length);
|
|
2206
|
-
return [
|
|
2207
|
-
...await acc,
|
|
2208
|
-
Promise.reject(error instanceof Error ? error.message : String(error))
|
|
2209
|
-
];
|
|
2210
|
-
}
|
|
2211
|
-
}, Promise.resolve([]));
|
|
2582
|
+
const pluginsResult = await plugins.reduce(
|
|
2583
|
+
async (acc, pluginCfg) => [
|
|
2584
|
+
...await acc,
|
|
2585
|
+
wrapProgress(pluginCfg, plugins.length, progressBar)
|
|
2586
|
+
],
|
|
2587
|
+
Promise.resolve([])
|
|
2588
|
+
);
|
|
2212
2589
|
progressBar?.endProgress("Done running plugins");
|
|
2213
2590
|
const errorsTransform = ({ reason }) => String(reason);
|
|
2214
2591
|
const results = await Promise.allSettled(pluginsResult);
|
|
2215
2592
|
logMultipleResults(results, "Plugins", void 0, errorsTransform);
|
|
2216
2593
|
const { fulfilled, rejected } = groupByStatus(results);
|
|
2217
2594
|
if (rejected.length > 0) {
|
|
2218
|
-
const errorMessages = rejected.map(({ reason }) => String(reason)).join("
|
|
2595
|
+
const errorMessages = rejected.map(({ reason }) => String(reason)).join("\n");
|
|
2219
2596
|
throw new Error(
|
|
2220
|
-
`
|
|
2597
|
+
`Executing ${pluralizeToken(
|
|
2598
|
+
"plugin",
|
|
2599
|
+
rejected.length
|
|
2600
|
+
)} failed.
|
|
2601
|
+
|
|
2602
|
+
${errorMessages}
|
|
2603
|
+
|
|
2604
|
+
`
|
|
2221
2605
|
);
|
|
2222
2606
|
}
|
|
2223
2607
|
return fulfilled.map((result) => result.value);
|
|
@@ -2514,9 +2898,6 @@ function reportsDiffToFileContent(reportsDiff, format) {
|
|
|
2514
2898
|
}
|
|
2515
2899
|
}
|
|
2516
2900
|
|
|
2517
|
-
// packages/core/src/lib/history.ts
|
|
2518
|
-
import { simpleGit as simpleGit2 } from "simple-git";
|
|
2519
|
-
|
|
2520
2901
|
// packages/core/src/lib/upload.ts
|
|
2521
2902
|
import {
|
|
2522
2903
|
uploadToPortal
|
|
@@ -2562,17 +2943,33 @@ function groupToGQL(group) {
|
|
|
2562
2943
|
};
|
|
2563
2944
|
}
|
|
2564
2945
|
function auditToGQL(audit) {
|
|
2946
|
+
const {
|
|
2947
|
+
slug,
|
|
2948
|
+
title,
|
|
2949
|
+
description,
|
|
2950
|
+
docsUrl,
|
|
2951
|
+
score,
|
|
2952
|
+
value,
|
|
2953
|
+
displayValue: formattedValue,
|
|
2954
|
+
details: details4
|
|
2955
|
+
} = audit;
|
|
2956
|
+
const {
|
|
2957
|
+
issues
|
|
2958
|
+
/*, table */
|
|
2959
|
+
} = details4 ?? {};
|
|
2565
2960
|
return {
|
|
2566
|
-
slug
|
|
2567
|
-
title
|
|
2568
|
-
description
|
|
2569
|
-
docsUrl
|
|
2570
|
-
score
|
|
2571
|
-
value
|
|
2572
|
-
formattedValue
|
|
2573
|
-
...
|
|
2961
|
+
slug,
|
|
2962
|
+
title,
|
|
2963
|
+
description,
|
|
2964
|
+
docsUrl,
|
|
2965
|
+
score,
|
|
2966
|
+
value,
|
|
2967
|
+
formattedValue,
|
|
2968
|
+
...details4 && {
|
|
2574
2969
|
details: {
|
|
2575
|
-
issues:
|
|
2970
|
+
...issues && { issues: issues.map(issueToGQL) }
|
|
2971
|
+
// @TODO add when https://github.com/code-pushup/cli/issues/530 is implemented
|
|
2972
|
+
// ...(table ? {table} : {}),
|
|
2576
2973
|
}
|
|
2577
2974
|
}
|
|
2578
2975
|
};
|
|
@@ -2679,24 +3076,6 @@ async function history(config, commits) {
|
|
|
2679
3076
|
await safeCheckout(initialBranch, forceCleanStatus);
|
|
2680
3077
|
return reports;
|
|
2681
3078
|
}
|
|
2682
|
-
async function getHashes(options, git = simpleGit2()) {
|
|
2683
|
-
const { from, to } = options;
|
|
2684
|
-
if (to && !from) {
|
|
2685
|
-
throw new Error(
|
|
2686
|
-
`git log command needs the "from" option defined to accept the "to" option.
|
|
2687
|
-
`
|
|
2688
|
-
);
|
|
2689
|
-
}
|
|
2690
|
-
const logs = await git.log({
|
|
2691
|
-
...options,
|
|
2692
|
-
from,
|
|
2693
|
-
to
|
|
2694
|
-
});
|
|
2695
|
-
return prepareHashes(logs);
|
|
2696
|
-
}
|
|
2697
|
-
function prepareHashes(logs) {
|
|
2698
|
-
return logs.all.map(({ hash }) => hash).reverse();
|
|
2699
|
-
}
|
|
2700
3079
|
|
|
2701
3080
|
// packages/core/src/lib/implementation/read-rc-file.ts
|
|
2702
3081
|
import { join as join6 } from "node:path";
|
|
@@ -2749,7 +3128,6 @@ export {
|
|
|
2749
3128
|
compareReports,
|
|
2750
3129
|
executePlugin,
|
|
2751
3130
|
executePlugins,
|
|
2752
|
-
getHashes,
|
|
2753
3131
|
history,
|
|
2754
3132
|
persistReport,
|
|
2755
3133
|
readRcByPath,
|