Skip to content

Commit 2f54230

Browse files
CLOUDP-311381: Add a new filter to foascli to support bump.sh fields (#681)
1 parent 934a8a1 commit 2f54230

File tree

5 files changed

+243
-1
lines changed

5 files changed

+243
-1
lines changed

Diff for: tools/cli/internal/apiversion/version.go

+3
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ func (v *APIVersion) IsPublicPreview() bool {
186186
}
187187

188188
func (v *APIVersion) IsUpcoming() bool { return IsUpcomingStabilityLevel(v.stabilityVersion) }
189+
190+
func (v *APIVersion) IsStable() bool { return IsStableStabilityLevel(v.stabilityVersion) }
191+
189192
func FindMatchesFromContentType(contentType string) []string {
190193
return contentPattern.FindStringSubmatch(contentType)
191194
}

Diff for: tools/cli/internal/openapi/filter/bump.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2025 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 filter
16+
17+
import (
18+
"github.com/getkin/kin-openapi/openapi3"
19+
)
20+
21+
// BumpFilter modifies includes the fields "x-state" and "x-beta" to the "preview" and "upcoming" APIs Operations.
22+
// The "x-state" and "x-beta" fields are bump.sh custom fields to include budges
23+
// Bump.sh feature: https://docs.bump.sh/help/specification-support/doc-badges/
24+
type BumpFilter struct {
25+
oas *openapi3.T
26+
metadata *Metadata
27+
}
28+
29+
const (
30+
stateFieldName = "x-state"
31+
stateFieldValueUpcoming = "Upcoming"
32+
stateFieldValuePreview = "Preview"
33+
betaFieldName = "x-beta"
34+
)
35+
36+
func (f *BumpFilter) ValidateMetadata() error {
37+
return validateMetadataWithVersion(f.metadata)
38+
}
39+
40+
func (f *BumpFilter) Apply() error {
41+
if f.metadata.targetVersion.IsStable() {
42+
return nil
43+
}
44+
45+
if f.metadata.targetVersion.IsUpcoming() {
46+
return f.includeBumpFieldForUpcoming()
47+
}
48+
49+
return f.includeBumpFieldForPreview()
50+
}
51+
52+
func (f *BumpFilter) includeBumpFieldForUpcoming() error {
53+
for _, p := range f.oas.Paths.Map() {
54+
for _, op := range p.Operations() {
55+
if op.Extensions == nil {
56+
op.Extensions = map[string]any{}
57+
}
58+
op.Extensions[stateFieldName] = stateFieldValueUpcoming
59+
}
60+
}
61+
62+
return nil
63+
}
64+
65+
func (f *BumpFilter) includeBumpFieldForPreview() error {
66+
for _, p := range f.oas.Paths.Map() {
67+
for _, op := range p.Operations() {
68+
if op.Extensions == nil {
69+
op.Extensions = map[string]any{}
70+
}
71+
op.Extensions[stateFieldName] = stateFieldValuePreview
72+
op.Extensions[betaFieldName] = true
73+
}
74+
}
75+
return nil
76+
}

Diff for: tools/cli/internal/openapi/filter/bump_test.go

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Copyright 2025 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 filter
16+
17+
import (
18+
"testing"
19+
20+
"github.com/getkin/kin-openapi/openapi3"
21+
"github.com/mongodb/openapi/tools/cli/internal/apiversion"
22+
"github.com/stretchr/testify/assert"
23+
"github.com/stretchr/testify/require"
24+
)
25+
26+
func TestBumpFilter_Apply_Preview(t *testing.T) {
27+
targetVersion, err := apiversion.New(apiversion.WithVersion("preview"))
28+
require.NoError(t, err)
29+
30+
oas := &openapi3.T{
31+
OpenAPI: "3.0.0",
32+
Info: &openapi3.Info{
33+
Version: "1.0",
34+
},
35+
Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{
36+
Get: &openapi3.Operation{
37+
OperationID: "testOperationID",
38+
Summary: "testSummary",
39+
Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{
40+
Content: openapi3.Content{
41+
"application/vnd.atlas.preview+json": {
42+
Schema: &openapi3.SchemaRef{
43+
Ref: "#/components/schemas/PaginatedAppUserView",
44+
},
45+
Extensions: map[string]any{
46+
"x-gen-version": "preview",
47+
},
48+
},
49+
},
50+
})),
51+
},
52+
Extensions: map[string]any{},
53+
})),
54+
}
55+
56+
filter := &BumpFilter{
57+
metadata: NewMetadata(targetVersion, "test"),
58+
oas: oas,
59+
}
60+
61+
require.NoError(t, filter.Apply())
62+
assert.Len(t, oas.Paths.Map(), 1)
63+
assert.Contains(t, oas.Paths.Map(), "test")
64+
65+
testPath := oas.Paths.Map()["test"]
66+
assert.NotNil(t, testPath.Get)
67+
68+
op := testPath.Get
69+
assert.Contains(t, op.Extensions, "x-state")
70+
assert.Equal(t, "Preview", op.Extensions["x-state"])
71+
assert.Contains(t, op.Extensions, "x-beta")
72+
assert.Equal(t, true, op.Extensions["x-beta"])
73+
}
74+
75+
func TestBumpFilter_Apply_Upcoming(t *testing.T) {
76+
targetVersion, err := apiversion.New(apiversion.WithVersion("2024-09-22.upcoming"))
77+
require.NoError(t, err)
78+
79+
oas := &openapi3.T{
80+
OpenAPI: "3.0.0",
81+
Info: &openapi3.Info{
82+
Version: "1.0",
83+
},
84+
Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{
85+
Get: &openapi3.Operation{
86+
OperationID: "testOperationID",
87+
Summary: "testSummary",
88+
Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{
89+
Content: openapi3.Content{
90+
"application/vnd.atlas.2024-09-22.upcoming+json": {
91+
Schema: &openapi3.SchemaRef{
92+
Ref: "#/components/schemas/PaginatedAppUserView",
93+
},
94+
},
95+
},
96+
})),
97+
},
98+
Extensions: map[string]any{},
99+
})),
100+
}
101+
102+
filter := &BumpFilter{
103+
metadata: NewMetadata(targetVersion, "test"),
104+
oas: oas,
105+
}
106+
107+
require.NoError(t, filter.Apply())
108+
assert.Len(t, oas.Paths.Map(), 1)
109+
assert.Contains(t, oas.Paths.Map(), "test")
110+
111+
testPath := oas.Paths.Map()["test"]
112+
assert.NotNil(t, testPath.Get)
113+
op := testPath.Get
114+
115+
assert.Contains(t, op.Extensions, "x-state")
116+
assert.Equal(t, "Upcoming", op.Extensions["x-state"])
117+
assert.NotContains(t, op.Extensions, "x-beta")
118+
}
119+
120+
func TestBumpFilter_Apply_Stable(t *testing.T) {
121+
targetVersion, err := apiversion.New(apiversion.WithVersion("2024-09-22"))
122+
require.NoError(t, err)
123+
124+
oas := &openapi3.T{
125+
OpenAPI: "3.0.0",
126+
Info: &openapi3.Info{
127+
Version: "1.0",
128+
},
129+
Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{
130+
Get: &openapi3.Operation{
131+
OperationID: "testOperationID",
132+
Summary: "testSummary",
133+
Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{
134+
Content: openapi3.Content{
135+
"application/vnd.atlas.2024-09-22+json": {
136+
Schema: &openapi3.SchemaRef{
137+
Ref: "#/components/schemas/PaginatedAppUserView",
138+
},
139+
},
140+
},
141+
})),
142+
},
143+
Extensions: map[string]any{},
144+
})),
145+
}
146+
147+
filter := &BumpFilter{
148+
metadata: NewMetadata(targetVersion, "test"),
149+
oas: oas,
150+
}
151+
152+
require.NoError(t, filter.Apply())
153+
assert.Len(t, oas.Paths.Map(), 1)
154+
assert.Contains(t, oas.Paths.Map(), "test")
155+
156+
testPath := oas.Paths.Map()["test"]
157+
assert.NotNil(t, testPath.Get)
158+
op := testPath.Get
159+
160+
assert.NotContains(t, op.Extensions, "x-state")
161+
assert.NotContains(t, op.Extensions, "x-beta")
162+
}

Diff for: tools/cli/internal/openapi/filter/filter.go

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func DefaultFilters(oas *openapi3.T, metadata *Metadata) []Filter {
8080
&OperationsFilter{oas: oas},
8181
&SunsetFilter{oas: oas},
8282
&SchemasFilter{oas: oas},
83+
&BumpFilter{oas: oas, metadata: metadata},
8384
}
8485
}
8586

Diff for: tools/cli/internal/openapi/filter/filter_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func TestDefaultFilters(t *testing.T) {
112112
metadata := &Metadata{}
113113
filters := DefaultFilters(doc, metadata)
114114

115-
assert.Len(t, filters, 9)
115+
assert.Len(t, filters, 10)
116116
}
117117

118118
func TestFiltersWithoutVersioning(t *testing.T) {

0 commit comments

Comments
 (0)