Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ linters:
- misspell
- musttag
- nilerr
- nilnesserr
- nolintlint
- paralleltest
- perfsprint
Expand Down
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
<!-- Stars Badge -->
<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>
<!-- Line Break --><br/>
<!-- CLI Tool Badge -->
<img alt="CLI Tool" src="https://img.shields.io/badge/CLI-Available-brightgreen.svg?style=for-the-badge&logo=terminal">
<!-- Go Install Badge -->
<img alt="Go Install" src="https://img.shields.io/badge/go%20install-ready-00ADD8.svg?style=for-the-badge&logo=go">
<!-- Line Break --><br/>
<!-- Built By Speakeasy Badge -->
<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>
<!-- License Badge -->
Expand All @@ -64,6 +69,54 @@ The `arazzo` package provides an API for working with Arazzo documents including

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.

### [overlay](./overlay)

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.

## CLI Tool

This repository also provides a comprehensive CLI tool for working with OpenAPI specifications, Arazzo workflows, and OpenAPI overlays.

### Installation

Install the CLI tool using Go:

```bash
go install github.com/speakeasy-api/openapi/cmd/openapi@latest
```

### Usage

The CLI provides three main command groups:

- **`openapi openapi`** - Commands for working with OpenAPI specifications ([documentation](./openapi/cmd/README.md))
- **`openapi arazzo`** - Commands for working with Arazzo workflow documents ([documentation](./arazzo/cmd/README.md))
- **`openapi overlay`** - Commands for working with OpenAPI overlays ([documentation](./overlay/cmd/README.md))

#### Quick Examples

```bash
# Validate an OpenAPI specification
openapi openapi validate ./spec.yaml

# Bundle external references into components section
openapi openapi bundle ./spec.yaml ./bundled-spec.yaml

# Inline all references to create a self-contained document
openapi openapi inline ./spec.yaml ./inlined-spec.yaml

# Upgrade OpenAPI spec to latest version
openapi openapi upgrade ./spec.yaml ./upgraded-spec.yaml

# Apply an overlay to a specification
openapi overlay apply --overlay overlay.yaml --schema spec.yaml

# Validate an Arazzo workflow document
openapi arazzo validate ./workflow.arazzo.yaml
```

For detailed usage instructions for each command group, see the individual documentation linked above.

## Sub Packages

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.
Expand Down Expand Up @@ -102,3 +155,4 @@ This repository is maintained by Speakeasy, but we welcome and encourage contrib
All contributions, whether they're bug reports, feature requests, or code changes, help make this project better for everyone.

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

91 changes: 91 additions & 0 deletions arazzo/cmd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Arazzo Commands

Commands for working with Arazzo workflow documents.

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).

## Available Commands

### `validate`

Validate an Arazzo workflow document for compliance with the Arazzo Specification.

```bash
# Validate an Arazzo workflow file
openapi arazzo validate ./workflow.arazzo.yaml

# Validate with verbose output
openapi arazzo validate -v ./workflow.arazzo.yaml
```

This command checks for:

- Structural validity according to the Arazzo Specification
- Workflow step definitions and dependencies
- Parameter and expression syntax
- Source description references and validity
- Step success and failure action definitions

## What is Arazzo?

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.

### Example Arazzo Document

```yaml
arazzo: 1.0.0
info:
title: User Management Workflow
version: 1.0.0

sourceDescriptions:
- name: userAPI
url: ./user-api.yaml
type: openapi

workflows:
- workflowId: createUserWorkflow
summary: Create a new user and fetch their profile
steps:
- stepId: createUser
description: Create a new user
operationId: userAPI.createUser
requestBody:
contentType: application/json
payload:
name: $inputs.userName
email: $inputs.userEmail
successCriteria:
- condition: $statusCode == 201
outputs:
userId: $response.body.id

- stepId: getUserProfile
description: Fetch the created user's profile
operationId: userAPI.getUser
dependsOn: createUser
parameters:
- name: userId
in: path
value: $steps.createUser.outputs.userId
successCriteria:
- condition: $statusCode == 200
```

## Common Use Cases

**API Testing Workflows**: Test user registration and login flows
**Data Processing Pipelines**: Process data through multiple API endpoints
**Integration Testing**: Test integration between multiple services
**Automated Workflows**: Chain API calls for business process automation

## Common Options

All commands support these common options:

- `-h, --help`: Show help for the command
- `-v, --verbose`: Enable verbose output (global flag)

## Output Formats

All commands work with both YAML and JSON input files. Validation results provide clear, structured feedback with specific error locations and descriptions.
8 changes: 8 additions & 0 deletions arazzo/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cmd

import "github.com/spf13/cobra"

// Apply adds Arazzo commands to the provided root command
func Apply(rootCmd *cobra.Command) {
rootCmd.AddCommand(validateCmd)
}
71 changes: 71 additions & 0 deletions arazzo/cmd/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package cmd

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"

"github.com/speakeasy-api/openapi/arazzo"
"github.com/spf13/cobra"
)

