Skip to content

Commit 8c877b6

Browse files
mliptak0claude
andcommitted
HYPERFLEET-1024 - feat: automate OpenAPI pipeline, add Go module, and schema linting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2807639 commit 8c877b6

25 files changed

Lines changed: 455 additions & 438 deletions

.github/workflows/ci.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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 Spectral CLI
28+
run: npm install -g @stoplight/spectral-cli@6.15.1
29+
30+
- name: Build all schemas
31+
run: |
32+
./build-schema.sh core
33+
./build-schema.sh core --swagger
34+
./build-schema.sh gcp
35+
./build-schema.sh gcp --swagger
36+
37+
- name: Check schema consistency
38+
run: |
39+
if ! git diff --exit-code schemas/; then
40+
echo "Committed schemas are out of sync with TypeSpec sources."
41+
echo "Run './build-schema.sh core --swagger && ./build-schema.sh gcp --swagger' and commit the results."
42+
exit 1
43+
fi
44+
45+
- name: Lint OpenAPI schemas
46+
run: |
47+
spectral lint schemas/core/openapi.yaml schemas/gcp/openapi.yaml --format github-actions
48+
49+
- name: Check version bump
50+
env:
51+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52+
run: |
53+
CURRENT=$(grep -oP '(?<=version: ")[^"]+' main.tsp)
54+
LATEST=$(gh release list --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null | sed 's/^v//' || echo "")
55+
if [ -z "$LATEST" ]; then
56+
echo "No previous releases found — version check skipped"
57+
exit 0
58+
fi
59+
if [ "$CURRENT" = "$LATEST" ]; then
60+
echo "Version '$CURRENT' matches latest release tag 'v$LATEST' — bump the version in main.tsp before merging."
61+
exit 1
62+
fi
63+
echo "Version bump OK: $LATEST → $CURRENT"

.github/workflows/release.yml

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,87 @@ 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: Extract version
29+
id: version
30+
run: |
31+
VERSION=$(grep -oP '(?<=version: ")[^"]+' main.tsp)
32+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
33+
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
2934
30-
- name: Build Core schema
31-
run: ./build-schema.sh core
35+
- name: Check if release already exists
36+
id: check_tag
37+
env:
38+
TAG: ${{ steps.version.outputs.tag }}
39+
run: |
40+
git fetch --tags
41+
if git rev-parse "$TAG" >/dev/null 2>&1; then
42+
echo "Tag $TAG already exists — skipping release"
43+
echo "skip=true" >> "$GITHUB_OUTPUT"
44+
else
45+
echo "skip=false" >> "$GITHUB_OUTPUT"
46+
fi
3247
33-
- name: Build GCP schema
34-
run: ./build-schema.sh gcp
48+
- name: Build all schemas
49+
if: steps.check_tag.outputs.skip == 'false'
50+
run: |
51+
./build-schema.sh core
52+
./build-schema.sh core --swagger
53+
./build-schema.sh gcp
54+
./build-schema.sh gcp --swagger
3555
3656
- name: Prepare release assets
57+
if: steps.check_tag.outputs.skip == 'false'
3758
run: |
3859
cp schemas/core/openapi.yaml core-openapi.yaml
60+
cp schemas/core/swagger.yaml core-swagger.yaml
3961
cp schemas/gcp/openapi.yaml gcp-openapi.yaml
62+
cp schemas/gcp/swagger.yaml gcp-swagger.yaml
4063
41-
- name: Create Release
64+
- name: Create release tag
65+
if: steps.check_tag.outputs.skip == 'false'
66+
env:
67+
TAG: ${{ steps.version.outputs.tag }}
68+
run: |
69+
git config user.name "github-actions[bot]"
70+
git config user.email "github-actions[bot]@users.noreply.github.com"
71+
git tag -a "$TAG" -m "Release $TAG"
72+
git push origin "$TAG"
73+
74+
- name: Create GitHub Release
75+
if: steps.check_tag.outputs.skip == 'false'
4276
uses: softprops/action-gh-release@v2
4377
with:
78+
tag_name: ${{ steps.version.outputs.tag }}
79+
generate_release_notes: true
80+
draft: false
81+
prerelease: false
4482
files: |
4583
core-openapi.yaml
84+
core-swagger.yaml
4685
gcp-openapi.yaml
47-
draft: false
48-
prerelease: false
49-
generate_release_notes: true
86+
gcp-swagger.yaml
5087
env:
5188
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: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,56 @@ 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 9457 (instance identifies a specific occurrence and may be a relative URI reference)
26+
- `build-schema.sh` now resolves `tsp` from `node_modules/.bin/` instead of requiring a global install, eliminating version mismatch between the globally installed compiler and the lockfile-pinned version
27+
28+
## [1.0.10] - 2026-05-05
29+
30+
### Added
31+
32+
- 409 Conflict response to cluster patch (PATCH `/clusters/{cluster_id}`) for soft-deleted cluster rejection
33+
- 409 Conflict response to nodepool create (POST `/clusters/{cluster_id}/nodepools`) for soft-deleted cluster rejection
34+
- 409 Conflict response to nodepool patch (PATCH `/clusters/{cluster_id}/nodepools/{nodepool_id}`) for soft-deleted cluster rejection
35+
36+
## [1.0.9] - 2026-05-04
37+
38+
### Added
39+
40+
- PUT endpoint for cluster adapter statuses (PUT `/clusters/{cluster_id}/statuses`) with upsert semantics
41+
- PUT endpoint for nodepool adapter statuses (PUT `/clusters/{cluster_id}/nodepools/{nodepool_id}/statuses`) with upsert semantics
42+
43+
## [1.0.8] - 2026-04-28
44+
45+
### Added
46+
47+
- "Reconciled" condition type to resource status conditions
48+
- "Finalized" condition type to adapter status conditions
49+
50+
### Fixed
51+
52+
- Inconsistent `observed_generation` values across examples
53+
54+
## [1.0.7] - 2026-04-20
55+
56+
### Added
57+
58+
- PATCH endpoint for clusters (PATCH `/clusters/{cluster_id}`) with `ClusterPatchRequest`
59+
- PATCH endpoint for nodepools (PATCH `/clusters/{cluster_id}/nodepools/{nodepool_id}`) with `NodePoolPatchRequest`
1960

