Skip to content

Commit f9496f5

Browse files
committed
feat: add a rule to validate OAS3.2 tag parents
1 parent 4e51c84 commit f9496f5

File tree

21 files changed

+628
-30
lines changed

21 files changed

+628
-30
lines changed

.changeset/long-moons-sin.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@redocly/openapi-core": minor
3+
"@redocly/cli": minor
4+
---
5+
6+
Added a `tag-parents` rule for validating the OpenAPI 3.2 specification.

__tests__/lint/oas3.2/snapshot.txt

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,49 @@ Property `wrong` is not expected here.
2626
Error was generated by the struct rule.
2727

2828

29-
[3] openapi.yaml:51:7 at #/paths/~1products/query/wrong
29+
[3] openapi.yaml:16:13 at #/tags/0/parent
30+
31+
Tag parent 'products' is not defined in the API description.
32+
33+
14 | summary: Books & Literature
34+
15 | description: Book catalog and recommendations
35+
16 | parent: products
36+
| ^^^^^^^^
37+
17 | kind: nav
38+
18 | wrong: Should catch wrong fields in tags!
39+
40+
Error was generated by the tag-parents rule.
41+
42+
43+
[4] openapi.yaml:23:13 at #/tags/1/parent
44+
45+
Tag parent 'products' is not defined in the API description.
46+
47+
21 | summary: Music CDs
48+
22 | description: Music CD catalog and reviews
49+
23 | parent: products
50+
| ^^^^^^^^
51+
24 | kind: nav
52+
25 |
53+
54+
Error was generated by the tag-parents rule.
55+
56+
57+
[5] openapi.yaml:29:13 at #/tags/2/parent
58+
59+
Tag parent 'products' is not defined in the API description.
60+
61+
27 | summary: Gift Cards
62+
28 | description: Digital and physical gift cards
63+
29 | parent: products
64+
| ^^^^^^^^
65+
30 | kind: nav
66+
31 |
67+
68+
Error was generated by the tag-parents rule.
69+
70+
71+
[6] openapi.yaml:51:7 at #/paths/~1products/query/wrong
3072

3173
Property `wrong` is not expected here.
3274

@@ -40,7 +82,7 @@ Property `wrong` is not expected here.
4082
Error was generated by the struct rule.
4183

4284

43-
[4] openapi.yaml:48:9 at #/paths/~1products/additionalOperations/test/wrong
85+
[7] openapi.yaml:48:9 at #/paths/~1products/additionalOperations/test/wrong
4486

4587
Property `wrong` is not expected here.
4688

@@ -54,7 +96,7 @@ Property `wrong` is not expected here.
5496
Error was generated by the struct rule.
5597

5698

57-
[5] openapi.yaml:156:9 at #/components/schemas/MyResponseType/discriminator/wrong
99+
[8] openapi.yaml:156:9 at #/components/schemas/MyResponseType/discriminator/wrong
58100

59101
Property `wrong` is not expected here.
60102

@@ -68,7 +110,7 @@ Property `wrong` is not expected here.
68110
Error was generated by the struct rule.
69111

70112

71-
[6] openapi.yaml:132:11 at #/components/securitySchemes/petstore_auth/flows/implicit/wrong
113+
[9] openapi.yaml:132:11 at #/components/securitySchemes/petstore_auth/flows/implicit/wrong
72114

73115
Property `wrong` is not expected here.
74116

@@ -82,7 +124,7 @@ Property `wrong` is not expected here.
82124
Error was generated by the struct rule.
83125

84126

85-
[7] openapi.yaml:144:9 at #/components/securitySchemes/device_auth/flows/deviceAuthorization
127+
[10] openapi.yaml:144:9 at #/components/securitySchemes/device_auth/flows/deviceAuthorization
86128

87129
The field `scopes` must be present on this level.
88130

@@ -96,7 +138,7 @@ The field `scopes` must be present on this level.
96138
Error was generated by the struct rule.
97139

98140

