Skip to content

Commit 361dde0

Browse files
feat(cli): add overlay upgrade command for upgrading to Overlay 1.1.0 (#131)
1 parent 0dee2a9 commit 361dde0

4 files changed

Lines changed: 164 additions & 3 deletions

File tree

cmd/openapi/commands/overlay/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ OpenAPI Overlays provide a way to modify OpenAPI and Arazzo specifications witho
1111
- [`apply`](#apply)
1212
- [`validate`](#validate)
1313
- [`compare`](#compare)
14+
- [`upgrade`](#upgrade)
1415
- [What are OpenAPI Overlays?](#what-are-openapi-overlays)
1516
- [Example Overlay](#example-overlay)
1617
- [Common Use Cases](#common-use-cases)
@@ -86,6 +87,40 @@ Features:
8687
- Provides diagnostic output showing detected changes
8788
- Creates overlay files that can recreate the transformation
8889

90+
### `upgrade`
91+
92+
Upgrade an Overlay document to the latest supported version (1.1.0).
93+
94+
```bash
95+
# Preview upgrade (output to stdout)
96+
openapi overlay upgrade my-overlay.yaml
97+
98+
# Upgrade and save to new file
99+
openapi overlay upgrade my-overlay.yaml upgraded-overlay.yaml
100+
101+
# Upgrade in-place
102+
openapi overlay upgrade -w my-overlay.yaml
103+
```
104+
105+
Features:
106+
107+
- Updates the Overlay version field from 1.0.0 to 1.1.0
108+
- Enables RFC 9535 JSONPath as the default implementation
109+
- Clears redundant `x-speakeasy-jsonpath: rfc9535` (now default in 1.1.0)
110+
- All existing actions remain valid and functional
111+
- Validates overlay before and after upgrade
112+
113+
Version Differences:
114+
115+
| Version | Default JSONPath | Setting |
116+
| ------- | ---------------- | -------------------------------------------- |
117+
| 1.0.0 | Legacy yamlpath | `x-speakeasy-jsonpath: rfc9535` for RFC 9535 |
118+
| 1.1.0+ | RFC 9535 | `x-speakeasy-jsonpath: legacy` for legacy |
119+
120+
Options:
121+
122+
- `-w, --write`: Write result in-place to input file
123+
89124
## What are OpenAPI Overlays?
90125

91126
OpenAPI Overlays are documents that describe modifications to be applied to OpenAPI specifications. They allow you to:

cmd/openapi/commands/overlay/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ import "github.com/spf13/cobra"
55
func Apply(rootCmd *cobra.Command) {
66
rootCmd.AddCommand(applyCmd)
77
rootCmd.AddCommand(compareCmd)
8+
rootCmd.AddCommand(upgradeCmd)
89
rootCmd.AddCommand(validateCmd)
910
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package overlay
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/speakeasy-api/openapi/overlay"
8+
"github.com/speakeasy-api/openapi/overlay/loader"
9+
"github.com/spf13/cobra"
10+
"gopkg.in/yaml.v3"
11+
)
12+
13+
var upgradeCmd = &cobra.Command{
14+
Use: "upgrade <overlay-file> [output-file]",
15+
Short: "Upgrade an Overlay document to the latest supported version (1.1.0)",
16+
Long: `Upgrade an Overlay specification document to the latest supported version (1.1.0).
17+
18+
The upgrade process includes:
19+
- Updating the Overlay version field from 1.0.0 to 1.1.0
20+
- Enabling RFC 9535 JSONPath as the default implementation
21+
- Clearing redundant x-speakeasy-jsonpath: rfc9535 (now default in 1.1.0)
22+
- All existing actions remain valid and functional
23+
- Support for new 1.1.0 features like copy actions and info description
24+
25+
Version Differences:
26+
1.0.0: Legacy JSONPath by default, RFC 9535 opt-in with x-speakeasy-jsonpath: rfc9535
27+
1.1.0: RFC 9535 JSONPath by default, legacy opt-out with x-speakeasy-jsonpath: legacy
28+
29+
Output options:
30+
- No output file specified: writes to stdout (pipe-friendly)
31+
- Output file specified: writes to the specified file
32+
- --write flag: writes in-place to the input file`,
33+
Example: ` # Preview upgrade (output to stdout)
34+
openapi overlay upgrade my-overlay.yaml
35+
36+
# Upgrade and save to new file
37+
openapi overlay upgrade my-overlay.yaml upgraded-overlay.yaml
38+
39+
# Upgrade in-place
40+
openapi overlay upgrade -w my-overlay.yaml`,
41+
Args: cobra.RangeArgs(1, 2),
42+
Run: runOverlayUpgrade,
43+
}
44+
45+
var overlayWriteInPlace bool
46+
47+
func init() {
48+
upgradeCmd.Flags().BoolVarP(&overlayWriteInPlace, "write", "w", false,
49+
"write result in-place to input file")
50+
}
51+
52+
func runOverlayUpgrade(cmd *cobra.Command, args []string) {
53+
ctx := cmd.Context()
54+
inputFile := args[0]
55+
56+
var outputFile string
57+
if len(args) > 1 {
58+
outputFile = args[1]
59+
}
60+
61+
// Load the overlay
62+
o, err := loader.LoadOverlay(inputFile)
63+
if err != nil {
64+
Dief("Failed to load overlay: %v", err)
65+
}
66+
67+
// Validate the overlay before upgrade
68+
if err := o.Validate(); err != nil {
69+
Dief("Overlay validation failed: %v", err)
70+
}
71+
72+
originalVersion := o.Version
73+
74+
// Perform the upgrade
75+
upgraded, err := overlay.Upgrade(ctx, o)
76+
if err != nil {
77+
Dief("Failed to upgrade overlay: %v", err)
78+
}
79+
80+
// Print status
81+
if !upgraded {
82+
fmt.Fprintf(os.Stderr, "No upgrade needed - overlay is already at version %s\n", originalVersion)
83+
} else {
84+
fmt.Fprintf(os.Stderr, "Successfully upgraded overlay from %s to %s\n", originalVersion, o.Version)
85+
}
86+
87+
// Validate the upgraded overlay
88+
if err := o.Validate(); err != nil {
89+
Dief("Upgraded overlay failed validation: %v", err)
90+
}
91+
92+
// Serialize output
93+
output, err := o.ToString()
94+
if err != nil {
95+
Dief("Failed to serialize overlay: %v", err)
96+
}
97+
98+
// Determine output destination
99+
switch {
100+
case overlayWriteInPlace:
101+
if err := os.WriteFile(inputFile, []byte(output), 0644); err != nil {
102+
Dief("Failed to write to input file: %v", err)
103+
}
104+
fmt.Fprintf(os.Stderr, "Wrote upgraded overlay to %s\n", inputFile)
105+
case outputFile != "":
106+
if err := os.WriteFile(outputFile, []byte(output), 0644); err != nil {
107+
Dief("Failed to write to output file: %v", err)
108+
}
109+
fmt.Fprintf(os.Stderr, "Wrote upgraded overlay to %s\n", outputFile)
110+
default:
111+
// Write to stdout
112+
var node yaml.Node
113+
if err := yaml.Unmarshal([]byte(output), &node); err != nil {
114+
Dief("Failed to parse output: %v", err)
115+
}
116+
encoder := yaml.NewEncoder(os.Stdout)
117+
encoder.SetIndent(2)
118+
if err := encoder.Encode(&node); err != nil {
119+
Dief("Failed to write to stdout: %v", err)
120+
}
121+
}
122+
}

overlay/README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<img width="200px" alt="OpenAPI" src="https://github.com/user-attachments/assets/b9fa9c14-1c6f-4d8b-910f-15e5f962bab6">
44
</p>
55
<h1 align="center"><b>OpenAPI Overlay</b></h1>
6-
<p align="center">An implementation of the <a href="https://github.com/OAI/Overlay-Specification/blob/3f398c6/versions/1.0.0.md">OpenAPI Overlay Specification</a> for applying modifications to OpenAPI documents
6+
<p align="center">An implementation of the <a href="https://github.com/OAI/Overlay-Specification/blob/main/versions/1.1.0.md">OpenAPI Overlay Specification 1.1.0</a> for applying modifications to OpenAPI documents
77
</p>
88
<p align="center">
99
<!-- Overlay Reference badge -->
@@ -25,16 +25,19 @@
2525
2626
## Features
2727

28-
- **OpenAPI Overlay Specification Compliance**: Full implementation of the [OpenAPI Overlay Specification](https://github.com/OAI/Overlay-Specification/blob/3f398c6/versions/1.0.0.md) (2023-10-12) and [version 1.1.0](https://github.com/OAI/Overlay-Specification/blob/e2c3cec/versions/1.1.0-dev.md)
28+
- **OpenAPI Overlay Specification Compliance**: Full implementation of the [OpenAPI Overlay Specification 1.0.0](https://github.com/OAI/Overlay-Specification/blob/main/versions/1.0.0.md) and [1.1.0](https://github.com/OAI/Overlay-Specification/blob/main/versions/1.1.0.md)
2929
- **JSONPath Target Selection**: Uses JSONPath expressions to select nodes for modification
30+
- **RFC 9535 JSONPath**: Version 1.1.0 uses RFC 9535-compliant JSONPath by default for improved interoperability
3031
- **Remove, Update, and Copy Actions**: Support for remove actions (pruning nodes), update actions (merging values), and copy actions (duplicating or moving nodes)
32+
- **Upgrade Support**: Built-in `Upgrade()` function to upgrade overlay documents from 1.0.0 to 1.1.0
33+
- **Info Description Field**: Version 1.1.0 supports a `description` field in the overlay info section
3134
- **Flexible Input/Output**: Works with both YAML and JSON formats
3235
- **Batch Operations**: Apply multiple modifications to large numbers of nodes in a single operation
3336
- **YAML v1.2 Support**: Uses [gopkg.in/yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) for YAML v1.2 parsing (superset of JSON)
3437

3538
## About OpenAPI Overlays
3639

37-
This specification defines a means of editing an OpenAPI Specification file by applying a list of actions. Each action is either a remove action that prunes nodes or an update that merges a value into nodes. The nodes impacted are selected by a target expression which uses JSONPath. This implementation also supports [version 1.1.0](https://github.com/OAI/Overlay-Specification/blob/e2c3cec/versions/1.1.0-dev.md) which adds a `copy` action for duplicating or moving nodes within the document.
40+
This specification defines a means of editing an OpenAPI Specification file by applying a list of actions. Each action is either a remove action that prunes nodes or an update that merges a value into nodes. The nodes impacted are selected by a target expression which uses JSONPath. This implementation supports [version 1.1.0](https://github.com/OAI/Overlay-Specification/blob/main/versions/1.1.0.md) which adds a `copy` action for duplicating or moving nodes within the document, RFC 9535 JSONPath as the default, and a description field in the info section.
3841

3942
The specification itself says very little about the input file to be modified or the output file. The presumed intention is that the input and output be an OpenAPI Specification, but that is not required.
4043

0 commit comments

Comments
 (0)