2061
## [1.0.6] - 2026-04-13
2162

@@ -63,7 +104,12 @@ First official stable release of the HyperFleet API specification.
63104
- Interactive API documentation
64105

65106
<!-- Links -->
66-
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.6...HEAD
107+
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.11...HEAD
108+
[1.0.11]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.10...v1.0.11
109+
[1.0.10]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.9...v1.0.10
110+
[1.0.9]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.8...v1.0.9
111+
[1.0.8]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.7...v1.0.8
112+
[1.0.7]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.6...v1.0.7
67113
[1.0.6]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.2...v1.0.6
68114
[1.0.2]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.0...v1.0.2
69115
[1.0.0]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/releases/tag/v1.0.0

CLAUDE.md

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ services/
107107
4. `./build-schema.sh core --swagger`
108108
- Test both provider variants when modifying shared models
109109
- Keep TypeSpec files focused (one resource per service file)
110-
- Use semantic versioning for releases (see RELEASING.md)
110+
- Use semantic versioning for releases (automated on merge to main)
111111

112112
## Common Tasks
113113

@@ -207,7 +207,7 @@ Before submitting changes:
207207
**The build-schema.sh script:**
208208
1. Validates provider parameter (core, gcp, etc.)
209209
2. Re-links `aliases.tsp``aliases-{provider}.tsp`
210-
3. Runs `tsp compile main.tsp`
210+
3. Runs `node_modules/.bin/tsp compile main.tsp`
211211
4. Copies output to `schemas/{provider}/openapi.yaml`
212212
5. (Optional) Converts to OpenAPI 2.0 with `--swagger` flag
213213

@@ -242,27 +242,18 @@ Match the version range to existing dependencies.
242242

243243
## Release Process
244244

245-
Quick reference (see RELEASING.md for details):
245+
Releases are **fully automated** via GitHub Actions (`.github/workflows/release.yml`).
246246

247-
```bash
248-
# 1. Build schemas
249-
npm run build:all
250-
251-
# 2. Commit and tag
252-
git add schemas/
253-
git commit -m "chore: update schemas for vX.Y.Z"
254-
git tag -a vX.Y.Z -m "Release vX.Y.Z"
255-
256-
# 3. Push tag
257-
git push upstream vX.Y.Z
258-
259-
# 4. Create GitHub Release with schema assets
260-
gh release create vX.Y.Z \
261-
--repo openshift-hyperfleet/hyperfleet-api-spec \
262-
--title "vX.Y.Z" \
263-
schemas/core/openapi.yaml#core-openapi.yaml \
264-
schemas/gcp/openapi.yaml#gcp-openapi.yaml
265-
```
247+
On every push to `main`, the release workflow:
248+
1. Extracts the version from the `@info` decorator in `main.tsp`
249+
2. Skips if a tag for that version already exists
250+
3. Builds all four schema variants (core/gcp OpenAPI 3.0 + Swagger 2.0)
251+
4. Creates an annotated Git tag (`vX.Y.Z`)
252+
5. Publishes a GitHub Release with all four artifacts attached
253+
254+
The CI workflow (`.github/workflows/ci.yml`) enforces that the version in `main.tsp` is bumped from the latest release tag before a PR can be merged.
255+
256+
To release a new version, simply bump the version in `main.tsp` and merge to `main`.
266257

267258
## Architecture Context
268259

CONTRIBUTING.md

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,13 @@ Thank you for your interest in contributing to the HyperFleet API specification!
2020
cd hyperfleet-api-spec
2121
```
2222

23-
2. Install TypeSpec compiler globally:
24-
25-
```bash
26-
npm install -g @typespec/compiler
27-
```
28-
29-
3. Install project dependencies:
23+
2. Install project dependencies (includes the TypeSpec compiler locally):
3024

3125
```bash
3226
npm install
3327
```
3428

35-
4. Verify your setup by building the schemas:
29+
3. Verify your setup by building the schemas:
3630

3731
```bash
3832
npm run build:core
@@ -212,15 +206,15 @@ refactor: consolidate common status fields
212206

213207
## Release Process
214208

215-
See [RELEASING.md](RELEASING.md) for detailed release instructions.
209+
Releases are **fully automated**. See [RELEASING.md](RELEASING.md) for details.
210+
211+
When a PR is merged to `main`, the release workflow automatically:
216212

217-
**Quick summary:**
213+
1. Extracts the version from `main.tsp`
214+
2. Creates an annotated Git tag
215+
3. Publishes a GitHub Release with all four schema artifacts attached
218216

219-
1. Build schemas: `npm run build:all`
220-
2. Commit changes
221-
3. Create tag: `git tag -a vX.Y.Z -m "Release vX.Y.Z"`
222-
4. Push tag: `git push upstream vX.Y.Z`
223-
5. Create GitHub Release with `core-openapi.yaml` and `gcp-openapi.yaml` assets
217+
The CI workflow enforces that the version in `main.tsp` is bumped from the latest release tag before a PR can be merged.
224218

225219
## Pull Request Process
226220

0 commit comments

Comments
 (0)