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
68 changes: 66 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
with:
subcommand: convert
file: tests/fixtures/valid-v3_0.yaml
to: v3_2
to: v3.2
output-file: converted.yaml

- name: assert converted output looks like v3.2
Expand All @@ -83,7 +83,7 @@ jobs:
with:
subcommand: convert
file: tests/fixtures/valid-v3_0.yaml
to: v3_2
to: v3.2
merge: tests/fixtures/overlay-v3_0.yaml
merge-options: deep-merge-object-schemas
collapse: 'true'
Expand All @@ -96,6 +96,54 @@ jobs:
grep -q '/pong:' merged.yaml || { echo "merged.yaml missing /pong path from overlay"; cat merged.yaml; exit 1; }
echo "OK: merge combined base and overlay paths"

- name: overlay validate
uses: ./
with:
subcommand: overlay validate
file: tests/fixtures/overlay-doc-v1_0.yaml

- name: overlay apply to spec
uses: ./
with:
subcommand: overlay apply
file: tests/fixtures/valid-v3_0.yaml
overlay: tests/fixtures/overlay-doc-v1_0.yaml
output-file: overlaid.yaml

- name: assert overlay injected the description
run: |
test -s overlaid.yaml || { echo "::error::overlaid.yaml is empty or missing"; exit 1; }
grep -q 'Added by an overlay document' overlaid.yaml || {
echo "::error::overlaid.yaml missing the overlay-injected description"
cat overlaid.yaml
exit 1
}
echo "OK: overlay apply injected the description"

- name: convert with apply overlay
uses: ./
with:
subcommand: convert
file: tests/fixtures/valid-v3_0.yaml
to: v3.2
apply: tests/fixtures/overlay-doc-v1_0.yaml
output-file: converted-overlaid.yaml

- name: assert convert --apply output is v3.2 with the description
run: |
test -s converted-overlaid.yaml || { echo "::error::converted-overlaid.yaml is empty or missing"; exit 1; }
grep -q '^openapi: *3\.2' converted-overlaid.yaml || {
echo "::error::converted-overlaid.yaml does not declare openapi 3.2"
cat converted-overlaid.yaml
exit 1
}
grep -q 'Added by an overlay document' converted-overlaid.yaml || {
echo "::error::converted-overlaid.yaml missing the overlay-injected description"
cat converted-overlaid.yaml
exit 1
}
echo "OK: convert --apply produced v3.2 with the overlay description"

- name: convert without 'to' must fail
id: convert-noto
continue-on-error: true
Expand All @@ -111,3 +159,19 @@ jobs:
exit 1
fi
echo "OK: convert correctly rejected missing 'to' input"

- name: overlay apply without 'overlay' must fail
id: overlay-noov
continue-on-error: true
uses: ./
with:
subcommand: overlay apply
file: tests/fixtures/valid-v3_0.yaml

- name: assert overlay apply without 'overlay' failed
run: |
if [[ "${{ steps.overlay-noov.outcome }}" != "failure" ]]; then
echo "Expected overlay apply without 'overlay' to fail, got outcome=${{ steps.overlay-noov.outcome }}"
exit 1
fi
echo "OK: overlay apply correctly rejected missing 'overlay' input"
112 changes: 93 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# roas-action

