Skip to content

Commit 94f150f

Browse files
mliptak0claude
andcommitted
HYPERFLEET-1024 - feat: automate OpenAPI pipeline, add Go module, and schema linting
Add CI workflow (ci.yml) that runs on every PR and push to main: rebuilds all four schemas from TypeSpec, checks consistency against committed files, lints both openapi.yaml files with spectral:oas, and enforces a version bump against the latest release tag. Replace manual release process with automated release.yml that triggers on push to main, extracts version from main.tsp, auto-creates an annotated tag, and publishes a GitHub Release with all four artifacts attached (core-openapi.yaml, core-swagger.yaml, gcp-openapi.yaml, gcp-swagger.yaml). Add go.mod and schemas/schemas.go exposing all generated schemas via //go:embed as embed.FS, enabling downstream Go consumers to import versioned schemas as a module dependency without vendoring local copies. Add .spectral.yaml with spectral:oas ruleset. Fix Error.instance field format from uri to uri-reference per RFC 7807. Bump actions/checkout and actions/setup-node to v6. Update CHANGELOG.md for v1.0.9. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5d10855 commit 94f150f

13 files changed

Lines changed: 162 additions & 34 deletions

File tree

.github/workflows/ci.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
validate:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v6
18+
19+
- name: Setup Node.js
20+
uses: actions/setup-node@v6
21+
with:
22+
node-version: '20'
23+
24+
- name: Install dependencies
25+
run: npm ci
26+
27+
- name: Install TypeSpec compiler
28+
run: npm install -g @typespec/compiler@1.11
29+
30+
- name: Install Spectral CLI
31+
run: npm install -g @stoplight/spectral-cli
32+
33+
- name: Build all schemas
34+
run: |
35+
./build-schema.sh core
36+
./build-schema.sh core --swagger
37+
./build-schema.sh gcp
38+
./build-schema.sh gcp --swagger
39+
40+
- name: Check schema consistency
41+
run: |
42+
if ! git diff --exit-code schemas/; then
43+
echo "Committed schemas are out of sync with TypeSpec sources."
44+
echo "Run './build-schema.sh core --swagger && ./build-schema.sh gcp --swagger' and commit the results."
45+
exit 1
46+
fi
47+
48+
- name: Lint OpenAPI schemas
49+
run: |
50+
spectral lint schemas/core/openapi.yaml schemas/gcp/openapi.yaml --format github-actions
51+
52+
- name: Check version bump
53+
env:
54+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55+
run: |
56+
CURRENT=$(grep -oP '(?<=version: ")[^"]+' main.tsp)
57+
LATEST=$(gh release list --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null | sed 's/^v//' || echo "")
58+
if [ -z "$LATEST" ]; then
59+
echo "No previous releases found — version check skipped"
60+
exit 0
61+
fi
62+
if [ "$CURRENT" = "$LATEST" ]; then
63+
echo "Version '$CURRENT' matches latest release tag 'v$LATEST' — bump the version in main.tsp before merging."
64+
exit 1
65+
fi
66+
echo "Version bump OK: $LATEST → $CURRENT"

.github/workflows/release.yml

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,86 @@ name: Create Release
22

33
on:
44
push:
5-
tags:
6-
- 'v*'
5+
branches:
6+
- main
77

88
jobs:
99
release:
1010
runs-on: ubuntu-latest
11-
1211
permissions:
1312
contents: write
1413

1514
steps:
1615
- name: Checkout code
17-
uses: actions/checkout@v4
16+
uses: actions/checkout@v6
17+
with:
18+
fetch-depth: 0
1819

1920
- name: Setup Node.js
20-
uses: actions/setup-node@v4
21+
uses: actions/setup-node@v6
2122
with:
2223
node-version: '20'
2324

2425
- name: Install dependencies
25-
run: npm install
26+
run: npm ci
2627

27-
- name: Install tsp
28-
run: npm install -g @typespec/compiler@1.6
28+
- name: Install TypeSpec compiler
29+
run: npm install -g @typespec/compiler@1.11
2930

30-
- name: Build Core schema
31-
run: ./build-schema.sh core
31+
- name: Extract version
32+
id: version
33+
run: |
34+
VERSION=$(grep -oP '(?<=version: ")[^"]+' main.tsp)
35+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
36+
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
3237
33-
- name: Build GCP schema
34-
run: ./build-schema.sh gcp
38+
- name: Check if release already exists
39+
id: check_tag
40+
run: |
41+
git fetch --tags
42+
if git rev-parse "${{ steps.version.outputs.tag }}" >/dev/null 2>&1; then
43+
echo "Tag ${{ steps.version.outputs.tag }} already exists — skipping release"
44+
echo "skip=true" >> "$GITHUB_OUTPUT"
45+
else
46+
echo "skip=false" >> "$GITHUB_OUTPUT"
47+
fi
48+
49+
- name: Build all schemas
50+
if: steps.check_tag.outputs.skip == 'false'
51+
run: |
52+
./build-schema.sh core
53+
./build-schema.sh core --swagger
54+
./build-schema.sh gcp
55+
./build-schema.sh gcp --swagger
3556
3657
- name: Prepare release assets
58+
if: steps.check_tag.outputs.skip == 'false'
3759
run: |
3860
cp schemas/core/openapi.yaml core-openapi.yaml
61+
cp schemas/core/swagger.yaml core-swagger.yaml
3962
cp schemas/gcp/openapi.yaml gcp-openapi.yaml
63+
cp schemas/gcp/swagger.yaml gcp-swagger.yaml
64+
65+
- name: Create release tag
66+
if: steps.check_tag.outputs.skip == 'false'
67+
run: |
68+
git config user.name "github-actions[bot]"
69+
git config user.email "github-actions[bot]@users.noreply.github.com"
70+
git tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}"
71+
git push origin "${{ steps.version.outputs.tag }}"
4072
41-
- name: Create Release
73+
- name: Create GitHub Release
74+
if: steps.check_tag.outputs.skip == 'false'
4275
uses: softprops/action-gh-release@v2
4376
with:
77+
tag_name: ${{ steps.version.outputs.tag }}
78+
generate_release_notes: true
79+
draft: false
80+
prerelease: false
4481
files: |
4582
core-openapi.yaml
83+
core-swagger.yaml
4684
gcp-openapi.yaml
47-
draft: false
48-
prerelease: false
49-
generate_release_notes: true
85+
gcp-swagger.yaml
5086
env:
5187
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.spectral.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
extends: ["spectral:oas"]

