Skip to content

Commit 1d0afcf

Browse files
committed
HYPERFLEET-1083 - feat: add Channel and Version TypeSpec models
Define Channel and Version resources in the API spec with full CRUD services, following the spec-as-JSONB pattern. Channels organize OCP release versions; Versions are nested under their parent Channel.
1 parent 2b7675f commit 1d0afcf

23 files changed

Lines changed: 4088 additions & 327 deletions

CHANGELOG.md

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

88
## [Unreleased]
99

10+
## [1.0.15] - 2026-05-18
11+
12+
### Added
13+
14+
- Channel resource model with `ChannelSpec` (`is_default`, `enabled_regex`) and full CRUD service at `/channels` (HYPERFLEET-1083)
15+
- Version resource model with `VersionSpec` (`raw_version`, `enabled`, `default`, `release_image`, `end_of_life_time`) and full CRUD service nested at `/channels/{channel_id}/versions` (HYPERFLEET-1083)
16+
- `owner_references` on Version pointing to parent Channel
17+
- Examples for both Channel and Version resources (create, patch, response)
18+
1019
## [1.0.14] - 2026-05-15
1120

1221
### Removed
@@ -138,7 +147,8 @@ First official stable release of the HyperFleet API specification.
138147
- Interactive API documentation
139148

140149
<!-- Links -->
141-
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.14...HEAD
150+
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.15...HEAD
151+
[1.0.15]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.14...v1.0.15
142152
[1.0.14]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.13...v1.0.14
143153
[1.0.13]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.12...v1.0.13
144154
[1.0.12]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.11...v1.0.12

CLAUDE.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,15 @@ Before submitting changes:
212212
- [ ] Changes committed including schema updates
213213
- [ ] PR description references related issue
214214

215+
## Node.js Version
216+
217+
CI uses **Node.js 20** (see `.github/workflows/ci.yml`). The `api-spec-converter` (Swagger 2.0 generation) is incompatible with Node.js 25+. If local Swagger builds fail, use Node 20 or build via Docker:
218+
219+
```bash
220+
docker run --rm -v "$(pwd):/app" -w /app node:20-slim bash -c \
221+
"npm install && ./build-schema.sh core --swagger && ./build-schema.sh gcp --swagger"
222+
```
223+
215224
## Build System Details
216225

217226
**The build-schema.sh script:**

aliases-core.tsp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,12 @@ import "./models-core/nodepool/model.tsp";
66
import "./models-core/nodepool/example_nodepool.tsp";
77
import "./models-core/nodepool/example_post.tsp";
88
import "./models-core/nodepool/example_patch.tsp";
9+
import "./models-core/channel/model.tsp";
10+
import "./models-core/channel/example_channel.tsp";
11+
import "./models-core/channel/example_post.tsp";
12+
import "./models-core/channel/example_patch.tsp";
13+
import "./models-core/version/model.tsp";
14+
import "./models-core/version/example_version.tsp";
15+
import "./models-core/version/example_post.tsp";
16+
import "./models-core/version/example_patch.tsp";
917
import "./services/statuses-internal.tsp";

aliases-gcp.tsp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,11 @@ import "./models-gcp/nodepool/model.tsp";
66
import "./models-gcp/nodepool/example_nodepool.tsp";
77
import "./models-gcp/nodepool/example_post.tsp";
88
import "./models-gcp/nodepool/example_patch.tsp";
9+
import "./models-core/channel/model.tsp";
10+
import "./models-core/channel/example_channel.tsp";
11+
import "./models-core/channel/example_post.tsp";
12+
import "./models-core/channel/example_patch.tsp";
13+
import "./models-core/version/model.tsp";
14+
import "./models-core/version/example_version.tsp";
15+
import "./models-core/version/example_post.tsp";
16+
import "./models-core/version/example_patch.tsp";

aliases.tsp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
aliases-gcp.tsp
1+
aliases-core.tsp

main.tsp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import "@typespec/openapi3";
55
import "./services/clusters.tsp";
66
import "./services/statuses.tsp";
77
import "./services/nodepools.tsp";
8+
import "./services/channels.tsp";
9+
import "./services/versions.tsp";
810
// Provider-specific security is imported via aliases.tsp
911
import "./aliases.tsp";
1012

@@ -21,7 +23,7 @@ using OpenAPI;
2123
*/
2224
@service(#{ title: "HyperFleet API" })
2325
@info(#{
24-
version: "1.0.14",
26+
version: "1.0.15",
2527
contact: #{
2628
name: "HyperFleet Team",
2729
url: "https://github.com/openshift-hyperfleet",
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import "./model.tsp";
2+
import "../../models/channels/model.tsp";
3+
import "../../models/common/model.tsp";
4+
5+
const exampleChannel: Channel = #{
6+
kind: "Channel",
7+
id: "019466a2-1234-7abc-9def-0123456789ab",
8+
href: "https://api.hyperfleet.com/v1/channels/019466a2-1234-7abc-9def-0123456789ab",
9+
name: "stable",
10+
labels: #{ tier: "production" },
11+
spec: #{
12+
is_default: true,
13+
enabled_regex: "^4\\.\\d+\\.\\d+$",
14+
},
15+
generation: 1,
16+
created_time: "2021-01-01T00:00:00Z",
17+
updated_time: "2021-01-01T10:02:00Z",
18+
created_by: "user-123@example.com",
19+
updated_by: "user-123@example.com",
20+
};
21+
22+
const exampleDeletedChannel: Channel = #{
23+
kind: "Channel",
24+
id: "019466a2-1234-7abc-9def-0123456789ab",
25+
href: "https://api.hyperfleet.com/v1/channels/019466a2-1234-7abc-9def-0123456789ab",
26+
name: "stable",
27+
labels: #{ tier: "production" },
28+
spec: #{
29+
is_default: true,
30+
enabled_regex: "^4\\.\\d+\\.\\d+$",
31+
},
32+
generation: 2,
33+
created_time: "2021-01-01T00:00:00Z",
34+
updated_time: "2021-01-01T10:02:00Z",
35+
deleted_time: "2021-01-01T10:05:00Z",
36+
created_by: "user-123@example.com",
37+
updated_by: "user-123@example.com",
38+
deleted_by: "user-123@example.com",
39+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import "./model.tsp";
2+
import "../../models/channels/model.tsp";
3+
4+
const exampleChannelPatchRequest: ChannelPatchRequest = #{
5+
spec: #{
6+
is_default: false,
7+
enabled_regex: "^4\\.17\\.\\d+$",
8+
},
9+
labels: #{ tier: "staging" },
10+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import "./model.tsp";
2+
import "../../models/channels/model.tsp";
3+
4+
const exampleChannelCreateRequest: ChannelCreateRequest = #{
5+
kind: "Channel",
6+
name: "stable",
7+
labels: #{ tier: "production" },
8+
spec: #{
9+
is_default: true,
10+
enabled_regex: "^4\\.\\d+\\.\\d+$",
11+
},
12+
};

models-core/channel/model.tsp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
model ChannelSpec {
2+
/** Whether this is the default channel */
3+
is_default: boolean;
4+
5+
/** Regex pattern for matching enabled versions */
6+
enabled_regex: string;
7+
}

0 commit comments

Comments
 (0)