var validateCmd = &cobra.Command{
Use: "validate <file>",
Short: "Validate an Arazzo workflow document",
Long: `Validate an Arazzo workflow document for compliance with the Arazzo Specification.

This command will parse and validate the provided Arazzo document, checking for:
- Structural validity according to the Arazzo Specification
- Required fields and proper data types
- Workflow step dependencies and consistency
- Runtime expression validation
- Source description references`,
Args: cobra.ExactArgs(1),
Run: runValidate,
}

func runValidate(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
file := args[0]

if err := validateArazzo(ctx, file); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}

func validateArazzo(ctx context.Context, file string) error {
cleanFile := filepath.Clean(file)
fmt.Printf("Validating Arazzo document: %s\n", cleanFile)

f, err := os.Open(cleanFile)
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}
defer f.Close()

_, validationErrors, err := arazzo.Unmarshal(ctx, f)
if err != nil {
return fmt.Errorf("failed to unmarshal file: %w", err)
}

if len(validationErrors) == 0 {
fmt.Printf("βœ… Arazzo document is valid - 0 errors\n")
return nil
}

fmt.Printf("❌ Arazzo document is invalid - %d errors:\n\n", len(validationErrors))

for i, validationErr := range validationErrors {
fmt.Printf("%d. %s\n", i+1, validationErr.Error())
}

return errors.New("arazzo document validation failed")
}

// GetValidateCommand returns the validate command for external use
func GetValidateCommand() *cobra.Command {
return validateCmd
}
101 changes: 101 additions & 0 deletions cmd/openapi/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package main

import (
"fmt"
"os"

arazzoCmd "github.com/speakeasy-api/openapi/arazzo/cmd"
openapiCmd "github.com/speakeasy-api/openapi/openapi/cmd"
overlayCmd "github.com/speakeasy-api/openapi/overlay/cmd"
"github.com/spf13/cobra"
)

var (
version = "dev"
)

var rootCmd = &cobra.Command{
Use: "openapi",
Short: "OpenAPI toolkit for working with OpenAPI specifications, overlays, and Arazzo workflows",
Long: `A comprehensive toolkit for working with OpenAPI specifications and Arazzo workflows.

This CLI provides tools for:

OpenAPI Specifications:
- Validate OpenAPI specification documents for compliance
- Upgrade OpenAPI specs to the latest supported version (3.1.1)
- Inline all references to create self-contained documents
- Bundle external references into components section while preserving structure

Arazzo Workflows:
- Validate Arazzo workflow documents for compliance

OpenAPI Overlays:
- Apply overlays to modify OpenAPI specifications
- Compare two specifications and generate overlays
- Validate overlay files for correctness

Each command group provides specialized functionality for working with different
aspects of the OpenAPI ecosystem, from basic validation to advanced document
transformation and workflow management.`,
Version: version,
}

var overlayCmds = &cobra.Command{
Use: "overlay",
Short: "Work with OpenAPI Overlays",
Long: `Commands for working with OpenAPI Overlays.

OpenAPI Overlays provide a way to modify OpenAPI and Arazzo specifications
without directly editing the original files. This is useful for:
- Adding vendor-specific extensions
- Modifying specifications for different environments
- Applying transformations to third-party APIs`,
}

var openapiCmds = &cobra.Command{
Use: "openapi",
Short: "Work with OpenAPI specifications",
Long: `Commands for working with OpenAPI specifications.

OpenAPI specifications define REST APIs in a standard format.
These commands help you validate and work with OpenAPI documents.`,
}

var arazzoCmds = &cobra.Command{
Use: "arazzo",
Short: "Work with Arazzo workflow documents",
Long: `Commands for working with Arazzo workflow documents.

Arazzo workflows describe sequences of API calls and their dependencies.
These commands help you validate and work with Arazzo documents.`,
}

func init() {
// Set version template
rootCmd.SetVersionTemplate(`{{printf "%s" .Version}}`)

// Add OpenAPI spec validation command
openapiCmd.Apply(openapiCmds)

// Add Arazzo workflow validation command
arazzoCmd.Apply(arazzoCmds)

// Add overlay subcommands using the Apply function
overlayCmd.Apply(overlayCmds)

// Add all commands to root
rootCmd.AddCommand(openapiCmds)
rootCmd.AddCommand(arazzoCmds)
rootCmd.AddCommand(overlayCmds)

// Global flags
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "verbose output")
}

func main() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
4 changes: 2 additions & 2 deletions cmd/update-examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ func main() {
func updateExamples() error {
fmt.Println("πŸ”„ Updating examples in README files...")

// Process both packages
packages := []string{"openapi", "arazzo"}
// Process all packages
packages := []string{"openapi", "arazzo", "overlay"}

for _, pkg := range packages {
if err := processPackage(pkg); err != nil {
Expand Down
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ go 1.24.3
require (
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
github.com/speakeasy-api/jsonpath v0.6.2
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.10.0
github.com/vmware-labs/yaml-jsonpath v0.3.2
golang.org/x/sync v0.16.0
golang.org/x/text v0.28.0
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
Loading
Loading