printReport method

int printReport(
  1. List<AuditRunResult> results, {
  2. required ProjectContext context,
  3. bool verbose = false,
  4. Severity? failOn = Severity.high,
  5. Set<String> exemptFromFailOn = const {},
})

Prints the full report and returns the process exit code: 0 if no issue meets failOn, 1 otherwise. Maintenance findings never affect the exit code. Pass failOn: null to always exit 0.

exemptFromFailOn holds ids of issues (typically critical/high findings kept visible by a baseline) that should still be shown but must not, on their own, trigger a non-zero exit code.

Implementation

int printReport(
  List<AuditRunResult> results, {
  required ProjectContext context,
  bool verbose = false,
  Severity? failOn = Severity.high,
  Set<String> exemptFromFailOn = const {},
}) {
  final securityIssues = <SecurityIssue>[];
  final maintenanceIssues = <SecurityIssue>[];
  final passedAudits = <Audit>[];

  for (final run in results) {
    if (!run.result.hasIssues) {
      passedAudits.add(run.audit);
      continue;
    }

    if (maintenanceAuditIds.contains(run.audit.id)) {
      maintenanceIssues.addAll(run.result.issues);
    } else {
      securityIssues.addAll(run.result.issues);
    }
  }

  final highRisk = securityIssues
      .where(
        (issue) =>
            issue.severity == Severity.critical ||
            issue.severity == Severity.high,
      )
      .toList();
  final mediumRisk = securityIssues
      .where((issue) => issue.severity == Severity.medium)
      .toList();
  final lowRisk = securityIssues
      .where(
        (issue) =>
            issue.severity == Severity.low || issue.severity == Severity.info,
      )
      .toList();

  _printHeader(context);
  _printSummary(
    highRisk,
    mediumRisk,
    lowRisk,
    maintenanceIssues,
    passedAudits,
    exemptFromFailOn,
  );

  var itemNumber = 1;
  itemNumber = _printRiskSection(
    'HIGH RISK',
    '✗',
    highRisk,
    itemNumber,
    exemptFromFailOn: exemptFromFailOn,
  );
  itemNumber = _printRiskSection(
    'MEDIUM RISK',
    '⚠',
    mediumRisk,
    itemNumber,
    exemptFromFailOn: exemptFromFailOn,
  );

  _printLowRiskSection(lowRisk, verbose: verbose);
  _printMaintenanceSection(maintenanceIssues, verbose: verbose);
  _printPassedSection(passedAudits);

  final hasFailingIssue =
      failOn != null &&
      securityIssues.any(
        (issue) =>
            issue.severity.isAtLeastAsSevereAs(failOn) &&
            !exemptFromFailOn.contains(issue.id),
      );
  final exitCode = hasFailingIssue ? 1 : 0;

  _printFooter(
    highRisk.length,
    mediumRisk.length,
    lowRisk.length,
    maintenanceIssues.length,
    exitCode,
  );

  return exitCode;
}