Skip to content

Commit af392a7

Browse files
rh-amarinclaude
andcommitted
HYPERFLEET-1103 - feat: restructure TypeSpec sources into core and shared
- Move GCP-specific models out of this repo (now in hyperfleet-api-spec-gcp) - Restructure sources into core/ (core-specific) and shared/ (cross-provider) - Add generic Resource model and CRUD service (from main reconciliation) - Add force-delete endpoints for clusters, nodepools, and resources (internal) - Add ResourceStatusesInternal for adapter resource status reporting - Simplify build script: single provider (core only), openapi output only - Add npm sub-path exports to enable downstream package imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a769d48 commit af392a7

56 files changed

Lines changed: 125 additions & 9533 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,28 @@ jobs:
2424
- name: Install dependencies
2525
run: npm ci
2626

27-
- name: Build all schemas
28-
run: |
29-
./build-schema.sh core
30-
./build-schema.sh core --swagger
31-
./build-schema.sh gcp
32-
./build-schema.sh gcp --swagger
27+
- name: Build core schema
28+
run: ./build-schema.sh
3329

3430
- name: Check schema consistency
3531
run: |
3632
if ! git diff --exit-code schemas/; then
3733
echo "Committed schemas are out of sync with TypeSpec sources."
38-
echo "Run './build-schema.sh core --swagger && ./build-schema.sh gcp --swagger' and commit the results."
34+
echo "Run './build-schema.sh' and commit the results."
3935
exit 1
4036
fi
4137
42-
- name: Lint OpenAPI schemas
38+
- name: Lint OpenAPI schema
4339
run: |
44-
npx spectral lint schemas/core/openapi.yaml schemas/gcp/openapi.yaml --format github-actions --fail-severity warn
40+
npx spectral lint schemas/core/openapi.yaml --format github-actions --fail-severity warn
4541
4642
- name: Check version bump
4743
env:
4844
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4945
run: |
50-
CURRENT=$(grep -oP '(?<=version: ")[^"]+' main.tsp)
46+
CURRENT=$(grep -oP '(?<=version: ")[^"]+' core/main.tsp)
5147
if [ -z "$CURRENT" ]; then
52-
echo "::error::Failed to extract version from main.tsp — check the @info decorator format" >&2
48+
echo "::error::Failed to extract version from core/main.tsp — check the @info decorator format" >&2
5349
exit 1
5450
fi
5551
LATEST=$(gh release list --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null | sed 's/^v//' || echo "")
@@ -59,10 +55,10 @@ jobs:
5955
fi
6056
HIGHEST=$(printf '%s\n%s\n' "$CURRENT" "$LATEST" | sort -V | tail -1)
6157
if [ "$CURRENT" = "$LATEST" ]; then
62-
echo "::error::Version '$CURRENT' matches latest release tag 'v$LATEST' — bump the version in main.tsp before merging."
58+
echo "::error::Version '$CURRENT' matches latest release tag 'v$LATEST' — bump the version in core/main.tsp before merging."
6359
exit 1
6460
elif [ "$HIGHEST" != "$CURRENT" ]; then
65-
echo "::error::Version '$CURRENT' is lower than latest release 'v$LATEST' — version in main.tsp must be strictly greater."
61+
echo "::error::Version '$CURRENT' is lower than latest release 'v$LATEST' — version in core/main.tsp must be strictly greater."
6662
exit 1
6763
fi
6864
echo "Version bump OK: $LATEST → $CURRENT"

.github/workflows/release.yml

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ jobs:
2828
- name: Extract version
2929
id: version
3030
run: |
31-
VERSION=$(grep -oP '(?<=version: ")[^"]+' main.tsp)
31+
VERSION=$(grep -oP '(?<=version: ")[^"]+' core/main.tsp)
3232
if [ -z "$VERSION" ]; then
33-
echo "::error::Failed to extract version from main.tsp — check the @info decorator format" >&2
33+
echo "::error::Failed to extract version from core/main.tsp — check the @info decorator format" >&2
3434
exit 1
3535
fi
3636
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
@@ -49,21 +49,14 @@ jobs:
4949
echo "skip=false" >> "$GITHUB_OUTPUT"
5050
fi
5151
52-
- name: Build all schemas
52+
- name: Build core schema
5353
if: steps.check_tag.outputs.skip == 'false'
54-
run: |
55-
./build-schema.sh core
56-
./build-schema.sh core --swagger
57-
./build-schema.sh gcp
58-
./build-schema.sh gcp --swagger
54+
run: ./build-schema.sh
5955

