Skip to content

Commit 6df29fe

Browse files
mliptak0claude
andcommitted
HYPERFLEET-1024 - fix: address code review findings
- Guard empty version extraction in CI and release workflows - Add semver-aware version comparison to reject downgrades - Use env vars for step outputs in release workflow (script injection) - Pin spectral-cli version in CI - Fix CHANGELOG: correct Node.js runtime reference, RFC 9457 - Add language specifier to fenced code block in README - Add linting docs to CONTRIBUTING.md and CLAUDE.md - Add pipeline overview diagram for sprint presentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 6a17bb6 commit 6df29fe

7 files changed

Lines changed: 111 additions & 3 deletions

File tree

.github/workflows/ci.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,21 @@ jobs:
5151
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5252
run: |
5353
CURRENT=$(grep -oP '(?<=version: ")[^"]+' main.tsp)
54+
if [ -z "$CURRENT" ]; then
55+
echo "::error::Failed to extract version from main.tsp — check the @info decorator format" >&2
56+
exit 1
57+
fi
5458
LATEST=$(gh release list --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null | sed 's/^v//' || echo "")
5559
if [ -z "$LATEST" ]; then
5660
echo "No previous releases found — version check skipped"
5761
exit 0
5862
fi
63+
HIGHEST=$(printf '%s\n%s\n' "$CURRENT" "$LATEST" | sort -V | tail -1)
5964
if [ "$CURRENT" = "$LATEST" ]; then
60-
echo "Version '$CURRENT' matches latest release tag 'v$LATEST' — bump the version in main.tsp before merging."
65+
echo "::error::Version '$CURRENT' matches latest release tag 'v$LATEST' — bump the version in main.tsp before merging."
66+
exit 1
67+
elif [ "$HIGHEST" != "$CURRENT" ]; then
68+
echo "::error::Version '$CURRENT' is lower than latest release 'v$LATEST' — version in main.tsp must be strictly greater."
6169
exit 1
6270
fi
6371
echo "Version bump OK: $LATEST → $CURRENT"

.github/workflows/release.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ jobs:
2929
id: version
3030
run: |
3131
VERSION=$(grep -oP '(?<=version: ")[^"]+' main.tsp)
32+
if [ -z "$VERSION" ]; then
33+
echo "::error::Failed to extract version from main.tsp — check the @info decorator format" >&2
34+
exit 1
35+
fi
3236
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
3337
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
3438

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
### Changed
1919

2020
- 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)
21+
- Bumped `actions/checkout` and `actions/setup-node` to v6
2222

2323
### Fixed
2424

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ Before submitting changes:
199199
- [ ] Core Swagger builds: `./build-schema.sh core --swagger`
200200
- [ ] Schema files generated: `ls schemas/*/openapi.yaml`
201201
- [ ] No TypeSpec compilation errors (check output)
202+
- [ ] Schemas pass linting: `spectral lint schemas/core/openapi.yaml schemas/gcp/openapi.yaml`
202203
- [ ] Changes committed including schema updates
203204
- [ ] PR description references related issue
204205

CONTRIBUTING.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,22 @@ npm run build:gcp:swagger
7979
npm run build:all
8080
```
8181

82+
### Linting Schemas
83+
84+
CI automatically lints OpenAPI schemas using a pinned version of [Spectral](https://github.com/stoplightio/spectral) installed locally in the workflow. For local linting during development, install Spectral globally:
85+
86+
```bash
87+
npm install -g @stoplight/spectral-cli
88+
```
89+
90+
Then lint the generated schemas:
91+
92+
```bash
93+
spectral lint schemas/core/openapi.yaml schemas/gcp/openapi.yaml
94+
```
95+
96+
The `.spectral.yaml` config at the repo root applies the `spectral:oas` ruleset.
97+
8298
### Validating Output
8399

84100
After building, verify the generated schemas:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ go get github.com/openshift-hyperfleet/hyperfleet-api-spec@v1.0.12
362362

363363
To test locally against an unreleased branch, use a `replace` directive in your `go.mod`:
364364

365-
```
365+
```go
366366
replace github.com/openshift-hyperfleet/hyperfleet-api-spec => /path/to/local/hyperfleet-api-spec
367367
```
368368

docs/pipeline-overview.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# HYPERFLEET-1024 — Automated OpenAPI Pipeline
2+
3+
## Before: Manual Process
4+
5+
```mermaid
6+
graph LR
7+
Dev[Developer] -->|1. Edit TypeSpec| TSP[main.tsp]
8+
TSP -->|2. Run build manually| Schemas[schemas/]
9+
Schemas -->|3. Create tag manually| Tag[git tag vX.Y.Z]
10+
Tag -->|4. Push tag| Remote[GitHub]
11+
Remote -->|5. Upload assets manually| Release[GitHub Release]
12+
Release -->|6. Copy files manually| Consumer[hyperfleet-api]
13+
14+
style Dev fill:#f9f,stroke:#333
15+
style Release fill:#fbb,stroke:#900
16+
style Consumer fill:#fbb,stroke:#900
17+
```
18+
19+
**Pain points:** no version enforcement, no linting, manual release steps, consumers vendor stale copies.
20+
21+
---
22+
23+
## After: Fully Automated
24+
25+
```mermaid
26+
graph LR
27+
Dev[Developer] -->|1. Edit TypeSpec + bump version| PR[Pull Request]
28+
29+
subgraph CI ["CI (on every PR)"]
30+
Build[Rebuild schemas]
31+
Lint[Spectral lint]
32+
Version[Version bump check]
33+
Consistency[Schema consistency]
34+
end
35+
36+
PR --> CI
37+
CI -->|All green| Merge[Merge to main]
38+
39+
subgraph Release ["Release (on push to main)"]
40+
Extract[Extract version from main.tsp]
41+
TagCreate[Create git tag]
42+
Publish[Publish GitHub Release + 4 artifacts]
43+
end
44+
45+
Merge --> Release
46+
47+
Release -->|Go module import| Consumer[hyperfleet-api]
48+
49+
style Dev fill:#f9f,stroke:#333
50+
style CI fill:#e6f3ff,stroke:#369
51+
style Release fill:#e6ffe6,stroke:#393
52+
style Consumer fill:#e6ffe6,stroke:#393
53+
```
54+
55+
---
56+
57+
## Key Benefits
58+
59+
```mermaid
60+
graph TB
61+
A["Version discipline enforced"] --- B["Schemas always match TypeSpec sources"]
62+
B --- C["OpenAPI linting on every PR"]
63+
C --- D["Zero-touch releases on merge"]
64+
D --- E["Go module: single source of truth"]
65+
66+
style A fill:#dcedc8,stroke:#558b2f
67+
style B fill:#dcedc8,stroke:#558b2f
68+
style C fill:#dcedc8,stroke:#558b2f
69+
style D fill:#dcedc8,stroke:#558b2f
70+
style E fill:#dcedc8,stroke:#558b2f
71+
```
72+
73+
| Before | After |
74+
|--------|-------|
75+
| Manual `git tag` + `gh release create` | Automatic on merge to main |
76+
| No linting gate | Spectral OAS lint on every PR |
77+
| Version bumps easily forgotten | CI blocks merge if version unchanged |
78+
| Consumers copy `openapi.yaml` by hand | `go get` pulls versioned schemas |
79+
| Schema drift between source and committed files | CI rebuilds and diffs against committed schemas |

0 commit comments

Comments
 (0)