Skip to content

Commit 12db223

Browse files
feat: add overlay support, a CLI tool and inlining and bundling capabilities (#20)
1 parent 63bfb77 commit 12db223

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+11647
-12
lines changed

.golangci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ linters:
3030
- misspell
3131
- musttag
3232
- nilerr
33+
- nilnesserr
3334
- nolintlint
3435
- paralleltest
3536
- perfsprint

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
<!-- Stars Badge -->
4848
<a href="https://github.com/speakeasy-api/openapi/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/speakeasy-api/openapi.svg?style=for-the-badge&logo=github"></a>
4949
<!-- Line Break --><br/>
50+
<!-- CLI Tool Badge -->
51+
<img alt="CLI Tool" src="https://img.shields.io/badge/CLI-Available-brightgreen.svg?style=for-the-badge&logo=terminal">
52+
<!-- Go Install Badge -->
53+
<img alt="Go Install" src="https://img.shields.io/badge/go%20install-ready-00ADD8.svg?style=for-the-badge&logo=go">
54+
<!-- Line Break --><br/>
5055
<!-- Built By Speakeasy Badge -->
5156
<a href="https://speakeasy.com/"><img src="https://custom-icon-badges.demolab.com/badge/-Built%20By%20Speakeasy-212015?style=for-the-badge&logoColor=FBE331&logo=speakeasy&labelColor=545454" /></a>
5257
<!-- License Badge -->
@@ -64,6 +69,54 @@ The `arazzo` package provides an API for working with Arazzo documents including
6469

6570
The `openapi` package provides an API for working with OpenAPI documents including reading, creating, mutating, walking, validating and upgrading them. Supports both OpenAPI 3.0.x and 3.1.x specifications.
6671

72+
### [overlay](./overlay)
73+
74+
The `overlay` package provides an API for working with OpenAPI Overlays including applying overlays to specifications, comparing specifications to generate overlays, and validating overlay documents.
75+
76+
## CLI Tool
77+
78+
This repository also provides a comprehensive CLI tool for working with OpenAPI specifications, Arazzo workflows, and OpenAPI overlays.
79+
80+
### Installation
81+
82+
Install the CLI tool using Go:
83+
84+
```bash
85+
go install github.com/speakeasy-api/openapi/cmd/openapi@latest
86+
```
87+
88+
### Usage
89+
90+
The CLI provides three main command groups:
91+
92+
- **`openapi openapi`** - Commands for working with OpenAPI specifications ([documentation](./openapi/cmd/README.md))
93+
- **`openapi arazzo`** - Commands for working with Arazzo workflow documents ([documentation](./arazzo/cmd/README.md))
94+
- **`openapi overlay`** - Commands for working with OpenAPI overlays ([documentation](./overlay/cmd/README.md))
95+
96+
#### Quick Examples
97+
98+
```bash
99+
# Validate an OpenAPI specification
100+
openapi openapi validate ./spec.yaml
101+
102+
# Bundle external references into components section
103+
openapi openapi bundle ./spec.yaml ./bundled-spec.yaml
104+
105+
# Inline all references to create a self-contained document
106+
openapi openapi inline ./spec.yaml ./inlined-spec.yaml
107+
108+
# Upgrade OpenAPI spec to latest version
109+
openapi openapi upgrade ./spec.yaml ./upgraded-spec.yaml
110+
111+
# Apply an overlay to a specification
112+
openapi overlay apply --overlay overlay.yaml --schema spec.yaml
113+
114+
# Validate an Arazzo workflow document
115+
openapi arazzo validate ./workflow.arazzo.yaml
116+
```
117+
118+
For detailed usage instructions for each command group, see the individual documentation linked above.
119+
67120
## Sub Packages
68121

69122
This repository also contains a number of sub packages that are used by the main packages to provide the required functionality. The below packages may be moved into their own repository in the future, depending on future needs.
@@ -102,3 +155,4 @@ This repository is maintained by Speakeasy, but we welcome and encourage contrib
102155
All contributions, whether they're bug reports, feature requests, or code changes, help make this project better for everyone.
103156

104157
Please ensure your contributions adhere to our coding standards and include appropriate tests where applicable.
158+

arazzo/cmd/README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Arazzo Commands
2+
3+
Commands for working with Arazzo workflow documents.
4+
5+
Arazzo workflows describe sequences of API calls and their dependencies. These commands help you validate and work with Arazzo documents according to the [Arazzo Specification](https://spec.openapis.org/arazzo/v1.0.0).
6+
7+
## Available Commands
8+
9+
### `validate`
10+
11+
Validate an Arazzo workflow document for compliance with the Arazzo Specification.
12+
13+
```bash
14+
# Validate an Arazzo workflow file
15+
openapi arazzo validate ./workflow.arazzo.yaml
16+
17+
# Validate with verbose output
18+
openapi arazzo validate -v ./workflow.arazzo.yaml
19+
```
20+
21+
This command checks for:
22+
23+
- Structural validity according to the Arazzo Specification
24+
- Workflow step definitions and dependencies
25+
- Parameter and expression syntax
26+
- Source description references and validity
27+
- Step success and failure action definitions
28+
29+
## What is Arazzo?
30+
31+
Arazzo is a specification for describing API workflows - sequences of API calls where the output of one call can be used as input to subsequent calls. It's designed to work alongside OpenAPI specifications to describe complex API interactions.
32+
33+
### Example Arazzo Document
34+
35+
```yaml
36+
arazzo: 1.0.0
37+
info:
38+
title: User Management Workflow
39+
version: 1.0.0
40+
41+
sourceDescriptions:
42+
- name: userAPI
43+
url: ./user-api.yaml
44+
type: openapi
45+
46+
workflows:
47+
- workflowId: createUserWorkflow
48+
summary: Create a new user and fetch their profile
49+
steps:
50+
- stepId: createUser
51+
description: Create a new user
52+
operationId: userAPI.createUser
53+
requestBody:
54+
contentType: application/json
55+
payload:
56+
name: $inputs.userName
57+
email: $inputs.userEmail
58+
successCriteria:
59+
- condition: $statusCode == 201
60+
outputs:
61+
userId: $response.body.id
62+
63+
- stepId: getUserProfile
64+
description: Fetch the created user's profile
65+
operationId: userAPI.getUser
66+
dependsOn: createUser
67+
parameters:
68+
- name: userId
69+
in: path
70+
value: $steps.createUser.outputs.userId
71+
successCriteria:
72+
- condition: $statusCode == 200
73+
```
74+
75+
## Common Use Cases
76+
77+
**API Testing Workflows**: Test user registration and login flows
78+
**Data Processing Pipelines**: Process data through multiple API endpoints
79+
**Integration Testing**: Test integration between multiple services
80+
**Automated Workflows**: Chain API calls for business process automation
81+
82+
## Common Options
83+
84+
All commands support these common options:
85+
86+
- `-h, --help`: Show help for the command
87+
- `-v, --verbose`: Enable verbose output (global flag)
88+
89+
## Output Formats
90+
91+
All commands work with both YAML and JSON input files. Validation results provide clear, structured feedback with specific error locations and descriptions.

arazzo/cmd/root.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package cmd
2+
3+
import "github.com/spf13/cobra"
4+
5+
// Apply adds Arazzo commands to the provided root command
6+
func Apply(rootCmd *cobra.Command) {
7+
rootCmd.AddCommand(validateCmd)
8+
}

arazzo/cmd/validate.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"os"
8+
"path/filepath"
9+
10+
"github.com/speakeasy-api/openapi/arazzo"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
var validateCmd = &cobra.Command{
15+
Use: "validate <file>",
16+
Short: "Validate an Arazzo workflow document",
17+
Long: `Validate an Arazzo workflow document for compliance with the Arazzo Specification.
18+
19+
This command will parse and validate the provided Arazzo document, checking for:
20+
- Structural validity according to the Arazzo Specification
21+
- Required fields and proper data types
22+
- Workflow step dependencies and consistency
23+
- Runtime expression validation
24+
- Source description references`,
25+
Args: cobra.ExactArgs(1),
26+
Run: runValidate,
27+
}
28+
29+
func runValidate(cmd *cobra.Command, args []string) {
30+
ctx := cmd.Context()
31+
file := args[0]
32+
33+
if err := validateArazzo(ctx, file); err != nil {
34+
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
35+
os.Exit(1)
36+
}
37+
}
38+
39+
func validateArazzo(ctx context.Context, file string) error {
40+
cleanFile := filepath.Clean(file)
41+
fmt.Printf("Validating Arazzo document: %s\n", cleanFile)
42+
43+
f, err := os.Open(cleanFile)
44+
if err != nil {
45+
return fmt.Errorf("failed to open file: %w", err)
46+
}
47+
defer f.Close()
48+
49+
_, validationErrors, err := arazzo.Unmarshal(ctx, f)
50+
if err != nil {
51+
return fmt.Errorf("failed to unmarshal file: %w", err)
52+
}
53+
54+
if len(validationErrors) == 0 {
55+
fmt.Printf("✅ Arazzo document is valid - 0 errors\n")
56+
return nil
57+
}
58+
59+
fmt.Printf("❌ Arazzo document is invalid - %d errors:\n\n", len(validationErrors))
60+
61+
for i, validationErr := range validationErrors {
62+
fmt.Printf("%d. %s\n", i+1, validationErr.Error())
63+
}
64+
65+
return errors.New("arazzo document validation failed")
66+
}
67+
68+
// GetValidateCommand returns the validate command for external use
69+
func GetValidateCommand() *cobra.Command {
70+
return validateCmd
71+
}

cmd/openapi/main.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
arazzoCmd "github.com/speakeasy-api/openapi/arazzo/cmd"
8+
openapiCmd "github.com/speakeasy-api/openapi/openapi/cmd"
9+
overlayCmd "github.com/speakeasy-api/openapi/overlay/cmd"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
var (
14+
version = "dev"
15+
)
16+
17+
var rootCmd = &cobra.Command{
18+
Use: "openapi",
19+
Short: "OpenAPI toolkit for working with OpenAPI specifications, overlays, and Arazzo workflows",
20+
Long: `A comprehensive toolkit for working with OpenAPI specifications and Arazzo workflows.
21+
22+
This CLI provides tools for:
23+
24+
OpenAPI Specifications:
25+
- Validate OpenAPI specification documents for compliance
26+
- Upgrade OpenAPI specs to the latest supported version (3.1.1)
27+
- Inline all references to create self-contained documents
28+
- Bundle external references into components section while preserving structure
29+
30+
Arazzo Workflows:
31+
- Validate Arazzo workflow documents for compliance
32+
33+
OpenAPI Overlays:
34+
- Apply overlays to modify OpenAPI specifications
35+
- Compare two specifications and generate overlays
36+
- Validate overlay files for correctness
37+
38+
Each command group provides specialized functionality for working with different
39+
aspects of the OpenAPI ecosystem, from basic validation to advanced document
40+
transformation and workflow management.`,
41+
Version: version,
42+
}
43+
44+
var overlayCmds = &cobra.Command{
45+
Use: "overlay",
46+
Short: "Work with OpenAPI Overlays",
47+
Long: `Commands for working with OpenAPI Overlays.
48+
49+
OpenAPI Overlays provide a way to modify OpenAPI and Arazzo specifications
50+
without directly editing the original files. This is useful for:
51+
- Adding vendor-specific extensions
52+
- Modifying specifications for different environments
53+
- Applying transformations to third-party APIs`,
54+
}
55+
56+
var openapiCmds = &cobra.Command{
57+
Use: "openapi",
58+
Short: "Work with OpenAPI specifications",
59+
Long: `Commands for working with OpenAPI specifications.
60+
61+
OpenAPI specifications define REST APIs in a standard format.
62+
These commands help you validate and work with OpenAPI documents.`,
63+
}
64+
65+
var arazzoCmds = &cobra.Command{
66+
Use: "arazzo",
67+
Short: "Work with Arazzo workflow documents",
68+
Long: `Commands for working with Arazzo workflow documents.
69+
70+
Arazzo workflows describe sequences of API calls and their dependencies.
71+
These commands help you validate and work with Arazzo documents.`,
72+
}
73+
74+
func init() {
75+
// Set version template
76+
rootCmd.SetVersionTemplate(`{{printf "%s" .Version}}`)
77+
78+
// Add OpenAPI spec validation command
79+
openapiCmd.Apply(openapiCmds)
80+
81+
// Add Arazzo workflow validation command
82+
arazzoCmd.Apply(arazzoCmds)
83+
84+
// Add overlay subcommands using the Apply function
85+
overlayCmd.Apply(overlayCmds)
86+
87+
// Add all commands to root
88+
rootCmd.AddCommand(openapiCmds)
89+
rootCmd.AddCommand(arazzoCmds)
90+
rootCmd.AddCommand(overlayCmds)
91+
92+
// Global flags
93+
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "verbose output")
94+
}
95+
96+
func main() {
97+
if err := rootCmd.Execute(); err != nil {
98+
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
99+
os.Exit(1)
100+
}
101+
}

cmd/update-examples/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ func main() {
3838
func updateExamples() error {
3939
fmt.Println("🔄 Updating examples in README files...")
4040

41-
// Process both packages
42-
packages := []string{"openapi", "arazzo"}
41+
// Process all packages
42+
packages := []string{"openapi", "arazzo", "overlay"}
4343

4444
for _, pkg := range packages {
4545
if err := processPackage(pkg); err != nil {

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@ go 1.24.3
55
require (
66
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
77
github.com/speakeasy-api/jsonpath v0.6.2
8+
github.com/spf13/cobra v1.7.0
89
github.com/stretchr/testify v1.10.0
10+
github.com/vmware-labs/yaml-jsonpath v0.3.2
911
golang.org/x/sync v0.16.0
1012
golang.org/x/text v0.28.0
1113
gopkg.in/yaml.v3 v3.0.1
1214
)
1315

1416
require (
1517
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
18+
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 // indirect
19+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
1620
github.com/kr/text v0.2.0 // indirect
1721
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
22+
github.com/spf13/pflag v1.0.5 // indirect
1823
)

0 commit comments

Comments
 (0)