Skip to content

Commit

Permalink
feat: prevent explicit sunset specs being compiled into new versions (#…
Browse files Browse the repository at this point in the history
…300)

Prevents resource API specs, that have been specifically marked as "sunset" at the document & operation level from being compiled into future versions of the collated spec.
  • Loading branch information
mikedevelops authored Jun 19, 2023
1 parent 27a69e1 commit f09cbd1
Show file tree
Hide file tree
Showing 39 changed files with 10,151 additions and 34 deletions.
12 changes: 12 additions & 0 deletions internal/backstage/backstage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ func TestLoadVersionsNoApis(t *testing.T) {
- Registry_2021-06-13_experimental
- Registry_2021-08-20_beta
- Registry_2021-08-20_experimental
- Registry_2023-06-01_beta
- Registry_2023-06-01_experimental
- Registry_2023-06-02_beta
- Registry_2023-06-02_experimental
- Registry_2023-06-03_beta
- Registry_2023-06-03_experimental
---
`[1:]+string(vervetAPIs))
}
Expand Down Expand Up @@ -159,6 +165,12 @@ func TestLoadVersionsSomeApis(t *testing.T) {
- Registry_2021-06-13_experimental
- Registry_2021-08-20_beta
- Registry_2021-08-20_experimental
- Registry_2023-06-01_beta
- Registry_2023-06-01_experimental
- Registry_2023-06-02_beta
- Registry_2023-06-02_experimental
- Registry_2023-06-03_beta
- Registry_2023-06-03_experimental
- someOtherApi
---
`[1:]+string(vervetAPIs))
Expand Down
7 changes: 7 additions & 0 deletions internal/cmd/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ resources/_examples/hello-world/2021-06-07/spec.yaml
resources/_examples/hello-world/2021-06-13/spec.yaml
resources/projects/2021-06-04/spec.yaml
resources/projects/2021-08-20/spec.yaml
resources/projects/2023-06-03/spec.yaml
resources/users/2023-06-01/spec.yaml
resources/users/2023-06-02/spec.yaml
`[1:])
}

Expand Down Expand Up @@ -71,6 +74,9 @@ func TestResourceInfo(t *testing.T) {
| testdata | hello-world | 2021-06-13~beta | /examples/hello-world | POST | helloWorldCreate |
| testdata | hello-world | 2021-06-13~beta | /examples/hello-world/{id} | GET | helloWorldGetOne |
| testdata | projects | 2021-08-20~experimental | /orgs/{org_id}/projects/{project_id} | DELETE | deleteOrgsProject |
| testdata | users | 2023-06-01~experimental | /users | GET | getUsers |
| testdata | users | 2023-06-02~experimental | /users | GET | getUsers |
| testdata | projects | 2023-06-03~experimental | /orgs/{org_id}/projects/{project_id} | DELETE | deleteOrgsProject |
+----------+-------------+-------------------------+--------------------------------------+--------+-------------------+
`[1:])
}
Expand All @@ -96,6 +102,7 @@ func TestResourceInfoResource(t *testing.T) {
+----------+----------+-------------------------+--------------------------------------+--------+-------------------+
| testdata | projects | 2021-06-04~experimental | /orgs/{orgId}/projects | GET | getOrgsProjects |
| testdata | projects | 2021-08-20~experimental | /orgs/{org_id}/projects/{project_id} | DELETE | deleteOrgsProject |
| testdata | projects | 2023-06-03~experimental | /orgs/{org_id}/projects/{project_id} | DELETE | deleteOrgsProject |
+----------+----------+-------------------------+--------------------------------------+--------+-------------------+
`[1:])
}
16 changes: 16 additions & 0 deletions internal/generator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ version-readme:
out + "/testdata/hello-world/2021-06-13/README",
out + "/testdata/projects/2021-06-04/README",
out + "/testdata/projects/2021-08-20/README",
out + "/testdata/projects/2023-06-03/README",
out + "/testdata/users/2023-06-01/README",
out + "/testdata/users/2023-06-02/README",
})

for _, test := range []struct {
Expand Down Expand Up @@ -121,6 +124,7 @@ resource-routes:
c.Assert(files, qt.ContentEquals, []string{
out + "/testdata/hello-world/routes.ts",
out + "/testdata/projects/routes.ts",
out + "/testdata/users/routes.ts",
})

routes, err := os.ReadFile(out + "/testdata/hello-world/routes.ts")
Expand Down Expand Up @@ -162,13 +166,19 @@ export const helloWorldGetOne = versions([
c.Assert(string(routes), qt.Equals, `
import { versions } from '@snyk/rest-node-libs';
import * as v2021_08_20 './2021-08-20';
import * as v2023_06_03 './2023-06-03';
import * as v2021_06_04 './2021-06-04';
export const deleteOrgsProject = versions([
{
handler: v2021_08_20.deleteOrgsProject,
version: '2021-08-20~experimental',
},
{
handler: v2023_06_03.deleteOrgsProject,
version: '2023-06-03~experimental',
},
]);
export const getOrgsProjects = versions([
{
Expand Down Expand Up @@ -316,6 +326,9 @@ version-models:
out + "/testdata/hello-world/2021-06-13/models.ts",
out + "/testdata/projects/2021-06-04/models.ts",
out + "/testdata/projects/2021-08-20/models.ts",
out + "/testdata/projects/2023-06-03/models.ts",
out + "/testdata/users/2023-06-01/models.ts",
out + "/testdata/users/2023-06-02/models.ts",
})

jsFile, err := os.ReadFile(out + "/testdata/projects/2021-06-04/models.ts")
Expand Down Expand Up @@ -449,6 +462,9 @@ version-readme:
out + "/testdata/hello-world/2021-06-13/README",
out + "/testdata/projects/2021-06-04/README",
out + "/testdata/projects/2021-08-20/README",
out + "/testdata/projects/2023-06-03/README",
out + "/testdata/users/2023-06-01/README",
out + "/testdata/users/2023-06-02/README",
})

