@code-pushup/cli 0.26.0 → 0.27.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/README.md +15 -0
- package/index.js +801 -347
- package/package.json +2 -3
- package/src/lib/autorun/autorun-command.d.ts +0 -1
- package/src/lib/compare/compare-command.d.ts +7 -0
- package/src/lib/implementation/compare.model.d.ts +2 -0
- package/src/lib/implementation/compare.options.d.ts +3 -0
- package/src/lib/implementation/logging.d.ts +0 -4
- package/src/lib/implementation/only-plugins.middleware.d.ts +1 -3
- package/src/lib/implementation/only-plugins.model.d.ts +5 -2
- package/src/lib/implementation/only-plugins.utils.d.ts +5 -9
- package/src/lib/options.d.ts +6 -0
- package/src/lib/print-config/print-config-command.d.ts +0 -3
- package/src/lib/yargs-cli.d.ts +4 -0
package/index.js
CHANGED
|
@@ -57,7 +57,7 @@ function getMissingRefsForCategories(categories, plugins) {
|
|
|
57
57
|
({ refs }) => refs.filter(({ type }) => type === "group").map(({ plugin, slug }) => `${plugin}#${slug} (group)`)
|
|
58
58
|
);
|
|
59
59
|
const groupRefsFromPlugins = plugins.flatMap(
|
|
60
|
-
({ groups, slug: pluginSlug }) => Array.isArray(
|
|
60
|
+
({ groups: groups2, slug: pluginSlug }) => Array.isArray(groups2) ? groups2.map(({ slug }) => `${pluginSlug}#${slug} (group)`) : []
|
|
61
61
|
);
|
|
62
62
|
const missingGroupRefs = hasMissingStrings(
|
|
63
63
|
groupRefsFromCategory,
|
|
@@ -92,6 +92,9 @@ var descriptionSchema = z.string({ description: "Description (markdown)" }).max(
|
|
|
92
92
|
var urlSchema = z.string().url();
|
|
93
93
|
var docsUrlSchema = urlSchema.optional().or(z.literal("")).describe("Documentation site");
|
|
94
94
|
var titleSchema = z.string({ description: "Descriptive name" }).max(MAX_TITLE_LENGTH);
|
|
95
|
+
var scoreSchema = z.number({
|
|
96
|
+
description: "Value between 0 and 1"
|
|
97
|
+
}).min(0).max(1);
|
|
95
98
|
function metaSchema(options2) {
|
|
96
99
|
const {
|
|
97
100
|
descriptionDescription,
|
|
@@ -223,6 +226,8 @@ var issueSchema = z3.object(
|
|
|
223
226
|
);
|
|
224
227
|
|
|
225
228
|
// packages/models/src/lib/audit-output.ts
|
|
229
|
+
var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
|
|
230
|
+
var auditDisplayValueSchema = z4.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
|
|
226
231
|
var auditDetailsSchema = z4.object(
|
|
227
232
|
{
|
|
228
233
|
issues: z4.array(issueSchema, { description: "List of findings" })
|
|
@@ -232,11 +237,9 @@ var auditDetailsSchema = z4.object(
|
|
|
232
237
|
var auditOutputSchema = z4.object(
|
|
233
238
|
{
|
|
234
239
|
slug: slugSchema.describe("Reference to audit"),
|
|
235
|
-
displayValue:
|
|
236
|
-
value:
|
|
237
|
-
score:
|
|
238
|
-
description: "Value between 0 and 1"
|
|
239
|
-
}).min(0).max(1),
|
|
240
|
+
displayValue: auditDisplayValueSchema,
|
|
241
|
+
value: auditValueSchema,
|
|
242
|
+
score: scoreSchema,
|
|
240
243
|
details: auditDetailsSchema.optional()
|
|
241
244
|
},
|
|
242
245
|
{ description: "Audit information" }
|
|
@@ -375,28 +378,28 @@ var groupSchema = scorableSchema(
|
|
|
375
378
|
var groupsSchema = z8.array(groupSchema, {
|
|
376
379
|
description: "List of groups"
|
|
377
380
|
}).optional().refine(
|
|
378
|
-
(
|
|
379
|
-
(
|
|
380
|
-
message: duplicateSlugsInGroupsErrorMsg(
|
|
381
|
+
(groups2) => !getDuplicateSlugsInGroups(groups2),
|
|
382
|
+
(groups2) => ({
|
|
383
|
+
message: duplicateSlugsInGroupsErrorMsg(groups2)
|
|
381
384
|
})
|
|
382
385
|
);
|
|
383
|
-
function duplicateRefsInGroupsErrorMsg(
|
|
384
|
-
const duplicateRefs = getDuplicateRefsInGroups(
|
|
386
|
+
function duplicateRefsInGroupsErrorMsg(groups2) {
|
|
387
|
+
const duplicateRefs = getDuplicateRefsInGroups(groups2);
|
|
385
388
|
return `In plugin groups the following references are not unique: ${errorItems(
|
|
386
389
|
duplicateRefs
|
|
387
390
|
)}`;
|
|
388
391
|
}
|
|
389
|
-
function getDuplicateRefsInGroups(
|
|
390
|
-
return hasDuplicateStrings(
|
|
392
|
+
function getDuplicateRefsInGroups(groups2) {
|
|
393
|
+
return hasDuplicateStrings(groups2.map(({ slug: ref }) => ref).filter(exists));
|
|
391
394
|
}
|
|
392
|
-
function duplicateSlugsInGroupsErrorMsg(
|
|
393
|
-
const duplicateRefs = getDuplicateSlugsInGroups(
|
|
395
|
+
function duplicateSlugsInGroupsErrorMsg(groups2) {
|
|
396
|
+
const duplicateRefs = getDuplicateSlugsInGroups(groups2);
|
|
394
397
|
return `In groups the following slugs are not unique: ${errorItems(
|
|
395
398
|
duplicateRefs
|
|
396
399
|
)}`;
|
|
397
400
|
}
|
|
398
|
-
function getDuplicateSlugsInGroups(
|
|
399
|
-
return Array.isArray(
|
|
401
|
+
function getDuplicateSlugsInGroups(groups2) {
|
|
402
|
+
return Array.isArray(groups2) ? hasDuplicateStrings(groups2.map(({ slug }) => slug)) : false;
|
|
400
403
|
}
|
|
401
404
|
|
|
402
405
|
// packages/models/src/lib/runner-config.ts
|
|
@@ -527,15 +530,15 @@ var pluginReportSchema = pluginMetaSchema.merge(
|
|
|
527
530
|
)
|
|
528
531
|
})
|
|
529
532
|
);
|
|
530
|
-
function missingRefsFromGroupsErrorMsg2(audits,
|
|
531
|
-
const missingRefs = getMissingRefsFromGroups2(audits,
|
|
533
|
+
function missingRefsFromGroupsErrorMsg2(audits, groups2) {
|
|
534
|
+
const missingRefs = getMissingRefsFromGroups2(audits, groups2);
|
|
532
535
|
return `group references need to point to an existing audit in this plugin report: ${errorItems(
|
|
533
536
|
missingRefs
|
|
534
537
|
)}`;
|
|
535
538
|
}
|
|
536
|
-
function getMissingRefsFromGroups2(audits,
|
|
539
|
+
function getMissingRefsFromGroups2(audits, groups2) {
|
|
537
540
|
return hasMissingStrings(
|
|
538
|
-
|
|
541
|
+
groups2.flatMap(
|
|
539
542
|
({ refs: auditRefs }) => auditRefs.map(({ slug: ref }) => ref)
|
|
540
543
|
),
|
|
541
544
|
audits.map(({ slug }) => slug)
|
|
@@ -568,6 +571,138 @@ var reportSchema = packageVersionSchema({
|
|
|
568
571
|
})
|
|
569
572
|
);
|
|
570
573
|
|
|
574
|
+
// packages/models/src/lib/reports-diff.ts
|
|
575
|
+
import { z as z14 } from "zod";
|
|
576
|
+
function makeComparisonSchema(schema) {
|
|
577
|
+
const sharedDescription = schema.description || "Result";
|
|
578
|
+
return z14.object({
|
|
579
|
+
before: schema.describe(`${sharedDescription} (source commit)`),
|
|
580
|
+
after: schema.describe(`${sharedDescription} (target commit)`)
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
function makeArraysComparisonSchema(diffSchema, resultSchema, description) {
|
|
584
|
+
return z14.object(
|
|
585
|
+
{
|
|
586
|
+
changed: z14.array(diffSchema),
|
|
587
|
+
unchanged: z14.array(resultSchema),
|
|
588
|
+
added: z14.array(resultSchema),
|
|
589
|
+
removed: z14.array(resultSchema)
|
|
590
|
+
},
|
|
591
|
+
{ description }
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
var scorableMetaSchema = z14.object({ slug: slugSchema, title: titleSchema });
|
|
595
|
+
var scorableWithPluginMetaSchema = scorableMetaSchema.merge(
|
|
596
|
+
z14.object({
|
|
597
|
+
plugin: pluginMetaSchema.pick({ slug: true, title: true }).describe("Plugin which defines it")
|
|
598
|
+
})
|
|
599
|
+
);
|
|
600
|
+
var scorableDiffSchema = scorableMetaSchema.merge(
|
|
601
|
+
z14.object({
|
|
602
|
+
scores: makeComparisonSchema(scoreSchema).merge(
|
|
603
|
+
z14.object({
|
|
604
|
+
diff: z14.number().min(-1).max(1).describe("Score change (`scores.after - scores.before`)")
|
|
605
|
+
})
|
|
606
|
+
).describe("Score comparison")
|
|
607
|
+
})
|
|
608
|
+
);
|
|
609
|
+
var scorableWithPluginDiffSchema = scorableDiffSchema.merge(
|
|
610
|
+
scorableWithPluginMetaSchema
|
|
611
|
+
);
|
|
612
|
+
var categoryDiffSchema = scorableDiffSchema;
|
|
613
|
+
var groupDiffSchema = scorableWithPluginDiffSchema;
|
|
614
|
+
var auditDiffSchema = scorableWithPluginDiffSchema.merge(
|
|
615
|
+
z14.object({
|
|
616
|
+
values: makeComparisonSchema(auditValueSchema).merge(
|
|
617
|
+
z14.object({
|
|
618
|
+
diff: z14.number().int().describe("Value change (`values.after - values.before`)")
|
|
619
|
+
})
|
|
620
|
+
).describe("Audit `value` comparison"),
|
|
621
|
+
displayValues: makeComparisonSchema(auditDisplayValueSchema).describe(
|
|
622
|
+
"Audit `displayValue` comparison"
|
|
623
|
+
)
|
|
624
|
+
})
|
|
625
|
+
);
|
|
626
|
+
var categoryResultSchema = scorableMetaSchema.merge(
|
|
627
|
+
z14.object({ score: scoreSchema })
|
|
628
|
+
);
|
|
629
|
+
var groupResultSchema = scorableWithPluginMetaSchema.merge(
|
|
630
|
+
z14.object({ score: scoreSchema })
|
|
631
|
+
);
|
|
632
|
+
var auditResultSchema = scorableWithPluginMetaSchema.merge(
|
|
633
|
+
auditOutputSchema.pick({ score: true, value: true, displayValue: true })
|
|
634
|
+
);
|
|
635
|
+
var reportsDiffSchema = z14.object({
|
|
636
|
+
commits: makeComparisonSchema(commitSchema).nullable().describe("Commits identifying compared reports"),
|
|
637
|
+
categories: makeArraysComparisonSchema(
|
|
638
|
+
categoryDiffSchema,
|
|
639
|
+
categoryResultSchema,
|
|
640
|
+
"Changes affecting categories"
|
|
641
|
+
),
|
|
642
|
+
groups: makeArraysComparisonSchema(
|
|
643
|
+
groupDiffSchema,
|
|
644
|
+
groupResultSchema,
|
|
645
|
+
"Changes affecting groups"
|
|
646
|
+
),
|
|
647
|
+
audits: makeArraysComparisonSchema(
|
|
648
|
+
auditDiffSchema,
|
|
649
|
+
auditResultSchema,
|
|
650
|
+
"Changes affecting audits"
|
|
651
|
+
)
|
|
652
|
+
}).merge(
|
|
653
|
+
packageVersionSchema({
|
|
654
|
+
versionDescription: "NPM version of the CLI (when `compare` was run)",
|
|
655
|
+
required: true
|
|
656
|
+
})
|
|
657
|
+
).merge(
|
|
658
|
+
executionMetaSchema({
|
|
659
|
+
descriptionDate: "Start date and time of the compare run",
|
|
660
|
+
descriptionDuration: "Duration of the compare run in ms"
|
|
661
|
+
})
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
// packages/utils/src/lib/diff.ts
|
|
665
|
+
function matchArrayItemsByKey({
|
|
666
|
+
before,
|
|
667
|
+
after,
|
|
668
|
+
key
|
|
669
|
+
}) {
|
|
670
|
+
const pairs = [];
|
|
671
|
+
const added = [];
|
|
672
|
+
const afterKeys = /* @__PURE__ */ new Set();
|
|
673
|
+
const keyFn = typeof key === "function" ? key : (item) => item[key];
|
|
674
|
+
for (const afterItem of after) {
|
|
675
|
+
const afterKey = keyFn(afterItem);
|
|
676
|
+
afterKeys.add(afterKey);
|
|
677
|
+
const match = before.find((beforeItem) => keyFn(beforeItem) === afterKey);
|
|
678
|
+
if (match) {
|
|
679
|
+
pairs.push({ before: match, after: afterItem });
|
|
680
|
+
} else {
|
|
681
|
+
added.push(afterItem);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
const removed = before.filter(
|
|
685
|
+
(beforeItem) => !afterKeys.has(keyFn(beforeItem))
|
|
686
|
+
);
|
|
687
|
+
return {
|
|
688
|
+
pairs,
|
|
689
|
+
added,
|
|
690
|
+
removed
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
function comparePairs(pairs, equalsFn) {
|
|
694
|
+
return pairs.reduce(
|
|
695
|
+
(acc, pair) => ({
|
|
696
|
+
...acc,
|
|
697
|
+
...equalsFn(pair) ? { unchanged: [...acc.unchanged, pair.after] } : { changed: [...acc.changed, pair] }
|
|
698
|
+
}),
|
|
699
|
+
{
|
|
700
|
+
changed: [],
|
|
701
|
+
unchanged: []
|
|
702
|
+
}
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
|
|
571
706
|
// packages/utils/src/lib/execute-process.ts
|
|
572
707
|
import { spawn } from "node:child_process";
|
|
573
708
|
|
|
@@ -576,7 +711,7 @@ import { join } from "node:path";
|
|
|
576
711
|
|
|
577
712
|
// packages/utils/src/lib/file-system.ts
|
|
578
713
|
import { bundleRequire } from "bundle-require";
|
|
579
|
-
import
|
|
714
|
+
import chalk2 from "chalk";
|
|
580
715
|
import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
|
|
581
716
|
|
|
582
717
|
// packages/utils/src/lib/formatting.ts
|
|
@@ -621,33 +756,106 @@ function isPromiseRejectedResult(result) {
|
|
|
621
756
|
return result.status === "rejected";
|
|
622
757
|
}
|
|
623
758
|
|
|
759
|
+
// packages/utils/src/lib/logging.ts
|
|
760
|
+
import isaacs_cliui from "@isaacs/cliui";
|
|
761
|
+
import { cliui } from "@poppinss/cliui";
|
|
762
|
+
import chalk from "chalk";
|
|
763
|
+
|
|
764
|
+
// packages/utils/src/lib/reports/constants.ts
|
|
765
|
+
var TERMINAL_WIDTH = 80;
|
|
766
|
+
var NEW_LINE = "\n";
|
|
767
|
+
var SCORE_COLOR_RANGE = {
|
|
768
|
+
GREEN_MIN: 0.9,
|
|
769
|
+
YELLOW_MIN: 0.5
|
|
770
|
+
};
|
|
771
|
+
var FOOTER_PREFIX = "Made with \u2764 by";
|
|
772
|
+
var CODE_PUSHUP_DOMAIN = "code-pushup.dev";
|
|
773
|
+
var README_LINK = "https://github.com/flowup/quality-metrics-cli#readme";
|
|
774
|
+
var reportHeadlineText = "Code PushUp Report";
|
|
775
|
+
var reportOverviewTableHeaders = [
|
|
776
|
+
"\u{1F3F7} Category",
|
|
777
|
+
"\u2B50 Score",
|
|
778
|
+
"\u{1F6E1} Audits"
|
|
779
|
+
];
|
|
780
|
+
var reportRawOverviewTableHeaders = ["Category", "Score", "Audits"];
|
|
781
|
+
var reportMetaTableHeaders = [
|
|
782
|
+
"Commit",
|
|
783
|
+
"Version",
|
|
784
|
+
"Duration",
|
|
785
|
+
"Plugins",
|
|
786
|
+
"Categories",
|
|
787
|
+
"Audits"
|
|
788
|
+
];
|
|
789
|
+
var pluginMetaTableHeaders = [
|
|
790
|
+
"Plugin",
|
|
791
|
+
"Audits",
|
|
792
|
+
"Version",
|
|
793
|
+
"Duration"
|
|
794
|
+
];
|
|
795
|
+
var detailsTableHeaders = [
|
|
796
|
+
"Severity",
|
|
797
|
+
"Message",
|
|
798
|
+
"Source file",
|
|
799
|
+
"Line(s)"
|
|
800
|
+
];
|
|
801
|
+
|
|
802
|
+
// packages/utils/src/lib/logging.ts
|
|
803
|
+
var singletonUiInstance;
|
|
804
|
+
function ui() {
|
|
805
|
+
if (singletonUiInstance === void 0) {
|
|
806
|
+
singletonUiInstance = cliui();
|
|
807
|
+
}
|
|
808
|
+
return {
|
|
809
|
+
...singletonUiInstance,
|
|
810
|
+
row: (args) => {
|
|
811
|
+
logListItem(args);
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
var singletonisaacUi;
|
|
816
|
+
function logListItem(args) {
|
|
817
|
+
if (singletonisaacUi === void 0) {
|
|
818
|
+
singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
|
|
819
|
+
}
|
|
820
|
+
singletonisaacUi.div(...args);
|
|
821
|
+
const content = singletonisaacUi.toString();
|
|
822
|
+
singletonisaacUi.rows = [];
|
|
823
|
+
singletonUiInstance?.logger.log(content);
|
|
824
|
+
}
|
|
825
|
+
function link(text) {
|
|
826
|
+
return chalk.underline(chalk.blueBright(text));
|
|
827
|
+
}
|
|
828
|
+
|
|
624
829
|
// packages/utils/src/lib/log-results.ts
|
|
625
|
-
function logMultipleResults(results, messagePrefix,
|
|
626
|
-
if (
|
|
830
|
+
function logMultipleResults(results, messagePrefix, succeededTransform, failedTransform) {
|
|
831
|
+
if (succeededTransform) {
|
|
627
832
|
const succeededResults = results.filter(isPromiseFulfilledResult);
|
|
628
833
|
logPromiseResults(
|
|
629
834
|
succeededResults,
|
|
630
835
|
`${messagePrefix} successfully: `,
|
|
631
|
-
|
|
836
|
+
succeededTransform
|
|
632
837
|
);
|
|
633
838
|
}
|
|
634
|
-
if (
|
|
839
|
+
if (failedTransform) {
|
|
635
840
|
const failedResults = results.filter(isPromiseRejectedResult);
|
|
636
841
|
logPromiseResults(
|
|
637
842
|
failedResults,
|
|
638
843
|
`${messagePrefix} failed: `,
|
|
639
|
-
|
|
844
|
+
failedTransform
|
|
640
845
|
);
|
|
641
846
|
}
|
|
642
847
|
}
|
|
643
|
-
function logPromiseResults(results, logMessage,
|
|
848
|
+
function logPromiseResults(results, logMessage, getMsg) {
|
|
644
849
|
if (results.length > 0) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
}
|
|
650
|
-
|
|
850
|
+
const log2 = results[0]?.status === "fulfilled" ? (m) => {
|
|
851
|
+
ui().logger.success(m);
|
|
852
|
+
} : (m) => {
|
|
853
|
+
ui().logger.warning(m);
|
|
854
|
+
};
|
|
855
|
+
log2(logMessage);
|
|
856
|
+
results.forEach((result) => {
|
|
857
|
+
log2(getMsg(result));
|
|
858
|
+
});
|
|
651
859
|
}
|
|
652
860
|
}
|
|
653
861
|
|
|
@@ -681,26 +889,24 @@ async function ensureDirectoryExists(baseDir) {
|
|
|
681
889
|
await mkdir(baseDir, { recursive: true });
|
|
682
890
|
return;
|
|
683
891
|
} catch (error) {
|
|
684
|
-
|
|
892
|
+
ui().logger.error(error.message);
|
|
685
893
|
if (error.code !== "EEXIST") {
|
|
686
894
|
throw error;
|
|
687
895
|
}
|
|
688
896
|
}
|
|
689
897
|
}
|
|
690
898
|
function logMultipleFileResults(fileResults, messagePrefix) {
|
|
691
|
-
const
|
|
899
|
+
const succeededTransform = (result) => {
|
|
692
900
|
const [fileName, size] = result.value;
|
|
693
|
-
const formattedSize = size ? ` (${
|
|
694
|
-
|
|
695
|
-
};
|
|
696
|
-
const failedCallback = (result) => {
|
|
697
|
-
console.warn(`- ${chalk.bold(result.reason)}`);
|
|
901
|
+
const formattedSize = size ? ` (${chalk2.gray(formatBytes(size))})` : "";
|
|
902
|
+
return `- ${chalk2.bold(fileName)}${formattedSize}`;
|
|
698
903
|
};
|
|
904
|
+
const failedTransform = (result) => `- ${chalk2.bold(result.reason)}`;
|
|
699
905
|
logMultipleResults(
|
|
700
906
|
fileResults,
|
|
701
907
|
messagePrefix,
|
|
702
|
-
|
|
703
|
-
|
|
908
|
+
succeededTransform,
|
|
909
|
+
failedTransform
|
|
704
910
|
);
|
|
705
911
|
}
|
|
706
912
|
var NoExportError = class extends Error {
|
|
@@ -719,43 +925,83 @@ async function importEsmModule(options2) {
|
|
|
719
925
|
return mod.default;
|
|
720
926
|
}
|
|
721
927
|
|
|
722
|
-
// packages/utils/src/lib/reports/
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
928
|
+
// packages/utils/src/lib/reports/md/details.ts
|
|
929
|
+
function details(title, content, cfg = { open: false }) {
|
|
930
|
+
return `<details${cfg.open ? " open" : ""}>
|
|
931
|
+
<summary>${title}</summary>
|
|
932
|
+
|
|
933
|
+
${content}
|
|
934
|
+
|
|
935
|
+
</details>
|
|
936
|
+
`;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// packages/utils/src/lib/reports/md/font-style.ts
|
|
940
|
+
var stylesMap = {
|
|
941
|
+
i: "_",
|
|
942
|
+
// italic
|
|
943
|
+
b: "**",
|
|
944
|
+
// bold
|
|
945
|
+
s: "~",
|
|
946
|
+
// strike through
|
|
947
|
+
c: "`"
|
|
948
|
+
// code
|
|
728
949
|
};
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
"
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
]
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
"
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
"
|
|
758
|
-
]
|
|
950
|
+
function style(text, styles = ["b"]) {
|
|
951
|
+
return styles.reduce((t, s) => `${stylesMap[s]}${t}${stylesMap[s]}`, text);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// packages/utils/src/lib/reports/md/headline.ts
|
|
955
|
+
function headline(text, hierarchy = 1) {
|
|
956
|
+
return `${"#".repeat(hierarchy)} ${text}`;
|
|
957
|
+
}
|
|
958
|
+
function h2(text) {
|
|
959
|
+
return headline(text, 2);
|
|
960
|
+
}
|
|
961
|
+
function h3(text) {
|
|
962
|
+
return headline(text, 3);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// packages/utils/src/lib/reports/md/link.ts
|
|
966
|
+
function link2(href, text) {
|
|
967
|
+
return `[${text || href}](${href})`;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// packages/utils/src/lib/reports/md/list.ts
|
|
971
|
+
function li(text, order = "unordered") {
|
|
972
|
+
const style2 = order === "unordered" ? "-" : "- [ ]";
|
|
973
|
+
return `${style2} ${text}`;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// packages/utils/src/lib/reports/md/table.ts
|
|
977
|
+
var alignString = /* @__PURE__ */ new Map([
|
|
978
|
+
["l", ":--"],
|
|
979
|
+
["c", ":--:"],
|
|
980
|
+
["r", "--:"]
|
|
981
|
+
]);
|
|
982
|
+
function tableMd(data, align) {
|
|
983
|
+
if (data.length === 0) {
|
|
984
|
+
throw new Error("Data can't be empty");
|
|
985
|
+
}
|
|
986
|
+
const alignmentSetting = align ?? data[0]?.map(() => "c");
|
|
987
|
+
const tableContent = data.map((arr) => `|${arr.join("|")}|`);
|
|
988
|
+
const alignmentRow = `|${alignmentSetting?.map((s) => alignString.get(s)).join("|")}|`;
|
|
989
|
+
return tableContent[0] + NEW_LINE + alignmentRow + NEW_LINE + tableContent.slice(1).join(NEW_LINE);
|
|
990
|
+
}
|
|
991
|
+
function tableHtml(data) {
|
|
992
|
+
if (data.length === 0) {
|
|
993
|
+
throw new Error("Data can't be empty");
|
|
994
|
+
}
|
|
995
|
+
const tableContent = data.map((arr, index) => {
|
|
996
|
+
if (index === 0) {
|
|
997
|
+
const headerRow = arr.map((s) => `<th>${s}</th>`).join("");
|
|
998
|
+
return `<tr>${headerRow}</tr>`;
|
|
999
|
+
}
|
|
1000
|
+
const row = arr.map((s) => `<td>${s}</td>`).join("");
|
|
1001
|
+
return `<tr>${row}</tr>`;
|
|
1002
|
+
});
|
|
1003
|
+
return `<table>${tableContent.join("")}</table>`;
|
|
1004
|
+
}
|
|
759
1005
|
|
|
760
1006
|
// packages/utils/src/lib/reports/utils.ts
|
|
761
1007
|
function formatReportScore(score) {
|
|
@@ -952,7 +1198,7 @@ var ProcessError = class extends Error {
|
|
|
952
1198
|
}
|
|
953
1199
|
};
|
|
954
1200
|
function executeProcess(cfg) {
|
|
955
|
-
const { observer, cwd, command, args } = cfg;
|
|
1201
|
+
const { observer, cwd, command, args, alwaysResolve = false } = cfg;
|
|
956
1202
|
const { onStdout, onError, onComplete } = observer ?? {};
|
|
957
1203
|
const date = (/* @__PURE__ */ new Date()).toISOString();
|
|
958
1204
|
const start = performance.now();
|
|
@@ -972,7 +1218,7 @@ function executeProcess(cfg) {
|
|
|
972
1218
|
});
|
|
973
1219
|
process2.on("close", (code) => {
|
|
974
1220
|
const timings = { date, duration: calcDuration(start) };
|
|
975
|
-
if (code === 0) {
|
|
1221
|
+
if (code === 0 || alwaysResolve) {
|
|
976
1222
|
onComplete?.();
|
|
977
1223
|
resolve({ code, stdout, stderr, ...timings });
|
|
978
1224
|
} else {
|
|
@@ -984,6 +1230,14 @@ function executeProcess(cfg) {
|
|
|
984
1230
|
});
|
|
985
1231
|
}
|
|
986
1232
|
|
|
1233
|
+
// packages/utils/src/lib/filter.ts
|
|
1234
|
+
function filterItemRefsBy(items, refFilterFn) {
|
|
1235
|
+
return items.map((item) => ({
|
|
1236
|
+
...item,
|
|
1237
|
+
refs: item.refs.filter(refFilterFn)
|
|
1238
|
+
})).filter((item) => item.refs.length);
|
|
1239
|
+
}
|
|
1240
|
+
|
|
987
1241
|
// packages/utils/src/lib/git.ts
|
|
988
1242
|
import { isAbsolute, join as join2, relative } from "node:path";
|
|
989
1243
|
import { simpleGit } from "simple-git";
|
|
@@ -1001,14 +1255,14 @@ function toUnixPath(path) {
|
|
|
1001
1255
|
|
|
1002
1256
|
// packages/utils/src/lib/git.ts
|
|
1003
1257
|
async function getLatestCommit(git = simpleGit()) {
|
|
1004
|
-
const
|
|
1258
|
+
const log2 = await git.log({
|
|
1005
1259
|
maxCount: 1,
|
|
1006
1260
|
format: { hash: "%H", message: "%s", author: "%an", date: "%aI" }
|
|
1007
1261
|
});
|
|
1008
|
-
if (!
|
|
1262
|
+
if (!log2.latest) {
|
|
1009
1263
|
return null;
|
|
1010
1264
|
}
|
|
1011
|
-
return commitSchema.parse(
|
|
1265
|
+
return commitSchema.parse(log2.latest);
|
|
1012
1266
|
}
|
|
1013
1267
|
function getGitRoot(git = simpleGit()) {
|
|
1014
1268
|
return git.revparse("--show-toplevel");
|
|
@@ -1027,12 +1281,6 @@ function groupByStatus(results) {
|
|
|
1027
1281
|
);
|
|
1028
1282
|
}
|
|
1029
1283
|
|
|
1030
|
-
// packages/utils/src/lib/logging.ts
|
|
1031
|
-
import chalk2 from "chalk";
|
|
1032
|
-
function link(text) {
|
|
1033
|
-
return chalk2.underline(chalk2.blueBright(text));
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
1284
|
// packages/utils/src/lib/progress.ts
|
|
1037
1285
|
import chalk3 from "chalk";
|
|
1038
1286
|
import { MultiProgressBars } from "multi-progress-bars";
|
|
@@ -1088,80 +1336,105 @@ function getProgressBar(taskName) {
|
|
|
1088
1336
|
};
|
|
1089
1337
|
}
|
|
1090
1338
|
|
|
1091
|
-
// packages/utils/src/lib/reports/
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
${content}
|
|
1096
|
-
</details>
|
|
1097
|
-
`;
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
// packages/utils/src/lib/reports/md/font-style.ts
|
|
1101
|
-
var stylesMap = {
|
|
1102
|
-
i: "_",
|
|
1103
|
-
// italic
|
|
1104
|
-
b: "**",
|
|
1105
|
-
// bold
|
|
1106
|
-
s: "~",
|
|
1107
|
-
// strike through
|
|
1108
|
-
c: "`"
|
|
1109
|
-
// code
|
|
1110
|
-
};
|
|
1111
|
-
function style(text, styles = ["b"]) {
|
|
1112
|
-
return styles.reduce((t, s) => `${stylesMap[s]}${t}${stylesMap[s]}`, text);
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
// packages/utils/src/lib/reports/md/headline.ts
|
|
1116
|
-
function headline(text, hierarchy = 1) {
|
|
1117
|
-
return `${"#".repeat(hierarchy)} ${text}`;
|
|
1339
|
+
// packages/utils/src/lib/reports/log-stdout-summary.ts
|
|
1340
|
+
import chalk4 from "chalk";
|
|
1341
|
+
function log(msg = "") {
|
|
1342
|
+
ui().logger.log(msg);
|
|
1118
1343
|
}
|
|
1119
|
-
function
|
|
1120
|
-
|
|
1344
|
+
function logStdoutSummary(report) {
|
|
1345
|
+
const printCategories = report.categories.length > 0;
|
|
1346
|
+
log(reportToHeaderSection(report));
|
|
1347
|
+
log();
|
|
1348
|
+
logPlugins(report);
|
|
1349
|
+
if (printCategories) {
|
|
1350
|
+
logCategories(report);
|
|
1351
|
+
}
|
|
1352
|
+
log(`${FOOTER_PREFIX} ${CODE_PUSHUP_DOMAIN}`);
|
|
1353
|
+
log();
|
|
1121
1354
|
}
|
|
1122
|
-
function
|
|
1123
|
-
|
|
1355
|
+
function reportToHeaderSection(report) {
|
|
1356
|
+
const { packageName, version: version2 } = report;
|
|
1357
|
+
return `${chalk4.bold(reportHeadlineText)} - ${packageName}@${version2}`;
|
|
1124
1358
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1359
|
+
function logPlugins(report) {
|
|
1360
|
+
const { plugins } = report;
|
|
1361
|
+
plugins.forEach((plugin) => {
|
|
1362
|
+
const { title, audits } = plugin;
|
|
1363
|
+
log();
|
|
1364
|
+
log(chalk4.magentaBright.bold(`${title} audits`));
|
|
1365
|
+
log();
|
|
1366
|
+
audits.forEach((audit) => {
|
|
1367
|
+
ui().row([
|
|
1368
|
+
{
|
|
1369
|
+
text: applyScoreColor({ score: audit.score, text: "\u25CF" }),
|
|
1370
|
+
width: 2,
|
|
1371
|
+
padding: [0, 1, 0, 0]
|
|
1372
|
+
},
|
|
1373
|
+
{
|
|
1374
|
+
text: audit.title,
|
|
1375
|
+
// eslint-disable-next-line no-magic-numbers
|
|
1376
|
+
padding: [0, 3, 0, 0]
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
text: chalk4.cyanBright(audit.displayValue || `${audit.value}`),
|
|
1380
|
+
width: 10,
|
|
1381
|
+
padding: [0, 0, 0, 0]
|
|
1382
|
+
}
|
|
1383
|
+
]);
|
|
1384
|
+
});
|
|
1385
|
+
log();
|
|
1386
|
+
});
|
|
1129
1387
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1388
|
+
function logCategories({ categories, plugins }) {
|
|
1389
|
+
const hAlign = (idx) => idx === 0 ? "left" : "right";
|
|
1390
|
+
const rows = categories.map(({ title, score, refs }) => [
|
|
1391
|
+
title,
|
|
1392
|
+
applyScoreColor({ score }),
|
|
1393
|
+
countCategoryAudits(refs, plugins)
|
|
1394
|
+
]);
|
|
1395
|
+
const table = ui().table();
|
|
1396
|
+
table.columnWidths([TERMINAL_WIDTH - 9 - 10 - 4, 9, 10]);
|
|
1397
|
+
table.head(
|
|
1398
|
+
reportRawOverviewTableHeaders.map((heading, idx) => ({
|
|
1399
|
+
content: chalk4.cyan(heading),
|
|
1400
|
+
hAlign: hAlign(idx)
|
|
1401
|
+
}))
|
|
1402
|
+
);
|
|
1403
|
+
rows.forEach(
|
|
1404
|
+
(row) => table.row(
|
|
1405
|
+
row.map((content, idx) => ({
|
|
1406
|
+
content: content.toString(),
|
|
1407
|
+
hAlign: hAlign(idx)
|
|
1408
|
+
}))
|
|
1409
|
+
)
|
|
1410
|
+
);
|
|
1411
|
+
log(chalk4.magentaBright.bold("Categories"));
|
|
1412
|
+
log();
|
|
1413
|
+
table.render();
|
|
1414
|
+
log();
|
|
1135
1415
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
["r", "--:"]
|
|
1142
|
-
]);
|
|
1143
|
-
function tableMd(data, align) {
|
|
1144
|
-
if (data.length === 0) {
|
|
1145
|
-
throw new Error("Data can't be empty");
|
|
1416
|
+
function applyScoreColor({ score, text }) {
|
|
1417
|
+
const formattedScore = text ?? formatReportScore(score);
|
|
1418
|
+
const style2 = text ? chalk4 : chalk4.bold;
|
|
1419
|
+
if (score >= SCORE_COLOR_RANGE.GREEN_MIN) {
|
|
1420
|
+
return style2.green(formattedScore);
|
|
1146
1421
|
}
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
const alignmentRow = `|${alignmentSetting?.map((s) => alignString.get(s)).join("|")}|`;
|
|
1150
|
-
return tableContent[0] + NEW_LINE + alignmentRow + NEW_LINE + tableContent.slice(1).join(NEW_LINE);
|
|
1151
|
-
}
|
|
1152
|
-
function tableHtml(data) {
|
|
1153
|
-
if (data.length === 0) {
|
|
1154
|
-
throw new Error("Data can't be empty");
|
|
1422
|
+
if (score >= SCORE_COLOR_RANGE.YELLOW_MIN) {
|
|
1423
|
+
return style2.yellow(formattedScore);
|
|
1155
1424
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1425
|
+
return style2.red(formattedScore);
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
// packages/utils/src/lib/reports/flatten-plugins.ts
|
|
1429
|
+
function listGroupsFromAllPlugins(report) {
|
|
1430
|
+
return report.plugins.flatMap(
|
|
1431
|
+
(plugin) => plugin.groups?.map((group) => ({ plugin, group })) ?? []
|
|
1432
|
+
);
|
|
1433
|
+
}
|
|
1434
|
+
function listAuditsFromAllPlugins(report) {
|
|
1435
|
+
return report.plugins.flatMap(
|
|
1436
|
+
(plugin) => plugin.audits.map((audit) => ({ plugin, audit }))
|
|
1437
|
+
);
|
|
1165
1438
|
}
|
|
1166
1439
|
|
|
1167
1440
|
// packages/utils/src/lib/reports/generate-md-report.ts
|
|
@@ -1170,7 +1443,7 @@ function generateMdReport(report) {
|
|
|
1170
1443
|
return (
|
|
1171
1444
|
// header section
|
|
1172
1445
|
// eslint-disable-next-line prefer-template
|
|
1173
|
-
|
|
1446
|
+
reportToHeaderSection2() + NEW_LINE + // categories overview section
|
|
1174
1447
|
(printCategories ? reportToOverviewSection(report) + NEW_LINE + NEW_LINE : "") + // categories section
|
|
1175
1448
|
(printCategories ? reportToCategoriesSection(report) + NEW_LINE + NEW_LINE : "") + // audits section
|
|
1176
1449
|
reportToAuditsSection(report) + NEW_LINE + NEW_LINE + // about section
|
|
@@ -1178,7 +1451,7 @@ function generateMdReport(report) {
|
|
|
1178
1451
|
`${FOOTER_PREFIX} ${link2(README_LINK, "Code PushUp")}`
|
|
1179
1452
|
);
|
|
1180
1453
|
}
|
|
1181
|
-
function
|
|
1454
|
+
function reportToHeaderSection2() {
|
|
1182
1455
|
return headline(reportHeadlineText) + NEW_LINE;
|
|
1183
1456
|
}
|
|
1184
1457
|
function reportToOverviewSection(report) {
|
|
@@ -1351,82 +1624,6 @@ function getAuditResult(audit, isHtml = false) {
|
|
|
1351
1624
|
return isHtml ? `<b>${displayValue || value}</b>` : style(String(displayValue || value));
|
|
1352
1625
|
}
|
|
1353
1626
|
|
|
1354
|
-
// packages/utils/src/lib/reports/generate-stdout-summary.ts
|
|
1355
|
-
import cliui from "@isaacs/cliui";
|
|
1356
|
-
import chalk4 from "chalk";
|
|
1357
|
-
import CliTable3 from "cli-table3";
|
|
1358
|
-
function addLine(line = "") {
|
|
1359
|
-
return line + NEW_LINE;
|
|
1360
|
-
}
|
|
1361
|
-
function generateStdoutSummary(report) {
|
|
1362
|
-
const printCategories = report.categories.length > 0;
|
|
1363
|
-
return addLine(reportToHeaderSection2(report)) + addLine() + addLine(reportToDetailSection(report)) + (printCategories ? addLine(reportToOverviewSection2(report)) : "") + addLine(`${FOOTER_PREFIX} ${CODE_PUSHUP_DOMAIN}`);
|
|
1364
|
-
}
|
|
1365
|
-
function reportToHeaderSection2(report) {
|
|
1366
|
-
const { packageName, version: version2 } = report;
|
|
1367
|
-
return `${chalk4.bold(reportHeadlineText)} - ${packageName}@${version2}`;
|
|
1368
|
-
}
|
|
1369
|
-
function reportToDetailSection(report) {
|
|
1370
|
-
const { plugins } = report;
|
|
1371
|
-
return plugins.reduce((acc, plugin) => {
|
|
1372
|
-
const { title, audits } = plugin;
|
|
1373
|
-
const ui2 = cliui({ width: TERMINAL_WIDTH });
|
|
1374
|
-
audits.forEach((audit) => {
|
|
1375
|
-
ui2.div(
|
|
1376
|
-
{
|
|
1377
|
-
text: withColor({ score: audit.score, text: "\u25CF" }),
|
|
1378
|
-
width: 2,
|
|
1379
|
-
padding: [0, 1, 0, 0]
|
|
1380
|
-
},
|
|
1381
|
-
{
|
|
1382
|
-
text: audit.title,
|
|
1383
|
-
// eslint-disable-next-line no-magic-numbers
|
|
1384
|
-
padding: [0, 3, 0, 0]
|
|
1385
|
-
},
|
|
1386
|
-
{
|
|
1387
|
-
text: chalk4.cyanBright(audit.displayValue || `${audit.value}`),
|
|
1388
|
-
width: 10,
|
|
1389
|
-
padding: [0, 0, 0, 0]
|
|
1390
|
-
}
|
|
1391
|
-
);
|
|
1392
|
-
});
|
|
1393
|
-
return acc + addLine() + addLine(chalk4.magentaBright.bold(`${title} audits`)) + addLine() + addLine(ui2.toString()) + addLine();
|
|
1394
|
-
}, "");
|
|
1395
|
-
}
|
|
1396
|
-
function reportToOverviewSection2({
|
|
1397
|
-
categories,
|
|
1398
|
-
plugins
|
|
1399
|
-
}) {
|
|
1400
|
-
const table = new CliTable3({
|
|
1401
|
-
// eslint-disable-next-line no-magic-numbers
|
|
1402
|
-
colWidths: [TERMINAL_WIDTH - 7 - 8 - 4, 7, 8],
|
|
1403
|
-
head: reportRawOverviewTableHeaders,
|
|
1404
|
-
colAligns: ["left", "right", "right"],
|
|
1405
|
-
style: {
|
|
1406
|
-
head: ["cyan"]
|
|
1407
|
-
}
|
|
1408
|
-
});
|
|
1409
|
-
table.push(
|
|
1410
|
-
...categories.map(({ title, score, refs }) => [
|
|
1411
|
-
title,
|
|
1412
|
-
withColor({ score }),
|
|
1413
|
-
countCategoryAudits(refs, plugins)
|
|
1414
|
-
])
|
|
1415
|
-
);
|
|
1416
|
-
return addLine(chalk4.magentaBright.bold("Categories")) + addLine() + addLine(table.toString());
|
|
1417
|
-
}
|
|
1418
|
-
function withColor({ score, text }) {
|
|
1419
|
-
const formattedScore = text ?? formatReportScore(score);
|
|
1420
|
-
const style2 = text ? chalk4 : chalk4.bold;
|
|
1421
|
-
if (score >= SCORE_COLOR_RANGE.GREEN_MIN) {
|
|
1422
|
-
return style2.green(formattedScore);
|
|
1423
|
-
}
|
|
1424
|
-
if (score >= SCORE_COLOR_RANGE.YELLOW_MIN) {
|
|
1425
|
-
return style2.yellow(formattedScore);
|
|
1426
|
-
}
|
|
1427
|
-
return style2.red(formattedScore);
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
1627
|
// packages/utils/src/lib/reports/scoring.ts
|
|
1431
1628
|
var GroupRefInvalidError = class extends Error {
|
|
1432
1629
|
constructor(auditSlug, pluginSlug) {
|
|
@@ -1438,7 +1635,7 @@ var GroupRefInvalidError = class extends Error {
|
|
|
1438
1635
|
function scoreReport(report) {
|
|
1439
1636
|
const allScoredAuditsAndGroups = /* @__PURE__ */ new Map();
|
|
1440
1637
|
const scoredPlugins = report.plugins.map((plugin) => {
|
|
1441
|
-
const { groups, ...pluginProps } = plugin;
|
|
1638
|
+
const { groups: groups2, ...pluginProps } = plugin;
|
|
1442
1639
|
plugin.audits.forEach((audit) => {
|
|
1443
1640
|
allScoredAuditsAndGroups.set(`${plugin.slug}-${audit.slug}-audit`, audit);
|
|
1444
1641
|
});
|
|
@@ -1451,7 +1648,7 @@ function scoreReport(report) {
|
|
|
1451
1648
|
}
|
|
1452
1649
|
return score;
|
|
1453
1650
|
}
|
|
1454
|
-
const scoredGroups =
|
|
1651
|
+
const scoredGroups = groups2?.map((group) => ({
|
|
1455
1652
|
...group,
|
|
1456
1653
|
score: calculateScore(group.refs, groupScoreFn)
|
|
1457
1654
|
})) ?? [];
|
|
@@ -1518,7 +1715,7 @@ function parseScoringParameters(refs, scoreFn) {
|
|
|
1518
1715
|
function sortReport(report) {
|
|
1519
1716
|
const { categories, plugins } = report;
|
|
1520
1717
|
const sortedCategories = categories.map((category) => {
|
|
1521
|
-
const { audits, groups } = category.refs.reduce(
|
|
1718
|
+
const { audits, groups: groups2 } = category.refs.reduce(
|
|
1522
1719
|
(acc, ref) => ({
|
|
1523
1720
|
...acc,
|
|
1524
1721
|
...ref.type === "group" ? {
|
|
@@ -1529,7 +1726,7 @@ function sortReport(report) {
|
|
|
1529
1726
|
}),
|
|
1530
1727
|
{ groups: [], audits: [] }
|
|
1531
1728
|
);
|
|
1532
|
-
const sortedAuditsAndGroups = [...audits, ...
|
|
1729
|
+
const sortedAuditsAndGroups = [...audits, ...groups2].sort(
|
|
1533
1730
|
compareCategoryAuditsAndGroups
|
|
1534
1731
|
);
|
|
1535
1732
|
const sortedRefs = [...category.refs].sort((a, b) => {
|
|
@@ -1566,9 +1763,9 @@ function sortPlugins(plugins) {
|
|
|
1566
1763
|
|
|
1567
1764
|
// packages/utils/src/lib/verbose-utils.ts
|
|
1568
1765
|
function getLogVerbose(verbose = false) {
|
|
1569
|
-
return (
|
|
1766
|
+
return (msg) => {
|
|
1570
1767
|
if (verbose) {
|
|
1571
|
-
|
|
1768
|
+
ui().logger.info(msg);
|
|
1572
1769
|
}
|
|
1573
1770
|
};
|
|
1574
1771
|
}
|
|
@@ -1586,7 +1783,7 @@ var verboseUtils = (verbose = false) => ({
|
|
|
1586
1783
|
|
|
1587
1784
|
// packages/core/package.json
|
|
1588
1785
|
var name = "@code-pushup/core";
|
|
1589
|
-
var version = "0.
|
|
1786
|
+
var version = "0.27.1";
|
|
1590
1787
|
|
|
1591
1788
|
// packages/core/src/lib/implementation/execute-plugin.ts
|
|
1592
1789
|
import chalk5 from "chalk";
|
|
@@ -1656,7 +1853,7 @@ async function executePlugin(pluginConfig, onProgress) {
|
|
|
1656
1853
|
audits: pluginConfigAudits,
|
|
1657
1854
|
description,
|
|
1658
1855
|
docsUrl,
|
|
1659
|
-
groups,
|
|
1856
|
+
groups: groups2,
|
|
1660
1857
|
...pluginMeta
|
|
1661
1858
|
} = pluginConfig;
|
|
1662
1859
|
const runnerResult = typeof runner === "object" ? await executeRunnerConfig(runner, onProgress) : await executeRunnerFunction(runner, onProgress);
|
|
@@ -1678,7 +1875,7 @@ async function executePlugin(pluginConfig, onProgress) {
|
|
|
1678
1875
|
audits: auditReports,
|
|
1679
1876
|
...description && { description },
|
|
1680
1877
|
...docsUrl && { docsUrl },
|
|
1681
|
-
...
|
|
1878
|
+
...groups2 && { groups: groups2 }
|
|
1682
1879
|
};
|
|
1683
1880
|
}
|
|
1684
1881
|
async function executePlugins(plugins, options2) {
|
|
@@ -1699,11 +1896,9 @@ async function executePlugins(plugins, options2) {
|
|
|
1699
1896
|
}
|
|
1700
1897
|
}, Promise.resolve([]));
|
|
1701
1898
|
progressBar?.endProgress("Done running plugins");
|
|
1702
|
-
const
|
|
1703
|
-
console.error(reason);
|
|
1704
|
-
};
|
|
1899
|
+
const errorsTransform = ({ reason }) => String(reason);
|
|
1705
1900
|
const results = await Promise.allSettled(pluginsResult);
|
|
1706
|
-
logMultipleResults(results, "Plugins", void 0,
|
|
1901
|
+
logMultipleResults(results, "Plugins", void 0, errorsTransform);
|
|
1707
1902
|
const { fulfilled, rejected } = groupByStatus(results);
|
|
1708
1903
|
if (rejected.length > 0) {
|
|
1709
1904
|
const errorMessages = rejected.map(({ reason }) => String(reason)).join(", ");
|
|
@@ -1758,7 +1953,7 @@ var PersistError = class extends Error {
|
|
|
1758
1953
|
async function persistReport(report, options2) {
|
|
1759
1954
|
const { outputDir, filename, format } = options2;
|
|
1760
1955
|
const sortedScoredReport = sortReport(scoreReport(report));
|
|
1761
|
-
|
|
1956
|
+
logStdoutSummary(sortedScoredReport);
|
|
1762
1957
|
const results = format.map((reportType) => {
|
|
1763
1958
|
switch (reportType) {
|
|
1764
1959
|
case "json":
|
|
@@ -1777,7 +1972,7 @@ async function persistReport(report, options2) {
|
|
|
1777
1972
|
try {
|
|
1778
1973
|
await mkdir2(outputDir, { recursive: true });
|
|
1779
1974
|
} catch (error) {
|
|
1780
|
-
|
|
1975
|
+
ui().logger.warning(error.toString());
|
|
1781
1976
|
throw new PersistDirError(outputDir);
|
|
1782
1977
|
}
|
|
1783
1978
|
}
|
|
@@ -1792,7 +1987,7 @@ async function persistReport(report, options2) {
|
|
|
1792
1987
|
}
|
|
1793
1988
|
async function persistResult(reportPath, content) {
|
|
1794
1989
|
return writeFile(reportPath, content).then(() => stat2(reportPath)).then((stats) => [reportPath, stats.size]).catch((error) => {
|
|
1795
|
-
|
|
1990
|
+
ui().logger.warning(error.toString());
|
|
1796
1991
|
throw new PersistError(reportPath);
|
|
1797
1992
|
});
|
|
1798
1993
|
}
|
|
@@ -1813,6 +2008,189 @@ async function collectAndPersistReports(options2) {
|
|
|
1813
2008
|
});
|
|
1814
2009
|
}
|
|
1815
2010
|
|
|
2011
|
+
// packages/core/src/lib/compare.ts
|
|
2012
|
+
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
2013
|
+
|
|
2014
|
+
// packages/core/src/lib/implementation/compare-scorables.ts
|
|
2015
|
+
function compareCategories(reports) {
|
|
2016
|
+
const { pairs, added, removed } = matchArrayItemsByKey({
|
|
2017
|
+
before: reports.before.categories,
|
|
2018
|
+
after: reports.after.categories,
|
|
2019
|
+
key: "slug"
|
|
2020
|
+
});
|
|
2021
|
+
const { changed, unchanged } = comparePairs(
|
|
2022
|
+
pairs,
|
|
2023
|
+
({ before, after }) => before.score === after.score
|
|
2024
|
+
);
|
|
2025
|
+
return {
|
|
2026
|
+
changed: changed.map(categoryPairToDiff),
|
|
2027
|
+
unchanged: unchanged.map(categoryToResult),
|
|
2028
|
+
added: added.map(categoryToResult),
|
|
2029
|
+
removed: removed.map(categoryToResult)
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
function compareGroups(reports) {
|
|
2033
|
+
const { pairs, added, removed } = matchArrayItemsByKey({
|
|
2034
|
+
before: listGroupsFromAllPlugins(reports.before),
|
|
2035
|
+
after: listGroupsFromAllPlugins(reports.after),
|
|
2036
|
+
key: ({ plugin, group }) => `${plugin.slug}/${group.slug}`
|
|
2037
|
+
});
|
|
2038
|
+
const { changed, unchanged } = comparePairs(
|
|
2039
|
+
pairs,
|
|
2040
|
+
({ before, after }) => before.group.score === after.group.score
|
|
2041
|
+
);
|
|
2042
|
+
return {
|
|
2043
|
+
changed: changed.map(pluginGroupPairToDiff),
|
|
2044
|
+
unchanged: unchanged.map(pluginGroupToResult),
|
|
2045
|
+
added: added.map(pluginGroupToResult),
|
|
2046
|
+
removed: removed.map(pluginGroupToResult)
|
|
2047
|
+
};
|
|
2048
|
+
}
|
|
2049
|
+
function compareAudits2(reports) {
|
|
2050
|
+
const { pairs, added, removed } = matchArrayItemsByKey({
|
|
2051
|
+
before: listAuditsFromAllPlugins(reports.before),
|
|
2052
|
+
after: listAuditsFromAllPlugins(reports.after),
|
|
2053
|
+
key: ({ plugin, audit }) => `${plugin.slug}/${audit.slug}`
|
|
2054
|
+
});
|
|
2055
|
+
const { changed, unchanged } = comparePairs(
|
|
2056
|
+
pairs,
|
|
2057
|
+
({ before, after }) => before.audit.value === after.audit.value && before.audit.score === after.audit.score
|
|
2058
|
+
);
|
|
2059
|
+
return {
|
|
2060
|
+
changed: changed.map(pluginAuditPairToDiff),
|
|
2061
|
+
unchanged: unchanged.map(pluginAuditToResult),
|
|
2062
|
+
added: added.map(pluginAuditToResult),
|
|
2063
|
+
removed: removed.map(pluginAuditToResult)
|
|
2064
|
+
};
|
|
2065
|
+
}
|
|
2066
|
+
function categoryToResult(category) {
|
|
2067
|
+
return {
|
|
2068
|
+
slug: category.slug,
|
|
2069
|
+
title: category.title,
|
|
2070
|
+
score: category.score
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
function categoryPairToDiff({
|
|
2074
|
+
before,
|
|
2075
|
+
after
|
|
2076
|
+
}) {
|
|
2077
|
+
return {
|
|
2078
|
+
slug: after.slug,
|
|
2079
|
+
title: after.title,
|
|
2080
|
+
scores: {
|
|
2081
|
+
before: before.score,
|
|
2082
|
+
after: after.score,
|
|
2083
|
+
diff: after.score - before.score
|
|
2084
|
+
}
|
|
2085
|
+
};
|
|
2086
|
+
}
|
|
2087
|
+
function pluginGroupToResult({ group, plugin }) {
|
|
2088
|
+
return {
|
|
2089
|
+
slug: group.slug,
|
|
2090
|
+
title: group.title,
|
|
2091
|
+
plugin: {
|
|
2092
|
+
slug: plugin.slug,
|
|
2093
|
+
title: plugin.title
|
|
2094
|
+
},
|
|
2095
|
+
score: group.score
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
function pluginGroupPairToDiff({
|
|
2099
|
+
before,
|
|
2100
|
+
after
|
|
2101
|
+
}) {
|
|
2102
|
+
return {
|
|
2103
|
+
slug: after.group.slug,
|
|
2104
|
+
title: after.group.title,
|
|
2105
|
+
plugin: {
|
|
2106
|
+
slug: after.plugin.slug,
|
|
2107
|
+
title: after.plugin.title
|
|
2108
|
+
},
|
|
2109
|
+
scores: {
|
|
2110
|
+
before: before.group.score,
|
|
2111
|
+
after: after.group.score,
|
|
2112
|
+
diff: after.group.score - before.group.score
|
|
2113
|
+
}
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
function pluginAuditToResult({ audit, plugin }) {
|
|
2117
|
+
return {
|
|
2118
|
+
slug: audit.slug,
|
|
2119
|
+
title: audit.title,
|
|
2120
|
+
plugin: {
|
|
2121
|
+
slug: plugin.slug,
|
|
2122
|
+
title: plugin.title
|
|
2123
|
+
},
|
|
2124
|
+
score: audit.score,
|
|
2125
|
+
value: audit.value,
|
|
2126
|
+
displayValue: audit.displayValue
|
|
2127
|
+
};
|
|
2128
|
+
}
|
|
2129
|
+
function pluginAuditPairToDiff({
|
|
2130
|
+
before,
|
|
2131
|
+
after
|
|
2132
|
+
}) {
|
|
2133
|
+
return {
|
|
2134
|
+
slug: after.audit.slug,
|
|
2135
|
+
title: after.audit.title,
|
|
2136
|
+
plugin: {
|
|
2137
|
+
slug: after.plugin.slug,
|
|
2138
|
+
title: after.plugin.title
|
|
2139
|
+
},
|
|
2140
|
+
scores: {
|
|
2141
|
+
before: before.audit.score,
|
|
2142
|
+
after: after.audit.score,
|
|
2143
|
+
diff: after.audit.score - before.audit.score
|
|
2144
|
+
},
|
|
2145
|
+
values: {
|
|
2146
|
+
before: before.audit.value,
|
|
2147
|
+
after: after.audit.value,
|
|
2148
|
+
diff: after.audit.value - before.audit.value
|
|
2149
|
+
},
|
|
2150
|
+
displayValues: {
|
|
2151
|
+
before: before.audit.displayValue,
|
|
2152
|
+
after: after.audit.displayValue
|
|
2153
|
+
}
|
|
2154
|
+
};
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
// packages/core/src/lib/compare.ts
|
|
2158
|
+
async function compareReportFiles(inputPaths, outputPath) {
|
|
2159
|
+
const [reportBefore, reportAfter] = await Promise.all([
|
|
2160
|
+
readJsonFile(inputPaths.before),
|
|
2161
|
+
readJsonFile(inputPaths.after)
|
|
2162
|
+
]);
|
|
2163
|
+
const reports = {
|
|
2164
|
+
before: reportSchema.parse(reportBefore),
|
|
2165
|
+
after: reportSchema.parse(reportAfter)
|
|
2166
|
+
};
|
|
2167
|
+
const reportsDiff = compareReports(reports);
|
|
2168
|
+
await writeFile2(outputPath, JSON.stringify(reportsDiff, null, 2));
|
|
2169
|
+
}
|
|
2170
|
+
function compareReports(reports) {
|
|
2171
|
+
const start = performance.now();
|
|
2172
|
+
const date = (/* @__PURE__ */ new Date()).toISOString();
|
|
2173
|
+
const commits = reports.before.commit != null && reports.after.commit != null ? { before: reports.before.commit, after: reports.after.commit } : null;
|
|
2174
|
+
const scoredReports = {
|
|
2175
|
+
before: scoreReport(reports.before),
|
|
2176
|
+
after: scoreReport(reports.after)
|
|
2177
|
+
};
|
|
2178
|
+
const categories = compareCategories(scoredReports);
|
|
2179
|
+
const groups2 = compareGroups(scoredReports);
|
|
2180
|
+
const audits = compareAudits2(scoredReports);
|
|
2181
|
+
const duration = calcDuration(start);
|
|
2182
|
+
return {
|
|
2183
|
+
commits,
|
|
2184
|
+
categories,
|
|
2185
|
+
groups: groups2,
|
|
2186
|
+
audits,
|
|
2187
|
+
packageName: name,
|
|
2188
|
+
version,
|
|
2189
|
+
date,
|
|
2190
|
+
duration
|
|
2191
|
+
};
|
|
2192
|
+
}
|
|
2193
|
+
|
|
1816
2194
|
// packages/core/src/lib/implementation/read-rc-file.ts
|
|
1817
2195
|
import { join as join5 } from "node:path";
|
|
1818
2196
|
var ConfigPathError = class extends Error {
|
|
@@ -1986,15 +2364,7 @@ var CLI_NAME = "Code PushUp CLI";
|
|
|
1986
2364
|
var CLI_SCRIPT_NAME = "code-pushup";
|
|
1987
2365
|
|
|
1988
2366
|
// packages/cli/src/lib/implementation/logging.ts
|
|
1989
|
-
import { cliui as cliui2 } from "@poppinss/cliui";
|
|
1990
2367
|
import chalk6 from "chalk";
|
|
1991
|
-
var singletonUiInstance;
|
|
1992
|
-
function ui() {
|
|
1993
|
-
if (singletonUiInstance === void 0) {
|
|
1994
|
-
singletonUiInstance = cliui2();
|
|
1995
|
-
}
|
|
1996
|
-
return singletonUiInstance;
|
|
1997
|
-
}
|
|
1998
2368
|
function renderConfigureCategoriesHint() {
|
|
1999
2369
|
ui().logger.info(
|
|
2000
2370
|
chalk6.gray(
|
|
@@ -2031,51 +2401,12 @@ function renderIntegratePortalHint() {
|
|
|
2031
2401
|
).render();
|
|
2032
2402
|
}
|
|
2033
2403
|
|
|
2034
|
-
// packages/cli/src/lib/implementation/global.utils.ts
|
|
2035
|
-
function filterKebabCaseKeys(obj) {
|
|
2036
|
-
return Object.entries(obj).filter(([key]) => !key.includes("-")).reduce(
|
|
2037
|
-
(acc, [key, value]) => typeof value === "string" || typeof value === "object" && Array.isArray(obj[key]) ? { ...acc, [key]: value } : typeof value === "object" && !Array.isArray(value) && value != null ? {
|
|
2038
|
-
...acc,
|
|
2039
|
-
[key]: filterKebabCaseKeys(value)
|
|
2040
|
-
} : { ...acc, [key]: value },
|
|
2041
|
-
{}
|
|
2042
|
-
);
|
|
2043
|
-
}
|
|
2044
|
-
function logErrorBeforeThrow(fn) {
|
|
2045
|
-
return async (...args) => {
|
|
2046
|
-
try {
|
|
2047
|
-
return await fn(...args);
|
|
2048
|
-
} catch (error) {
|
|
2049
|
-
console.error(error);
|
|
2050
|
-
await new Promise((resolve) => process.stdout.write("", resolve));
|
|
2051
|
-
throw error;
|
|
2052
|
-
}
|
|
2053
|
-
};
|
|
2054
|
-
}
|
|
2055
|
-
function coerceArray(param) {
|
|
2056
|
-
return [...new Set(toArray(param).flatMap((f) => f.split(",")))];
|
|
2057
|
-
}
|
|
2058
|
-
|
|
2059
|
-
// packages/cli/src/lib/implementation/only-plugins.options.ts
|
|
2060
|
-
var onlyPluginsOption = {
|
|
2061
|
-
describe: "List of plugins to run. If not set all plugins are run.",
|
|
2062
|
-
type: "array",
|
|
2063
|
-
default: [],
|
|
2064
|
-
coerce: coerceArray
|
|
2065
|
-
};
|
|
2066
|
-
function yargsOnlyPluginsOptionsDefinition() {
|
|
2067
|
-
return {
|
|
2068
|
-
onlyPlugins: onlyPluginsOption
|
|
2069
|
-
};
|
|
2070
|
-
}
|
|
2071
|
-
|
|
2072
2404
|
// packages/cli/src/lib/autorun/autorun-command.ts
|
|
2073
2405
|
function yargsAutorunCommandObject() {
|
|
2074
2406
|
const command = "autorun";
|
|
2075
2407
|
return {
|
|
2076
2408
|
command,
|
|
2077
2409
|
describe: "Shortcut for running collect followed by upload",
|
|
2078
|
-
builder: yargsOnlyPluginsOptionsDefinition(),
|
|
2079
2410
|
handler: async (args) => {
|
|
2080
2411
|
ui().logger.log(chalk7.bold(CLI_NAME));
|
|
2081
2412
|
ui().logger.info(chalk7.gray(`Run ${command}...`));
|
|
@@ -2112,7 +2443,6 @@ function yargsCollectCommandObject() {
|
|
|
2112
2443
|
return {
|
|
2113
2444
|
command,
|
|
2114
2445
|
describe: "Run Plugins and collect results",
|
|
2115
|
-
builder: yargsOnlyPluginsOptionsDefinition(),
|
|
2116
2446
|
handler: async (args) => {
|
|
2117
2447
|
const options2 = args;
|
|
2118
2448
|
ui().logger.log(chalk8.bold(CLI_NAME));
|
|
@@ -2149,15 +2479,79 @@ function renderUploadAutorunHint() {
|
|
|
2149
2479
|
).render();
|
|
2150
2480
|
}
|
|
2151
2481
|
|
|
2482
|
+
// packages/cli/src/lib/compare/compare-command.ts
|
|
2483
|
+
import chalk9 from "chalk";
|
|
2484
|
+
import { join as join6 } from "node:path";
|
|
2485
|
+
|
|
2486
|
+
// packages/cli/src/lib/implementation/compare.options.ts
|
|
2487
|
+
function yargsCompareOptionsDefinition() {
|
|
2488
|
+
return {
|
|
2489
|
+
before: {
|
|
2490
|
+
describe: "Path to source report.json",
|
|
2491
|
+
type: "string",
|
|
2492
|
+
demandOption: true
|
|
2493
|
+
},
|
|
2494
|
+
after: {
|
|
2495
|
+
describe: "Path to target report.json",
|
|
2496
|
+
type: "string",
|
|
2497
|
+
demandOption: true
|
|
2498
|
+
}
|
|
2499
|
+
};
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
// packages/cli/src/lib/compare/compare-command.ts
|
|
2503
|
+
function yargsCompareCommandObject() {
|
|
2504
|
+
const command = "compare";
|
|
2505
|
+
return {
|
|
2506
|
+
command,
|
|
2507
|
+
describe: "Compare 2 report files and create a diff file",
|
|
2508
|
+
builder: yargsCompareOptionsDefinition(),
|
|
2509
|
+
handler: async (args) => {
|
|
2510
|
+
ui().logger.log(chalk9.bold(CLI_NAME));
|
|
2511
|
+
ui().logger.info(chalk9.gray(`Run ${command}...`));
|
|
2512
|
+
const options2 = args;
|
|
2513
|
+
const { before, after, persist } = options2;
|
|
2514
|
+
const outputPath = join6(
|
|
2515
|
+
persist.outputDir,
|
|
2516
|
+
`${persist.filename}-diff.json`
|
|
2517
|
+
);
|
|
2518
|
+
await compareReportFiles({ before, after }, outputPath);
|
|
2519
|
+
ui().logger.info(`Reports diff written to ${chalk9.bold(outputPath)}`);
|
|
2520
|
+
}
|
|
2521
|
+
};
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
// packages/cli/src/lib/implementation/global.utils.ts
|
|
2525
|
+
function filterKebabCaseKeys(obj) {
|
|
2526
|
+
return Object.entries(obj).filter(([key]) => !key.includes("-")).reduce(
|
|
2527
|
+
(acc, [key, value]) => typeof value === "string" || typeof value === "object" && Array.isArray(obj[key]) ? { ...acc, [key]: value } : typeof value === "object" && !Array.isArray(value) && value != null ? {
|
|
2528
|
+
...acc,
|
|
2529
|
+
[key]: filterKebabCaseKeys(value)
|
|
2530
|
+
} : { ...acc, [key]: value },
|
|
2531
|
+
{}
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
function logErrorBeforeThrow(fn) {
|
|
2535
|
+
return async (...args) => {
|
|
2536
|
+
try {
|
|
2537
|
+
return await fn(...args);
|
|
2538
|
+
} catch (error) {
|
|
2539
|
+
console.error(error);
|
|
2540
|
+
await new Promise((resolve) => process.stdout.write("", resolve));
|
|
2541
|
+
throw error;
|
|
2542
|
+
}
|
|
2543
|
+
};
|
|
2544
|
+
}
|
|
2545
|
+
function coerceArray(param) {
|
|
2546
|
+
return [...new Set(toArray(param).flatMap((f) => f.split(",")))];
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2152
2549
|
// packages/cli/src/lib/print-config/print-config-command.ts
|
|
2153
2550
|
function yargsConfigCommandObject() {
|
|
2154
2551
|
const command = "print-config";
|
|
2155
2552
|
return {
|
|
2156
2553
|
command,
|
|
2157
2554
|
describe: "Print config",
|
|
2158
|
-
builder: {
|
|
2159
|
-
onlyPlugins: onlyPluginsOption
|
|
2160
|
-
},
|
|
2161
2555
|
handler: (yargsArgs) => {
|
|
2162
2556
|
const { _, $0, ...args } = yargsArgs;
|
|
2163
2557
|
const cleanArgs = filterKebabCaseKeys(args);
|
|
@@ -2167,15 +2561,15 @@ function yargsConfigCommandObject() {
|
|
|
2167
2561
|
}
|
|
2168
2562
|
|
|
2169
2563
|
// packages/cli/src/lib/upload/upload-command.ts
|
|
2170
|
-
import
|
|
2564
|
+
import chalk10 from "chalk";
|
|
2171
2565
|
function yargsUploadCommandObject() {
|
|
2172
2566
|
const command = "upload";
|
|
2173
2567
|
return {
|
|
2174
2568
|
command,
|
|
2175
2569
|
describe: "Upload report results to the portal",
|
|
2176
2570
|
handler: async (args) => {
|
|
2177
|
-
ui().logger.log(
|
|
2178
|
-
ui().logger.info(
|
|
2571
|
+
ui().logger.log(chalk10.bold(CLI_NAME));
|
|
2572
|
+
ui().logger.info(chalk10.gray(`Run ${command}...`));
|
|
2179
2573
|
const options2 = args;
|
|
2180
2574
|
if (options2.upload == null) {
|
|
2181
2575
|
renderIntegratePortalHint();
|
|
@@ -2196,6 +2590,7 @@ var commands = [
|
|
|
2196
2590
|
yargsAutorunCommandObject(),
|
|
2197
2591
|
yargsCollectCommandObject(),
|
|
2198
2592
|
yargsUploadCommandObject(),
|
|
2593
|
+
yargsCompareCommandObject(),
|
|
2199
2594
|
yargsConfigCommandObject()
|
|
2200
2595
|
];
|
|
2201
2596
|
|
|
@@ -2234,58 +2629,64 @@ async function coreConfigMiddleware(processArgs) {
|
|
|
2234
2629
|
}
|
|
2235
2630
|
|
|
2236
2631
|
// packages/cli/src/lib/implementation/only-plugins.utils.ts
|
|
2237
|
-
import
|
|
2238
|
-
function
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
}
|
|
2244
|
-
function filterCategoryByPluginSlug(categories, {
|
|
2245
|
-
onlyPlugins,
|
|
2632
|
+
import chalk11 from "chalk";
|
|
2633
|
+
function validateOnlyPluginsOption({
|
|
2634
|
+
plugins,
|
|
2635
|
+
categories
|
|
2636
|
+
}, {
|
|
2637
|
+
onlyPlugins = [],
|
|
2246
2638
|
verbose = false
|
|
2247
|
-
}) {
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
if (!onlyPlugins?.length) {
|
|
2252
|
-
return categories;
|
|
2253
|
-
}
|
|
2254
|
-
return categories.filter(
|
|
2255
|
-
(category) => category.refs.every((ref) => {
|
|
2256
|
-
const isNotSkipped = onlyPlugins.includes(ref.plugin);
|
|
2257
|
-
if (!isNotSkipped && verbose) {
|
|
2258
|
-
console.info(
|
|
2259
|
-
`${chalk10.yellow("\u26A0")} Category "${category.title}" is ignored because it references audits from skipped plugin "${ref.plugin}"`
|
|
2260
|
-
);
|
|
2261
|
-
}
|
|
2262
|
-
return isNotSkipped;
|
|
2263
|
-
})
|
|
2639
|
+
} = {}) {
|
|
2640
|
+
const onlyPluginsSet = new Set(onlyPlugins);
|
|
2641
|
+
const missingPlugins = onlyPlugins.filter(
|
|
2642
|
+
(plugin) => !plugins.some(({ slug }) => slug === plugin)
|
|
2264
2643
|
);
|
|
2265
|
-
}
|
|
2266
|
-
function validateOnlyPluginsOption(plugins, {
|
|
2267
|
-
onlyPlugins,
|
|
2268
|
-
verbose = false
|
|
2269
|
-
}) {
|
|
2270
|
-
const missingPlugins = onlyPlugins?.length ? onlyPlugins.filter((plugin) => !plugins.some(({ slug }) => slug === plugin)) : [];
|
|
2271
2644
|
if (missingPlugins.length > 0 && verbose) {
|
|
2272
|
-
|
|
2273
|
-
`${
|
|
2645
|
+
ui().logger.info(
|
|
2646
|
+
`${chalk11.yellow(
|
|
2274
2647
|
"\u26A0"
|
|
2275
2648
|
)} The --onlyPlugin argument references plugins with "${missingPlugins.join(
|
|
2276
2649
|
'", "'
|
|
2277
2650
|
)}" slugs, but no such plugins are present in the configuration. Expected one of the following plugin slugs: "${plugins.map(({ slug }) => slug).join('", "')}".`
|
|
2278
2651
|
);
|
|
2279
2652
|
}
|
|
2653
|
+
if (categories.length > 0) {
|
|
2654
|
+
const removedCategorieSlugs = filterItemRefsBy(
|
|
2655
|
+
categories,
|
|
2656
|
+
({ plugin }) => !onlyPluginsSet.has(plugin)
|
|
2657
|
+
).map(({ slug }) => slug);
|
|
2658
|
+
ui().logger.info(
|
|
2659
|
+
`The --onlyPlugin argument removed categories with "${removedCategorieSlugs.join(
|
|
2660
|
+
'", "'
|
|
2661
|
+
)}" slugs.
|
|
2662
|
+
`
|
|
2663
|
+
);
|
|
2664
|
+
}
|
|
2280
2665
|
}
|
|
2281
2666
|
|
|
2282
2667
|
// packages/cli/src/lib/implementation/only-plugins.middleware.ts
|
|
2283
|
-
function onlyPluginsMiddleware(
|
|
2284
|
-
|
|
2668
|
+
function onlyPluginsMiddleware(originalProcessArgs) {
|
|
2669
|
+
const { categories = [], onlyPlugins: originalOnlyPlugins } = originalProcessArgs;
|
|
2670
|
+
if (originalOnlyPlugins && originalOnlyPlugins.length > 0) {
|
|
2671
|
+
const { verbose, plugins, onlyPlugins } = originalProcessArgs;
|
|
2672
|
+
validateOnlyPluginsOption(
|
|
2673
|
+
{ plugins, categories },
|
|
2674
|
+
{ onlyPlugins, verbose }
|
|
2675
|
+
);
|
|
2676
|
+
const onlyPluginsSet = new Set(onlyPlugins);
|
|
2677
|
+
return {
|
|
2678
|
+
...originalProcessArgs,
|
|
2679
|
+
plugins: plugins.filter(({ slug }) => onlyPluginsSet.has(slug)),
|
|
2680
|
+
categories: filterItemRefsBy(
|
|
2681
|
+
categories,
|
|
2682
|
+
({ plugin }) => onlyPluginsSet.has(plugin)
|
|
2683
|
+
)
|
|
2684
|
+
};
|
|
2685
|
+
}
|
|
2285
2686
|
return {
|
|
2286
|
-
...
|
|
2287
|
-
|
|
2288
|
-
categories
|
|
2687
|
+
...originalProcessArgs,
|
|
2688
|
+
// if undefined fill categories with empty array
|
|
2689
|
+
categories
|
|
2289
2690
|
};
|
|
2290
2691
|
}
|
|
2291
2692
|
|
|
@@ -2369,20 +2770,44 @@ function yargsGlobalOptionsDefinition() {
|
|
|
2369
2770
|
};
|
|
2370
2771
|
}
|
|
2371
2772
|
|
|
2773
|
+
// packages/cli/src/lib/implementation/only-plugins.options.ts
|
|
2774
|
+
var onlyPluginsOption = {
|
|
2775
|
+
describe: "List of plugins to run. If not set all plugins are run.",
|
|
2776
|
+
type: "array",
|
|
2777
|
+
default: [],
|
|
2778
|
+
coerce: coerceArray
|
|
2779
|
+
};
|
|
2780
|
+
function yargsOnlyPluginsOptionsDefinition() {
|
|
2781
|
+
return {
|
|
2782
|
+
onlyPlugins: onlyPluginsOption
|
|
2783
|
+
};
|
|
2784
|
+
}
|
|
2785
|
+
|
|
2372
2786
|
// packages/cli/src/lib/options.ts
|
|
2373
2787
|
var options = {
|
|
2374
2788
|
...yargsGlobalOptionsDefinition(),
|
|
2375
|
-
...yargsCoreConfigOptionsDefinition()
|
|
2789
|
+
...yargsCoreConfigOptionsDefinition(),
|
|
2790
|
+
...yargsOnlyPluginsOptionsDefinition()
|
|
2791
|
+
};
|
|
2792
|
+
var groups = {
|
|
2793
|
+
"Global Options:": [
|
|
2794
|
+
...Object.keys(yargsGlobalOptionsDefinition()),
|
|
2795
|
+
...Object.keys(yargsOnlyPluginsOptionsDefinition())
|
|
2796
|
+
],
|
|
2797
|
+
"Persist Options:": Object.keys(yargsPersistConfigOptionsDefinition()),
|
|
2798
|
+
"Upload Options:": Object.keys(yargsUploadConfigOptionsDefinition())
|
|
2376
2799
|
};
|
|
2377
2800
|
|
|
2378
2801
|
// packages/cli/src/lib/yargs-cli.ts
|
|
2379
|
-
import
|
|
2802
|
+
import chalk12 from "chalk";
|
|
2380
2803
|
import yargs from "yargs";
|
|
2381
2804
|
function yargsCli(argv, cfg) {
|
|
2382
2805
|
const { usageMessage, scriptName, noExitProcess } = cfg;
|
|
2383
2806
|
const commands2 = cfg.commands ?? [];
|
|
2384
2807
|
const middlewares2 = cfg.middlewares ?? [];
|
|
2385
2808
|
const options2 = cfg.options ?? {};
|
|
2809
|
+
const groups2 = cfg.groups ?? {};
|
|
2810
|
+
const examples = cfg.examples ?? [];
|
|
2386
2811
|
const cli2 = yargs(argv);
|
|
2387
2812
|
cli2.help().version(false).alias("h", "help").check((args) => {
|
|
2388
2813
|
const persist = args["persist"];
|
|
@@ -2394,11 +2819,17 @@ function yargsCli(argv, cfg) {
|
|
|
2394
2819
|
(config) => Array.isArray(config) ? config.at(-1) : config
|
|
2395
2820
|
).options(options2).wrap(TERMINAL_WIDTH);
|
|
2396
2821
|
if (usageMessage) {
|
|
2397
|
-
cli2.usage(
|
|
2822
|
+
cli2.usage(chalk12.bold(usageMessage));
|
|
2398
2823
|
}
|
|
2399
2824
|
if (scriptName) {
|
|
2400
2825
|
cli2.scriptName(scriptName);
|
|
2401
2826
|
}
|
|
2827
|
+
examples.forEach(
|
|
2828
|
+
([exampleName, description]) => cli2.example(exampleName, description)
|
|
2829
|
+
);
|
|
2830
|
+
Object.entries(groups2).forEach(
|
|
2831
|
+
([groupName, optionNames]) => cli2.group(optionNames, groupName)
|
|
2832
|
+
);
|
|
2402
2833
|
middlewares2.forEach(({ middlewareFunction, applyBeforeValidation }) => {
|
|
2403
2834
|
cli2.middleware(
|
|
2404
2835
|
logErrorBeforeThrow(middlewareFunction),
|
|
@@ -2439,6 +2870,29 @@ var cli = (args) => yargsCli(args, {
|
|
|
2439
2870
|
usageMessage: CLI_NAME,
|
|
2440
2871
|
scriptName: CLI_SCRIPT_NAME,
|
|
2441
2872
|
options,
|
|
2873
|
+
groups,
|
|
2874
|
+
examples: [
|
|
2875
|
+
[
|
|
2876
|
+
"code-pushup",
|
|
2877
|
+
"Run collect followed by upload based on configuration from code-pushup.config.* file."
|
|
2878
|
+
],
|
|
2879
|
+
[
|
|
2880
|
+
"code-pushup collect --tsconfig=tsconfig.base.json",
|
|
2881
|
+
"Run collect using custom tsconfig to parse code-pushup.config.ts file."
|
|
2882
|
+
],
|
|
2883
|
+
[
|
|
2884
|
+
"code-pushup collect --onlyPlugins=coverage",
|
|
2885
|
+
"Run collect with only coverage plugin, other plugins from config file will be skipped."
|
|
2886
|
+
],
|
|
2887
|
+
[
|
|
2888
|
+
"code-pushup upload --persist.outputDir=dist --persist.filename=cp-report --upload.apiKey=$CP_API_KEY",
|
|
2889
|
+
"Upload dist/cp-report.json to portal using API key from environment variable"
|
|
2890
|
+
],
|
|
2891
|
+
[
|
|
2892
|
+
"code-pushup print-config --config code-pushup.config.test.js",
|
|
2893
|
+
"Print resolved config object parsed from custom config location"
|
|
2894
|
+
]
|
|
2895
|
+
],
|
|
2442
2896
|
middlewares,
|
|
2443
2897
|
commands
|
|
2444
2898
|
});
|