CHANGELOG.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.0.11] - 2026-05-07
11+
1012
### Added
1113

12-
- CONTRIBUTING.md with development guidelines and workflow
13-
- CHANGELOG.md following Keep a Changelog format
14-
- CLAUDE.md with AI agent context and validation workflow
14+
- CI workflow (`ci.yml`) that runs on every PR and push to main: rebuilds all schemas, checks consistency against committed files, lints with `spectral:oas` ruleset, and enforces version bump against latest release tag
15+
- Go module (`go.mod` + `schemas/schemas.go`) exposing all four generated schemas via `//go:embed` as `embed.FS`, enabling downstream consumers to import versioned schemas as a Go module dependency
16+
- `.spectral.yaml` with `spectral:oas` ruleset for OpenAPI 3.0 linting
1517

1618
### Changed
1719

18-
- Improved README.md structure to align with HyperFleet documentation standards
20+
- Release workflow now triggers automatically on push to main instead of requiring a manual tag push; auto-creates annotated tag from version in `main.tsp` and attaches all four schema artifacts (`core-openapi.yaml`, `core-swagger.yaml`, `gcp-openapi.yaml`, `gcp-swagger.yaml`)
21+
- Bumped `actions/checkout` and `actions/setup-node` to v6 (Node.js 24 runtime)
22+
23+
### Fixed
24+
25+
- `Error.instance` field format changed from `uri` to `uri-reference` per RFC 7807 (instance identifies a specific occurrence and may be a relative URI reference)
1926

2027
## [1.0.10] - 2026-05-05
2128

@@ -96,7 +103,8 @@ First official stable release of the HyperFleet API specification.
96103
- Interactive API documentation
97104

98105
<!-- Links -->
99-
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.10...HEAD
106+
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.11...HEAD
107+
[1.0.11]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.10...v1.0.11
100108
[1.0.10]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.9...v1.0.10
101109
[1.0.9]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.8...v1.0.9
102110
[1.0.8]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.7...v1.0.8

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/openshift-hyperfleet/hyperfleet-api-spec
2+
3+
go 1.23

main.tsp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ using OpenAPI;
2020
*
2121
*/
2222
@service(#{ title: "HyperFleet API" })
23-
@info(#{ version: "1.0.10", contact: #{ name: "HyperFleet Team" }, license: #{ name: "Apache 2.0" ,url: "https://www.apache.org/licenses/LICENSE-2.0"} })
23+
@info(#{ version: "1.0.11", contact: #{ name: "HyperFleet Team" }, license: #{ name: "Apache 2.0" ,url: "https://www.apache.org/licenses/LICENSE-2.0"} })
2424
@server("https://hyperfleet.redhat.com", "Production")
2525
@route("/api/hyperfleet/v1")
2626
namespace HyperFleet;

models/common/model.tsp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ model Error {
7979
detail?: string;
8080

8181
/** URI reference for this specific occurrence */
82-
@format("uri")
82+
@format("uri-reference")
8383
@example("/api/hyperfleet/v1/clusters")
8484
instance?: string;
8585

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

schemas/core/openapi.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
openapi: 3.0.0
22
info:
33
title: HyperFleet API
4-
version: 1.0.10
4+
version: 1.0.11
55
contact:
66
name: HyperFleet Team
77
license:
@@ -1323,7 +1323,7 @@ components:
13231323
example: The cluster name field is required
13241324
instance:
13251325
type: string
1326-
format: uri
1326+
format: uri-reference
13271327
description: URI reference for this specific occurrence
13281328
example: /api/hyperfleet/v1/clusters
13291329
code:

schemas/core/swagger.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ info:
1616
name: Apache 2.0
1717
url: 'https://www.apache.org/licenses/LICENSE-2.0'
1818
title: HyperFleet API
19-
version: 1.0.10
19+
version: 1.0.11
2020
host: hyperfleet.redhat.com
2121
basePath: /
2222
schemes:
@@ -1498,7 +1498,7 @@ definitions:
14981498
instance:
14991499
description: URI reference for this specific occurrence
15001500
example: /api/hyperfleet/v1/clusters
1501-
format: uri
1501+
format: uri-reference
15021502
type: string
15031503
status:
15041504
description: HTTP status code

0 commit comments

Comments
 (0)