actualFiles, err := filepath.Glob(out + "/*/*/*/README")
Expand Down
7 changes: 7 additions & 0 deletions resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ func (rv *ResourceVersions) At(vs string) (*ResourceVersion, error) {
if !ok {
return nil, ErrNoMatchingVersion
}

// skip resolving versions for resources that have been marked as sunset in a previous version
if lifecycle, err := r.Document.Lifecycle(); err == nil && lifecycle == LifecycleSunset &&
resolvedVersion.DeprecatedBy(v) {
return nil, ErrNoMatchingVersion
}

return r, nil
}

Expand Down
34 changes: 33 additions & 1 deletion resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func TestVersionRangesProjects(t *testing.T) {
c := qt.New(t)
eps, err := LoadResourceVersions(testdata.Path("resources/projects"))
c.Assert(err, qt.IsNil)
c.Assert(eps.Versions(), qt.HasLen, 2)
c.Assert(eps.Versions(), qt.HasLen, 3)
tests := []struct {
query, match, err string
}{{
Expand Down Expand Up @@ -110,3 +110,35 @@ func TestLoadResourceVersionsWithDuplicateSpecs(t *testing.T) {
c.Assert(err, qt.IsNotNil)
c.Assert(err, qt.ErrorMatches, "duplicate spec found in "+dirPath+"/2022-08-31")
}

func TestResourceVersionsAtSunset(t *testing.T) {
c := qt.New(t)
eps, err := LoadResourceVersions(testdata.Path("sunset-specs"))
c.Assert(err, qt.IsNil)
c.Assert(eps.Versions(), qt.HasLen, 2)
tests := []struct {
query, match, err string
}{{
query: "2023-01-01~experimental",
match: "2023-01-01~experimental",
}, {
query: "2023-01-10~experimental",
match: "2023-01-01~experimental",
}, {
query: "2023-02-01~experimental",
match: "2023-02-01~experimental",
}, {
query: "2023-03-01~experimental",
err: "no matching version",
}}
for i, t := range tests {
c.Logf("test#%d: %#v", i, t)
e, err := eps.At(t.query)
if t.err != "" {
c.Assert(err, qt.ErrorMatches, t.err)
} else {
c.Assert(err, qt.IsNil)
c.Assert(e.Version.String(), qt.Equals, t.match)
}
}
}
7 changes: 7 additions & 0 deletions spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ func (sv *SpecVersions) resolveOperations() {
// carried forward and remain active.
for opKey, opValue := range currentActiveOps {
currentPathItem := doc.Paths[opKey.path]

// skip promoting sunset operations into current document
lc, ok := opValue.operation.Extensions[ExtSnykApiLifecycle].(string)
if lc, err := ParseLifecycle(lc); ok && err == nil && lc == LifecycleSunset {
continue
}

if currentPathItem == nil {
currentPathItem = &openapi3.PathItem{
Extensions: opValue.pathItem.Extensions,
Expand Down
102 changes: 71 additions & 31 deletions spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ func TestSpecs(t *testing.T) {
MustParseVersion("2021-06-13~beta"),
MustParseVersion("2021-08-20~experimental"),
MustParseVersion("2021-08-20~beta"),
MustParseVersion("2023-06-01~experimental"),
MustParseVersion("2023-06-01~beta"),
MustParseVersion("2023-06-02~experimental"),
MustParseVersion("2023-06-02~beta"),
MustParseVersion("2023-06-03~experimental"),
MustParseVersion("2023-06-03~beta"),
})

type expectResourceVersion struct {
version string
path string
opFunc func(*openapi3.PathItem) *openapi3.Operation
version string
path string
opFunc func(*openapi3.PathItem) *openapi3.Operation
shouldExist bool
}
tests := []struct {
query, match string
Expand All @@ -38,37 +45,44 @@ func TestSpecs(t *testing.T) {
query: "2021-07-01~experimental",
match: "2021-06-13~experimental",
hasVersions: []expectResourceVersion{{
version: "2021-06-13~beta",
path: "/examples/hello-world",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
version: "2021-06-13~beta",
path: "/examples/hello-world",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
shouldExist: true,
}, {
version: "2021-06-13~beta",
path: "/examples/hello-world/{id}",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
version: "2021-06-13~beta",
path: "/examples/hello-world/{id}",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
shouldExist: true,
}, {
version: "2021-06-04~experimental",
path: "/orgs/{orgId}/projects",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
version: "2021-06-04~experimental",
path: "/orgs/{orgId}/projects",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
shouldExist: true,
}},
}, {
query: "2021-09-01~experimental",
match: "2021-08-20~experimental",
hasVersions: []expectResourceVersion{{
version: "2021-06-13~beta",
path: "/examples/hello-world",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
version: "2021-06-13~beta",
path: "/examples/hello-world",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
shouldExist: true,
}, {
version: "2021-06-13~beta",
path: "/examples/hello-world/{id}",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
version: "2021-06-13~beta",
path: "/examples/hello-world/{id}",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
shouldExist: true,
}, {
version: "2021-06-04~experimental",
path: "/orgs/{orgId}/projects",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
version: "2021-06-04~experimental",
path: "/orgs/{orgId}/projects",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
shouldExist: true,
}, {
version: "2021-08-20~experimental",
path: "/orgs/{org_id}/projects/{project_id}",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Delete },
version: "2021-08-20~experimental",
path: "/orgs/{org_id}/projects/{project_id}",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Delete },
shouldExist: true,
}},
}, {
query: "2021-07-01~wip",
Expand All @@ -80,13 +94,34 @@ func TestSpecs(t *testing.T) {
query: "2021-07-01~beta",
match: "2021-06-13~beta",
hasVersions: []expectResourceVersion{{
version: "2021-06-13~beta",
path: "/examples/hello-world",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
version: "2021-06-13~beta",
path: "/examples/hello-world",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
shouldExist: true,
}, {
version: "2021-06-13~beta",
path: "/examples/hello-world/{id}",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
version: "2021-06-13~beta",
path: "/examples/hello-world/{id}",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
shouldExist: true,
}},
}, {
query: "2023-06-02~experimental",
match: "2023-06-02~experimental",
hasVersions: []expectResourceVersion{{
version: "2023-06-02~experimental",
path: "/users",
opFunc: func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
shouldExist: true,
}},
}, {
query: "2023-06-03~experimental",
match: "2023-06-03~experimental",
hasVersions: []expectResourceVersion{{
version: "2023-06-03~experimental",
path: "/users",
// should be omitted from the 2023-06-03 spec because it was marked sunset
// in version 2023-06-02
shouldExist: false,
}},
}}
for i, t := range tests {
Expand All @@ -105,9 +140,14 @@ func TestSpecs(t *testing.T) {
c.Assert(version, qt.Equals, t.match)
for _, expected := range t.hasVersions {
pathItem := spec.Paths[expected.path]

if !expected.shouldExist {
c.Assert(pathItem, qt.IsNil)
continue
}

c.Assert(pathItem, qt.Not(qt.IsNil))
op := expected.opFunc(pathItem)
c.Assert(op, qt.Not(qt.IsNil))
versionStr, err := ExtensionString(op.Extensions, ExtSnykApiVersion)
c.Assert(err, qt.IsNil)
c.Assert(versionStr, qt.Equals, expected.version)
Expand Down
Loading

0 comments on commit f09cbd1

Please sign in to comment.