Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,20 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Build all schemas
run: |
./build-schema.sh core
./build-schema.sh core --swagger
./build-schema.sh gcp
./build-schema.sh gcp --swagger
- name: Build core schema
run: ./build-schema.sh

- name: Check schema consistency
run: |
if ! git diff --exit-code schemas/; then
echo "Committed schemas are out of sync with TypeSpec sources."
echo "Run './build-schema.sh core --swagger && ./build-schema.sh gcp --swagger' and commit the results."
echo "Run './build-schema.sh' and commit the results."
exit 1
fi

- name: Lint OpenAPI schemas
- name: Lint OpenAPI schema
run: |
npx spectral lint schemas/core/openapi.yaml schemas/gcp/openapi.yaml --format github-actions --fail-severity warn
npx spectral lint schemas/core/openapi.yaml --format github-actions --fail-severity warn

- name: Check version bump
env:
Expand Down
14 changes: 2 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,14 @@ jobs:
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

- name: Build all schemas
- name: Build core schema
if: steps.check_tag.outputs.skip == 'false'
run: |
./build-schema.sh core
./build-schema.sh core --swagger
./build-schema.sh gcp
./build-schema.sh gcp --swagger
run: ./build-schema.sh

- name: Prepare release assets
if: steps.check_tag.outputs.skip == 'false'
run: |
cp schemas/core/openapi.yaml core-openapi.yaml
cp schemas/core/swagger.yaml core-swagger.yaml
cp schemas/gcp/openapi.yaml gcp-openapi.yaml
cp schemas/gcp/swagger.yaml gcp-swagger.yaml

- name: Create release tag
if: steps.check_tag.outputs.skip == 'false'
Expand All @@ -85,8 +78,5 @@ jobs:
prerelease: false
files: |
core-openapi.yaml
core-swagger.yaml
gcp-openapi.yaml
gcp-swagger.yaml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.18] - 2026-05-26

### Changed

- Restructured TypeSpec sources into `core/` and `shared/` directories (HYPERFLEET-1103)
- Removed GCP provider from core repository; GCP contracts now live in a dedicated `hyperfleet-api-spec-gcp` repository (HYPERFLEET-1103)
- `build-schema.sh` simplified: no provider argument required, generates core OpenAPI only
- CI/CD workflows updated to reflect new `main.tsp` location at repository root

Comment thread
rh-amarin marked this conversation as resolved.
## [1.0.17] - 2026-05-21

### Added
Expand Down Expand Up @@ -170,7 +179,8 @@ First official stable release of the HyperFleet API specification.
- Interactive API documentation

<!-- Links -->
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.17...HEAD
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.18...HEAD
[1.0.18]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.17...v1.0.18
[1.0.17]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.16...v1.0.17
[1.0.16]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.15...v1.0.16
[1.0.15]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.14...v1.0.15
Expand Down
134 changes: 47 additions & 87 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,51 @@
# HyperFleet API Spec - AI Agent Context

