Documentation
¶
Overview ¶
Package differ provides OpenAPI specification comparison and breaking change detection.
Overview ¶
The differ package enables comparison of OpenAPI specifications to identify differences, categorize changes, and detect breaking API changes. It supports both OAS 2.0 and OAS 3.x documents.
Usage ¶
The package provides two API styles:
- Package-level convenience functions for simple, one-off operations
- Struct-based API for reusable instances with custom configuration
Diff Modes ¶
The differ supports two operational modes:
- ModeSimple: Reports all semantic differences without categorization
- ModeBreaking: Categorizes changes by severity and identifies breaking changes
Change Categories ¶
Changes are categorized by the part of the specification that changed:
- CategoryEndpoint: Path/endpoint changes
- CategoryOperation: HTTP operation changes
- CategoryParameter: Parameter changes
- CategoryRequestBody: Request body changes
- CategoryResponse: Response changes
- CategorySchema: Schema/definition changes
- CategorySecurity: Security scheme changes
- CategoryServer: Server/host changes
- CategoryInfo: Metadata changes
Severity Levels ¶
In ModeBreaking, changes are assigned severity levels:
- SeverityCritical: Critical breaking changes (removed endpoints, operations)
- SeverityError: Breaking changes (removed required parameters, type changes)
- SeverityWarning: Potentially problematic changes (deprecated operations, new required fields)
- SeverityInfo: Non-breaking changes (additions, relaxed constraints)
Example (Simple Diff) ¶
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
// Simple diff using functional options
result, err := differ.DiffWithOptions(
differ.WithSourceFilePath("api-v1.yaml"),
differ.WithTargetFilePath("api-v2.yaml"),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d changes\n", len(result.Changes))
for _, change := range result.Changes {
fmt.Println(change.String())
}
}
Example (Breaking Change Detection) ¶
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
// Diff with breaking mode using functional options
result, err := differ.DiffWithOptions(
differ.WithSourceFilePath("api-v1.yaml"),
differ.WithTargetFilePath("api-v2.yaml"),
differ.WithMode(differ.ModeBreaking),
differ.WithIncludeInfo(true),
)
if err != nil {
log.Fatal(err)
}
if result.HasBreakingChanges {
fmt.Printf("⚠️ Found %d breaking change(s)!\n", result.BreakingCount)
}
fmt.Printf("Summary: %d breaking, %d warnings, %d info\n",
result.BreakingCount, result.WarningCount, result.InfoCount)
// Print changes grouped by severity
for _, change := range result.Changes {
fmt.Println(change.String())
}
}
Example (Reusable Differ Instance) ¶
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
// Create a reusable differ instance
d := differ.New()
d.Mode = differ.ModeBreaking
d.IncludeInfo = false // Skip informational changes
// Compare multiple spec pairs with same configuration
pairs := []struct{ old, new string }{
{"api-v1.yaml", "api-v2.yaml"},
{"api-v2.yaml", "api-v3.yaml"},
{"api-v3.yaml", "api-v4.yaml"},
}
for _, pair := range pairs {
result, err := d.Diff(pair.old, pair.new)
if err != nil {
log.Printf("Error comparing %s to %s: %v", pair.old, pair.new, err)
continue
}
fmt.Printf("\n%s → %s:\n", pair.old, pair.new)
if result.HasBreakingChanges {
fmt.Printf(" ⚠️ %d breaking changes\n", result.BreakingCount)
} else {
fmt.Println(" ✓ No breaking changes")
}
}
}
Working with Parsed Documents ¶
For efficiency when documents are already parsed, use WithSourceParsed and WithTargetParsed:
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
"github.com/erraggy/oastools/parser"
)
func main() {
// Parse documents once
source, err := parser.ParseWithOptions(
parser.WithFilePath("api-v1.yaml"),
parser.WithValidateStructure(true),
)
if err != nil {
log.Fatal(err)
}
target, err := parser.ParseWithOptions(
parser.WithFilePath("api-v2.yaml"),
parser.WithValidateStructure(true),
)
if err != nil {
log.Fatal(err)
}
// Compare parsed documents
result, err := differ.DiffWithOptions(
differ.WithSourceParsed(*source),
differ.WithTargetParsed(*target),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d changes\n", len(result.Changes))
}
Change Analysis ¶
The Change struct provides detailed information about each difference:
for _, change := range result.Changes {
fmt.Printf("Path: %s\n", change.Path)
fmt.Printf("Type: %s\n", change.Type)
fmt.Printf("Category: %s\n", change.Category)
fmt.Printf("Severity: %s\n", change.Severity)
fmt.Printf("Message: %s\n", change.Message)
if change.OldValue != nil {
fmt.Printf("Old value: %v\n", change.OldValue)
}
if change.NewValue != nil {
fmt.Printf("New value: %v\n", change.NewValue)
}
}
Breaking Change Examples ¶
Common breaking changes detected in ModeBreaking:
- Removed endpoints or operations (SeverityCritical)
- Removed required parameters (SeverityCritical)
- Changed parameter types (SeverityError)
- Made optional parameters required (SeverityError)
- Removed enum values (SeverityError)
- Removed success response codes (SeverityError)
- Removed schemas (SeverityError)
- Changed authentication requirements (SeverityError)
Non-Breaking Change Examples ¶
Common non-breaking changes in ModeBreaking:
- Added endpoints or operations (SeverityInfo)
- Added optional parameters (SeverityInfo)
- Made required parameters optional (SeverityInfo)
- Added enum values (SeverityInfo)
- Added response codes (SeverityInfo)
- Documentation updates (SeverityInfo)
Version Compatibility ¶
The differ works with:
- OAS 2.0 (Swagger) documents
- OAS 3.0.x documents
- OAS 3.1.x documents
- OAS 3.2.x documents
- Cross-version comparisons (with limitations)
When comparing documents of different OAS versions (e.g., 2.0 vs 3.0), the diff is limited to common elements present in both versions.
Coverage Details ¶
The differ provides comprehensive comparison of OpenAPI specification elements:
Response Comparison ¶
Response objects are fully compared including:
- Headers: All header properties (description, required, deprecated, type, style, schema)
- Content/MediaTypes: Media type objects and their schemas
- Links: Link objects (operationRef, operationId, description)
- Examples: Example map keys (not deep value comparison)
- Extensions: All x-* fields on Response objects
Header comparison includes:
- Description and deprecation status
- Required flag changes
- Type and style modifications
- Schema changes (delegates to schema comparison)
- Extensions on Header objects
MediaType comparison includes:
- Schema changes (delegates to comprehensive schema comparison)
- Extensions on MediaType objects
Link comparison includes:
- Operation references (operationRef, operationId)
- Description changes
- Extensions on Link objects
Schema Comparison ¶
Schema objects are comprehensively compared including all fields:
Metadata:
- title, description
Type information:
- type, format
Numeric constraints:
- multipleOf, maximum, exclusiveMaximum, minimum, exclusiveMinimum
String constraints:
- maxLength, minLength, pattern
Array constraints:
- maxItems, minItems, uniqueItems
Object constraints:
- maxProperties, minProperties
- required fields (with smart severity: adding required=ERROR, removing=INFO)
OAS-specific fields:
- nullable, readOnly, writeOnly, deprecated
Schema comparison uses smart severity assignment in breaking mode:
- ERROR: Stricter constraints (adding required fields, lowering max values, raising min values)
- WARNING: Changes that might affect consumers (type changes, constraint modifications)
- INFO: Relaxations and non-breaking changes (removing required, raising max, lowering min)
Note: Recursive schema properties (properties, items, allOf, oneOf, anyOf, not) are compared separately to avoid cyclic comparison issues.
Extension (x-*) Field Coverage ¶
The OpenAPI Specification allows custom extension fields (starting with "x-") at many levels of the document. The differ detects and reports changes to extensions at commonly-used locations:
Extensions ARE diffed for these types:
- Document level (OAS2Document, OAS3Document)
- Info object
- Server objects
- PathItem objects
- Operation objects
- Parameter objects
- RequestBody objects
- Response objects
- Header objects (response headers)
- Link objects (response links)
- MediaType objects (content types)
- Schema objects
- SecurityScheme objects
- Tag objects
- Components object
Extensions are NOT currently diffed for these less commonly-used types:
- Contact, License, ExternalDocs (nested within Info)
- ServerVariable (nested within Server)
- Reference objects
- Items (OAS 2.0 array item definitions)
- Example, Encoding (response-related nested objects)
- Discriminator, XML (schema-related nested objects)
- OAuthFlows, OAuthFlow (security-related nested objects)
The rationale for this selective coverage is that extensions are most commonly placed at document, path, operation, parameter, response, and schema levels where they provide cross-cutting metadata. Extensions in deeply nested objects like ServerVariable, Discriminator, or Example are rare in practice.
If your use case requires extension diffing for the uncovered types, please open an issue at https://github.com/erraggy/oastools/issues
All extension changes are reported with CategoryExtension and are assigned SeverityInfo in breaking mode, as specification extensions are non-normative and optional according to the OpenAPI Specification.
Related Packages ¶
The differ integrates with other oastools packages:
- github.com/erraggy/oastools/parser - Parse specifications before diffing
- github.com/erraggy/oastools/validator - Validate specifications before comparison
- github.com/erraggy/oastools/fixer - Fix common validation errors in specifications
- github.com/erraggy/oastools/converter - Convert versions before comparing different OAS versions
- github.com/erraggy/oastools/joiner - Join specifications before comparison
- github.com/erraggy/oastools/generator - Generate code from compared specifications
- github.com/erraggy/oastools/builder - Programmatically build specifications to compare
Example ¶
Example demonstrates basic diff usage with functional options
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
// Compare two OpenAPI specifications
result, err := differ.DiffWithOptions(
differ.WithSourceFilePath("../testdata/petstore-v1.yaml"),
differ.WithTargetFilePath("../testdata/petstore-v2.yaml"),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d changes\n", len(result.Changes))
fmt.Printf("Source version: %s\n", result.SourceVersion)
fmt.Printf("Target version: %s\n", result.TargetVersion)
}
Example (Breaking) ¶
Example_breaking demonstrates breaking change detection
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
result, err := differ.DiffWithOptions(
differ.WithSourceFilePath("../testdata/petstore-v1.yaml"),
differ.WithTargetFilePath("../testdata/petstore-v2.yaml"),
differ.WithMode(differ.ModeBreaking),
differ.WithIncludeInfo(true),
)
if err != nil {
log.Fatal(err)
}
if result.HasBreakingChanges {
fmt.Printf("⚠️ Found %d breaking change(s)\n", result.BreakingCount)
} else {
fmt.Println("✓ No breaking changes detected")
}
fmt.Printf("Summary: %d breaking, %d warnings, %d info\n",
result.BreakingCount, result.WarningCount, result.InfoCount)
}
Example (BreakingChanges) ¶
Example_breakingChanges demonstrates how to detect breaking changes between two API versions and interpret the results by severity.
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
// Compare two API versions with breaking mode enabled
result, err := differ.DiffWithOptions(
differ.WithSourceFilePath("../testdata/petstore-v1.yaml"),
differ.WithTargetFilePath("../testdata/petstore-v2.yaml"),
differ.WithMode(differ.ModeBreaking),
differ.WithIncludeInfo(true), // Include all change levels
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Comparing %s to %s\n", result.SourceVersion, result.TargetVersion)
fmt.Printf("Total changes: %d\n\n", len(result.Changes))
// Critical changes: API consumers WILL break
// Examples: removed endpoints, required parameters, response schema changes
criticalCount := 0
errorCount := 0
warningCount := 0
infoCount := 0
for _, change := range result.Changes {
// Severity constants from internal/severity package:
// SeverityCritical = 3, SeverityError = 2, SeverityWarning = 1, SeverityInfo = 0
switch change.Severity {
case 3: // Critical
criticalCount++
fmt.Printf("CRITICAL [%s]: %s\n", change.Path, change.Message)
case 2: // Error
errorCount++
case 1: // Warning
warningCount++
case 0: // Info
infoCount++
}
}
// Summary by severity
fmt.Printf("\nSummary:\n")
fmt.Printf("- Critical (API will break): %d\n", criticalCount)
fmt.Printf("- Errors (likely to break): %d\n", errorCount)
fmt.Printf("- Warnings (may affect clients): %d\n", warningCount)
fmt.Printf("- Info (non-breaking changes): %d\n", infoCount)
// Check if changes are backward compatible
if result.HasBreakingChanges {
fmt.Println("\n⚠️ This update contains BREAKING CHANGES")
fmt.Println("Consider versioning the API (e.g., /v2/...)")
} else {
fmt.Println("\n✓ Changes are backward compatible")
}
}
Example (ChangeAnalysis) ¶
Example_changeAnalysis demonstrates detailed change analysis
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
d := differ.New()
d.Mode = differ.ModeBreaking
result, err := d.Diff("../testdata/petstore-v1.yaml", "../testdata/petstore-v2.yaml")
if err != nil {
log.Fatal(err)
}
// Group changes by category
categories := make(map[differ.ChangeCategory]int)
for _, change := range result.Changes {
categories[change.Category]++
}
fmt.Println("Changes by category:")
for category, count := range categories {
fmt.Printf(" %s: %d\n", category, count)
}
}
Example (FilterBySeverity) ¶
Example_filterBySeverity demonstrates filtering changes by severity
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
d := differ.New()
d.Mode = differ.ModeBreaking
d.IncludeInfo = false // Exclude info-level changes
result, err := d.Diff("../testdata/petstore-v1.yaml", "../testdata/petstore-v2.yaml")
if err != nil {
log.Fatal(err)
}
// Only breaking changes and warnings remain
fmt.Printf("Breaking and warnings only: %d changes\n", len(result.Changes))
fmt.Printf("Breaking: %d, Warnings: %d\n", result.BreakingCount, result.WarningCount)
}
Example (Parsed) ¶
Example_parsed demonstrates comparing already-parsed documents
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
"github.com/erraggy/oastools/parser"
)
func main() {
// Parse documents once
source, err := parser.ParseWithOptions(
parser.WithFilePath("../testdata/petstore-v1.yaml"),
parser.WithValidateStructure(true),
)
if err != nil {
log.Fatal(err)
}
target, err := parser.ParseWithOptions(
parser.WithFilePath("../testdata/petstore-v2.yaml"),
parser.WithValidateStructure(true),
)
if err != nil {
log.Fatal(err)
}
// Compare parsed documents
result, err := differ.DiffWithOptions(
differ.WithSourceParsed(*source),
differ.WithTargetParsed(*target),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d changes between %s and %s\n",
len(result.Changes), result.SourceVersion, result.TargetVersion)
}
Example (ReusableDiffer) ¶
Example_reusableDiffer demonstrates creating a reusable differ instance
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
// Create a reusable differ with specific configuration
d := differ.New()
d.Mode = differ.ModeBreaking
d.IncludeInfo = false
d.UserAgent = "my-api-tool/1.0"
// Use the same differ for multiple comparisons
specs := []struct{ old, new string }{
{"../testdata/petstore-v1.yaml", "../testdata/petstore-v2.yaml"},
}
for _, spec := range specs {
result, err := d.Diff(spec.old, spec.new)
if err != nil {
log.Printf("Error: %v", err)
continue
}
fmt.Printf("%s → %s: ", spec.old, spec.new)
if result.HasBreakingChanges {
fmt.Printf("%d breaking\n", result.BreakingCount)
} else {
fmt.Println("compatible")
}
}
}
Example (Simple) ¶
Example_simple demonstrates simple diff mode
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/differ"
)
func main() {
result, err := differ.DiffWithOptions(
differ.WithSourceFilePath("../testdata/petstore-v1.yaml"),
differ.WithTargetFilePath("../testdata/petstore-v2.yaml"),
differ.WithMode(differ.ModeSimple),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Simple diff found %d changes\n", len(result.Changes))
// Print first few changes
for i, change := range result.Changes {
if i >= 3 {
break
}
fmt.Println(change.String())
}
}
Index ¶
- Constants
- type BreakingChangeRule
- type BreakingRulesConfig
- type Change
- type ChangeCategory
- type ChangeType
- type DiffMode
- type DiffResult
- type Differ
- type EndpointRules
- type ExtensionRules
- type InfoRules
- type OperationRules
- type Option
- func WithBreakingRules(rules *BreakingRulesConfig) Option
- func WithIncludeInfo(enabled bool) Option
- func WithMode(mode DiffMode) Option
- func WithSourceFilePath(path string) Option
- func WithSourceMap(sm *parser.SourceMap) Option
- func WithSourceParsed(result parser.ParseResult) Option
- func WithTargetFilePath(path string) Option
- func WithTargetMap(sm *parser.SourceMap) Option
- func WithTargetParsed(result parser.ParseResult) Option
- func WithUserAgent(ua string) Option
- type ParameterRules
- type RequestBodyRules
- type ResponseRules
- type RuleKey
- type SchemaRules
- type SecurityRules
- type ServerRules
- type Severity
Examples ¶
Constants ¶
const ( // SeverityInfo indicates informational changes (additions, relaxed constraints) SeverityInfo = severity.SeverityInfo // SeverityWarning indicates potentially problematic changes SeverityWarning = severity.SeverityWarning // SeverityError indicates breaking changes (removed features, stricter constraints) SeverityError = severity.SeverityError // SeverityCritical indicates critical breaking changes (removed endpoints, operations) SeverityCritical = severity.SeverityCritical )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BreakingChangeRule ¶ added in v1.31.0
type BreakingChangeRule struct {
// Severity overrides the default severity for this change type.
// If nil, the default severity is used.
Severity *Severity
// Ignore completely ignores this change type (not included in results).
Ignore bool
}
BreakingChangeRule configures how a specific change type is treated.
type BreakingRulesConfig ¶ added in v1.31.0
type BreakingRulesConfig struct {
// Operation configures rules for operation-level changes
Operation *OperationRules
// Parameter configures rules for parameter changes
Parameter *ParameterRules
// RequestBody configures rules for request body changes
RequestBody *RequestBodyRules
// Response configures rules for response changes
Response *ResponseRules
// Schema configures rules for schema changes
Schema *SchemaRules
// Security configures rules for security scheme changes
Security *SecurityRules
// Server configures rules for server changes
Server *ServerRules
// Endpoint configures rules for endpoint (path) changes
Endpoint *EndpointRules
// Info configures rules for info object changes
Info *InfoRules
// Extension configures rules for extension (x-*) changes
Extension *ExtensionRules
}
BreakingRulesConfig configures which changes are considered breaking and their severity levels. Use this to customize breaking change detection based on your organization's API compatibility policies.
Example:
rules := &differ.BreakingRulesConfig{
Operation: &differ.OperationRules{
OperationIDModified: &differ.BreakingChangeRule{
Severity: differ.SeverityPtr(differ.SeverityInfo), // Not breaking for us
},
},
Schema: &differ.SchemaRules{
PropertyRemoved: &differ.BreakingChangeRule{Ignore: true}, // We handle this differently
},
}
d := differ.New()
d.BreakingRules = rules
func DefaultRules ¶ added in v1.31.0
func DefaultRules() *BreakingRulesConfig
DefaultRules returns a BreakingRulesConfig with all default behaviors. This is equivalent to not setting any rules.
func LenientRules ¶ added in v1.31.0
func LenientRules() *BreakingRulesConfig
LenientRules returns a BreakingRulesConfig that treats fewer changes as breaking. This downgrades many errors to warnings.
func StrictRules ¶ added in v1.31.0
func StrictRules() *BreakingRulesConfig
StrictRules returns a BreakingRulesConfig that treats more changes as breaking. This elevates many warnings to errors.
type Change ¶
type Change struct {
// Path is the JSON path to the changed element (e.g., "paths./pets.get")
Path string
// Type indicates if this is an addition, removal, or modification
Type ChangeType
// Category indicates which part of the spec was changed
Category ChangeCategory
// Severity indicates the impact level (only used in ModeBreaking)
Severity Severity
// OldValue is the value in the source document (nil for additions)
OldValue any
// NewValue is the value in the target document (nil for removals)
NewValue any
// Message is a human-readable description of the change
Message string
// Line is the 1-based line number in the source file (0 if unknown)
Line int
// Column is the 1-based column number in the source file (0 if unknown)
Column int
// File is the source file path (empty for main document)
File string
}
Change represents a single difference between two OpenAPI specifications
func (Change) HasLocation ¶ added in v1.27.0
HasLocation returns true if this change has source location information.
type ChangeCategory ¶
type ChangeCategory string
ChangeCategory indicates which part of the spec was changed
const ( // CategoryEndpoint indicates a path/endpoint change CategoryEndpoint ChangeCategory = "endpoint" // CategoryOperation indicates an HTTP operation change CategoryOperation ChangeCategory = "operation" // CategoryParameter indicates a parameter change CategoryParameter ChangeCategory = "parameter" // CategoryRequestBody indicates a request body change CategoryRequestBody ChangeCategory = "request_body" // CategoryResponse indicates a response change CategoryResponse ChangeCategory = "response" // CategorySchema indicates a schema/definition change CategorySchema ChangeCategory = "schema" // CategorySecurity indicates a security scheme change CategorySecurity ChangeCategory = "security" // CategoryServer indicates a server change CategoryServer ChangeCategory = "server" // CategoryInfo indicates metadata change (info, contact, license, etc.) CategoryInfo ChangeCategory = "info" // CategoryExtension indicates a specification extension (x-*) change CategoryExtension ChangeCategory = "extension" )
type ChangeType ¶
type ChangeType string
ChangeType indicates whether a change is an addition, removal, or modification
const ( // ChangeTypeAdded indicates a new element was added ChangeTypeAdded ChangeType = "added" // ChangeTypeRemoved indicates an element was removed ChangeTypeRemoved ChangeType = "removed" // ChangeTypeModified indicates an existing element was changed ChangeTypeModified ChangeType = "modified" )
type DiffResult ¶
type DiffResult struct {
// SourceVersion is the source document's OAS version string
SourceVersion string
// SourceOASVersion is the enumerated source OAS version
SourceOASVersion parser.OASVersion
// SourceStats contains statistical information about the source document
SourceStats parser.DocumentStats
// SourceSize is the size of the source document in bytes
SourceSize int64
// TargetVersion is the target document's OAS version string
TargetVersion string
// TargetOASVersion is the enumerated target OAS version
TargetOASVersion parser.OASVersion
// TargetStats contains statistical information about the target document
TargetStats parser.DocumentStats
// TargetSize is the size of the target document in bytes
TargetSize int64
// Changes contains all detected changes
Changes []Change
// BreakingCount is the number of breaking changes (Critical + Error severity)
BreakingCount int
// WarningCount is the number of warnings
WarningCount int
// InfoCount is the number of informational changes
InfoCount int
// HasBreakingChanges is true if any breaking changes were detected
HasBreakingChanges bool
}
DiffResult contains the results of comparing two OpenAPI specifications
func DiffWithOptions ¶ added in v1.11.0
func DiffWithOptions(opts ...Option) (*DiffResult, error)
DiffWithOptions compares two OpenAPI specifications using functional options. This provides a flexible, extensible API that combines input source selection and configuration in a single function call.
Example:
result, err := differ.DiffWithOptions(
differ.WithSourceFilePath("api-v1.yaml"),
differ.WithTargetFilePath("api-v2.yaml"),
differ.WithMode(differ.ModeBreaking),
)
type Differ ¶
type Differ struct {
// Mode determines the type of diff operation (Simple or Breaking)
Mode DiffMode
// IncludeInfo determines whether to include informational changes
IncludeInfo bool
// UserAgent is the User-Agent string used when fetching URLs
// Defaults to "oastools" if not set
UserAgent string
// SourceMap provides source location lookup for the source document.
// When set, changes will include Line, Column, and File information
// for elements in the source document.
SourceMap *parser.SourceMap
// TargetMap provides source location lookup for the target document.
// When set, changes will include Line, Column, and File information
// for elements in the target document (used for additions).
TargetMap *parser.SourceMap
// BreakingRules configures which changes are considered breaking
// and their severity levels. When nil, default rules are used.
// See BreakingRulesConfig for configuration options.
BreakingRules *BreakingRulesConfig
}
Differ handles OpenAPI specification comparison
func (*Differ) Diff ¶
func (d *Differ) Diff(sourcePath, targetPath string) (*DiffResult, error)
Diff compares two OpenAPI specification files
func (*Differ) DiffParsed ¶
func (d *Differ) DiffParsed(source, target parser.ParseResult) (*DiffResult, error)
DiffParsed compares two already-parsed OpenAPI specifications
type EndpointRules ¶ added in v1.31.0
type EndpointRules struct {
// Removed configures the rule for when an endpoint is removed.
// Default: SeverityCritical
Removed *BreakingChangeRule
// Added configures the rule for when an endpoint is added.
// Default: SeverityInfo
Added *BreakingChangeRule
// DescriptionModified configures the rule for description changes.
// Default: SeverityInfo
DescriptionModified *BreakingChangeRule
}
EndpointRules configures rules for endpoint (path) changes.
type ExtensionRules ¶ added in v1.31.0
type ExtensionRules struct {
// Removed configures the rule for when an extension is removed.
// Default: SeverityInfo
Removed *BreakingChangeRule
// Added configures the rule for when an extension is added.
// Default: SeverityInfo
Added *BreakingChangeRule
// Modified configures the rule for when an extension is modified.
// Default: SeverityInfo
Modified *BreakingChangeRule
}
ExtensionRules configures rules for specification extension (x-*) changes.
type InfoRules ¶ added in v1.31.0
type InfoRules struct {
// TitleModified configures the rule for title changes.
// Default: SeverityInfo
TitleModified *BreakingChangeRule
// VersionModified configures the rule for version changes.
// Default: SeverityInfo
VersionModified *BreakingChangeRule
// DescriptionModified configures the rule for description changes.
// Default: SeverityInfo
DescriptionModified *BreakingChangeRule
}
InfoRules configures rules for info object changes.
type OperationRules ¶ added in v1.31.0
type OperationRules struct {
// Removed configures the rule for when an operation is removed.
// Default: SeverityCritical
Removed *BreakingChangeRule
// OperationIDModified configures the rule for operationId changes.
// Default: SeverityWarning
OperationIDModified *BreakingChangeRule
// SummaryModified configures the rule for summary changes.
// Default: SeverityInfo
SummaryModified *BreakingChangeRule
// DescriptionModified configures the rule for description changes.
// Default: SeverityInfo
DescriptionModified *BreakingChangeRule
// DeprecatedModified configures the rule for deprecated flag changes.
// Default: SeverityInfo
DeprecatedModified *BreakingChangeRule
// TagsModified configures the rule for operation tags changes.
// Default: SeverityInfo
TagsModified *BreakingChangeRule
// Added configures the rule for when an operation is added.
// Default: SeverityInfo
Added *BreakingChangeRule
}
OperationRules configures rules for HTTP operation changes.
type Option ¶ added in v1.11.0
type Option func(*diffConfig) error
Option is a function that configures a diff operation
func WithBreakingRules ¶ added in v1.31.0
func WithBreakingRules(rules *BreakingRulesConfig) Option
WithBreakingRules configures which changes are considered breaking and their severity levels. This allows customizing breaking change detection based on your organization's API compatibility policies.
Example:
result, _ := differ.DiffWithOptions(
differ.WithSourceFilePath("v1.yaml"),
differ.WithTargetFilePath("v2.yaml"),
differ.WithMode(differ.ModeBreaking),
differ.WithBreakingRules(&differ.BreakingRulesConfig{
Operation: &differ.OperationRules{
OperationIDModified: &differ.BreakingChangeRule{
Severity: differ.SeverityPtr(differ.SeverityInfo),
},
},
}),
)
func WithIncludeInfo ¶ added in v1.11.0
WithIncludeInfo enables or disables informational changes Default: true
func WithMode ¶ added in v1.11.0
WithMode sets the diff mode (Simple or Breaking) Default: ModeSimple
func WithSourceFilePath ¶ added in v1.11.0
WithSourceFilePath specifies a file path or URL as the source document
func WithSourceMap ¶ added in v1.27.0
WithSourceMap provides a SourceMap for the source document. When set, changes will include Line, Column, and File information for elements that exist in (or were removed from) the source document.
func WithSourceParsed ¶ added in v1.11.0
func WithSourceParsed(result parser.ParseResult) Option
WithSourceParsed specifies a parsed ParseResult as the source document
func WithTargetFilePath ¶ added in v1.11.0
WithTargetFilePath specifies a file path or URL as the target document
func WithTargetMap ¶ added in v1.27.0
WithTargetMap provides a SourceMap for the target document. When set, changes will include Line, Column, and File information for elements that were added in the target document.
func WithTargetParsed ¶ added in v1.11.0
func WithTargetParsed(result parser.ParseResult) Option
WithTargetParsed specifies a parsed ParseResult as the target document
func WithUserAgent ¶ added in v1.11.0
WithUserAgent sets the User-Agent string for HTTP requests Default: "" (uses parser default)
type ParameterRules ¶ added in v1.31.0
type ParameterRules struct {
// Removed configures the rule for when a parameter is removed.
// Default: SeverityError (required) / SeverityWarning (optional)
Removed *BreakingChangeRule
// Added configures the rule for when a parameter is added.
// Default: SeverityError (required) / SeverityInfo (optional)
Added *BreakingChangeRule
// RequiredChanged configures the rule for required field changes.
// Default: SeverityError (false→true) / SeverityInfo (true→false)
RequiredChanged *BreakingChangeRule
// TypeChanged configures the rule for type changes.
// Default: SeverityError
TypeChanged *BreakingChangeRule
// FormatChanged configures the rule for format changes.
// Default: SeverityWarning
FormatChanged *BreakingChangeRule
// StyleChanged configures the rule for style changes.
// Default: SeverityWarning
StyleChanged *BreakingChangeRule
// SchemaChanged configures the rule for schema changes.
// Default: varies by schema change
SchemaChanged *BreakingChangeRule
// DescriptionModified configures the rule for description changes.
// Default: SeverityInfo
DescriptionModified *BreakingChangeRule
}
ParameterRules configures rules for parameter changes.
type RequestBodyRules ¶ added in v1.31.0
type RequestBodyRules struct {
// Removed configures the rule for when a request body is removed.
// Default: SeverityError
Removed *BreakingChangeRule
// Added configures the rule for when a request body is added.
// Default: SeverityError (required) / SeverityInfo (optional)
Added *BreakingChangeRule
// RequiredChanged configures the rule for required field changes.
// Default: SeverityError (false→true) / SeverityInfo (true→false)
RequiredChanged *BreakingChangeRule
// MediaTypeRemoved configures the rule for when a media type is removed.
// Default: SeverityWarning
MediaTypeRemoved *BreakingChangeRule
// MediaTypeAdded configures the rule for when a media type is added.
// Default: SeverityInfo
MediaTypeAdded *BreakingChangeRule
// SchemaChanged configures the rule for schema changes.
// Default: varies by schema change
SchemaChanged *BreakingChangeRule
}
RequestBodyRules configures rules for request body changes.
type ResponseRules ¶ added in v1.31.0
type ResponseRules struct {
// Removed configures the rule for when a response is removed.
// Default: SeverityError (success codes) / SeverityWarning (error codes)
Removed *BreakingChangeRule
// Added configures the rule for when a response is added.
// Default: SeverityInfo
Added *BreakingChangeRule
// DescriptionModified configures the rule for description changes.
// Default: SeverityInfo
DescriptionModified *BreakingChangeRule
// MediaTypeRemoved configures the rule for when a media type is removed.
// Default: SeverityWarning
MediaTypeRemoved *BreakingChangeRule
// MediaTypeAdded configures the rule for when a media type is added.
// Default: SeverityInfo
MediaTypeAdded *BreakingChangeRule
// HeaderRemoved configures the rule for when a header is removed.
// Default: SeverityWarning
HeaderRemoved *BreakingChangeRule
// HeaderAdded configures the rule for when a header is added.
// Default: SeverityInfo
HeaderAdded *BreakingChangeRule
// SchemaChanged configures the rule for schema changes.
// Default: varies by schema change
SchemaChanged *BreakingChangeRule
}
ResponseRules configures rules for response changes.
type RuleKey ¶ added in v1.31.0
type RuleKey struct {
Category ChangeCategory
ChangeType ChangeType
SubType string // Additional context (e.g., "operationId", "required")
}
RuleKey identifies a specific change type for rule lookup.
type SchemaRules ¶ added in v1.31.0
type SchemaRules struct {
// Removed configures the rule for when a schema is removed.
// Default: SeverityError
Removed *BreakingChangeRule
// Added configures the rule for when a schema is added.
// Default: SeverityInfo
Added *BreakingChangeRule
// TypeChanged configures the rule for type changes.
// Default: SeverityError
TypeChanged *BreakingChangeRule
// FormatChanged configures the rule for format changes.
// Default: SeverityWarning
FormatChanged *BreakingChangeRule
// RequiredAdded configures the rule for when a required field is added.
// Default: SeverityError
RequiredAdded *BreakingChangeRule
// RequiredRemoved configures the rule for when a required field is removed.
// Default: SeverityInfo
RequiredRemoved *BreakingChangeRule
// PropertyRemoved configures the rule for when a property is removed.
// Default: SeverityWarning
PropertyRemoved *BreakingChangeRule
// PropertyAdded configures the rule for when a property is added.
// Default: SeverityInfo
PropertyAdded *BreakingChangeRule
// EnumValueRemoved configures the rule for when an enum value is removed.
// Default: SeverityError
EnumValueRemoved *BreakingChangeRule
// EnumValueAdded configures the rule for when an enum value is added.
// Default: SeverityInfo
EnumValueAdded *BreakingChangeRule
// MaximumDecreased configures the rule for when maximum is decreased.
// Default: SeverityError
MaximumDecreased *BreakingChangeRule
// MinimumIncreased configures the rule for when minimum is increased.
// Default: SeverityError
MinimumIncreased *BreakingChangeRule
// MaxLengthDecreased configures the rule for when maxLength is decreased.
// Default: SeverityError
MaxLengthDecreased *BreakingChangeRule
// MinLengthIncreased configures the rule for when minLength is increased.
// Default: SeverityWarning
MinLengthIncreased *BreakingChangeRule
// PatternChanged configures the rule for when pattern is changed.
// Default: SeverityWarning
PatternChanged *BreakingChangeRule
// NullableRemoved configures the rule for when nullable is removed.
// Default: SeverityError
NullableRemoved *BreakingChangeRule
// NullableAdded configures the rule for when nullable is added.
// Default: SeverityInfo
NullableAdded *BreakingChangeRule
// AdditionalPropertiesChanged configures the rule for additionalProperties changes.
// Default: SeverityWarning
AdditionalPropertiesChanged *BreakingChangeRule
// DescriptionModified configures the rule for description changes.
// Default: SeverityInfo
DescriptionModified *BreakingChangeRule
}
SchemaRules configures rules for schema changes.
type SecurityRules ¶ added in v1.31.0
type SecurityRules struct {
// Removed configures the rule for when a security scheme is removed.
// Default: SeverityError
Removed *BreakingChangeRule
// Added configures the rule for when a security scheme is added.
// Default: SeverityWarning
Added *BreakingChangeRule
// TypeChanged configures the rule for type changes.
// Default: SeverityError
TypeChanged *BreakingChangeRule
// ScopeRemoved configures the rule for when a scope is removed.
// Default: SeverityWarning
ScopeRemoved *BreakingChangeRule
// ScopeAdded configures the rule for when a scope is added.
// Default: SeverityInfo
ScopeAdded *BreakingChangeRule
}
SecurityRules configures rules for security scheme changes.
type ServerRules ¶ added in v1.31.0
type ServerRules struct {
// Removed configures the rule for when a server is removed.
// Default: SeverityWarning
Removed *BreakingChangeRule
// Added configures the rule for when a server is added.
// Default: SeverityInfo
Added *BreakingChangeRule
// DescriptionModified configures the rule for description changes.
// Default: SeverityInfo
DescriptionModified *BreakingChangeRule
// VariableChanged configures the rule for server variable changes.
// Default: SeverityWarning
VariableChanged *BreakingChangeRule
}
ServerRules configures rules for server changes.
type Severity ¶
Severity indicates the severity level of a change
func SeverityPtr ¶ added in v1.31.0
SeverityPtr is a helper function to create a pointer to a Severity value. This is useful when configuring BreakingChangeRule.Severity.