6056
- name: Prepare release assets
6157
if: steps.check_tag.outputs.skip == 'false'
6258
run: |
6359
cp schemas/core/openapi.yaml core-openapi.yaml
64-
cp schemas/core/swagger.yaml core-swagger.yaml
65-
cp schemas/gcp/openapi.yaml gcp-openapi.yaml
66-
cp schemas/gcp/swagger.yaml gcp-swagger.yaml
6760
6861
- name: Create release tag
6962
if: steps.check_tag.outputs.skip == 'false'
@@ -85,8 +78,5 @@ jobs:
8578
prerelease: false
8679
files: |
8780
core-openapi.yaml
88-
core-swagger.yaml
89-
gcp-openapi.yaml
90-
gcp-swagger.yaml
9181
env:
9282
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CHANGELOG.md

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

88
## [Unreleased]
99

10-
## [1.0.17] - 2026-05-21
11-
12-
### Added
13-
14-
- Generic `Resource` type with `kind` discriminator and JSONB `spec` field, replacing per-entity model hierarchies for new resource types (HYPERFLEET-1083)
15-
- `ResourceCreateRequest`, `ResourcePatchRequest`, `ResourceList`, `ResourceStatus` types in core contract
16-
- Generic `/resources` CRUD routes in core contract (GET list, GET by ID, POST, PATCH, DELETE) per design doc Section 3.2
17-
- `/channels` and `/channels/{channel_id}/versions` CRUD routes in GCP contract
18-
- `references` field on Resource for non-ownership associations between entities (Section 9)
19-
- `ChannelSpec` validation schema in GCP contract (`is_default`, `enabled_regex`)
20-
- `VersionSpec` validation schema in GCP contract (`raw_version`, `enabled`, `is_default`, `release_image`, `end_of_life_time`)
21-
- `KindChannel` and `KindVersion` kind aliases in GCP contract
22-
23-
### Changed
24-
25-
- `GET /resources/{id}/statuses` and `POST /resources/{id}/force-delete` moved to core contract
26-
- `GET /clusters/{id}/statuses` and `GET /nodepools/{id}/statuses` moved to core contract
27-
28-
## [1.0.16] - 2026-05-20
29-
30-
### Added
31-
32-
- `channelGroup` optional field to `ReleaseSpec` in GCP cluster model (GCP-696)
33-
34-
## [1.0.15] - 2026-05-18
35-
36-
### Added
37-
38-
- `ForceDeleteRequest` model with required `reason` field (HYPERFLEET-1075)
39-
- POST `/clusters/{cluster_id}/force-delete` internal endpoint for force-deleting stuck clusters (HYPERFLEET-1075)
40-
- POST `/clusters/{cluster_id}/nodepools/{nodepool_id}/force-delete` internal endpoint for force-deleting stuck nodepools (HYPERFLEET-1075)
41-
4210
## [1.0.14] - 2026-05-15
4311

4412
### Removed
@@ -170,10 +138,7 @@ First official stable release of the HyperFleet API specification.
170138
- Interactive API documentation
171139

172140
<!-- Links -->
173-
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.17...HEAD
174-
[1.0.17]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.16...v1.0.17
175-
[1.0.16]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.15...v1.0.16
176-
[1.0.15]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.14...v1.0.15
141+
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.14...HEAD
177142
[1.0.14]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.13...v1.0.14
178143
[1.0.13]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.12...v1.0.13
179144
[1.0.12]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.11...v1.0.12

aliases-core.tsp

Lines changed: 0 additions & 11 deletions
This file was deleted.

aliases-gcp.tsp

Lines changed: 0 additions & 18 deletions
This file was deleted.

aliases.tsp

Lines changed: 0 additions & 1 deletion
This file was deleted.

build-schema.sh

Lines changed: 10 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,140 +1,42 @@
11
#!/bin/bash
22

3-
# Build HyperFleet OpenAPI Schema
4-
# Usage: ./build-schema.sh <provider> [--swagger|--openapi2]
5-
# provider: core, gcp, or any provider with aliases-{provider}.tsp file (required, must be first argument)
6-
# --swagger, --openapi2: Also generate OpenAPI 2.0 (Swagger) format
3+
# Build HyperFleet core OpenAPI schema
4+
# Usage: ./build-schema.sh
75

86
set -e
97

