Releases: erraggy/oastools
v1.6.0 - Reference Validation, Format Preservation, and Code Quality Improvements
Overview
This release delivers significant enhancements to the oastools module with three major improvements: comprehensive $ref validation and conversion support, automatic format preservation for JSON and YAML outputs, and substantial code quality improvements through consolidation and deduplication.
🎯 New Features
Reference Validation and Conversion Support (#13)
Addresses critical issues with $ref handling in both validator and converter packages:
Validator Enhancements:
- Added comprehensive
$refvalidation for both OAS 2.0 and OAS 3.x documents - Validates that all
$refpaths point to valid components in the correct format - Recursively validates refs in schemas, parameters, responses, and request bodies
- 600+ lines of new validation logic with 10 comprehensive test cases
Converter Enhancements:
- Automatic
$refpath rewriting when converting between OAS versions - Correctly translates reference paths during conversions:
- OAS 2.0 → 3.x:
#/definitions/→#/components/schemas/ - OAS 3.x → 2.0:
#/components/schemas/→#/definitions/
- OAS 2.0 → 3.x:
- Handles nested refs in all schema types (properties, allOf, anyOf, oneOf)
- Fixed parameter
Reffield not being copied during conversion - 350+ lines of ref rewriting logic with 4 comprehensive test cases
Format Preservation (#14)
Automatic input format preservation for convert and join commands:
Parser Updates:
- Added
SourceFormatfield toParseResultto track input format (JSON/YAML) - Intelligent format detection from file extensions and content
- Support for JSON and YAML format detection from readers and byte slices
Converter Updates:
- Preserves source format through the conversion pipeline
- JSON input → JSON output, YAML input → YAML output
- Consistent 2-space indentation for JSON output
Joiner Updates:
- Format of first input file determines output format
- Added
WriteResult()method with format-aware marshaling - Handles mixed format inputs gracefully
Benefits:
- Maintains format consistency in toolchains and version control
- No manual conversion needed after processing
- Backwards-compatible - existing workflows unchanged
🔧 Code Quality & Maintainability
Consolidated Duplication (#12)
Major refactoring to eliminate 1,667+ lines of duplicated code and documentation:
New Internal Packages:
internal/httputil- Unified HTTP constants and validation (100 lines saved)internal/severity- Unified severity type for all packages (46 lines saved)internal/issues- Unified issue struct for validation/conversion (64 lines saved)internal/testutil- Reusable test fixtures and helpers (87 lines saved)
Code Consolidation:
- New
parser/operations.gowithGetOAS2Operations()andGetOAS3Operations()helpers - Single source of truth for HTTP methods, status codes, and severity levels
- Eliminated 329 lines of duplicated code across packages
Documentation Improvements:
- Reduced root
doc.gofrom 347 → 14 lines (96% reduction) - Streamlined package documentation (40-85% reductions)
- Removed 29 redundant example function variants
- Cleaner pkg.go.dev experience with focused, essential information
Test Infrastructure:
- Standardized temporary file handling with
t.TempDir() - Extracted reusable test fixtures to
internal/testutil - Modern Go testing patterns throughout
Results:
- 1,667+ total lines reduced (54% overall)
- Zero breaking changes - 100% backward compatibility maintained
- All 332 tests passing with race detection
🏗️ Infrastructure & CI/CD
- Added GitHub Actions workflow for Go testing and quality checks
- Added golangci-lint workflow for automated code quality enforcement
- Updated linters configuration in
.golangci.yml - Enhanced CI/CD pipeline for better code quality assurance
📋 What's Changed
- refactor: Consolidate code and test duplication across packages (#12)
- feat(validator,converter): add $ref validation and conversion support (#13)
- feat(parser,converter,joiner): preserve input format in output (#14)
- Added GitHub Actions workflows for Go and golangci-lint
- Updated linters configuration and CI/CD pipeline
📊 Testing
All packages maintain comprehensive test coverage:
- Parser: All tests passing ✅
- Validator: 23 tests (including 10 new ref validation tests) ✅
- Converter: 23 tests (including 4 new ref rewriting tests) ✅
- Joiner: All tests passing (including format preservation tests) ✅
- All tests run with race detection enabled
🔄 Backward Compatibility
This release maintains 100% backward compatibility with v1.5.0. All existing code using the oastools public API will continue to work without modifications.
Full Changelog: v1.5.0...v1.6.0
v1.5.0 - Adds Converter
Release Notes: oastools v1.5.0
Release Date: 16-Nov-2025
Type: Minor Release - New Features
Overview
Version 1.5.0 introduces a powerful new converter package and CLI command for
converting OpenAPI specifications between different OAS versions. This release
enables seamless migration of API specifications across OAS 2.0 (Swagger) and
OAS 3.x versions while tracking conversion issues and incompatibilities.
New Features
Converter Package (github.com/erraggy/oastools/converter)
A comprehensive public API for converting OpenAPI specifications between
versions with detailed issue tracking and reporting.
Key Features:
- Convert between OAS 2.0 ↔ OAS 3.x
- Best-effort conversion preserving maximum information
- Detailed tracking of conversion issues and incompatibilities
- Dual API pattern (convenience functions + reusable instances)
- Full support for all OAS features with transparent limitation reporting
Supported Conversions:
- OAS 2.0 → OAS 3.0.x (configurable target version)
- OAS 3.x → OAS 2.0
- OAS 3.x → OAS 3.y (version updates with minimal conversion)
API Design:
Package-level convenience functions:
result, err := converter.Convert("openapi-v2.yaml", "3.0.3", options)Reusable converter instances:
c := converter.New()
c.TargetVersion = "3.0.3"
c.StrictMode = false
result, err := c.Convert("swagger.yaml")Convert CLI Command
New oastools convert command for converting specifications from the command
line.
Usage:
# Convert OAS 2.0 to OAS 3.0.3
oastools convert -t 3.0.3 swagger.yaml -o openapi.yaml
# Convert OAS 3.1.0 to OAS 2.0
oastools convert -t 2.0 openapi-v3.yaml -o swagger.yaml
# Strict mode: fail on any conversion issues
oastools convert --strict -t 3.0.3 swagger.yamlFlags:
-t, --target <version>- Target OAS version (required)-o, --output <file>- Output file path (default: stdout)--strict- Fail on any conversion issues/warnings--no-warnings- Suppress warning messages
Conversion Details
OAS 2.0 → OAS 3.x
Automatic Conversions:
swagger/host/basePath→serversarraydefinitions→components.schemasparameters→components.parametersresponses→components.responsessecurityDefinitions→components.securitySchemesconsumes/produces→requestBody.contentandresponses[*].content- Body parameters →
requestBodyobjects
Known Limitations (tracked as issues):
collectionFormatvalues may not map perfectly tostyleparameterallowEmptyValueremoved in OAS 3.0 (tracked as warning)- Some OAuth2 flow names changed between versions
OAS 3.x → OAS 2.0
Automatic Conversions:
- First
server→host/basePath/schemes components.schemas→definitionscomponents.parameters→parameterscomponents.responses→responsescomponents.securitySchemes→securityDefinitionsrequestBody→ body parameter with schema- Media types →
consumes/produces
Known Limitations (tracked as critical issues):
- Webhooks cannot be represented in OAS 2.0 (OAS 3.1+)
- Callbacks cannot be converted
- Links cannot be converted
- Multiple servers (only first server is converted)
- Cookie parameters (
in: cookie) not supported in OAS 2.0 anyOf/oneOfmay require manual schema adjustments
Issue Tracking
The converter provides detailed issue tracking similar to the validator:
Severity Levels:
- Critical: Features that cannot be converted (data loss)
- Warning: Lossy conversions or best-effort transformations
- Info: Informational messages about conversion choices
Example Output:
Conversion Issues (3):
✗ paths./pets.get.parameters[0] (Critical): Cookie parameters are not
supported in OAS 2.0
⚠ paths./users.post.requestBody (Warning): Multiple media types found,
using first (application/json)
ℹ webhooks (Info): Webhooks are OAS 3.1+ only and cannot be converted to 2.0
Breaking Changes
None. This release is fully backward compatible with v1.4.x.
Migration Guide
For Library Users
Add the converter package to your imports:
import "github.com/erraggy/oastools/converter"Basic conversion:
result, err := converter.Convert("swagger.yaml", "3.0.3", nil)
if err != nil {
log.Fatal(err)
}
if result.HasCriticalIssues() {
fmt.Printf("Conversion completed with %d critical issues:\n",
result.CriticalCount)
for _, issue := range result.Issues {
if issue.Severity == converter.SeverityCritical {
fmt.Printf(" %s\n", issue.String())
}
}
}
// Write converted document
err = converter.WriteResult(result, "openapi.yaml")For CLI Users
Simply update to v1.5.0 and start using the new convert command:
# Upgrade
go install github.com/erraggy/oastools/cmd/oastools@v1.5.0
# Convert specifications
oastools convert -t 3.0.3 swagger.yaml -o openapi.yamlDocumentation
- Package documentation: https://pkg.go.dev/github.com/erraggy/oastools/converter
- CLI help:
oastools convert --help - Examples: See
converter/example_test.go
Testing
This release includes comprehensive test coverage for the converter package:
- Unit tests for all conversion functions
- Integration tests with real-world specifications
- Edge case handling
- Error condition coverage
All tests pass with race detection enabled.
Contributors
- Claude (AI Assistant)
- Project maintained by @erraggy
Full Changelog: v1.4.0...v1.5.0
v1.4.0 - Adds simpler API
What's Changed
This adds package-level convenience functions to all three core packages (parser, validator, and joiner) to provide a simpler API for one-off operations while maintaining full backward compatibility with the existing struct-based API.
New Package-Level Functions
Parser Package
parser.Parse(specPath, resolveRefs, validateStructure)- Parse a file with optionsparser.ParseReader(r, resolveRefs, validateStructure)- Parse from io.Readerparser.ParseBytes(data, resolveRefs, validateStructure)- Parse from bytes
Validator Package
validator.Validate(specPath, includeWarnings, strictMode)- Validate a file with optionsvalidator.ValidateParsed(parseResult, includeWarnings, strictMode)- Validate already-parsed result
Joiner Package
joiner.Join(specPaths, config)- Join files with configurationjoiner.JoinParsed(parsedDocs, config)- Join already-parsed documents
API Design Philosophy
The library now provides two complementary API styles:
- Package-level convenience functions - For simple, one-off operations
- Struct-based API - For reusable instances with configuration
When to Use Convenience Functions
- Simple scripts or one-time operations
- Prototyping and quick testing
- Code examples and documentation
- Default configuration is sufficient
When to Use Struct-Based API
- Processing multiple files with the same configuration
- Need to reuse the same parser/validator/joiner instance
- Advanced configuration requirements
- Performance-critical scenarios where instance reuse matters
Example Usage
Before (Struct-Based API)
// Still works! No breaking changes
p := parser.New()
result, err := p.Parse("openapi.yaml")After (Convenience Function)
// Simpler for one-off operations
result, err := parser.Parse("openapi.yaml", false, true)Internal Refactoring
To demonstrate best practices and maintain consistency:
- Updated
validator.Validate()to useparser.Parse()internally - Updated
joiner.Join()to useparser.Parse()internally
Test Coverage Added
Parser Package (parser/parser_test.go):
- ✅ TestParseConvenience - Tests parser.Parse() with various scenarios
- ✅ TestParseReaderConvenience - Tests parser.ParseReader() with different inputs
- ✅ TestParseBytesConvenience - Tests parser.ParseBytes() including JSON format
Validator Package (validator/validator_test.go):
- ✅ TestValidateConvenience - Tests validator.Validate() with valid/invalid files
- ✅ TestValidateParsedConvenience - Tests validator.ValidateParsed() with pre-parsed documents
Joiner Package (joiner/joiner_test.go):
- ✅ TestJoinConvenience - Tests joiner.Join() with various collision strategies
- ✅ TestJoinParsedConvenience - Tests joiner.JoinParsed() with pre-parsed documents
Test Coverage Statistics
- Parser: 85.1% coverage (comprehensive testing)
- Validator: 75.0% coverage (all new functions tested)
- Joiner: 73.8% coverage (all scenarios covered)
Documentation Updated
CLAUDE.md
- Added "API Design Philosophy" section
- Comprehensive documentation of both API styles
- Usage examples for convenience functions and reusable instances
- Adds a new "Test Coverage Requirements" section that:
- Mandates comprehensive test coverage for ALL exported functionality
- Provides clear guidelines for testing functions, types, constants, and variables
- Includes examples of proper test naming patterns
- Lists pre-submission requirements and anti-patterns to avoid
README.md
- Split library usage into "Simple API" and "Advanced API" sections
- Shows convenience functions first for better onboarding
- Includes examples for both patterns
Package Documentation
- Updated
doc.gofiles in all packages - Added examples showing both API styles
- Clear guidance on when to use each approach
All Quality Checks Pass
- ✅ All tests pass (100+ test cases)
- ✅ No linting errors
- ✅ Code properly formatted
- ✅ Race detection enabled
These changes have complete test coverage for all new convenience functions, ensuring that future contributors will understand the importance of testing all exported functionality.
Full Changelog: v1.3.1...v1.4.0
v1.3.1
Minor Cleanup Release
API Improvements
- Validator may now validate already parsed results
- Joiner may now join already parsed results
- The
parser.ParserResultnow includes aSourcePath stringfield for the source the document was read from.
If that source is other than from theParser.Parse(sourcePath string)method, than the method name plus.yaml
will be set instead. So ifParser.ParseReader(r io.Reader)was called, the parse result'sSourcePathwill be
ParseReader.yaml.
Makefile Improvements
- If
gotestsumis installed, it will be used in place ofgo test
Cleanup
- Removed unused (and unexported) constants (validator.go:34-43)
- Fixed the
testdatapath used for skipped unit tests, and removed theskipIfTestFileNotFoundfavoring panics in
the future - Removed the
*parser.Parserfields from the validator and joiner as it is only needed once and not all cases
require it. - Removed test cases expecting the parser field removed above
v1.3.0
Release Notes - v1.3.0
Overview
Version 1.3.0 is a major release that externalizes the entire API, making all core packages publicly available for use in external Go applications. This release transforms oastools from a CLI-only tool into a comprehensive library with full programmatic access to parsing, validation, and joining functionality.
New Features
1. Public API
All core functionality is now available as a public Go library:
- Parser Package: Parse and analyze OpenAPI specifications programmatically
- Validator Package: Validate OpenAPI specifications in your own applications
- Joiner Package: Join multiple OpenAPI specifications with full programmatic control
2. Comprehensive Package Documentation
All packages now include extensive documentation:
- Package-level doc.go: Each package has comprehensive documentation covering features, usage, security considerations, and limitations
- Example tests: All packages include
example_test.gowith runnable examples for godoc - Root package doc: New root-level
doc.goprovides an overview of the entire library
Parser Package Documentation
- Complete overview of parsing capabilities
- Security considerations (path traversal protection, cache limits)
- Performance notes and optimization tips
- Usage examples for all major features
Validator Package Documentation
- Detailed validation rules and error types
- Explanation of validation levels (errors vs warnings)
- Strict mode documentation
- Security considerations and resource limits
- Common validation errors reference
Joiner Package Documentation
- Collision strategy documentation
- Security considerations (file permissions, path validation)
- Performance optimization guidance
- Limitations and compatibility notes
3. Runnable Examples
Each package now includes comprehensive examples:
Parser Examples
- Basic parsing
- Parsing with validation
- Parsing with reference resolution
- Parsing from bytes and io.Reader
- OAS 2.0 and OAS 3.x specific examples
Validator Examples
- Basic validation
- Strict mode validation
- Suppressing warnings
- Validation error handling
- Multi-version validation
Joiner Examples
- Basic joining
- Custom collision strategies
- Accept-left and accept-right strategies
- Multiple document joining
- Warning handling
- OAS 2.0 joining
- Array merging
- Tag deduplication
- Collision error handling
4. Enhanced Documentation Files
- README.md: Updated with library usage examples and new project structure
- CLAUDE.md: Updated with public API structure and extension guidelines
- Added MIT License badge to README
Improvements
Documentation
- Added comprehensive package-level documentation for all three public packages
- Created 30+ runnable examples across all packages
- Updated README with library usage examples
- Enhanced CLAUDE.md with public API guidelines
Code Organization
- Cleaner project structure with public packages at the root level
- Removed the now-empty
internal/directory - Better separation between CLI and library code
Developer Experience
- Full godoc documentation available at pkg.go.dev
- Runnable examples that can be copied directly into projects
- Clear migration path from internal to public packages
Installation
As a Library
go get github.com/erraggy/oastools@v1.3.0As a CLI Tool
go install github.com/erraggy/oastools/cmd/oastools@v1.3.0Usage Examples
Parse an OpenAPI Specification
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/parser"
)
func main() {
p := parser.New()
result, err := p.Parse("openapi.yaml")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Version: %s\n", result.Version)
}Validate an OpenAPI Specification
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/validator"
)
func main() {
v := validator.New()
v.StrictMode = true
result, err := v.Validate("openapi.yaml")
if err != nil {
log.Fatal(err)
}
if !result.Valid {
for _, verr := range result.Errors {
fmt.Printf("%s: %s\n", verr.Path, verr.Message)
}
}
}Join Multiple OpenAPI Specifications
package main
import (
"log"
"github.com/erraggy/oastools/joiner"
)
func main() {
config := joiner.DefaultConfig()
config.PathStrategy = joiner.StrategyFailOnCollision
config.SchemaStrategy = joiner.StrategyAcceptLeft
j := joiner.New(config)
result, err := j.Join([]string{"base.yaml", "ext1.yaml", "ext2.yaml"})
if err != nil {
log.Fatal(err)
}
err = j.WriteResult(result, "merged.yaml")
if err != nil {
log.Fatal(err)
}
}Compatibility
- Go Version: Requires Go 1.24 or higher (unchanged)
- OpenAPI Versions: Supports OAS 2.0 through OAS 3.2.0 (unchanged)
- CLI Compatibility: The command-line interface remains fully backward compatible
- API Stability: The public API surface is now stable and will follow semantic versioning
Known Limitations
- HTTP(S) references in
$refare not yet supported (unchanged) - External references are restricted to base directory and subdirectories for security (unchanged)
- Cross-version joining (OAS 2.0 with OAS 3.x) is not supported (unchanged)
Security
- All security features from previous versions are maintained
- Output files continue to be created with restrictive permissions (0600)
- Path traversal protection remains in place for external references
- Resource limits (MaxCachedDocuments, schema nesting depth) unchanged
Testing
All existing tests pass with the new structure. To verify:
make checkAcknowledgments
This release makes oastools a true library, not just a CLI tool. All code continues to be generated by Claude Code using claude-4-5-sonnet.
Contributors
- Generated by Claude Code (claude-4-5-sonnet)
Full Changelog
Added
- Public API: All three packages (parser, validator, joiner) are now public
- Package documentation: Added comprehensive doc.go for parser, validator, joiner, and root package
- Example tests: Added example_test.go with 30+ examples for joiner package
- Enhanced existing example tests for parser and validator packages
- Root package documentation providing library overview
- MIT License badge in README
- Library usage section in README
Changed
- BREAKING: Moved parser package from internal/ to root level
- BREAKING: Moved validator package from internal/ to root level
- BREAKING: Moved joiner package from internal/ to root level
- Updated all import references throughout the codebase
- Updated README.md with library usage examples and new structure
- Updated CLAUDE.md with public API guidelines and extension points
- Enhanced project structure documentation
Removed
- Removed empty internal/ directory
- Removed references to internal packages in documentation
Future Plans
- HTTP(S) reference support (planned for v1.4.0)
- Additional validation rules (ongoing)
- Performance optimizations (ongoing)
- Additional examples and documentation (ongoing)
Support
- Issues: https://github.com/erraggy/oastools/issues
- Documentation: https://pkg.go.dev/github.com/erraggy/oastools
Released: 2025-11-10
v1.2.0
v1.1.0
v1.0.2
Silly, but this simply adds the MIT license text file that Google's Package Doc site requires for rendering this here:
https://pkg.go.dev/github.com/erraggy/oastools/internal/validator
v1.0.1 - Fixes Validation error URLs
This corrects the URLs output for validation errors.
v1.0.0
What's Changed
- Add Claude Code GitHub Workflow by @erraggy in #1
- feat(parser): initial implementation by @erraggy in #2
- changes from merge to join by @erraggy in #3
- feat(validator) initial and full implementation by @erraggy in #4
New Contributors
Full Changelog: https://github.com/erraggy/oastools/commits/v1.0.0