| name | bootstrap-api-version |
| description | Bootstrap a new ARM API version by copying the latest version, wiring it into the frontend, SDK, tests, and integration fixtures. Invoke with the new version string (e.g. "2027-03-15-preview"). |
Bootstrap a New API Version
Scaffold a new ARM API version as an identical copy of the latest existing version, then wire it into every registration point, test suite, and build target. The result is a branch with two commits: one for the API scaffold, one for the E2E test.
Inputs
The user provides:
- NEW_VERSION: the API version string, e.g.
2027-03-15-preview
Derived values:
- NEW_PKG: version string without hyphens, prefixed with
v (e.g. v20270315preview)
- PREV_PKG: the most recent existing version — discover by listing directories matching
internal/api/v*preview/ and picking the latest alphabetically
- PREV_VERSION: the dash-separated form of PREV_PKG (e.g.
2026-06-30-preview)
- TIMEBOMB_DATE: one calendar month after the version date, in RFC3339 UTC format
Discovery
Before making any changes, read the codebase to find current registration points. The patterns below describe WHAT to look for and WHERE, not exact paths — paths may drift as the repo evolves.
- TypeSpec version enum: Search for
enum Versions in api/ .tsp files
- API build config: Find
VERSION ?= in api/Makefile; find autorest tag blocks in api/readme.md and api/testsdk.md
- API spec readme: Find the spec-level
readme.md under api/redhatopenshift/.../hcpopenshiftclusters/ — it has package-YYYY-MM-DD-preview tag blocks used by make -C api lint-openapi
- Language-specific SDK configs: Search for
readme.go.md and readme.python.md alongside the main readme.md in the API spec directory — these have per-version tag blocks and (for Go) a batch list
- Frontend registration: Search for
RegisterVersion calls and blank imports of previous API version packages in frontend/
- Integration test registry: Search for
AllAPIVersions in test-integration/
- Cross-version test constants: Search for the previous version's dash-separated string in
test-integration/ test files
- Version compliance fixtures: Find
artifacts/VersionCompliance/ under test-integration/ and list its expected/ directories
- Defaults consistency test: Search for
TestEnsureDefaultsConsistency and find where previous versions are tested
- OpenAPI spec path in defaults test: Search for
openapi.json in internal/api/defaults_test.go or similar
- E2E framework helpers: Search for version-suffixed functions like
CreateHCPClusterFromParam + PREV_PKG in test/util/framework/
- E2E test files: Find
cluster_create_ + PREV_PKG files in test/e2e/
- Import alias rules: Check
.golangci.yml for importas rules referencing SDK packages
Step-by-step checklist
Split into two commits (see Commit Strategy below).
Commit 1: API scaffold
1. TypeSpec version enum
Add a new enum variant to the Versions enum in the main .tsp file, following the pattern of existing entries. Then regenerate: cd api && npm run compile && npm run format. This produces the OpenAPI spec, example files, and preview directory for the new version.
2. API build configuration
- Update
VERSION ?= default in api/Makefile to NEW_PKG
- Add a new autorest tag section for NEW_PKG in
api/readme.md (before the previous version's tag — newest first), pointing to the new version's openapi.json
- Add a matching tag section in
api/testsdk.md with the SDK module name
- Update any example commands in
api/docs/ that reference the previous version's tag
2a. API spec readme
Update the spec-level readme.md at api/redhatopenshift/.../hcpopenshiftclusters/readme.md:
- Update the default
tag: value at the top to package-NEW_VERSION
- Add a new
Tag: package-NEW_VERSION block (before the previous version's tag — newest first) pointing to the new version's openapi.json
This file uses dash-separated version format (package-YYYY-MM-DD-preview) and is required by make -C api lint-openapi.
2b. Language-specific SDK configs
Find readme.go.md and readme.python.md in the same directory as the main API readme.md. These have per-version tag blocks for autorest code generation:
readme.go.md: Add NEW_VERSION to the batch list under $(go) && $(multiapi), and add a new Tag: package-NEW_VERSION and go section (before the previous version's tag) with the output folder path.
readme.python.md: Add a new Tag: package-NEW_VERSION and python section (before the previous version's tag) with namespace and output folder using underscore-separated version (e.g. v2027_03_15_preview).
3. Internal API version package
Generate models: cd api && make models VERSION=NEW_PKG
Then copy every non-generated .go file from internal/api/PREV_PKG/ to internal/api/NEW_PKG/. In each copied file:
- Change the
package declaration from PREV_PKG to NEW_PKG
- Update the copyright year to the current year
- In
register.go: update the version string returned by String() to the new version
The files to copy are all .go files in the previous version's directory that are NOT inside generated/. This typically includes a register.go, several *_methods.go files, and *_test.go files.
4. Frontend registration
Find where previous versions are registered in the frontend:
- A blank-import file (imports version packages for their
init() side effects) — add a new blank import
- The file containing
RegisterVersion calls — add import + call for the new package
5. Test SDK generation
cd api && make testsdk VERSION=NEW_PKG
Then wire the new SDK module into test/go.mod with a require + local replace directive, following the pattern of the previous version's entry.
6. Integration test infrastructure
- Find
AllAPIVersions() and add a RegisterVersion call for the new version (with its import)
- Find cross-version test constants (version strings like
"2025-12-23-preview") and add one for the new version
7. Version compliance test fixtures
For each scenario directory under the VersionCompliance artifacts tree, copy the previous version's expected response files to the new version:
expected/get/PREV_VERSION.json → expected/get/NEW_VERSION.json
expected/list/PREV_VERSION.json → expected/list/NEW_VERSION.json
Since the new version is initially identical, these are exact copies.
8. Defaults consistency test
Find the defaults consistency test(s) that test each API version's defaults against internal canonical defaults. Add test cases for the new version following the pattern of the previous version's cases. This requires importing the new version package.
9. Defaults test OpenAPI path
Find the test that reads the OpenAPI spec to verify defaults (searches for openapi.json path). Update the path to point to the new version's spec.
10. Tidy and verify
make tidy
make fmt
make licenses
make lint
make -C api validate-examples
make -C api lint-openapi
make test
make verify
Commit 2: E2E test with timebomb
11. E2E test framework helpers
Find the previous version's helpers in the test framework directory. Four areas need version-suffixed additions — copy each function/type, replacing the version suffix:
- Deployment params: Cluster/NodePool param structs, factory functions, and infra-population helpers
- HCP helpers: Build, create-and-wait, get, and update functions for clusters and node pools
- Deployment helpers: High-level orchestration functions (create cluster from params, create customer resources)
- Per-test framework: Client factory methods that create SDK clients for the new version
Import the new SDK package with the alias hcpsdk<YYYYMMDD>preview (e.g. hcpsdk20270315preview — note: no v prefix, matching the importas lint rules in .golangci.yml).
12. E2E test file
Create a new E2E test file following the pattern of the previous version's cluster create test. Key elements:
- Labels:
RequireNothing, Critical, Positive, AroRpApiCompatible
- Timebomb pattern: In non-development environments, query ARM to check if the API version is registered for the resource provider. If not available before TIMEBOMB_DATE, skip gracefully. If not available after TIMEBOMB_DATE, hard-fail. Development environments always run.
- Test flow: create resource group → create customer resources → create HCP cluster → get credentials → verify cluster health
- Use the new version's framework helpers for creation. Credential retrieval can use any version's helper (it's version-independent).
13. Record E2E test specs
make record-nonlocal-e2e
This updates test fixture files that track the E2E test suite contents.
14. Final tidy
make tidy && make fmt && make lint
Commit strategy
Split into exactly two commits:
-
api: scaffold new API version NEW_VERSION
Body: "Add the NEW_VERSION API version as a copy of PREV_VERSION with no feature changes. This establishes the version entry point so new features can be added incrementally in follow-up PRs."
Contains: steps 1-10 (including 2a and 2b)
-
test: add E2E test with timebomb for NEW_VERSION API version
Contains: steps 11-14
Common pitfalls
- Forgetting
register.go String() update: The copied register.go must return the NEW version string, not the previous one. This is the one semantic change in an otherwise mechanical copy.
- Import alias enforcement:
.golangci.yml may enforce import aliases for SDK packages. Check the importas config and use any required aliases.
- License headers: Run
make licenses before committing — all new .go files need Apache 2.0 headers.
- go.work sync: The SDK module lives under
test/ which should already be in go.work. Run make tidy to ensure go work sync picks it up correctly.
- Version compliance fixtures: Initially identical copies. When features are later added to the new version, these fixtures must be updated or
TestVersionCompliance will fail with a clear diff showing exactly what to fix.
- E2E file naming: E2E test files must NOT use the
_test.go suffix (except the entry point). Follow the convention of existing test files.
- Copilot instructions: Per
CONTRIBUTING.md, also add a condensed version of any new skill to .github/copilot-instructions.md for GitHub Copilot compatibility.