10-
# Colors for output
118
RED='\033[0;31m'
129
GREEN='\033[0;32m'
1310
YELLOW='\033[1;33m'
14-
NC='\033[0m' # No Color
11+
NC='\033[0m'
1512

16-
# Parse arguments
17-
GENERATE_SWAGGER=false
18-
19-
# Provider is required and must be the first argument
20-
if [ $# -lt 1 ]; then
21-
echo -e "${RED}Error: Provider argument is required${NC}"
22-
echo "Usage: $0 <provider> [--swagger|--openapi2]"
23-
echo " provider: core, gcp, or any provider with aliases-{provider}.tsp file"
24-
echo " --swagger, --openapi2: Also generate OpenAPI 2.0 (Swagger) format"
25-
exit 1
26-
fi
27-
28-
PROVIDER="$1"
29-
shift
30-
31-
# Check if provider looks like an option (starts with -)
32-
if [[ "$PROVIDER" == -* ]]; then
33-
echo -e "${RED}Error: Provider must be the first argument${NC}"
34-
echo "Usage: $0 <provider> [--swagger|--openapi2]"
35-
exit 1
36-
fi
37-
38-
# Parse remaining options
39-
for arg in "$@"; do
40-
case $arg in
41-
--swagger|--openapi2)
42-
GENERATE_SWAGGER=true
43-
;;
44-
-*)
45-
echo -e "${RED}Error: Unknown option: $arg${NC}"
46-
echo "Usage: $0 <provider> [--swagger|--openapi2]"
47-
exit 1
48-
;;
49-
*)
50-
echo -e "${RED}Error: Unexpected argument: $arg${NC}"
51-
echo "Usage: $0 <provider> [--swagger|--openapi2]"
52-
exit 1
53-
;;
54-
esac
55-
done
56-
57-
# Script directory (where the script is located)
5813
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5914
cd "$SCRIPT_DIR"
6015

61-
# Define the aliases file for the provider
62-
ALIASES_FILE="aliases-${PROVIDER}.tsp"
63-
64-
# Check if the aliases file exists
65-
if [ ! -f "$ALIASES_FILE" ]; then
66-
echo -e "${RED}Error: Provider aliases file not found: ${ALIASES_FILE}${NC}"
67-
echo ""
68-
echo "Available providers:"
69-
for file in aliases-*.tsp; do
70-
if [ -f "$file" ]; then
71-
provider_name=$(echo "$file" | sed 's/aliases-\(.*\)\.tsp/\1/')
72-
echo " - $provider_name"
73-
fi
74-
done
75-
exit 1
76-
fi
77-
78-
# Check if main.tsp exists
79-
if [ ! -f "main.tsp" ]; then
80-
echo -e "${RED}Error: main.tsp not found in current directory${NC}"
81-
exit 1
82-
fi
83-
84-
# Check if tsp command is available
8516
if [ ! -x "${SCRIPT_DIR}/node_modules/.bin/tsp" ]; then
8617
echo -e "${RED}Error: tsp not found in node_modules. Run 'npm install' first.${NC}"
8718
exit 1
8819
fi
8920
TSP="${SCRIPT_DIR}/node_modules/.bin/tsp"
9021

91-
# Check if api-spec-converter is available when swagger output is requested
92-
if [ "$GENERATE_SWAGGER" = true ]; then
93-
if ! npx api-spec-converter --version &> /dev/null; then
94-
echo -e "${RED}Error: api-spec-converter not found. Please install it.${NC}"
95-
echo "Install with: npm install --save-dev api-spec-converter"
96-
exit 1
97-
fi
98-
fi
99-
100-
echo -e "${GREEN}Building HyperFleet API schema for provider: ${PROVIDER}${NC}"
101-
if [ "$GENERATE_SWAGGER" = true ]; then
102-
echo -e "${GREEN}Output formats: OpenAPI 3.0 + OpenAPI 2.0 (Swagger)${NC}"
103-
else
104-
echo -e "${GREEN}Output format: OpenAPI 3.0${NC}"
105-
fi
106-
echo ""
107-
108-
# Step 1: Re-link aliases.tsp to the provider-specific aliases file
109-
echo -e "${YELLOW}Step 1: Linking aliases.tsp to ${ALIASES_FILE}${NC}"
110-
if [ -L "aliases.tsp" ] || [ -f "aliases.tsp" ]; then
111-
rm -f aliases.tsp
112-
fi
113-
ln -sf "$ALIASES_FILE" aliases.tsp
114-
echo -e "${GREEN}✓ Linked aliases.tsp → ${ALIASES_FILE}${NC}"
22+
echo -e "${GREEN}Building HyperFleet core API schema${NC}"
11523
echo ""
11624

