diff --git a/packages/cli/src/commands/lint.ts b/packages/cli/src/commands/lint.ts index 6a5b17594..6f722d5c3 100644 --- a/packages/cli/src/commands/lint.ts +++ b/packages/cli/src/commands/lint.ts @@ -14,7 +14,14 @@ import { formatOutput, writeOutput } from '../services/output'; import { FailSeverity, ILintConfig, OutputFormat } from '../services/config'; import { CLIError } from '../errors'; -import { getScoringConfig } from '../formatters/utils/getScoring'; +import { ScoringConfig } from "./../formatters/types"; +import { + getScoringConfig, + getScoringLevel, + groupBySource, + getCountsBySeverity, + uniqueErrors +} from '../formatters//utils'; const formatOptions = Object.values(OutputFormat); @@ -204,18 +211,22 @@ const lintCommand: CommandModule = { results = filterResultsBySeverity(results, failSeverity); } + const scoringConfigData = getScoringConfig(scoringConfig); + await Promise.all( format.map(f => { const formattedOutput = formatOutput(results, f, { failSeverity: getDiagnosticSeverity(failSeverity), - scoringConfig: getScoringConfig(scoringConfig), + scoringConfig: scoringConfigData, }); return writeOutput(formattedOutput, output?.[f] ?? ''); }), ); - + //process.stdout.write(`${scoringThresholdNotEnough(results, scoringConfigData)}\n`); if (results.length > 0) { - process.exit(severeEnoughToFail(results, failSeverity) ? 1 : 0); + process.exit( + scoringThresholdNotEnough(results, scoringConfigData) ? 1 : severeEnoughToFail(results, failSeverity) ? 1 : 0, + ); } else if (config.quiet !== true) { const isErrorSeverity = getDiagnosticSeverity(failSeverity) === DiagnosticSeverity.Error; process.stdout.write( @@ -283,6 +294,25 @@ const filterResultsBySeverity = (results: IRuleResult[], failSeverity: FailSever return results.filter(r => r.severity <= diagnosticSeverity); }; +const scoringThresholdNotEnough = (results: IRuleResult[], scoringConfig: ScoringConfig | undefined): boolean => { + if (scoringConfig !== void 0) { + const groupedResults = groupBySource(results); + let groupedUniqueResults = { ...groupedResults }; + if (scoringConfig.uniqueErrors) { + groupedUniqueResults = { ...groupBySource(uniqueErrors(results)) }; + } + return ( + scoringConfig.threshold > + getScoringLevel( + getCountsBySeverity(groupedUniqueResults), + scoringConfig.scoringSubtract, + scoringConfig.warningsSubtract, + ) + ); + } + return false; +}; + export const severeEnoughToFail = (results: IRuleResult[], failSeverity: FailSeverity): boolean => { const diagnosticSeverity = getDiagnosticSeverity(failSeverity); return results.some(r => r.severity <= diagnosticSeverity); diff --git a/packages/cli/src/formatters/utils/getScoring.ts b/packages/cli/src/formatters/utils/getScoring.ts index e71c1dfec..561ddee63 100644 --- a/packages/cli/src/formatters/utils/getScoring.ts +++ b/packages/cli/src/formatters/utils/getScoring.ts @@ -1,6 +1,6 @@ import { SEVERITY_MAP } from '@stoplight/spectral-core'; import { DiagnosticSeverity } from '@stoplight/types'; -import { ScoringConfig } from '../types'; +import { ScoringConfig, ScoringTable } from '../types'; import * as path from '@stoplight/path'; import fs from 'fs'; @@ -16,16 +16,16 @@ export const getScoringConfig = (scoringFile?: string): ScoringConfig | undefine return scoringConfig; }; -export const getScoringText = ( +export const getScoringLevel = ( issuesCount: { [DiagnosticSeverity.Error]: number; [DiagnosticSeverity.Warning]: number; [DiagnosticSeverity.Information]: number; [DiagnosticSeverity.Hint]: number; }, - scoringConfig: ScoringConfig, -): string => { - const { scoringSubtract, scoringLetter, warningsSubtract } = scoringConfig; + scoringSubtract: ScoringTable[], + warningsSubtract: boolean, +): number => { let scoring = 100; Object.keys(issuesCount).forEach(key => { const scoringKey = Object.keys(SEVERITY_MAP).filter(mappedKey => SEVERITY_MAP[mappedKey] == key)[0]; @@ -34,13 +34,25 @@ export const getScoringText = ( let subtractValue = 0; Object.keys(scoringSubtract[scoringKey]).forEach( subtractKey => - subtractValue = issuesCount[key] >= subtractKey ? - scoringSubtract[scoringKey][subtractKey] : - subtractValue + (subtractValue = issuesCount[key] >= subtractKey ? scoringSubtract[scoringKey][subtractKey] : subtractValue), ); scoring -= subtractValue; } }); + return scoring; +}; + +export const getScoringText = ( + issuesCount: { + [DiagnosticSeverity.Error]: number; + [DiagnosticSeverity.Warning]: number; + [DiagnosticSeverity.Information]: number; + [DiagnosticSeverity.Hint]: number; + }, + scoringConfig: ScoringConfig, +): string => { + const { scoringSubtract, scoringLetter, warningsSubtract } = scoringConfig; + const scoring = getScoringLevel(issuesCount, scoringSubtract, warningsSubtract); let scoringLevel: string = Object.keys(scoringLetter)[Object.keys(scoringLetter).length - 1]; Object.keys(scoringLetter) .reverse()