99-
[8] openapi.yaml:2:1 at #/info
141+
[11] openapi.yaml:2:1 at #/info
100142

101143
Info object should contain `license` field.
102144

@@ -109,7 +151,7 @@ Info object should contain `license` field.
109151
Warning was generated by the info-license rule.
110152

111153

112-
[9] openapi.yaml:9:10 at #/servers/0/url
154+
[12] openapi.yaml:9:10 at #/servers/0/url
113155

114156
Server `url` should not point to example.com or localhost.
115157

@@ -123,7 +165,7 @@ Server `url` should not point to example.com or localhost.
123165
Warning was generated by the no-server-example.com rule.
124166

125167

126-
[10] openapi.yaml:39:5 at #/paths/~1giftcards/get/operationId
168+
[13] openapi.yaml:39:5 at #/paths/~1giftcards/get/operationId
127169

128170
Operation object should contain `operationId` field.
129171

@@ -137,7 +179,7 @@ Operation object should contain `operationId` field.
137179
Warning was generated by the operation-operationId rule.
138180

139181

140-
[11] openapi.yaml:49:5 at #/paths/~1products/query/operationId
182+
[14] openapi.yaml:49:5 at #/paths/~1products/query/operationId
141183

142184
Operation object should contain `operationId` field.
143185

@@ -151,7 +193,7 @@ Operation object should contain `operationId` field.
151193
Warning was generated by the operation-operationId rule.
152194

153195

154-
[12] openapi.yaml:65:7 at #/paths/~1products/query/responses
196+
[15] openapi.yaml:65:7 at #/paths/~1products/query/responses
155197

156198
Operation must have at least one `4XX` response.
157199

@@ -165,7 +207,7 @@ Operation must have at least one `4XX` response.
165207
Warning was generated by the operation-4xx-response rule.
166208

167209

168-
[13] openapi.yaml:46:7 at #/paths/~1products/additionalOperations/test/operationId
210+
[16] openapi.yaml:46:7 at #/paths/~1products/additionalOperations/test/operationId
169211

170212
Operation object should contain `operationId` field.
171213

@@ -179,7 +221,7 @@ Operation object should contain `operationId` field.
179221
Warning was generated by the operation-operationId rule.
180222

181223

182-
[14] openapi.yaml:70:5 at #/paths/~1stream/get/operationId
224+
[17] openapi.yaml:70:5 at #/paths/~1stream/get/operationId
183225

184226
Operation object should contain `operationId` field.
185227

@@ -193,7 +235,7 @@ Operation object should contain `operationId` field.
193235
Warning was generated by the operation-operationId rule.
194236

195237

196-
[15] openapi.yaml:72:7 at #/paths/~1stream/get/responses
238+
[18] openapi.yaml:72:7 at #/paths/~1stream/get/responses
197239

198240
Operation must have at least one `4XX` response.
199241

@@ -207,7 +249,7 @@ Operation must have at least one `4XX` response.
207249
Warning was generated by the operation-4xx-response rule.
208250

209251

210-
[16] openapi.yaml:83:5 at #/paths/~1thing/get/operationId
252+
[19] openapi.yaml:83:5 at #/paths/~1thing/get/operationId
211253

212254
Operation object should contain `operationId` field.
213255

@@ -221,7 +263,7 @@ Operation object should contain `operationId` field.
221263
Warning was generated by the operation-operationId rule.
222264

223265

224-
[17] openapi.yaml:85:7 at #/paths/~1thing/get/responses
266+
[20] openapi.yaml:85:7 at #/paths/~1thing/get/responses
225267

226268
Operation must have at least one `4XX` response.
227269

@@ -235,7 +277,7 @@ Operation must have at least one `4XX` response.
235277
Warning was generated by the operation-4xx-response rule.
236278

237279

238-
[18] openapi.yaml:149:5 at #/components/schemas/MyResponseType
280+
[21] openapi.yaml:149:5 at #/components/schemas/MyResponseType
239281

240282
Component: "MyResponseType" is never used.
241283

