@probelabs/visor 0.1.72 → 0.1.74
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 +32 -0
- package/action.yml +5 -1
- package/dist/check-execution-engine.d.ts +92 -3
- package/dist/check-execution-engine.d.ts.map +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/index.js +546 -74
- package/dist/output-formatters.d.ts +2 -0
- package/dist/output-formatters.d.ts.map +1 -1
- package/dist/sdk/{check-execution-engine-RXV4MUD2.mjs → check-execution-engine-75SSXUBP.mjs} +2 -2
- package/dist/sdk/{chunk-J355UUEI.mjs → chunk-NINHE4RF.mjs} +295 -28
- package/dist/sdk/chunk-NINHE4RF.mjs.map +1 -0
- package/dist/sdk/sdk.d.mts +99 -60
- package/dist/sdk/sdk.d.ts +99 -60
- package/dist/sdk/sdk.js +293 -26
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +1 -1
- package/package.json +3 -3
- package/dist/sdk/chunk-J355UUEI.mjs.map +0 -1
- /package/dist/sdk/{check-execution-engine-RXV4MUD2.mjs.map → check-execution-engine-75SSXUBP.mjs.map} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -1540,7 +1540,7 @@ var init_reviewer = __esm({
|
|
|
1540
1540
|
if (config && checks && checks.length > 0) {
|
|
1541
1541
|
const { CheckExecutionEngine: CheckExecutionEngine2 } = await Promise.resolve().then(() => (init_check_execution_engine(), check_execution_engine_exports));
|
|
1542
1542
|
const engine = new CheckExecutionEngine2();
|
|
1543
|
-
const
|
|
1543
|
+
const { results } = await engine.executeGroupedChecks(
|
|
1544
1544
|
prInfo,
|
|
1545
1545
|
checks,
|
|
1546
1546
|
void 0,
|
|
@@ -1548,7 +1548,7 @@ var init_reviewer = __esm({
|
|
|
1548
1548
|
void 0,
|
|
1549
1549
|
debug
|
|
1550
1550
|
);
|
|
1551
|
-
return
|
|
1551
|
+
return results;
|
|
1552
1552
|
}
|
|
1553
1553
|
throw new Error(
|
|
1554
1554
|
"No configuration provided. Please create a .visor.yaml file with check definitions. Built-in prompts have been removed - all checks must be explicitly configured."
|
|
@@ -6016,6 +6016,7 @@ var init_check_execution_engine = __esm({
|
|
|
6016
6016
|
config;
|
|
6017
6017
|
webhookContext;
|
|
6018
6018
|
routingSandbox;
|
|
6019
|
+
executionStats = /* @__PURE__ */ new Map();
|
|
6019
6020
|
constructor(workingDirectory) {
|
|
6020
6021
|
this.workingDirectory = workingDirectory || process.cwd();
|
|
6021
6022
|
this.gitAnalyzer = new GitRepositoryAnalyzer(this.workingDirectory);
|
|
@@ -6554,12 +6555,14 @@ ${expr}
|
|
|
6554
6555
|
apiCallDetails: reviewSummary.debug.apiCallDetails
|
|
6555
6556
|
};
|
|
6556
6557
|
}
|
|
6558
|
+
const executionStatistics = this.buildExecutionStatistics();
|
|
6557
6559
|
return {
|
|
6558
6560
|
repositoryInfo,
|
|
6559
6561
|
reviewSummary,
|
|
6560
6562
|
executionTime,
|
|
6561
6563
|
timestamp,
|
|
6562
6564
|
checksExecuted: filteredChecks,
|
|
6565
|
+
executionStatistics,
|
|
6563
6566
|
debug: debugInfo
|
|
6564
6567
|
};
|
|
6565
6568
|
} catch (error) {
|
|
@@ -6752,7 +6755,7 @@ ${expr}
|
|
|
6752
6755
|
});
|
|
6753
6756
|
}
|
|
6754
6757
|
/**
|
|
6755
|
-
* Execute review checks and return grouped results for new architecture
|
|
6758
|
+
* Execute review checks and return grouped results with statistics for new architecture
|
|
6756
6759
|
*/
|
|
6757
6760
|
async executeGroupedChecks(prInfo, checks, timeout, config, outputFormat, debug, maxParallelism, failFast, tagFilter) {
|
|
6758
6761
|
const logFn = outputFormat === "json" || outputFormat === "sarif" ? debug ? console.error : () => {
|
|
@@ -6782,7 +6785,10 @@ ${expr}
|
|
|
6782
6785
|
checks = tagFilteredChecks;
|
|
6783
6786
|
if (checks.length === 0) {
|
|
6784
6787
|
logger.warn("\u26A0\uFE0F No checks remain after tag filtering");
|
|
6785
|
-
return {
|
|
6788
|
+
return {
|
|
6789
|
+
results: {},
|
|
6790
|
+
statistics: this.buildExecutionStatistics()
|
|
6791
|
+
};
|
|
6786
6792
|
}
|
|
6787
6793
|
if (!config?.checks) {
|
|
6788
6794
|
throw new Error("Config with check definitions required for grouped execution");
|
|
@@ -6822,9 +6828,15 @@ ${expr}
|
|
|
6822
6828
|
);
|
|
6823
6829
|
const groupedResults = {};
|
|
6824
6830
|
groupedResults[checkResult.group] = [checkResult];
|
|
6825
|
-
return
|
|
6831
|
+
return {
|
|
6832
|
+
results: groupedResults,
|
|
6833
|
+
statistics: this.buildExecutionStatistics()
|
|
6834
|
+
};
|
|
6826
6835
|
}
|
|
6827
|
-
return {
|
|
6836
|
+
return {
|
|
6837
|
+
results: {},
|
|
6838
|
+
statistics: this.buildExecutionStatistics()
|
|
6839
|
+
};
|
|
6828
6840
|
}
|
|
6829
6841
|
/**
|
|
6830
6842
|
* Execute single check and return grouped result
|
|
@@ -6870,7 +6882,7 @@ ${expr}
|
|
|
6870
6882
|
};
|
|
6871
6883
|
}
|
|
6872
6884
|
/**
|
|
6873
|
-
* Execute multiple checks with dependency awareness - return grouped results
|
|
6885
|
+
* Execute multiple checks with dependency awareness - return grouped results with statistics
|
|
6874
6886
|
*/
|
|
6875
6887
|
async executeGroupedDependencyAwareChecks(prInfo, checks, timeout, config, logFn, debug, maxParallelism, failFast) {
|
|
6876
6888
|
const reviewSummary = await this.executeDependencyAwareChecks(
|
|
@@ -6883,7 +6895,17 @@ ${expr}
|
|
|
6883
6895
|
maxParallelism,
|
|
6884
6896
|
failFast
|
|
6885
6897
|
);
|
|
6886
|
-
|
|
6898
|
+
const executionStatistics = this.buildExecutionStatistics();
|
|
6899
|
+
const groupedResults = await this.convertReviewSummaryToGroupedResults(
|
|
6900
|
+
reviewSummary,
|
|
6901
|
+
checks,
|
|
6902
|
+
config,
|
|
6903
|
+
prInfo
|
|
6904
|
+
);
|
|
6905
|
+
return {
|
|
6906
|
+
results: groupedResults,
|
|
6907
|
+
statistics: executionStatistics
|
|
6908
|
+
};
|
|
6887
6909
|
}
|
|
6888
6910
|
/**
|
|
6889
6911
|
* Convert ReviewSummary to GroupedCheckResults
|
|
@@ -7146,9 +7168,9 @@ ${expr}
|
|
|
7146
7168
|
let shouldStopExecution = false;
|
|
7147
7169
|
let completedChecksCount = 0;
|
|
7148
7170
|
const totalChecksCount = stats.totalChecks;
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7171
|
+
for (const checkName of checks) {
|
|
7172
|
+
this.initializeCheckStats(checkName);
|
|
7173
|
+
}
|
|
7152
7174
|
for (let levelIndex = 0; levelIndex < dependencyGraph.executionOrder.length && !shouldStopExecution; levelIndex++) {
|
|
7153
7175
|
const executionGroup = dependencyGraph.executionOrder[levelIndex];
|
|
7154
7176
|
const checksInLevel = executionGroup.parallel;
|
|
@@ -7278,11 +7300,13 @@ ${expr}
|
|
|
7278
7300
|
}
|
|
7279
7301
|
let finalResult;
|
|
7280
7302
|
if (isForEachDependent && forEachParentName) {
|
|
7303
|
+
this.recordForEachPreview(checkName, forEachItems);
|
|
7281
7304
|
if (debug) {
|
|
7282
7305
|
log2(
|
|
7283
7306
|
`\u{1F504} Debug: Check "${checkName}" depends on forEach check "${forEachParentName}", executing ${forEachItems.length} times`
|
|
7284
7307
|
);
|
|
7285
7308
|
}
|
|
7309
|
+
logger.info(` Processing ${forEachItems.length} items...`);
|
|
7286
7310
|
const allIssues = [];
|
|
7287
7311
|
const allOutputs = [];
|
|
7288
7312
|
const aggregatedContents = [];
|
|
@@ -7339,6 +7363,7 @@ ${expr}
|
|
|
7339
7363
|
`\u{1F504} Debug: Executing check "${checkName}" for item ${itemIndex + 1}/${forEachItems.length}`
|
|
7340
7364
|
);
|
|
7341
7365
|
}
|
|
7366
|
+
const iterationStart = this.recordIterationStart(checkName);
|
|
7342
7367
|
const itemResult = await this.executeWithRouting(
|
|
7343
7368
|
checkName,
|
|
7344
7369
|
checkConfig,
|
|
@@ -7358,6 +7383,17 @@ ${expr}
|
|
|
7358
7383
|
parent: forEachParentName
|
|
7359
7384
|
}
|
|
7360
7385
|
);
|
|
7386
|
+
const iterationDuration = (Date.now() - iterationStart) / 1e3;
|
|
7387
|
+
this.recordIterationComplete(
|
|
7388
|
+
checkName,
|
|
7389
|
+
iterationStart,
|
|
7390
|
+
true,
|
|
7391
|
+
itemResult.issues || [],
|
|
7392
|
+
itemResult.output
|
|
7393
|
+
);
|
|
7394
|
+
logger.info(
|
|
7395
|
+
` \u2714 ${itemIndex + 1}/${forEachItems.length} (${iterationDuration.toFixed(1)}s)`
|
|
7396
|
+
);
|
|
7361
7397
|
return { index: itemIndex, itemResult };
|
|
7362
7398
|
});
|
|
7363
7399
|
const forEachConcurrency = Math.max(
|
|
@@ -7419,8 +7455,8 @@ ${expr}
|
|
|
7419
7455
|
debug
|
|
7420
7456
|
);
|
|
7421
7457
|
if (!shouldRun) {
|
|
7422
|
-
|
|
7423
|
-
logger.info(`\u23ED
|
|
7458
|
+
this.recordSkip(checkName, "if_condition", checkConfig.if);
|
|
7459
|
+
logger.info(`\u23ED Skipped (if: ${this.truncate(checkConfig.if, 40)})`);
|
|
7424
7460
|
return {
|
|
7425
7461
|
checkName,
|
|
7426
7462
|
error: null,
|
|
@@ -7444,6 +7480,13 @@ ${expr}
|
|
|
7444
7480
|
debug,
|
|
7445
7481
|
results
|
|
7446
7482
|
);
|
|
7483
|
+
this.recordIterationComplete(
|
|
7484
|
+
checkName,
|
|
7485
|
+
checkStartTime,
|
|
7486
|
+
true,
|
|
7487
|
+
finalResult.issues || [],
|
|
7488
|
+
finalResult.output
|
|
7489
|
+
);
|
|
7447
7490
|
if (checkConfig.forEach) {
|
|
7448
7491
|
try {
|
|
7449
7492
|
const finalResultWithOutput = finalResult;
|
|
@@ -7473,7 +7516,22 @@ ${expr}
|
|
|
7473
7516
|
};
|
|
7474
7517
|
const checkDuration = ((Date.now() - checkStartTime) / 1e3).toFixed(1);
|
|
7475
7518
|
const issueCount = enrichedIssues.length;
|
|
7476
|
-
|
|
7519
|
+
const checkStats = this.executionStats.get(checkName);
|
|
7520
|
+
if (checkStats && checkStats.totalRuns > 1) {
|
|
7521
|
+
if (issueCount > 0) {
|
|
7522
|
+
logger.success(
|
|
7523
|
+
`Check complete: ${checkName} (${checkDuration}s) - ${checkStats.totalRuns} runs, ${issueCount} issue${issueCount === 1 ? "" : "s"}`
|
|
7524
|
+
);
|
|
7525
|
+
} else {
|
|
7526
|
+
logger.success(
|
|
7527
|
+
`Check complete: ${checkName} (${checkDuration}s) - ${checkStats.totalRuns} runs`
|
|
7528
|
+
);
|
|
7529
|
+
}
|
|
7530
|
+
} else if (checkStats && checkStats.outputsProduced && checkStats.outputsProduced > 0) {
|
|
7531
|
+
logger.success(
|
|
7532
|
+
`Check complete: ${checkName} (${checkDuration}s) - ${checkStats.outputsProduced} items`
|
|
7533
|
+
);
|
|
7534
|
+
} else if (issueCount > 0) {
|
|
7477
7535
|
logger.success(
|
|
7478
7536
|
`Check complete: ${checkName} (${checkDuration}s) - ${issueCount} issue${issueCount === 1 ? "" : "s"} found`
|
|
7479
7537
|
);
|
|
@@ -7486,9 +7544,10 @@ ${expr}
|
|
|
7486
7544
|
result: enrichedResult
|
|
7487
7545
|
};
|
|
7488
7546
|
} catch (error) {
|
|
7489
|
-
failedChecksCount++;
|
|
7490
7547
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
7491
7548
|
const checkDuration = ((Date.now() - checkStartTime) / 1e3).toFixed(1);
|
|
7549
|
+
this.recordError(checkName, error instanceof Error ? error : new Error(String(error)));
|
|
7550
|
+
this.recordIterationComplete(checkName, checkStartTime, false, [], void 0);
|
|
7492
7551
|
logger.error(`\u2716 Check failed: ${checkName} (${checkDuration}s) - ${errorMessage}`);
|
|
7493
7552
|
if (debug) {
|
|
7494
7553
|
log2(`\u{1F527} Debug: Error in check ${checkName}: ${errorMessage}`);
|
|
@@ -7596,19 +7655,13 @@ ${expr}
|
|
|
7596
7655
|
}
|
|
7597
7656
|
}
|
|
7598
7657
|
}
|
|
7599
|
-
const
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
logger.step(`Execution complete (${executionDuration}s)`);
|
|
7603
|
-
logger.info(` \u2714 Successful: ${successfulChecks}/${totalChecksCount}`);
|
|
7604
|
-
if (skippedChecksCount > 0) {
|
|
7605
|
-
logger.info(` \u23ED Skipped: ${skippedChecksCount}`);
|
|
7606
|
-
}
|
|
7607
|
-
if (failedChecksCount > 0) {
|
|
7608
|
-
logger.info(` \u2716 Failed: ${failedChecksCount}`);
|
|
7658
|
+
const executionStatistics = this.buildExecutionStatistics();
|
|
7659
|
+
if (logFn === console.log) {
|
|
7660
|
+
this.logExecutionSummary(executionStatistics);
|
|
7609
7661
|
}
|
|
7610
7662
|
if (shouldStopExecution) {
|
|
7611
|
-
logger.
|
|
7663
|
+
logger.info("");
|
|
7664
|
+
logger.warn(`\u26A0\uFE0F Execution stopped early due to fail-fast`);
|
|
7612
7665
|
}
|
|
7613
7666
|
if (debug) {
|
|
7614
7667
|
if (shouldStopExecution) {
|
|
@@ -8563,6 +8616,220 @@ ${result.value.result.debug.rawResponse}`;
|
|
|
8563
8616
|
}
|
|
8564
8617
|
return "pr_updated";
|
|
8565
8618
|
}
|
|
8619
|
+
/**
|
|
8620
|
+
* Initialize execution statistics for a check
|
|
8621
|
+
*/
|
|
8622
|
+
initializeCheckStats(checkName) {
|
|
8623
|
+
this.executionStats.set(checkName, {
|
|
8624
|
+
checkName,
|
|
8625
|
+
totalRuns: 0,
|
|
8626
|
+
successfulRuns: 0,
|
|
8627
|
+
failedRuns: 0,
|
|
8628
|
+
skipped: false,
|
|
8629
|
+
totalDuration: 0,
|
|
8630
|
+
issuesFound: 0,
|
|
8631
|
+
issuesBySeverity: {
|
|
8632
|
+
critical: 0,
|
|
8633
|
+
error: 0,
|
|
8634
|
+
warning: 0,
|
|
8635
|
+
info: 0
|
|
8636
|
+
},
|
|
8637
|
+
perIterationDuration: []
|
|
8638
|
+
});
|
|
8639
|
+
}
|
|
8640
|
+
/**
|
|
8641
|
+
* Record the start of a check iteration
|
|
8642
|
+
* Returns the start timestamp for duration tracking
|
|
8643
|
+
*/
|
|
8644
|
+
recordIterationStart(_checkName) {
|
|
8645
|
+
return Date.now();
|
|
8646
|
+
}
|
|
8647
|
+
/**
|
|
8648
|
+
* Record completion of a check iteration
|
|
8649
|
+
*/
|
|
8650
|
+
recordIterationComplete(checkName, startTime, success, issues, output) {
|
|
8651
|
+
const stats = this.executionStats.get(checkName);
|
|
8652
|
+
if (!stats) return;
|
|
8653
|
+
const duration = Date.now() - startTime;
|
|
8654
|
+
stats.totalRuns++;
|
|
8655
|
+
if (success) {
|
|
8656
|
+
stats.successfulRuns++;
|
|
8657
|
+
} else {
|
|
8658
|
+
stats.failedRuns++;
|
|
8659
|
+
}
|
|
8660
|
+
stats.totalDuration += duration;
|
|
8661
|
+
stats.perIterationDuration.push(duration);
|
|
8662
|
+
for (const issue of issues) {
|
|
8663
|
+
stats.issuesFound++;
|
|
8664
|
+
if (issue.severity === "critical") stats.issuesBySeverity.critical++;
|
|
8665
|
+
else if (issue.severity === "error") stats.issuesBySeverity.error++;
|
|
8666
|
+
else if (issue.severity === "warning") stats.issuesBySeverity.warning++;
|
|
8667
|
+
else if (issue.severity === "info") stats.issuesBySeverity.info++;
|
|
8668
|
+
}
|
|
8669
|
+
if (output !== void 0) {
|
|
8670
|
+
stats.outputsProduced = (stats.outputsProduced || 0) + 1;
|
|
8671
|
+
}
|
|
8672
|
+
}
|
|
8673
|
+
/**
|
|
8674
|
+
* Record that a check was skipped
|
|
8675
|
+
*/
|
|
8676
|
+
recordSkip(checkName, reason, condition) {
|
|
8677
|
+
const stats = this.executionStats.get(checkName);
|
|
8678
|
+
if (!stats) return;
|
|
8679
|
+
stats.skipped = true;
|
|
8680
|
+
stats.skipReason = reason;
|
|
8681
|
+
if (condition) {
|
|
8682
|
+
stats.skipCondition = condition;
|
|
8683
|
+
}
|
|
8684
|
+
}
|
|
8685
|
+
/**
|
|
8686
|
+
* Record forEach preview items
|
|
8687
|
+
*/
|
|
8688
|
+
recordForEachPreview(checkName, items) {
|
|
8689
|
+
const stats = this.executionStats.get(checkName);
|
|
8690
|
+
if (!stats || !items.length) return;
|
|
8691
|
+
const preview = items.slice(0, 3).map((item) => {
|
|
8692
|
+
const str = typeof item === "string" ? item : JSON.stringify(item);
|
|
8693
|
+
return str.length > 50 ? str.substring(0, 47) + "..." : str;
|
|
8694
|
+
});
|
|
8695
|
+
if (items.length > 3) {
|
|
8696
|
+
preview.push(`...${items.length - 3} more`);
|
|
8697
|
+
}
|
|
8698
|
+
stats.forEachPreview = preview;
|
|
8699
|
+
}
|
|
8700
|
+
/**
|
|
8701
|
+
* Record an error for a check
|
|
8702
|
+
*/
|
|
8703
|
+
recordError(checkName, error) {
|
|
8704
|
+
const stats = this.executionStats.get(checkName);
|
|
8705
|
+
if (!stats) return;
|
|
8706
|
+
stats.errorMessage = error instanceof Error ? error.message : String(error);
|
|
8707
|
+
}
|
|
8708
|
+
/**
|
|
8709
|
+
* Build the final execution statistics object
|
|
8710
|
+
*/
|
|
8711
|
+
buildExecutionStatistics() {
|
|
8712
|
+
const checks = Array.from(this.executionStats.values());
|
|
8713
|
+
const totalExecutions = checks.reduce((sum, s) => sum + s.totalRuns, 0);
|
|
8714
|
+
const successfulExecutions = checks.reduce((sum, s) => sum + s.successfulRuns, 0);
|
|
8715
|
+
const failedExecutions = checks.reduce((sum, s) => sum + s.failedRuns, 0);
|
|
8716
|
+
const skippedChecks = checks.filter((s) => s.skipped).length;
|
|
8717
|
+
const totalDuration = checks.reduce((sum, s) => sum + s.totalDuration, 0);
|
|
8718
|
+
return {
|
|
8719
|
+
totalChecksConfigured: checks.length,
|
|
8720
|
+
totalExecutions,
|
|
8721
|
+
successfulExecutions,
|
|
8722
|
+
failedExecutions,
|
|
8723
|
+
skippedChecks,
|
|
8724
|
+
totalDuration,
|
|
8725
|
+
checks
|
|
8726
|
+
};
|
|
8727
|
+
}
|
|
8728
|
+
/**
|
|
8729
|
+
* Truncate a string to max length with ellipsis
|
|
8730
|
+
*/
|
|
8731
|
+
truncate(str, maxLen) {
|
|
8732
|
+
if (str.length <= maxLen) return str;
|
|
8733
|
+
return str.substring(0, maxLen - 3) + "...";
|
|
8734
|
+
}
|
|
8735
|
+
/**
|
|
8736
|
+
* Format the Status column for execution summary table
|
|
8737
|
+
*/
|
|
8738
|
+
formatStatusColumn(stats) {
|
|
8739
|
+
if (stats.skipped) {
|
|
8740
|
+
if (stats.skipReason === "if_condition") return "\u23ED if";
|
|
8741
|
+
if (stats.skipReason === "fail_fast") return "\u23ED ff";
|
|
8742
|
+
if (stats.skipReason === "dependency_failed") return "\u23ED dep";
|
|
8743
|
+
return "\u23ED";
|
|
8744
|
+
}
|
|
8745
|
+
if (stats.totalRuns === 0) return "-";
|
|
8746
|
+
const symbol = stats.failedRuns === 0 ? "\u2714" : stats.successfulRuns === 0 ? "\u2716" : "\u2714/\u2716";
|
|
8747
|
+
if (stats.totalRuns > 1) {
|
|
8748
|
+
if (stats.failedRuns > 0 && stats.successfulRuns > 0) {
|
|
8749
|
+
return `${symbol} ${stats.successfulRuns}/${stats.totalRuns}`;
|
|
8750
|
+
} else {
|
|
8751
|
+
return `${symbol} \xD7${stats.totalRuns}`;
|
|
8752
|
+
}
|
|
8753
|
+
}
|
|
8754
|
+
return symbol;
|
|
8755
|
+
}
|
|
8756
|
+
/**
|
|
8757
|
+
* Format the Details column for execution summary table
|
|
8758
|
+
*/
|
|
8759
|
+
formatDetailsColumn(stats) {
|
|
8760
|
+
const parts = [];
|
|
8761
|
+
if (stats.outputsProduced && stats.outputsProduced > 0) {
|
|
8762
|
+
parts.push(`\u2192${stats.outputsProduced}`);
|
|
8763
|
+
}
|
|
8764
|
+
if (stats.issuesBySeverity.critical > 0) {
|
|
8765
|
+
parts.push(`${stats.issuesBySeverity.critical}\u{1F534}`);
|
|
8766
|
+
}
|
|
8767
|
+
if (stats.issuesBySeverity.warning > 0) {
|
|
8768
|
+
parts.push(`${stats.issuesBySeverity.warning}\u26A0\uFE0F`);
|
|
8769
|
+
}
|
|
8770
|
+
if (stats.issuesBySeverity.info > 0 && stats.issuesBySeverity.critical === 0 && stats.issuesBySeverity.warning === 0) {
|
|
8771
|
+
parts.push(`${stats.issuesBySeverity.info}\u{1F4A1}`);
|
|
8772
|
+
}
|
|
8773
|
+
if (stats.errorMessage) {
|
|
8774
|
+
parts.push(this.truncate(stats.errorMessage, 20));
|
|
8775
|
+
} else if (stats.skipCondition) {
|
|
8776
|
+
parts.push(this.truncate(stats.skipCondition, 20));
|
|
8777
|
+
}
|
|
8778
|
+
return parts.join(" ");
|
|
8779
|
+
}
|
|
8780
|
+
/**
|
|
8781
|
+
* Log the execution summary table
|
|
8782
|
+
*/
|
|
8783
|
+
logExecutionSummary(stats) {
|
|
8784
|
+
const totalIssues = stats.checks.reduce((sum, s) => sum + s.issuesFound, 0);
|
|
8785
|
+
const criticalIssues = stats.checks.reduce((sum, s) => sum + s.issuesBySeverity.critical, 0);
|
|
8786
|
+
const warningIssues = stats.checks.reduce((sum, s) => sum + s.issuesBySeverity.warning, 0);
|
|
8787
|
+
const durationSec = (stats.totalDuration / 1e3).toFixed(1);
|
|
8788
|
+
const summaryTable = new (require("cli-table3"))({
|
|
8789
|
+
style: {
|
|
8790
|
+
head: [],
|
|
8791
|
+
border: []
|
|
8792
|
+
},
|
|
8793
|
+
colWidths: [41]
|
|
8794
|
+
});
|
|
8795
|
+
summaryTable.push(
|
|
8796
|
+
[`Execution Complete (${durationSec}s)`],
|
|
8797
|
+
[`Checks: ${stats.totalChecksConfigured} configured \u2192 ${stats.totalExecutions} executions`],
|
|
8798
|
+
[
|
|
8799
|
+
`Status: ${stats.successfulExecutions} \u2714 \u2502 ${stats.failedExecutions} \u2716 \u2502 ${stats.skippedChecks} \u23ED`
|
|
8800
|
+
]
|
|
8801
|
+
);
|
|
8802
|
+
if (totalIssues > 0) {
|
|
8803
|
+
let issuesLine = `Issues: ${totalIssues} total`;
|
|
8804
|
+
if (criticalIssues > 0) issuesLine += ` (${criticalIssues} \u{1F534}`;
|
|
8805
|
+
if (warningIssues > 0) issuesLine += `${criticalIssues > 0 ? " " : " ("}${warningIssues} \u26A0\uFE0F)`;
|
|
8806
|
+
else if (criticalIssues > 0) issuesLine += ")";
|
|
8807
|
+
summaryTable.push([issuesLine]);
|
|
8808
|
+
}
|
|
8809
|
+
logger.info("");
|
|
8810
|
+
logger.info(summaryTable.toString());
|
|
8811
|
+
logger.info("");
|
|
8812
|
+
logger.info("Check Details:");
|
|
8813
|
+
const detailsTable = new (require("cli-table3"))({
|
|
8814
|
+
head: ["Check", "Duration", "Status", "Details"],
|
|
8815
|
+
colWidths: [21, 10, 10, 21],
|
|
8816
|
+
style: {
|
|
8817
|
+
head: ["cyan"],
|
|
8818
|
+
border: ["grey"]
|
|
8819
|
+
}
|
|
8820
|
+
});
|
|
8821
|
+
for (const checkStats of stats.checks) {
|
|
8822
|
+
const duration = checkStats.skipped ? "-" : `${(checkStats.totalDuration / 1e3).toFixed(1)}s`;
|
|
8823
|
+
const status = this.formatStatusColumn(checkStats);
|
|
8824
|
+
const details = this.formatDetailsColumn(checkStats);
|
|
8825
|
+
detailsTable.push([checkStats.checkName, duration, status, details]);
|
|
8826
|
+
}
|
|
8827
|
+
logger.info(detailsTable.toString());
|
|
8828
|
+
logger.info("");
|
|
8829
|
+
logger.info(
|
|
8830
|
+
"Legend: \u2714=success \u2502 \u2716=failed \u2502 \u23ED=skipped \u2502 \xD7N=iterations \u2502 \u2192N=outputs \u2502 N\u{1F534}=critical \u2502 N\u26A0\uFE0F=warnings"
|
|
8831
|
+
);
|
|
8832
|
+
}
|
|
8566
8833
|
};
|
|
8567
8834
|
}
|
|
8568
8835
|
});
|