GitHub Action that runs [`roas`](https://github.com/sv-tools/roas) to validate or
convert OpenAPI specifications (Swagger 2.0, OpenAPI 3.0.x / 3.1.x / 3.2.x).
convert OpenAPI specifications (Swagger 2.0, OpenAPI 3.0.x / 3.1.x / 3.2.x) and to
validate, convert, or apply [OpenAPI Overlay](https://spec.openapis.org/overlay/latest.html)
documents (Overlay 1.0 / 1.1).

The action is Docker-based and wraps the official
[`ghcr.io/sv-tools/roas`](https://github.com/sv-tools/roas/pkgs/container/roas)
Expand Down Expand Up @@ -40,7 +42,7 @@ Upconvert a spec to OpenAPI 3.2 and write the result next to the source:
output-file: openapi.v3_2.yaml
```

Layer overlay specs on top of a base via `merge`:
Layer additional specs on top of a base via `merge`:

```yaml
- uses: sv-tools/roas-action@v1
Expand All @@ -54,27 +56,85 @@ Layer overlay specs on top of a base via `merge`:
output-file: openapi.merged.yaml
```

Apply OpenAPI Overlay documents while converting (`apply` runs last in the
pipeline: convert → merge → apply → collapse):

```yaml
- uses: sv-tools/roas-action@v1
with:
subcommand: convert
file: openapi.yaml
to: v3.2
apply: |
overlays/add-servers.overlay.yaml
overlays/redact-internal.overlay.yaml
output-file: openapi.overlaid.yaml
```

### Overlay documents

Validate an OpenAPI Overlay document:

```yaml
- uses: sv-tools/roas-action@v1
with:
subcommand: overlay validate
file: overlays/add-servers.overlay.yaml
```

Upconvert an Overlay 1.0 document to Overlay 1.1:

```yaml
- uses: sv-tools/roas-action@v1
with:
subcommand: overlay convert
file: overlays/add-servers.overlay.yaml
to: v1.1
output-file: add-servers.v1_1.overlay.yaml
```

Apply one or more overlays to a target spec (`file` is the spec, `overlay`
lists the overlays, applied in order):

```yaml
- uses: sv-tools/roas-action@v1
with:
subcommand: overlay apply
file: openapi.yaml
overlay: |
overlays/add-servers.overlay.yaml
overlays/redact-internal.overlay.yaml
output-file: openapi.overlaid.yaml
```

## Inputs

| Name | Required | Default | Applies to | Description |
|-----------------|----------|------------|------------|-----------------------------------------------------------------------------------------------|
| `subcommand` | no | `validate` | both | `validate` or `convert`. |
| `file` | yes | — | both | Path to the OpenAPI spec (JSON or YAML), relative to the repo root. |
| `from` | no | — | both | Force the input spec version. One of `v2`, `v3.0`, `v3.1`, `v3.2`. |
| `to` | yes\* | — | convert | Target version for `convert`. Required when `subcommand: convert`. |
| `merge` | no | — | convert | Newline-separated list of overlay specs to merge on top of the base after version conversion. |
| `merge-options` | no | — | convert | Whitespace-separated merge options (requires `merge`). See [merge options](#merge-options). |
| `collapse` | no | `false` | convert | Lift inline components into the root bag and replace call sites with `$ref`s. |
| `format` | no | auto | both | Force input format: `json` or `yaml`. By default inferred from the file extension. |
| `load` | no | — | both\*\* | Whitespace-separated `$ref` loaders: `file`, `http`. On `convert` requires `collapse: true`. |
| `ignore` | no | — | validate | Whitespace-separated validation checks to skip (see [check list](#validation-checks)). |
| `print` | no | `false` | validate | If `true`, echo the parsed spec on stdout (diagnostics stay on stderr). |
| `output-format` | no | match in | convert | Force output format: `json` or `yaml`. |
| `output-file` | no | stdout | convert | Write the converted spec to this path. If unset, output streams to the action log. |
"Applies to" abbreviations: **V** = `validate`, **C** = `convert`,
**OV** = `overlay validate`, **OC** = `overlay convert`, **OA** = `overlay apply`.

| Name | Required | Default | Applies to | Description |
|-----------------|----------|------------|----------------|----------------------------------------------------------------------------------------------------|
| `subcommand` | no | `validate` | — | `validate`, `convert`, `overlay validate`, `overlay convert`, or `overlay apply`. |
| `file` | yes | — | all | Positional input: the spec (V, C, OA) or the Overlay document (OV, OC), relative to the repo root. |
| `from` | no | — | V, C | Force the input spec version. One of `v2`, `v3.0`, `v3.1`, `v3.2`. |
| `to` | yes\* | — | C, OC | Target version. For C: `v3.0`/`v3.1`/`v3.2` etc. For OC: `v1.0`/`v1.1`. Required for both. |
| `merge` | no | — | C | Newline-separated list of specs to merge on top of the base after version conversion. |
| `merge-options` | no | — | C | Whitespace-separated merge options (requires `merge`). See [merge options](#merge-options). |
| `apply` | no | — | C | Newline-separated Overlay documents to apply after merge (before collapse). |
| `overlay` | yes\* | — | OA | Newline-separated Overlay documents to apply to the spec. Required when `subcommand: overlay apply`.|
| `apply-options` | no | — | C, OA | Whitespace-separated overlay apply options. See [overlay apply options](#overlay-apply-options). |
| `collapse` | no | `false` | C | Lift inline components into the root bag and replace call sites with `$ref`s. |
| `format` | no | auto | all | Force input format: `json` or `yaml`. By default inferred from the file extension. |
| `load` | no | — | V, C\*\* | Whitespace-separated `$ref` loaders: `file`, `http`. On `convert` requires `collapse: true`. |
| `ignore` | no | — | V, OV | Whitespace-separated checks to skip. See [validation checks](#validation-checks). |
| `print` | no | `false` | V, OV | If `true`, echo the parsed spec/overlay on stdout (diagnostics stay on stderr). |
| `output-format` | no | match in | C, OC, OA | Force output format: `json` or `yaml`. |
| `output-file` | no | stdout | all | Write command output to this path. If unset, output streams to the action log. |

### Validation checks

Values accepted by `ignore` (passed straight through to `roas validate --ignore`):
For `validate`, values accepted by `ignore` (passed straight through to
`roas validate --ignore`):

```
missing-tags, external-references, invalid-urls, non-uniq-operation-ids,
Expand All @@ -86,7 +146,21 @@ empty-info-title, empty-info-version, empty-response-description,
empty-external-documentation-url
```

Run `roas validate --help` for the description of each check.
For `overlay validate`, `ignore` accepts only `empty-info-title` and
`empty-info-version`.

Run `roas validate --help` (or `roas overlay validate --help`) for the
description of each check.

### Overlay apply options

Values accepted by `apply-options` (passed straight through as
`--apply-option`, for `convert` with `apply` and for `overlay apply`):

- `error-on-zero-match` — fail when an action's `target` JSONPath selects zero
nodes. By default a zero-match action is a no-op (per the Overlay spec).
- `error-on-mixed-kind-match` — fail when an `update` action's `target` selects
a mix of objects and arrays. Normative in Overlay 1.1; this opts 1.0 in.

### Merge options

Expand Down
25 changes: 16 additions & 9 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
name: 'Roas OpenAPI Action'
description: 'Validate and convert OpenAPI specs with roas'
description: 'Validate and convert OpenAPI specs and Overlay documents with roas'
branding:
icon: 'check-circle'
color: 'purple'
inputs:
subcommand:
description: 'roas subcommand: validate or convert'
description: 'roas subcommand: validate, convert, overlay validate, overlay convert, or overlay apply'
default: 'validate'
file:
description: 'Path to the OpenAPI spec (JSON or YAML)'
description: 'Positional input: the OpenAPI spec (validate, convert, overlay apply) or the Overlay document (overlay validate, overlay convert), as JSON or YAML'
required: true
from:
description: 'Force input spec version (e.g. v2, v3_0, v3_1, v3_2)'
description: 'Force input spec version (e.g. v2, v3.0, v3.1, v3.2). Spec validate/convert only.'
to:
description: 'Target version for convert (e.g. v3_1, v3_2). Required when subcommand=convert.'
description: 'Target version. For convert: a spec version (e.g. v3.1, v3.2). For overlay convert: an overlay version (v1.0, v1.1). Required for convert and overlay convert.'
merge:
description: 'Newline-separated list of additional specs to merge on top of the base (convert only). Each source is upconverted to the target version, then merged in incoming-order.'
merge-options:
description: 'Whitespace-separated merge options (convert only, requires merge): base-wins, error-on-conflict, deep-merge-object-schemas, merge-info, replace-lists-when-empty.'
apply:
description: 'Newline-separated list of Overlay documents to apply on top of the converted/merged spec (convert only). Applied in order, last in the pipeline (after merge, before collapse).'
overlay:
description: 'Newline-separated list of Overlay documents to apply to the target spec (overlay apply only). Applied in order. Required when subcommand=overlay apply.'
apply-options:
description: 'Whitespace-separated overlay apply options (convert with apply, or overlay apply): error-on-zero-match, error-on-mixed-kind-match.'
collapse:
description: 'Lift inline components into the root bag and replace call sites with $refs (convert only).'
default: 'false'
load:
description: 'Whitespace-separated $ref loaders to enable: file, http'
ignore:
description: 'Whitespace-separated validation checks to skip (validate only)'
description: 'Whitespace-separated checks to skip. validate: validation checks. overlay validate: empty-info-title, empty-info-version.'
format:
description: 'Force input format: json or yaml'
output-format:
description: 'Force output format for convert: json or yaml'
description: 'Force output format for convert, overlay convert, and overlay apply: json or yaml'
output-file:
description: 'Write convert output to this path instead of stdout'
description: 'Write command output to this path instead of stdout'
print:
description: 'Echo parsed spec on stdout (validate only)'
description: 'Echo the parsed spec/overlay on stdout (validate and overlay validate only)'
default: 'false'
runs:
using: 'docker'
Expand All @@ -41,3 +47,4 @@ runs:
INPUT_OUTPUT_FILE: ${{ inputs.output-file }}
INPUT_OUTPUT_FORMAT: ${{ inputs.output-format }}
INPUT_MERGE_OPTIONS: ${{ inputs.merge-options }}
INPUT_APPLY_OPTIONS: ${{ inputs.apply-options }}
Loading