@@ -253,6 +295,6 @@ Warning was generated by the no-unused-components rule.
253295
validating openapi.yaml using lint rules for api 'main'...
254296
openapi.yaml: validated in <test>ms
255297

256-
❌ Validation failed with 7 errors and 11 warnings.
298+
❌ Validation failed with 10 errors and 11 warnings.
257299
run `redocly lint --generate-ignore-file` to add all problems to the ignore file.
258300

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
openapi: 3.2.0
2+
info:
3+
title: Test API
4+
version: 1.0.0
5+
paths: {}
6+
tags:
7+
- name: tag
8+
parent: none
9+
description: A tag with an undefined parent
10+
11+
- name: foo
12+
parent: bar
13+
description: Circular references
14+
- name: bar
15+
parent: foo
16+
description: Circular references
17+
- name: baz
18+
parent: foo
19+
description: Circular references
20+
21+
- name: self
22+
parent: self
23+
description: Self-referencing tag
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apis:
2+
main:
3+
root: openapi.yaml
4+
rules:
5+
tag-parents: error
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
[1] openapi.yaml:8:13 at #/tags/0/parent
2+
3+
Tag parent 'none' is not defined in the API description.
4+
5+
6 | tags:
6+
7 | - name: tag
7+
8 | parent: none
8+
| ^^^^
9+
9 | description: A tag with an undefined parent
10+
10 |
11+
12+
Error was generated by the tag-parents rule.
13+
14+
15+
[2] openapi.yaml:12:13 at #/tags/1/parent
16+
17+
Circular reference detected in tag parent hierarchy for tag 'foo'.
18+
19+
10 |
20+
11 | - name: foo
21+
12 | parent: bar
22+
| ^^^
23+
13 | description: Circular references
24+
14 | - name: bar
25+
26+
Error was generated by the tag-parents rule.
27+
28+
29+
[3] openapi.yaml:15:13 at #/tags/2/parent
30+
31+
Circular reference detected in tag parent hierarchy for tag 'bar'.
32+
33+
13 | description: Circular references
34+
14 | - name: bar
35+
15 | parent: foo
36+
| ^^^
37+
16 | description: Circular references
38+
17 | - name: baz
39+
40+
Error was generated by the tag-parents rule.
41+
42+
43+
[4] openapi.yaml:18:13 at #/tags/3/parent
44+
45+
Circular reference detected in tag parent hierarchy for tag 'baz'.
46+
47+
16 | description: Circular references
48+
17 | - name: baz
49+
18 | parent: foo
50+
| ^^^
51+
19 | description: Circular references
52+
20 |
53+
54+
Error was generated by the tag-parents rule.
55+
56+
57+
[5] openapi.yaml:22:13 at #/tags/4/parent
58+
59+
Circular reference detected in tag parent hierarchy for tag 'self'.
60+
61+
20 |
62+
21 | - name: self
63+
22 | parent: self
64+
| ^^^^
65+
23 | description: Self-referencing tag
66+
24 |
67+
68+
Error was generated by the tag-parents rule.
69+
70+
71+
72+
validating openapi.yaml using lint rules for api 'main'...
73+
openapi.yaml: validated in <test>ms
74+
75+
❌ Validation failed with 5 errors.
76+
run `redocly lint --generate-ignore-file` to add all problems to the ignore file.
77+

docs/@v2/rules/built-in-rules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ The rules list is split into sections.
105105
- [operation-singular-tag](./oas/operation-singular-tag.md): Each operation may only have one tag
106106
- [operation-tag-defined](./oas/operation-tag-defined.md): Tags can only be used if they are defined at the top level
107107
- [tag-description](./oas/tag-description.md): Tags must have descriptions
108+
- [tag-parents](./oas/tag-parents.md): Tag parent references must be properly defined and free of circular dependencies
108109
- [tags-alphabetical](./oas/tags-alphabetical.md): Tags in the top-level `tags` section must appear alphabetically
109110

110111
## AsyncAPI rules

0 commit comments

Comments
 (0)