Clearing up some dead code and adding docs to what-changed

Signed-off-by: Dave Shanley <dave@quobix.com>
This commit is contained in:
Dave Shanley
2022-11-21 09:57:21 -05:00
parent c4b6e68197
commit 3ad8ec3d43
14 changed files with 120 additions and 85 deletions

View File

@@ -8,12 +8,14 @@ import (
"github.com/pb33f/libopenapi/datamodel/low/v3" "github.com/pb33f/libopenapi/datamodel/low/v3"
) )
// CallbackChanges represents all changes made between two Callback OpenAPI objects.
type CallbackChanges struct { type CallbackChanges struct {
PropertyChanges PropertyChanges
ExpressionChanges map[string]*PathItemChanges `json:"expressions,omitempty" yaml:"expressions,omitempty"` ExpressionChanges map[string]*PathItemChanges `json:"expressions,omitempty" yaml:"expressions,omitempty"`
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"` ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
} }
// TotalChanges returns a total count of all changes made between Callback objects
func (c *CallbackChanges) TotalChanges() int { func (c *CallbackChanges) TotalChanges() int {
d := c.PropertyChanges.TotalChanges() d := c.PropertyChanges.TotalChanges()
for k := range c.ExpressionChanges { for k := range c.ExpressionChanges {
@@ -25,6 +27,7 @@ func (c *CallbackChanges) TotalChanges() int {
return d return d
} }
// TotalBreakingChanges returns a total count of all changes made between Callback objects
func (c *CallbackChanges) TotalBreakingChanges() int { func (c *CallbackChanges) TotalBreakingChanges() int {
d := c.PropertyChanges.TotalBreakingChanges() d := c.PropertyChanges.TotalBreakingChanges()
for k := range c.ExpressionChanges { for k := range c.ExpressionChanges {
@@ -36,6 +39,8 @@ func (c *CallbackChanges) TotalBreakingChanges() int {
return d return d
} }
// CompareCallback will compare two Callback objects and return a pointer to CallbackChanges with all the things
// that have changed between them.
func CompareCallback(l, r *v3.Callback) *CallbackChanges { func CompareCallback(l, r *v3.Callback) *CallbackChanges {
cc := new(CallbackChanges) cc := new(CallbackChanges)

View File

@@ -16,10 +16,10 @@ const (
// PropertyAdded means that a new property to an object was added // PropertyAdded means that a new property to an object was added
PropertyAdded PropertyAdded
// ObjectAdded means that a new object was added // ObjectAdded means that a new object was added to a parent object
ObjectAdded ObjectAdded
// ObjectRemoved means that an object was removed // ObjectRemoved means that an object was removed from a parent object
ObjectRemoved ObjectRemoved
// PropertyRemoved means that a property of an object was removed // PropertyRemoved means that a property of an object was removed

View File

@@ -11,18 +11,38 @@ import (
"reflect" "reflect"
) )
// ComponentsChanges represents changes made to both OpenAPI and Swagger documents. This model is based on OpenAPI 3
// components, however it's also used to contain Swagger definitions changes. Swagger for some reason decided to not
// contain definitions inside a single parent like Components, and instead scattered them across the root of the
// Swagger document, giving everything a `Definitions` postfix. This design attempts to unify those models into
// a single entity that contains all changes.
//
// Schemas are treated differently from every other component / definition in this library. Schemas can be highly
// recursive, and are not resolved by the model, every ref is recorded, but it's not looked at essentially. This means
// that when what-changed performs a check, everything that is *not* a schema is checked *inline*, Those references are
// resolved in place and a change is recorded in place. Schemas however are *not* resolved. which means no change
// will be recorded in place for any object referencing it.
//
// That is why there is a separate SchemaChanges object in ComponentsChanges. Schemas are checked at the source, and
// not inline when referenced. A schema change will only be found once, however a change to ANY other definition or
// component, will be found inline (and will duplicate for every use).
//
// The other oddity here is SecuritySchemes. For some reason OpenAPI does not use a $ref for these entities, it
// uses a name lookup, which means there are no direct links between any model and a security scheme reference.
// So like Schemas, SecuritySchemes are treated differently and handled individually.
//
// An important note: Everything EXCEPT Schemas and SecuritySchemes is ONLY checked for additions or removals.
// modifications are not checked, these checks occur in-place by implementing objects as they are autp-resolved
// when the model is built.
type ComponentsChanges struct { type ComponentsChanges struct {
PropertyChanges PropertyChanges
SchemaChanges map[string]*SchemaChanges `json:"schemas,omitempty" yaml:"schemas,omitempty"` SchemaChanges map[string]*SchemaChanges `json:"schemas,omitempty" yaml:"schemas,omitempty"`
SecuritySchemeChanges map[string]*SecuritySchemeChanges `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"` SecuritySchemeChanges map[string]*SecuritySchemeChanges `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"` ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
//ExamplesChanges map[string]*ExampleChanges
//RequestBodyChanges map[string]*RequestBodyChanges
//HeaderChanges map[string]*HeaderChanges
//LinkChanges map[string]*LinkChanges
//CallbackChanges map[string]*CallbackChanges
} }
// CompareComponents will compare OpenAPI components for any changes. Accepts Swagger Definition objects
// like ParameterDefinitions or Definitions etc.
func CompareComponents(l, r any) *ComponentsChanges { func CompareComponents(l, r any) *ComponentsChanges {
var changes []*Change var changes []*Change
@@ -170,37 +190,13 @@ func CompareComponents(l, r any) *ComponentsChanges {
completedComponents++ completedComponents++
cc.SchemaChanges = res.result.(map[string]*SchemaChanges) cc.SchemaChanges = res.result.(map[string]*SchemaChanges)
break break
case v3.ResponsesLabel:
completedComponents++
//cc.ResponsesChanges = res.result.(map[string]*ResponseChanges)
break
case v3.ParametersLabel:
completedComponents++
//cc.ParameterChanges = res.result.(map[string]*ParameterChanges)
break
case v3.ExamplesLabel:
completedComponents++
//cc.ExamplesChanges = res.result.(map[string]*ExampleChanges)
break
case v3.RequestBodiesLabel:
completedComponents++
//cc.RequestBodyChanges = res.result.(map[string]*RequestBodyChanges)
break
case v3.HeadersLabel:
completedComponents++
//cc.HeaderChanges = res.result.(map[string]*HeaderChanges)
break
case v3.SecuritySchemesLabel: case v3.SecuritySchemesLabel:
completedComponents++ completedComponents++
cc.SecuritySchemeChanges = res.result.(map[string]*SecuritySchemeChanges) cc.SecuritySchemeChanges = res.result.(map[string]*SecuritySchemeChanges)
break break
case v3.LinksLabel: case v3.ResponsesLabel, v3.ParametersLabel, v3.ExamplesLabel, v3.RequestBodiesLabel, v3.HeadersLabel,
v3.LinksLabel, v3.CallbacksLabel:
completedComponents++ completedComponents++
//cc.LinkChanges = res.result.(map[string]*LinkChanges)
break
case v3.CallbacksLabel:
completedComponents++
//cc.CallbackChanges = res.result.(map[string]*CallbackChanges)
break break
} }
} }
@@ -238,66 +234,29 @@ func runComparison[T any, R any](l, r map[low.KeyReference[string]]low.ValueRefe
} }
} }
// TotalChanges returns total changes for all Components and Definitions
func (c *ComponentsChanges) TotalChanges() int { func (c *ComponentsChanges) TotalChanges() int {
v := c.PropertyChanges.TotalChanges() v := c.PropertyChanges.TotalChanges()
for k := range c.SchemaChanges { for k := range c.SchemaChanges {
v += c.SchemaChanges[k].TotalChanges() v += c.SchemaChanges[k].TotalChanges()
} }
//for k := range c.ResponsesChanges {
// v += c.ResponsesChanges[k].TotalChanges()
//}
//for k := range c.ParameterChanges {
// v += c.ParameterChanges[k].TotalChanges()
//}
//for k := range c.ExamplesChanges {
// v += c.ExamplesChanges[k].TotalChanges()
//}
//for k := range c.RequestBodyChanges {
// v += c.RequestBodyChanges[k].TotalChanges()
//}
//for k := range c.HeaderChanges {
// v += c.HeaderChanges[k].TotalChanges()
//}
for k := range c.SecuritySchemeChanges { for k := range c.SecuritySchemeChanges {
v += c.SecuritySchemeChanges[k].TotalChanges() v += c.SecuritySchemeChanges[k].TotalChanges()
} }
//for k := range c.LinkChanges {
// v += c.LinkChanges[k].TotalChanges()
//}
//for k := range c.CallbackChanges {
// v += c.CallbackChanges[k].TotalChanges()
//}
if c.ExtensionChanges != nil { if c.ExtensionChanges != nil {
v += c.ExtensionChanges.TotalChanges() v += c.ExtensionChanges.TotalChanges()
} }
return v return v
} }
// TotalBreakingChanges returns all breaking changes found for all Components and Definitions
func (c *ComponentsChanges) TotalBreakingChanges() int { func (c *ComponentsChanges) TotalBreakingChanges() int {
v := c.PropertyChanges.TotalBreakingChanges() v := c.PropertyChanges.TotalBreakingChanges()
for k := range c.SchemaChanges { for k := range c.SchemaChanges {
v += c.SchemaChanges[k].TotalBreakingChanges() v += c.SchemaChanges[k].TotalBreakingChanges()
} }
//for k := range c.ResponsesChanges {
// v += c.ResponsesChanges[k].TotalBreakingChanges()
//}
//for k := range c.ParameterChanges {
// v += c.ParameterChanges[k].TotalBreakingChanges()
//}
//for k := range c.RequestBodyChanges {
// v += c.RequestBodyChanges[k].TotalBreakingChanges()
//}
//for k := range c.HeaderChanges {
// v += c.HeaderChanges[k].TotalBreakingChanges()
//}
for k := range c.SecuritySchemeChanges { for k := range c.SecuritySchemeChanges {
v += c.SecuritySchemeChanges[k].TotalBreakingChanges() v += c.SecuritySchemeChanges[k].TotalBreakingChanges()
} }
//for k := range c.LinkChanges {
// v += c.LinkChanges[k].TotalBreakingChanges()
//}
//for k := range c.CallbackChanges {
// v += c.CallbackChanges[k].TotalBreakingChanges()
//}
return v return v
} }

View File

@@ -1,6 +1,13 @@
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley // Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Package model
//
// What-changed models are unified across OpenAPI and Swagger. Everything is kept flat for simplicity, so please
// excuse the size of the package. There is a lot of data to crunch!
//
// Every model in here is either universal (works across both versions of OpenAPI) or is bound to a specific version
// of OpenAPI. There is only a single model however - so version specific objects are marked accordingly.
package model package model
import ( import (
@@ -11,6 +18,7 @@ import (
"reflect" "reflect"
) )
// DocumentChanges represents all the changes made to an OpenAPI document.
type DocumentChanges struct { type DocumentChanges struct {
PropertyChanges PropertyChanges
InfoChanges *InfoChanges `json:"info,omitempty" yaml:"info,omitempty"` InfoChanges *InfoChanges `json:"info,omitempty" yaml:"info,omitempty"`
@@ -24,6 +32,7 @@ type DocumentChanges struct {
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"` ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
} }
// TotalChanges returns a total count of all changes made in the Document
func (d *DocumentChanges) TotalChanges() int { func (d *DocumentChanges) TotalChanges() int {
c := d.PropertyChanges.TotalChanges() c := d.PropertyChanges.TotalChanges()
if d.InfoChanges != nil { if d.InfoChanges != nil {
@@ -56,6 +65,7 @@ func (d *DocumentChanges) TotalChanges() int {
return c return c
} }
// TotalBreakingChanges returns a total count of all breaking changes made in the Document
func (d *DocumentChanges) TotalBreakingChanges() int { func (d *DocumentChanges) TotalBreakingChanges() int {
c := d.PropertyChanges.TotalBreakingChanges() c := d.PropertyChanges.TotalBreakingChanges()
if d.InfoChanges != nil { if d.InfoChanges != nil {
@@ -85,6 +95,8 @@ func (d *DocumentChanges) TotalBreakingChanges() int {
return c return c
} }
// CompareDocuments will compare any two OpenAPI documents (either Swagger or OpenAPI) and return a pointer to
// DocumentChanges that outlines everything that was found to have changed.
func CompareDocuments(l, r any) *DocumentChanges { func CompareDocuments(l, r any) *DocumentChanges {
var changes []*Change var changes []*Change

View File

@@ -7,11 +7,13 @@ import (
v3 "github.com/pb33f/libopenapi/datamodel/low/v3" v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
) )
// EncodingChanges represent all the changes made to an Encoding object
type EncodingChanges struct { type EncodingChanges struct {
PropertyChanges PropertyChanges
HeaderChanges map[string]*HeaderChanges `json:"headers,omitempty" yaml:"headers,omitempty"` HeaderChanges map[string]*HeaderChanges `json:"headers,omitempty" yaml:"headers,omitempty"`
} }
// TotalChanges returns the total number of changes made between two Encoding objects
func (e *EncodingChanges) TotalChanges() int { func (e *EncodingChanges) TotalChanges() int {
c := e.PropertyChanges.TotalChanges() c := e.PropertyChanges.TotalChanges()
if e.HeaderChanges != nil { if e.HeaderChanges != nil {
@@ -22,6 +24,7 @@ func (e *EncodingChanges) TotalChanges() int {
return c return c
} }
// TotalBreakingChanges returns the number of changes made between two Encoding objects that were breaking.
func (e *EncodingChanges) TotalBreakingChanges() int { func (e *EncodingChanges) TotalBreakingChanges() int {
c := e.PropertyChanges.TotalBreakingChanges() c := e.PropertyChanges.TotalBreakingChanges()
if e.HeaderChanges != nil { if e.HeaderChanges != nil {
@@ -32,6 +35,8 @@ func (e *EncodingChanges) TotalBreakingChanges() int {
return c return c
} }
// CompareEncoding returns a pointer to *EncodingChanges that contain all changes made between a left and right
// set of Encoding objects.
func CompareEncoding(l, r *v3.Encoding) *EncodingChanges { func CompareEncoding(l, r *v3.Encoding) *EncodingChanges {
var changes []*Change var changes []*Change

View File

@@ -32,8 +32,8 @@ func (e *ExampleChanges) TotalBreakingChanges() int {
return l return l
} }
// TotalChanges // CompareExamples returns a pointer to ExampleChanges that contains all changes made between
// left and right Example instances.
func CompareExamples(l, r *base.Example) *ExampleChanges { func CompareExamples(l, r *base.Example) *ExampleChanges {
ec := new(ExampleChanges) ec := new(ExampleChanges)

View File

@@ -8,19 +8,23 @@ import (
v2 "github.com/pb33f/libopenapi/datamodel/low/v2" v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
) )
// v2 Examples object. // ExamplesChanges represents changes made between Swagger Examples objects (Not OpenAPI 3).
type ExamplesChanges struct { type ExamplesChanges struct {
PropertyChanges PropertyChanges
} }
// TotalChanges represents the total number of changes made between Example instances.
func (a *ExamplesChanges) TotalChanges() int { func (a *ExamplesChanges) TotalChanges() int {
return a.PropertyChanges.TotalChanges() return a.PropertyChanges.TotalChanges()
} }
// TotalBreakingChanges will always return 0. Examples cannot break a contract.
func (a *ExamplesChanges) TotalBreakingChanges() int { func (a *ExamplesChanges) TotalBreakingChanges() int {
return 0 // not supported. return 0 // not supported.
} }
// CompareExamplesV2 compares two Swagger Examples objects, returning a pointer to
//ExamplesChanges if anything was found.
func CompareExamplesV2(l, r *v2.Examples) *ExamplesChanges { func CompareExamplesV2(l, r *v2.Examples) *ExamplesChanges {
lHashes := make(map[string]string) lHashes := make(map[string]string)

View File

@@ -13,6 +13,7 @@ type ExtensionChanges struct {
PropertyChanges PropertyChanges
} }
// TotalChanges returns the total number of object extensions that were made.
func (e *ExtensionChanges) TotalChanges() int { func (e *ExtensionChanges) TotalChanges() int {
return e.PropertyChanges.TotalChanges() return e.PropertyChanges.TotalChanges()
} }

View File

@@ -10,6 +10,8 @@ import (
"reflect" "reflect"
) )
// HeaderChanges represents changes made between two Header objects. Supports both Swagger and OpenAPI header
// objects, V2 only property Items is broken out into its own.
type HeaderChanges struct { type HeaderChanges struct {
PropertyChanges PropertyChanges
SchemaChanges *SchemaChanges `json:"schemas,omitempty" yaml:"schemas,omitempty"` SchemaChanges *SchemaChanges `json:"schemas,omitempty" yaml:"schemas,omitempty"`
@@ -17,10 +19,11 @@ type HeaderChanges struct {
ContentChanges map[string]*MediaTypeChanges `json:"content,omitempty" yaml:"content,omitempty"` ContentChanges map[string]*MediaTypeChanges `json:"content,omitempty" yaml:"content,omitempty"`
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"` ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
// V2 changes // Items only supported by Swagger (V2)
ItemsChanges *ItemsChanges `json:"items,omitempty" yaml:"items,omitempty"` ItemsChanges *ItemsChanges `json:"items,omitempty" yaml:"items,omitempty"`
} }
// TotalChanges returns the total number of changes made between two Header objects.
func (h *HeaderChanges) TotalChanges() int { func (h *HeaderChanges) TotalChanges() int {
c := h.PropertyChanges.TotalChanges() c := h.PropertyChanges.TotalChanges()
for k := range h.ExamplesChanges { for k := range h.ExamplesChanges {
@@ -41,6 +44,7 @@ func (h *HeaderChanges) TotalChanges() int {
return c return c
} }
// TotalBreakingChanges returns the total number of breaking changes made between two Header instances.
func (h *HeaderChanges) TotalBreakingChanges() int { func (h *HeaderChanges) TotalBreakingChanges() int {
c := h.PropertyChanges.TotalBreakingChanges() c := h.PropertyChanges.TotalBreakingChanges()
for k := range h.ContentChanges { for k := range h.ContentChanges {
@@ -55,6 +59,7 @@ func (h *HeaderChanges) TotalBreakingChanges() int {
return c return c
} }
// shared header properties
func addOpenAPIHeaderProperties(left, right low.OpenAPIHeader, changes *[]*Change) []*PropertyCheck { func addOpenAPIHeaderProperties(left, right low.OpenAPIHeader, changes *[]*Change) []*PropertyCheck {
var props []*PropertyCheck var props []*PropertyCheck
@@ -89,6 +94,7 @@ func addOpenAPIHeaderProperties(left, right low.OpenAPIHeader, changes *[]*Chang
return props return props
} }
// swagger only properties
func addSwaggerHeaderProperties(left, right low.SwaggerHeader, changes *[]*Change) []*PropertyCheck { func addSwaggerHeaderProperties(left, right low.SwaggerHeader, changes *[]*Change) []*PropertyCheck {
var props []*PropertyCheck var props []*PropertyCheck
@@ -151,6 +157,7 @@ func addSwaggerHeaderProperties(left, right low.SwaggerHeader, changes *[]*Chang
return props return props
} }
// common header properties
func addCommonHeaderProperties(left, right low.HasDescription, changes *[]*Change) []*PropertyCheck { func addCommonHeaderProperties(left, right low.HasDescription, changes *[]*Change) []*PropertyCheck {
var props []*PropertyCheck var props []*PropertyCheck
@@ -161,14 +168,20 @@ func addCommonHeaderProperties(left, right low.HasDescription, changes *[]*Chang
return props return props
} }
// CompareHeadersV2 is a Swagger compatible, typed signature used for other generic functions. It simply
// wraps CompareHeaders and provides nothing other that a typed interface.
func CompareHeadersV2(l, r *v2.Header) *HeaderChanges { func CompareHeadersV2(l, r *v2.Header) *HeaderChanges {
return CompareHeaders(l, r) return CompareHeaders(l, r)
} }
// CompareHeadersV3 is an OpenAPI 3+ compatible, typed signature used for other generic functions. It simply
// wraps CompareHeaders and provides nothing other that a typed interface.
func CompareHeadersV3(l, r *v3.Header) *HeaderChanges { func CompareHeadersV3(l, r *v3.Header) *HeaderChanges {
return CompareHeaders(l, r) return CompareHeaders(l, r)
} }
// CompareHeaders will compare left and right Header objects (any version of Swagger or OpenAPI) and return
// a pointer to HeaderChanges with anything that has changed, or nil if nothing changed.
func CompareHeaders(l, r any) *HeaderChanges { func CompareHeaders(l, r any) *HeaderChanges {
var changes []*Change var changes []*Change

View File

@@ -8,11 +8,15 @@ import (
v3 "github.com/pb33f/libopenapi/datamodel/low/v3" v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
) )
// ItemsChanges represent changes found between a left (original) and right (modified) object. Items is only
// used by Swagger documents.
type ItemsChanges struct { type ItemsChanges struct {
PropertyChanges PropertyChanges
ItemsChanges *ItemsChanges `json:"items,omitempty" yaml:"items,omitempty"` ItemsChanges *ItemsChanges `json:"items,omitempty" yaml:"items,omitempty"`
} }
// TotalChanges returns the total number of changes found between two Items objects
// This is a recursive function because Items can contain Items. Be careful!
func (i *ItemsChanges) TotalChanges() int { func (i *ItemsChanges) TotalChanges() int {
c := i.PropertyChanges.TotalChanges() c := i.PropertyChanges.TotalChanges()
if i.ItemsChanges != nil { if i.ItemsChanges != nil {
@@ -21,6 +25,8 @@ func (i *ItemsChanges) TotalChanges() int {
return c return c
} }
// TotalBreakingChanges returns the total number of breaking changes found between two Swagger Items objects
// This is a recursive method, Items are recursive, be careful!
func (i *ItemsChanges) TotalBreakingChanges() int { func (i *ItemsChanges) TotalBreakingChanges() int {
c := i.PropertyChanges.TotalBreakingChanges() c := i.PropertyChanges.TotalBreakingChanges()
if i.ItemsChanges != nil { if i.ItemsChanges != nil {
@@ -29,6 +35,11 @@ func (i *ItemsChanges) TotalBreakingChanges() int {
return c return c
} }
// CompareItems compares two sets of Swagger Item objects. If there are any changes found then a pointer to
// ItemsChanges will be returned, otherwise nil is returned.
//
// It is worth nothing that Items can contain Items. This means recursion is possible and has the potential for
// runaway code if not using the resolver's circular reference checking.
func CompareItems(l, r *v2.Items) *ItemsChanges { func CompareItems(l, r *v2.Items) *ItemsChanges {
var changes []*Change var changes []*Change

View File

@@ -8,12 +8,14 @@ import (
v3 "github.com/pb33f/libopenapi/datamodel/low/v3" v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
) )
// LinkChanges represent changes made between two OpenAPI Link Objects.
type LinkChanges struct { type LinkChanges struct {
PropertyChanges PropertyChanges
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"` ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
ServerChanges *ServerChanges `json:"server,omitempty" yaml:"server,omitempty"` ServerChanges *ServerChanges `json:"server,omitempty" yaml:"server,omitempty"`
} }
// TotalChanges returns the total changes made between OpenAPI Link objects
func (l *LinkChanges) TotalChanges() int { func (l *LinkChanges) TotalChanges() int {
c := l.PropertyChanges.TotalChanges() c := l.PropertyChanges.TotalChanges()
if l.ExtensionChanges != nil { if l.ExtensionChanges != nil {
@@ -25,6 +27,7 @@ func (l *LinkChanges) TotalChanges() int {
return c return c
} }
// TotalBreakingChanges returns the number of breaking changes made between two OpenAPI Link Objects
func (l *LinkChanges) TotalBreakingChanges() int { func (l *LinkChanges) TotalBreakingChanges() int {
c := l.PropertyChanges.TotalBreakingChanges() c := l.PropertyChanges.TotalBreakingChanges()
if l.ServerChanges != nil { if l.ServerChanges != nil {
@@ -33,6 +36,8 @@ func (l *LinkChanges) TotalBreakingChanges() int {
return c return c
} }
// CompareLinks checks a left and right OpenAPI Link for any changes. If they are found, returns a pointer to
// LinkChanges, and returns nil if nothing is found.
func CompareLinks(l, r *v3.Link) *LinkChanges { func CompareLinks(l, r *v3.Link) *LinkChanges {
if low.AreEqual(l, r) { if low.AreEqual(l, r) {
return nil return nil

View File

@@ -7,6 +7,7 @@ import (
"github.com/pb33f/libopenapi/datamodel/low/v3" "github.com/pb33f/libopenapi/datamodel/low/v3"
) )
// MediaTypeChanges represent changes made between two OpenAPI MediaType instances.
type MediaTypeChanges struct { type MediaTypeChanges struct {
PropertyChanges PropertyChanges
SchemaChanges *SchemaChanges `json:"schemas,omitempty" yaml:"schemas,omitempty"` SchemaChanges *SchemaChanges `json:"schemas,omitempty" yaml:"schemas,omitempty"`
@@ -15,6 +16,7 @@ type MediaTypeChanges struct {
EncodingChanges map[string]*EncodingChanges `json:"encoding,omitempty" yaml:"encoding,omitempty"` EncodingChanges map[string]*EncodingChanges `json:"encoding,omitempty" yaml:"encoding,omitempty"`
} }
// TotalChanges returns the total number of changes between two MediaType instances.
func (m *MediaTypeChanges) TotalChanges() int { func (m *MediaTypeChanges) TotalChanges() int {
c := m.PropertyChanges.TotalChanges() c := m.PropertyChanges.TotalChanges()
for k := range m.ExampleChanges { for k := range m.ExampleChanges {
@@ -34,6 +36,7 @@ func (m *MediaTypeChanges) TotalChanges() int {
return c return c
} }
// TotalBreakingChanges returns the total number of breaking changes made between two MediaType instances.
func (m *MediaTypeChanges) TotalBreakingChanges() int { func (m *MediaTypeChanges) TotalBreakingChanges() int {
c := m.PropertyChanges.TotalBreakingChanges() c := m.PropertyChanges.TotalBreakingChanges()
for k := range m.ExampleChanges { for k := range m.ExampleChanges {
@@ -50,6 +53,8 @@ func (m *MediaTypeChanges) TotalBreakingChanges() int {
return c return c
} }
// CompareMediaTypes compares a left and a right MediaType object for any changes. If found, a pointer to a
// MediaTypeChanges instance is returned, otherwise nothing is returned.
func CompareMediaTypes(l, r *v3.MediaType) *MediaTypeChanges { func CompareMediaTypes(l, r *v3.MediaType) *MediaTypeChanges {
var props []*PropertyCheck var props []*PropertyCheck

View File

@@ -8,6 +8,7 @@ import (
"github.com/pb33f/libopenapi/datamodel/low/v3" "github.com/pb33f/libopenapi/datamodel/low/v3"
) )
// OAuthFlowsChanges represents changes found between two OpenAPI OAuthFlows objects.
type OAuthFlowsChanges struct { type OAuthFlowsChanges struct {
PropertyChanges PropertyChanges
ImplicitChanges *OAuthFlowChanges `json:"implicit,omitempty" yaml:"implicit,omitempty"` ImplicitChanges *OAuthFlowChanges `json:"implicit,omitempty" yaml:"implicit,omitempty"`
@@ -17,6 +18,7 @@ type OAuthFlowsChanges struct {
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"` ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
} }
// TotalChanges returns the number of changes made between two OAuthFlows instances.
func (o *OAuthFlowsChanges) TotalChanges() int { func (o *OAuthFlowsChanges) TotalChanges() int {
c := o.PropertyChanges.TotalChanges() c := o.PropertyChanges.TotalChanges()
if o.ImplicitChanges != nil { if o.ImplicitChanges != nil {
@@ -37,6 +39,7 @@ func (o *OAuthFlowsChanges) TotalChanges() int {
return c return c
} }
// TotalBreakingChanges returns the number of breaking changes made between two OAuthFlows objects.
func (o *OAuthFlowsChanges) TotalBreakingChanges() int { func (o *OAuthFlowsChanges) TotalBreakingChanges() int {
c := o.PropertyChanges.TotalBreakingChanges() c := o.PropertyChanges.TotalBreakingChanges()
if o.ImplicitChanges != nil { if o.ImplicitChanges != nil {
@@ -54,6 +57,8 @@ func (o *OAuthFlowsChanges) TotalBreakingChanges() int {
return c return c
} }
// CompareOAuthFlows compares a left and right OAuthFlows object. If changes are found a pointer to *OAuthFlowsChanges
// is returned, otherwise nil is returned.
func CompareOAuthFlows(l, r *v3.OAuthFlows) *OAuthFlowsChanges { func CompareOAuthFlows(l, r *v3.OAuthFlows) *OAuthFlowsChanges {
if low.AreEqual(l, r) { if low.AreEqual(l, r) {
return nil return nil
@@ -126,11 +131,13 @@ func CompareOAuthFlows(l, r *v3.OAuthFlows) *OAuthFlowsChanges {
return oa return oa
} }
// OAuthFlowChanges represents an OpenAPI OAuthFlow object.
type OAuthFlowChanges struct { type OAuthFlowChanges struct {
PropertyChanges PropertyChanges
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"` ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
} }
// TotalChanges returns the total number of changes made between two OAuthFlow objects
func (o *OAuthFlowChanges) TotalChanges() int { func (o *OAuthFlowChanges) TotalChanges() int {
c := o.PropertyChanges.TotalChanges() c := o.PropertyChanges.TotalChanges()
if o.ExtensionChanges != nil { if o.ExtensionChanges != nil {
@@ -139,10 +146,12 @@ func (o *OAuthFlowChanges) TotalChanges() int {
return c return c
} }
// TotalBreakingChanges returns the total number of breaking changes made between two OAuthFlow objects
func (o *OAuthFlowChanges) TotalBreakingChanges() int { func (o *OAuthFlowChanges) TotalBreakingChanges() int {
return o.PropertyChanges.TotalBreakingChanges() return o.PropertyChanges.TotalBreakingChanges()
} }
// CompareOAuthFlow checks a left and a right OAuthFlow object
func CompareOAuthFlow(l, r *v3.OAuthFlow) *OAuthFlowChanges { func CompareOAuthFlow(l, r *v3.OAuthFlow) *OAuthFlowChanges {
if low.AreEqual(l, r) { if low.AreEqual(l, r) {
return nil return nil

View File

@@ -3,28 +3,34 @@
// Package what_changed // Package what_changed
// //
// The low level (or plumbing) models are designed to capture every single detail about specification, including // what changed is a feature that performs an accurate and deep analysis of what has changed between two OpenAPI
// all lines, columns, positions, tags, comments and essentially everything you would ever want to know. // documents. The report generated outlines every single change made between two specifications (left and right)
// Positions of every key, value and meta-data that is lost when blindly un-marshaling JSON/YAML into a struct. // rendered in the document hierarchy, so exploring it is the same as exploring the document model.
// //
// The high model (porcelain) is a much simpler representation of the low model, keys are simple strings and indices // There are two main functions, one of generating a report for Swagger documents (OpenAPI 2)
// are numbers. When developing consumers of the model, the high model is really what you want to use instead of the // And OpenAPI 3+ documents.
// low model, it's much easier to navigate and is designed for easy consumption.
// //
// The high model requires the low model to be built. Every high model has a 'GoLow' method that allows the consumer // This package uses a combined model for OpenAPI and Swagger changes, it does not break them out into separate
// to 'drop down' from the porcelain API to the plumbing API, which gives instant access to everything low. // versions like the datamodel package. The reason for this is to prevent sprawl across versions and to provide
// a single API and model for any application that wants to use this feature.
package what_changed package what_changed
import ( import (
"github.com/pb33f/libopenapi/datamodel/low/v2" "github.com/pb33f/libopenapi/datamodel/low/v2"
"github.com/pb33f/libopenapi/datamodel/low/v3" "github.com/pb33f/libopenapi/datamodel/low/v3"
"github.com/pb33f/libopenapi/what_changed/model" "github.com/pb33f/libopenapi/what-changed/model"
) )
// CompareOpenAPIDocuments will compare left (original) and right (updated) OpenAPI 3+ documents and extract every change
// made across the entire specification. The report outlines every property changed, everything that was added,
// or removed and which of those changes were breaking.
func CompareOpenAPIDocuments(original, updated *v3.Document) *model.DocumentChanges { func CompareOpenAPIDocuments(original, updated *v3.Document) *model.DocumentChanges {
return model.CompareDocuments(original, updated) return model.CompareDocuments(original, updated)
} }
// CompareSwaggerDocuments will compare left (original) and a right (updated) Swagger documents and extract every change
// made across the entire specification. The report outlines every property changes, everything that was added,
// or removed and which of those changes were breaking.
func CompareSwaggerDocuments(original, updated *v2.Swagger) *model.DocumentChanges { func CompareSwaggerDocuments(original, updated *v2.Swagger) *model.DocumentChanges {
return model.CompareDocuments(original, updated) return model.CompareDocuments(original, updated)
} }