This repository generates OpenAPI specifications from TypeSpec definitions. It supports multiple provider variants (core, GCP) using a shared codebase with provider-specific type aliases.
This repository generates the HyperFleet core OpenAPI specification from TypeSpec definitions. The GCP-specific contract lives in [hyperfleet-api-spec-gcp](https://github.com/openshift-hyperfleet/hyperfleet-api-spec-gcp), which imports shared models from this repo as the `hyperfleet` npm package.

## Quick Reference

**Build commands:**
```bash
npm run build:core # Generate core OpenAPI spec
npm run build:gcp # Generate GCP OpenAPI spec
npm run build:all # Generate all variants with Swagger
npm run build # Generate core OpenAPI spec
./build-schema.sh # Same, via script directly
```

**Validation workflow:**
```bash
npm install # Install dependencies
./build-schema.sh gcp # Build GCP OpenAPI 3.0
./build-schema.sh gcp --swagger # Build GCP OpenAPI 2.0 (Swagger)
./build-schema.sh core # Build core OpenAPI 3.0
./build-schema.sh core --swagger # Build core OpenAPI 2.0 (Swagger)
ls -l schemas/*/openapi.yaml # Confirm outputs exist
./build-schema.sh # Build core OpenAPI 3.0
ls -l schemas/core/openapi.yaml # Confirm output exists
```

## Key Concepts

### Provider Variants via Aliases
### Repository Layout

The repo uses a single `main.tsp` but generates different specs per provider:

```typescript
// aliases-core.tsp
alias ClusterSpec = Record<unknown>; // Generic

// aliases-gcp.tsp
alias ClusterSpec = GCPClusterSpec; // Provider-specific
```

The `aliases.tsp` symlink determines which provider types are active. The `build-schema.sh` script automatically re-links this during builds. The symlink is tracked in git and should always point to `aliases-core.tsp` by default. Do not remove it from version control or add it to `.gitignore`.
shared/ # Cross-provider models and services (published as the `hyperfleet` npm package)
core/ # Core-only models and internal services
main.tsp # Entry point — imports shared + core
schemas/core/ # Generated output (committed)
```

**When adding new models:**
- Shared models → `models/`
- Provider-specific → `models-{provider}/`
- Always update alias files if you introduce provider-specific types
- Cross-provider models → `shared/models/`
- Core-only models → `core/models/`
- GCP-specific → separate repo (`hyperfleet-api-spec-gcp`)

### Public vs Internal APIs

Status endpoints are split:
- `services/statuses.tsp` - GET operations (external clients)
- `services/statuses-internal.tsp` - PUT operations (internal adapters only)
- `shared/services/statuses.tsp` - GET operations (external clients)
- `core/services/statuses-internal.tsp` - PUT operations (internal adapters only) and resource force-delete

The split allows generating different API contracts per audience. Only `statuses.tsp` is imported by default.

## Code Style

### TypeSpec Conventions

**Imports first, namespace second:**
**Imports first, namespace second** (applies to service and model files; example `const` files do not declare a namespace):
```typescript
import "@typespec/http";
import "../models/common/model.tsp";
Expand All @@ -79,33 +70,30 @@ interface Clusters {
### File Organization

```
models/{resource}/
shared/models/{resource}/
├── model.tsp # Shared model definitions
└── interfaces.tsp # Optional: shared interfaces

models-{provider}/{resource}/
└── model.tsp # Provider-specific models
shared/services/
└── {resource}.tsp # Shared service endpoints

services/
└── {resource}.tsp # Service endpoints
core/models/{resource}/
└── model.tsp # Core-specific models

core/services/
└── {resource}-internal.tsp # Internal-only endpoints
```

## Boundaries

**DO NOT:**
- Modify generated files in `schemas/` or `tsp-output/` directly
- Modify generated files in `schemas/` or `tsp-output-core/` directly
- Add dependencies without checking TypeSpec version compatibility
- Auto-generate documentation - it degrades agent performance per research
- Use `--swagger` flag unless you need OpenAPI 2.0 for legacy tools
- Commit `node_modules/` or build artifacts

**DO:**
- Run builds in this order before committing schema changes:
1. `./build-schema.sh gcp`
2. `./build-schema.sh gcp --swagger`
3. `./build-schema.sh core`
4. `./build-schema.sh core --swagger`
- Test both provider variants when modifying shared models
- Run `./build-schema.sh` and commit `schemas/core/openapi.yaml` with your changes
- Keep TypeSpec files focused (one resource per service file)
- Use semantic versioning for releases (automated on merge to main)

Expand All @@ -114,7 +102,7 @@ services/
### Add a new endpoint to existing service

```typescript
// services/clusters.tsp
// shared/services/clusters.tsp
namespace HyperFleet;

@route("/clusters")
Expand All @@ -131,7 +119,7 @@ interface Clusters {

1. Create model:
```typescript
// models/health/model.tsp
// shared/models/health/model.tsp
import "@typespec/http";

model HealthStatus {
Expand All @@ -143,7 +131,7 @@ model HealthStatus {

2. Create service:
```typescript
// services/health.tsp
// shared/services/health.tsp
import "@typespec/http";
import "../models/health/model.tsp";
import "../models/common/model.tsp";
Expand All @@ -158,35 +146,14 @@ interface Health {

3. Import in `main.tsp`:
```typescript
import "./services/health.tsp";
import "./shared/services/health.tsp";
```

4. Build: `npm run build:core`
4. Build: `npm run build`

### Add provider-specific fields

```typescript
// models-gcp/cluster/model.tsp
model GCPClusterSpec {
projectId: string;
region: string;
network?: GCPNetwork;
}

model GCPNetwork {
vpcId: string;
subnetId: string;
}
```

Update alias:
```typescript
// aliases-gcp.tsp
import "./models-gcp/cluster/model.tsp";
alias ClusterSpec = GCPClusterSpec;
```

Build: `npm run build:gcp`
Provider-specific models live in the provider's own repository (e.g., `hyperfleet-api-spec-gcp`). See that repo for examples of how to extend core shared models.

## Version Bump and Changelog

Expand All @@ -202,36 +169,29 @@ When bumping the version in `main.tsp`, always update `CHANGELOG.md`:
Before submitting changes:

- [ ] Dependencies installed: `npm install`
- [ ] GCP variant builds: `./build-schema.sh gcp`
- [ ] GCP Swagger builds: `./build-schema.sh gcp --swagger`
- [ ] Core variant builds: `./build-schema.sh core`
- [ ] Core Swagger builds: `./build-schema.sh core --swagger`
- [ ] Schema files generated: `ls schemas/*/openapi.yaml`
- [ ] Core schema builds: `./build-schema.sh`
- [ ] Schema file generated: `ls schemas/core/openapi.yaml`
- [ ] No TypeSpec compilation errors (check output)
- [ ] Schemas pass linting: `spectral lint schemas/core/openapi.yaml schemas/gcp/openapi.yaml`
- [ ] Changes committed including schema updates
- [ ] Schema passes linting: `spectral lint schemas/core/openapi.yaml`
- [ ] Changes committed including schema update
- [ ] PR description references related issue

## Build System Details

**The build-schema.sh script:**
1. Validates provider parameter (core, gcp, etc.)
2. Re-links `aliases.tsp` → `aliases-{provider}.tsp`
3. Runs `node_modules/.bin/tsp compile main.tsp`
4. Copies output to `schemas/{provider}/openapi.yaml`
5. (Optional) Converts to OpenAPI 2.0 with `--swagger` flag
1. Extracts the version from `main.tsp` and syncs it into `package.json`
2. Runs `node_modules/.bin/tsp compile main.tsp --output-dir tsp-output-core`
3. Moves output to `schemas/core/openapi.yaml`

**Output locations:**
- TypeSpec: `tsp-output/schema/openapi.yaml` (temporary)
- Final: `schemas/{provider}/openapi.yaml` (committed)
- TypeSpec temp: `tsp-output-core/schema/openapi.yaml` (auto-deleted)
- Final: `schemas/core/openapi.yaml` (committed)

## VS Code Extension Notes
**Version sync:** `package.json` version is kept in lockstep with `main.tsp` automatically on every build. The CI consistency check (`git diff --exit-code`) enforces that both are committed together.

The TypeSpec extension may show false errors:
- Non-active provider models appear undefined (expected)
- Duplicate type warnings from multiple alias files (expected)
## VS Code Extension Notes

Both the CLI and "Emit from TypeSpec" command work correctly despite warnings.
The TypeSpec extension may show false errors for models resolved only at compile time. Both the CLI and "Emit from TypeSpec" command work correctly.

## Dependencies

Expand All @@ -257,9 +217,9 @@ Releases are **fully automated** via GitHub Actions (`.github/workflows/release.
On every push to `main`, the release workflow:
1. Extracts the version from the `@info` decorator in `main.tsp`
2. Skips if a tag for that version already exists
3. Builds all four schema variants (core/gcp OpenAPI 3.0 + Swagger 2.0)
3. Builds the core OpenAPI schema
4. Creates an annotated Git tag (`vX.Y.Z`)
5. Publishes a GitHub Release with all four artifacts attached
5. Publishes a GitHub Release with `core-openapi.yaml` attached

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.

Expand Down
Loading