Skip to content

Commit 2510427

Browse files
CLOUDP-304967: Add IPA rule for description format (#592)
1 parent 9884dbe commit 2510427

File tree

6 files changed

+310
-0
lines changed

6 files changed

+310
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import testRule from './__helpers__/testRule';
2+
import { DiagnosticSeverity } from '@stoplight/types';
3+
4+
testRule('xgen-IPA-117-description-ends-with-period', [
5+
{
6+
name: 'valid description',
7+
document: {
8+
components: {
9+
schemas: {
10+
Schema: {
11+
properties: {
12+
id: {
13+
description: 'Description.',
14+
},
15+
},
16+
},
17+
},
18+
},
19+
},
20+
errors: [],
21+
},
22+
{
23+
name: 'invalid descriptions',
24+
document: {
25+
components: {
26+
schemas: {
27+
Schema: {
28+
properties: {
29+
noPeriod: {
30+
description: 'Description',
31+
},
32+
},
33+
},
34+
},
35+
},
36+
},
37+
errors: [
38+
{
39+
code: 'xgen-IPA-117-description-ends-with-period',
40+
message: 'Descriptions must end with a full stop(.).',
41+
path: ['components', 'schemas', 'Schema', 'properties', 'noPeriod'],
42+
severity: DiagnosticSeverity.Warning,
43+
},
44+
],
45+
},
46+
{
47+
name: 'ignores descriptions ending with table',
48+
document: {
49+
components: {
50+
schemas: {
51+
Schema: {
52+
properties: {
53+
noPeriod: {
54+
description: 'Description\n| Table |',
55+
},
56+
},
57+
},
58+
},
59+
},
60+
},
61+
errors: [],
62+
},
63+
{
64+
name: 'invalid components with exceptions',
65+
document: {
66+
components: {
67+
schemas: {
68+
Schema: {
69+
properties: {
70+
noPeriod: {
71+
description: 'Description',
72+
'x-xgen-IPA-exception': {
73+
'xgen-IPA-117-description-ends-with-period': 'reason',
74+
},
75+
},
76+
},
77+
},
78+
},
79+
},
80+
},
81+
errors: [],
82+
},
83+
]);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import testRule from './__helpers__/testRule';
2+
import { DiagnosticSeverity } from '@stoplight/types';
3+
4+
testRule('xgen-IPA-117-description-starts-with-uppercase', [
5+
{
6+
name: 'valid description',
7+
document: {
8+
components: {
9+
schemas: {
10+
Schema: {
11+
properties: {
12+
id: {
13+
description: 'Description',
14+
},
15+
},
16+
},
17+
},
18+
},
19+
},
20+
errors: [],
21+
},
22+
{
23+
name: 'invalid descriptions',
24+
document: {
25+
components: {
26+
schemas: {
27+
Schema: {
28+
properties: {
29+
noUpperCase: {
30+
description: 'description',
31+
},
32+
},
33+
},
34+
},
35+
},
36+
},
37+
errors: [
38+
{
39+
code: 'xgen-IPA-117-description-starts-with-uppercase',
40+
message: 'Descriptions must start with Uppercase.',
41+
path: ['components', 'schemas', 'Schema', 'properties', 'noUpperCase'],
42+
severity: DiagnosticSeverity.Warning,
43+
},
44+
],
45+
},
46+
{
47+
name: 'invalid components with exceptions',
48+
document: {
49+
components: {
50+
schemas: {
51+
Schema: {
52+
properties: {
53+
noUpperCase: {
54+
description: 'description',
55+
'x-xgen-IPA-exception': {
56+
'xgen-IPA-117-description-starts-with-uppercase': 'reason',
57+
},
58+
},
59+
},
60+
},
61+
},
62+
},
63+
},
64+
errors: [],
65+
},
66+
]);

tools/spectral/ipa/rulesets/IPA-117.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
functions:
55
- IPA117HasDescription
6+
- IPA117DescriptionStartsWithUpperCase
7+
- IPA117DescriptionEndsWithPeriod
68

79
rules:
810
xgen-IPA-117-description:
@@ -30,3 +32,52 @@ rules:
3032
- '$.components.parameters[*]'
3133
then:
3234
function: 'IPA117HasDescription'
35+
xgen-IPA-117-description-starts-with-uppercase:
36+
description: |
37+
Descriptions must start with Uppercase.
38+
39+
##### Implementation details
40+
Rule checks the format of the description property in the following components:
41+
- Info object
42+
- Tags
43+
- Operation objects
44+
- Inline schema properties for operation object requests and responses
45+
- Parameter objects (in operations and components)
46+
- Schema properties
47+
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-117-description-starts-with-uppercase'
48+
severity: warn
49+
given:
50+
- '$.info'
51+
- '$.tags[*]'
52+
- '$.paths[*][get,put,post,delete,options,head,patch,trace]'
53+
- '$.paths[*][get,put,post,delete,options,head,patch,trace].parameters[*]'
54+
- '$.paths[*][get,put,post,delete,options,head,patch,trace]..content..properties[*]'
55+
- '$.components.schemas..properties[*]'
56+
- '$.components.parameters[*]'
57+
then:
58+
function: 'IPA117DescriptionStartsWithUpperCase'
59+
xgen-IPA-117-description-ends-with-period:
60+
description: |
61+
Descriptions must end with a full stop(.).
62+
63+
##### Implementation details
64+
Rule checks the format of the description property in the following components:
65+
- Info object
66+
- Tags
67+
- Operation objects
68+
- Inline schema properties for operation object requests and responses
69+
- Parameter objects (in operations and components)
70+
- Schema properties
71+
The rule ignores descriptions that end with `|`, i.e. inline markdown tables
72+
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-117-description-ends-with-period'
73+
severity: warn
74+
given:
75+
- '$.info'
76+
- '$.tags[*]'
77+
- '$.paths[*][get,put,post,delete,options,head,patch,trace]'
78+
- '$.paths[*][get,put,post,delete,options,head,patch,trace].parameters[*]'
79+
- '$.paths[*][get,put,post,delete,options,head,patch,trace]..content..properties[*]'
80+
- '$.components.schemas..properties[*]'
81+
- '$.components.parameters[*]'
82+
then:
83+
function: 'IPA117DescriptionEndsWithPeriod'

tools/spectral/ipa/rulesets/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,35 @@ Rule checks for description property in the following components:
546546
- Schema properties
547547
The rule also fails if the description is an empty string.
548548

549+
#### xgen-IPA-117-description-starts-with-uppercase
550+
551+
![warn](https://img.shields.io/badge/warning-yellow)
552+
Descriptions must start with Uppercase.
553+
554+
##### Implementation details
555+
Rule checks the format of the description property in the following components:
556+
- Info object
557+
- Tags
558+
- Operation objects
559+
- Inline schema properties for operation object requests and responses
560+
- Parameter objects (in operations and components)
561+
- Schema properties
562+
563+
#### xgen-IPA-117-description-ends-with-period
564+
565+
![warn](https://img.shields.io/badge/warning-yellow)
566+
Descriptions must end with a full stop(.).
567+
568+
##### Implementation details
569+
Rule checks the format of the description property in the following components:
570+
- Info object
571+
- Tags
572+
- Operation objects
573+
- Inline schema properties for operation object requests and responses
574+
- Parameter objects (in operations and components)
575+
- Schema properties
576+
The rule ignores descriptions that end with `|`, i.e. inline markdown tables
577+
549578

550579

551580
### IPA-123
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { hasException } from './utils/exceptions.js';
2+
import {
3+
collectAdoption,
4+
collectAndReturnViolation,
5+
collectException,
6+
handleInternalError,
7+
} from './utils/collectionUtils.js';
8+
9+
const RULE_NAME = 'xgen-IPA-117-description-ends-with-period';
10+
const ERROR_MESSAGE_PERIOD = 'Descriptions must end with a full stop(.).';
11+
12+
export default (input, opts, { path }) => {
13+
// Ignore missing descriptions or descriptions that ends with an inline table
14+
if (!input['description'] || input['description'].endsWith('|') || input['description'].endsWith('|\n')) {
15+
return;
16+
}
17+
18+
if (hasException(input, RULE_NAME)) {
19+
collectException(input, RULE_NAME, path);
20+
return;
21+
}
22+
23+
const errors = checkViolationsAndReturnErrors(input['description'], path);
24+
if (errors.length !== 0) {
25+
return collectAndReturnViolation(path, RULE_NAME, errors);
26+
}
27+
collectAdoption(path, RULE_NAME);
28+
};
29+
30+
function checkViolationsAndReturnErrors(description, path) {
31+
const periodEnd = new RegExp(`[.]$`);
32+
33+
try {
34+
if (!periodEnd.test(description)) {
35+
return [{ path, message: ERROR_MESSAGE_PERIOD }];
36+
}
37+
return [];
38+
} catch (e) {
39+
handleInternalError(RULE_NAME, path, e);
40+
}
41+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { hasException } from './utils/exceptions.js';
2+
import {
3+
collectAdoption,
4+
collectAndReturnViolation,
5+
collectException,
6+
handleInternalError,
7+
} from './utils/collectionUtils.js';
8+
9+
const RULE_NAME = 'xgen-IPA-117-description-starts-with-uppercase';
10+
const ERROR_MESSAGE_UPPER_CASE = 'Descriptions must start with Uppercase.';
11+
12+
export default (input, opts, { path }) => {
13+
if (!input['description']) {
14+
return;
15+
}
16+
17+
if (hasException(input, RULE_NAME)) {
18+
collectException(input, RULE_NAME, path);
19+
return;
20+
}
21+
22+
const errors = checkViolationsAndReturnErrors(input['description'], path);
23+
if (errors.length !== 0) {
24+
return collectAndReturnViolation(path, RULE_NAME, errors);
25+
}
26+
collectAdoption(path, RULE_NAME);
27+
};
28+
29+
function checkViolationsAndReturnErrors(description, path) {
30+
const upperCaseStart = new RegExp(`^[A-Z]`);
31+
32+
try {
33+
if (!upperCaseStart.test(description)) {
34+
return [{ path, message: ERROR_MESSAGE_UPPER_CASE }];
35+
}
36+
return [];
37+
} catch (e) {
38+
handleInternalError(RULE_NAME, path, e);
39+
}
40+
}

0 commit comments

Comments
 (0)