117-
# Step 2: Create output directory for the provider
118-
OUTPUT_DIR="schemas/${PROVIDER}"
119-
echo -e "${YELLOW}Step 2: Preparing output directory...${NC}"
25+
OUTPUT_DIR="schemas/core"
26+
echo -e "${YELLOW}Step 1: Preparing output directory...${NC}"
12027
mkdir -p "$OUTPUT_DIR"
12128
echo -e "${GREEN}✓ Created output directory: ${OUTPUT_DIR}${NC}"
12229
echo ""
12330

124-
# Step 3: Compile TypeSpec to generate OpenAPI schema
125-
echo -e "${YELLOW}Step 3: Compiling TypeSpec...${NC}"
126-
TEMP_OUTPUT_DIR="tsp-output-${PROVIDER}"
31+
echo -e "${YELLOW}Step 2: Compiling TypeSpec from core/main.tsp...${NC}"
32+
TEMP_OUTPUT_DIR="tsp-output-core"
12733

128-
# Cleanup function to remove temporary directory on exit
12934
cleanup() {
130-
if [ -d "$TEMP_OUTPUT_DIR" ]; then
131-
rm -rf "$TEMP_OUTPUT_DIR"
132-
fi
35+
rm -rf "$TEMP_OUTPUT_DIR"
13336
}
13437
trap cleanup EXIT
13538

136-
if "$TSP" compile main.tsp --output-dir "$TEMP_OUTPUT_DIR"; then
137-
# Move the generated schema to the provider-specific directory
39+
if "$TSP" compile ./main.tsp --output-dir "$TEMP_OUTPUT_DIR"; then
13840
if [ -f "${TEMP_OUTPUT_DIR}/schema/openapi.yaml" ]; then
13941
mv "${TEMP_OUTPUT_DIR}/schema/openapi.yaml" "${OUTPUT_DIR}/openapi.yaml"
14042
echo ""
@@ -152,25 +54,5 @@ else
15254
exit 1
15355
fi
15456

155-
# Step 4: Convert to OpenAPI 2.0 (Swagger) if requested
156-
if [ "$GENERATE_SWAGGER" = true ]; then
157-
echo ""
158-
echo -e "${YELLOW}Step 4: Converting to OpenAPI 2.0 (Swagger)...${NC}"
159-
160-
if npx api-spec-converter \
161-
--from=openapi_3 \
162-
--to=swagger_2 \
163-
--syntax=yaml \
164-
"${OUTPUT_DIR}/openapi.yaml" > "${OUTPUT_DIR}/swagger.yaml" 2>/dev/null; then
165-
echo -e "${GREEN}✓ Successfully generated OpenAPI 2.0 (Swagger) schema${NC}"
166-
echo -e "${GREEN}Output: ${OUTPUT_DIR}/swagger.yaml${NC}"
167-
else
168-
echo -e "${RED}✗ Failed to convert to OpenAPI 2.0 (Swagger)${NC}"
169-
echo "The OpenAPI 3.0 schema may contain features not supported in OpenAPI 2.0"
170-
rm -f "${OUTPUT_DIR}/swagger.yaml"
171-
exit 1
172-
fi
173-
fi
174-
17557
echo ""
17658
echo -e "${GREEN}Build complete!${NC}"
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import "../../aliases-core.tsp";
2-
import "../../models/clusters/model.tsp";
3-
import "../../models/common/model.tsp";
1+
import "./model.tsp";
2+
import "../../../shared/models/clusters/model.tsp";
3+
import "../../../shared/models/common/model.tsp";
44

55
const exampleCluster: Cluster = #{
66
kind: "Cluster",
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import "../../aliases-core.tsp";
2-
import "../../models/clusters/model.tsp";
1+
import "./model.tsp";
2+
import "../../../shared/models/clusters/model.tsp";
33

44
const exampleClusterPatchRequest: ClusterPatchRequest = #{
55
spec: #{},
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import "../../aliases-core.tsp";
2-
import "../../models/clusters/model.tsp";
1+
import "./model.tsp";
2+
import "../../../shared/models/clusters/model.tsp";
33

44
const exampleClusterCreateRequest: ClusterCreateRequest = #{
55
kind: "Cluster",

0 commit comments

Comments
 (0)