Skip to content

Commit 5c1b255

Browse files
committed
Update
1 parent 04c2eb8 commit 5c1b255

File tree

2 files changed

+119
-73
lines changed

2 files changed

+119
-73
lines changed

tools/cli/internal/openapi/oasdiff.go

Lines changed: 27 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package openapi
1616

1717
import (
18+
"encoding/json"
1819
"log"
1920
"slices"
2021
"strings"
@@ -41,10 +42,6 @@ type OasDiffResult struct {
4142
SpecInfoPair *load.SpecInfoPair
4243
}
4344

44-
const (
45-
xgenSoaMigration = "x-xgen-soa-migration"
46-
)
47-
4845
func (o OasDiff) NewDiffResult() (*OasDiffResult, error) {
4946
flattenBaseSpec, err := allof.MergeSpec(o.base.Spec)
5047
if err != nil {
@@ -122,9 +119,15 @@ func (o OasDiff) mergePaths() error {
122119
basePaths.Set(externalPath, removeExternalRefs(externalPathData))
123120
} else {
124121
if shouldSkipPathConflict(originalPath, externalPathData, externalPath) {
125-
log.Println("Skipping conflict for path: ", externalPath)
126-
continue
122+
log.Printf("Skipping conflict for path: %s", externalPath)
123+
if o.arePathsIdenticalWithExcludeExtensions(externalPath) {
124+
log.Printf("No doc diff detected for path %s, merging the paths", externalPath)
125+
basePaths.Set(externalPath, removeExternalRefs(externalPathData))
126+
} else {
127+
log.Printf("Doc diff detected failing as allowDocsDiff=true is not supported.")
128+
}
127129
}
130+
128131
return errors.PathConflictError{
129132
Entry: externalPath,
130133
}
@@ -134,73 +137,6 @@ func (o OasDiff) mergePaths() error {
134137
return nil
135138
}
136139

137-
// shouldSkipConflict checks if the conflict should be skipped.
138-
// The method goes through each path operation, and validates if it exists for
139-
// both paths, if it does not, the path conflict should not be ignored.
140-
// If it does, then we check if there is an x-xgen-soa-migration annotation
141-
// If it does, then we allow the conflict to be skipped.
142-
func shouldSkipPathConflict(basePath, externalPath *openapi3.PathItem, basePathName string) bool {
143-
if basePath.Get != nil && externalPath.Get == nil {
144-
return false
145-
}
146-
147-
if basePath.Put != nil && externalPath.Put == nil {
148-
return false
149-
}
150-
151-
if basePath.Post != nil && externalPath.Post == nil {
152-
return false
153-
}
154-
155-
if basePath.Patch != nil && externalPath.Patch == nil {
156-
return false
157-
}
158-
159-
if basePath.Delete != nil && externalPath.Delete == nil {
160-
return false
161-
}
162-
163-
// now check if there is an x-xgen-soa-migration annotation in any of the operations, but if any of the operations
164-
// doesn't have, then we should not skip the conflict
165-
return allMethodsHaveExtension(basePath, basePathName)
166-
}
167-
168-
// allMethodsHaveExtension checks if all the methods in a path have the x-xgen-soa-migration extension.
169-
func allMethodsHaveExtension(basePath *openapi3.PathItem, basePathName string) bool {
170-
if basePath.Get != nil {
171-
if basePath.Get.Extensions == nil || basePath.Get.Extensions[xgenSoaMigration] == nil {
172-
return false
173-
}
174-
}
175-
176-
if basePath.Put != nil {
177-
if basePath.Put.Extensions == nil || basePath.Put.Extensions[xgenSoaMigration] == nil {
178-
return false
179-
}
180-
}
181-
182-
if basePath.Post != nil {
183-
if basePath.Post.Extensions == nil || basePath.Post.Extensions[xgenSoaMigration] == nil {
184-
return false
185-
}
186-
}
187-
188-
if basePath.Patch != nil {
189-
if basePath.Patch.Extensions == nil || basePath.Patch.Extensions[xgenSoaMigration] == nil {
190-
return false
191-
}
192-
}
193-
194-
if basePath.Delete != nil {
195-
if basePath.Delete.Extensions == nil || basePath.Delete.Extensions[xgenSoaMigration] == nil {
196-
return false
197-
}
198-
}
199-
200-
log.Println("Detected x-xgen-soa-migration annotation in all operations for path: ", basePathName)
201-
return true
202-
}
203-
204140
// removeExternalRefs updates the external references of OASes to remove the reference to openapi-mms.json.
205141
// Example of an external ref is "$ref": "openapi-mms.json#/components/responses/internalServerError"
206142
// Example of an external ref after removeExternalRefs: "$ref": "#/components/responses/internalServerError"
@@ -493,6 +429,24 @@ func (o OasDiff) areSchemaIdentical(name string) bool {
493429
return !ok
494430
}
495431

432+
// arePathsIdenticalWithExcludeExtensions checks if the paths are identical with the extensions excluded
433+
func (o OasDiff) arePathsIdenticalWithExcludeExtensions(name string) bool {
434+
// If the diff only has extensions diff, then we consider the paths to be identical
435+
exclude := []string{"extensions"}
436+
customConfig := diff.NewConfig().WithExcludeElements(exclude)
437+
d, err := diff.Get(customConfig, o.base.Spec, o.external.Spec)
438+
if err != nil {
439+
log.Fatalf("error in calculating the diff of the specs: %s", err)
440+
}
441+
442+
_, ok := d.PathsDiff.Modified[name]
443+
if ok {
444+
j, _ := json.MarshalIndent(d.PathsDiff.Modified[name], "", " ")
445+
log.Printf("arePathsIdenticalWithExcludeExtensions diff: %s", j)
446+
}
447+
return !ok
448+
}
449+
496450
type ByName []*openapi3.Tag
497451

498452
func (a ByName) Len() int { return len(a) }
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2024 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package openapi
16+
17+
import (
18+
"log"
19+
20+
"github.com/getkin/kin-openapi/openapi3"
21+
)
22+
23+
const (
24+
xgenSoaMigration = "x-xgen-soa-migration"
25+
)
26+
27+
// shouldSkipConflict checks if the conflict should be skipped.
28+
// The method goes through each path operation and performs the following checks:
29+
// 1. Validates if both paths have same operations, if not, then it returns false.
30+
// 2. If both paths have the same operations, then it checks if there is an x-xgen-soa-migration annotation.
31+
// If there is no annotation, then it returns false.
32+
func shouldSkipPathConflict(basePath, externalPath *openapi3.PathItem, basePathName string) bool {
33+
if basePath.Get != nil && externalPath.Get == nil || basePath.Get == nil && externalPath.Get != nil {
34+
return false
35+
}
36+
37+
if basePath.Put != nil && externalPath.Put == nil || basePath.Put == nil && externalPath.Put != nil {
38+
return false
39+
}
40+
41+
if basePath.Post != nil && externalPath.Post == nil || basePath.Post == nil && externalPath.Post != nil {
42+
return false
43+
}
44+
45+
if basePath.Patch != nil && externalPath.Patch == nil || basePath.Patch == nil && externalPath.Patch != nil {
46+
return false
47+
}
48+
49+
if basePath.Delete != nil && externalPath.Delete == nil || basePath.Delete == nil && externalPath.Delete != nil {
50+
return false
51+
}
52+
53+
// now check if there is an x-xgen-soa-migration annotation in any of the operations, but if any of the operations
54+
// doesn't have, then we should not skip the conflict
55+
return allOperationsHaveExtension(basePath, basePathName, xgenSoaMigration)
56+
}
57+
58+
// allMethodsHaveExtension checks if all the operations in the base pat have the given extension name.
59+
func allOperationsHaveExtension(basePath *openapi3.PathItem, basePathName, extensionName string) bool {
60+
if basePath.Get != nil {
61+
if basePath.Get.Extensions == nil || basePath.Get.Extensions[extensionName] == nil {
62+
return false
63+
}
64+
}
65+
66+
if basePath.Put != nil {
67+
if basePath.Put.Extensions == nil || basePath.Put.Extensions[extensionName] == nil {
68+
return false
69+
}
70+
}
71+
72+
if basePath.Post != nil {
73+
if basePath.Post.Extensions == nil || basePath.Post.Extensions[extensionName] == nil {
74+
return false
75+
}
76+
}
77+
78+
if basePath.Patch != nil {
79+
if basePath.Patch.Extensions == nil || basePath.Patch.Extensions[extensionName] == nil {
80+
return false
81+
}
82+
}
83+
84+
if basePath.Delete != nil {
85+
if basePath.Delete.Extensions == nil || basePath.Delete.Extensions[extensionName] == nil {
86+
return false
87+
}
88+
}
89+
90+
log.Println("Detected x-xgen-soa-migration annotation in all operations for path: ", basePathName)
91+
return true
92+
}

0 commit comments

Comments
 (0)