This repository demonstrates how to implement automated breaking changes detection for OpenAPI specifications using the oasdiff tool. Breaking changes detection is a critical practice in API development to ensure backward compatibility and prevent unexpected disruptions for API consumers.
.
├── .github/workflows # CI/CD configurations
├── api # OpenAPI specifications
│ ├── v1 # Base version of the API
│ └── v2 # Updated version of the API to check for breaking changes
└── scripts # Utility scripts for API validation
This project implements two levels of breaking changes detection:
- Local Pre-commit Hook: Prevents committing breaking changes to the repository
- GitHub Actions Workflow: Validates changes in the CI pipeline
Both mechanisms use the oasdiff
tool to compare OpenAPI specifications and detect potentially breaking changes that could affect API consumers.
- Git
- Go 1.21 or later
- Clone this repository
- Install the oasdiff tool:
go install github.com/oasdiff/oasdiff@latest
- The pre-commit hook is automatically set up when you clone the repository
The pre-commit hook automatically runs when you try to commit changes to the repository. It:
- Identifies modified/added YAML files in the staging area
- If OpenAPI files are modified, runs the breaking changes check
- Blocks the commit if breaking changes are detected
- Allows the commit to proceed if no breaking changes are found
To run the check manually:
./scripts/check-breaking.sh
The CI/CD pipeline includes a workflow that:
- Triggers when changes are pushed to files in the
api/
orscripts/
directories - Sets up Go and installs the oasdiff tool
- Runs the breaking changes check script
- Fails the build if breaking changes are detected
This ensures that no breaking changes make it into the main branch, even if they bypass the local pre-commit hook.
Implementing automated breaking changes detection provides several benefits:
- Backward Compatibility: Ensures changes to the API don't break existing clients
- Clear Communication: Helps identify when changes need to be communicated to API consumers
- Version Management: Helps enforce proper semantic versioning practices
- Documentation: Creates a traceable history of API changes
- Quality Control: Prevents accidental regressions in the API
The oasdiff tool can detect a wide range of breaking changes, including:
- Removed endpoints or operations
- Changed parameter requirements
- Modified response structures
- Schema property changes
- Authentication changes
- And many more
This basic setup can be extended in several ways:
Enhance the workflow to automatically generate a changelog based on detected differences between API versions.
- name: Generate Changelog
run: oasdiff changelog api/v1/openapi.yaml api/v2/openapi.yaml --format markdown > CHANGELOG.md
Add OpenAPI linting to catch specification errors and style issues:
- name: Validate OpenAPI
run: |
npm install -g @stoplight/spectral-cli
spectral lint api/v2/openapi.yaml
Automatically generate API documentation when the specifications change:
- name: Generate Documentation
run: |
npm install -g redoc-cli
redoc-cli bundle api/v2/openapi.yaml -o docs/index.html
Send notifications to development teams when potential breaking changes are detected:
- name: Notify About Breaking Changes
if: failure()
uses: slackapi/slack-github-action@v1
with:
slack-message: "⚠️ Breaking changes detected in the API!"
slack-channel: "api-development"
Generate HTML reports visualizing the differences between API versions:
- name: Generate Diff Report
run: oasdiff diff api/v1/openapi.yaml api/v2/openapi.yaml --format html > report.html
This repository includes a practical example of how to properly handle API changes. Here's what we did:
Initially, we attempted to remove the name
property completely from the Pet schema in v2:
# Breaking change that was rejected
Pet:
type: object
required:
- id
properties:
id:
type: integer
# name property has been removed completely - this breaks compatibility!
This change was detected by oasdiff as breaking backward compatibility and was rejected by the pre-commit hook.
We then applied proper versioning by:
- Keeping but deprecating the original property:
name:
type: string
deprecated: true
description: "This field is deprecated and will be removed in v3.0.0. Use 'displayName' instead."
- Adding a replacement field:
displayName:
type: string
description: "The display name of the pet. Replaces the deprecated 'name' field."
- Documenting the changes in the OpenAPI specification:
description: |
# API Changes in 2.0.0
## Deprecations
- The `name` property in Pet schema is deprecated and will be removed in v3.0.0
## New Features
- Added `displayName` property to Pet schema to replace the deprecated `name` field
- Added `id` as a required property for Pet objects
This approach maintains backward compatibility while clearly communicating the path forward for API consumers.
- Always increment the API version appropriately when introducing breaking changes
- Add deprecation notices before removing endpoints or features
- Document all changes, whether breaking or non-breaking
- Use feature flags to gradually roll out changes when possible
- Follow semantic versioning principles for your API