From 0bcde89c4240f2411d423786fa00f09cf705c97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 26 Sep 2025 15:44:07 +0200 Subject: [PATCH] feat(formatters): add severity custom attribute to TeamCity inspections --- packages/formatters/src/__tests__/teamcity.test.ts | 12 ++++++------ packages/formatters/src/teamcity.ts | 12 ++++++++++-- .../results-format-teamcity.scenario | 6 +++--- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/formatters/src/__tests__/teamcity.test.ts b/packages/formatters/src/__tests__/teamcity.test.ts index 027794a47..015a016ef 100644 --- a/packages/formatters/src/__tests__/teamcity.test.ts +++ b/packages/formatters/src/__tests__/teamcity.test.ts @@ -8,16 +8,16 @@ describe('Teamcity formatter', () => { const result = teamcity(mixedErrors, { failSeverity: DiagnosticSeverity.Error }); expect(result) .toContain(`##teamcity[inspectionType category='openapi' id='info-contact' name='info-contact' description='hint -- Info object should contain \`contact\` object.'] -##teamcity[inspection typeId='info-contact' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='3' message='hint -- Info object should contain \`contact\` object.'] +##teamcity[inspection typeId='info-contact' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='3' message='hint -- Info object should contain \`contact\` object.' SEVERITY='HINT'] ##teamcity[inspectionType category='openapi' id='info-description' name='info-description' description='warning -- OpenAPI object info \`description\` must be present and non-empty string.'] -##teamcity[inspection typeId='info-description' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='3' message='warning -- OpenAPI object info \`description\` must be present and non-empty string.'] +##teamcity[inspection typeId='info-description' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='3' message='warning -- OpenAPI object info \`description\` must be present and non-empty string.' SEVERITY='WARNING'] ##teamcity[inspectionType category='openapi' id='info-matches-stoplight' name='info-matches-stoplight' description='error -- Info must contain Stoplight'] -##teamcity[inspection typeId='info-matches-stoplight' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='5' message='error -- Info must contain Stoplight'] +##teamcity[inspection typeId='info-matches-stoplight' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='5' message='error -- Info must contain Stoplight' SEVERITY='ERROR'] ##teamcity[inspectionType category='openapi' id='operation-description' name='operation-description' description='information -- Operation \`description\` must be present and non-empty string.'] -##teamcity[inspection typeId='operation-description' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='17' message='information -- Operation \`description\` must be present and non-empty string.'] +##teamcity[inspection typeId='operation-description' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='17' message='information -- Operation \`description\` must be present and non-empty string.' SEVERITY='INFO'] ##teamcity[inspectionType category='openapi' id='operation-description' name='operation-description' description='information -- Operation \`description\` must be present and non-empty string.'] -##teamcity[inspection typeId='operation-description' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='64' message='information -- Operation \`description\` must be present and non-empty string.'] +##teamcity[inspection typeId='operation-description' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='64' message='information -- Operation \`description\` must be present and non-empty string.' SEVERITY='INFO'] ##teamcity[inspectionType category='openapi' id='operation-description' name='operation-description' description='information -- Operation \`description\` must be present and non-empty string.'] -##teamcity[inspection typeId='operation-description' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='86' message='information -- Operation \`description\` must be present and non-empty string.']`); +##teamcity[inspection typeId='operation-description' file='/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json' line='86' message='information -- Operation \`description\` must be present and non-empty string.' SEVERITY='INFO']`); }); }); diff --git a/packages/formatters/src/teamcity.ts b/packages/formatters/src/teamcity.ts index c69bf5df5..45e0d7257 100644 --- a/packages/formatters/src/teamcity.ts +++ b/packages/formatters/src/teamcity.ts @@ -1,4 +1,4 @@ -import { Dictionary, Optional } from '@stoplight/types'; +import { DiagnosticSeverity, Dictionary, Optional } from '@stoplight/types'; import { IRuleResult } from '@stoplight/spectral-core'; import { Formatter } from './types'; import { getSeverityName, groupBySource } from './utils'; @@ -27,12 +27,20 @@ function inspectionType(result: IRuleResult & { source: string }): string { return `##teamcity[inspectionType category='openapi' id='${code}' name='${code}' description='${severity} -- ${message}${documentationUrl}']`; } +const SEVERITY_TEAMCITY_NAMES: Dictionary = { + [DiagnosticSeverity.Error]: 'ERROR', + [DiagnosticSeverity.Warning]: 'WARNING', + [DiagnosticSeverity.Information]: 'INFO', + [DiagnosticSeverity.Hint]: 'HINT', +}; + function inspection(result: IRuleResult & { source: string }): string { const code = escapeString(result.code); const severity = getSeverityName(result.severity); + const teamCitySeverity = SEVERITY_TEAMCITY_NAMES[result.severity]; const message = escapeString(result.message); const line = result.range.start.line + 1; - return `##teamcity[inspection typeId='${code}' file='${result.source}' line='${line}' message='${severity} -- ${message}']`; + return `##teamcity[inspection typeId='${code}' file='${result.source}' line='${line}' message='${severity} -- ${message}' SEVERITY='${teamCitySeverity}']`; } function renderResults(results: IRuleResult[]): string { diff --git a/test-harness/scenarios/documentation-url/results-format-teamcity.scenario b/test-harness/scenarios/documentation-url/results-format-teamcity.scenario index 6fc9cd445..be51a273f 100644 --- a/test-harness/scenarios/documentation-url/results-format-teamcity.scenario +++ b/test-harness/scenarios/documentation-url/results-format-teamcity.scenario @@ -54,8 +54,8 @@ info: ====command==== {bin} lint {document} --format=teamcity --ruleset "{asset:ruleset.json}" --show-documentation-url ====stdout==== -##teamcity[inspectionType category='openapi' id='api-servers' name='api-servers' description='warning -- "servers" must be present and non-empty array. -- https://www.example.com/docs/api-servers.md']##teamcity[inspection typeId='api-servers' file='{document}' line='1' message='warning -- "servers" must be present and non-empty array.'] +##teamcity[inspectionType category='openapi' id='api-servers' name='api-servers' description='warning -- "servers" must be present and non-empty array. -- https://www.example.com/docs/api-servers.md']##teamcity[inspection typeId='api-servers' file='{document}' line='1' message='warning -- "servers" must be present and non-empty array.' SEVERITY='WARNING'] ##teamcity[inspectionType category='openapi' id='info-contact' name='info-contact' description='warning -- Info object must have a "contact" object.'] -##teamcity[inspection typeId='info-contact' file='{document}' line='2' message='warning -- Info object must have a "contact" object.'] +##teamcity[inspection typeId='info-contact' file='{document}' line='2' message='warning -- Info object must have a "contact" object.' SEVERITY='WARNING'] ##teamcity[inspectionType category='openapi' id='info-description' name='info-description' description='warning -- Info "description" must be present and non-empty string. -- https://www.example.com/docs/info-description.md'] -##teamcity[inspection typeId='info-description' file='{document}' line='2' message='warning -- Info "description" must be present and non-empty string.'] \ No newline at end of file +##teamcity[inspection typeId='info-description' file='{document}' line='2' message='warning -- Info "description" must be present and non-empty string.' SEVERITY='WARNING']