feat(gcp): auto-merge resources across API versions (#561) #38

Merged
stack72 merged 2 commits from issue-561-auto-merge-gcp-versions into main 2026-06-05 22:51:56 +00:00
Owner

Summary

  • Replace manual ADDITIONAL_VERSIONS / ADDITIONAL_VERSION_RESOURCE_FILTER with automatic discovery of all stable (non-alpha/beta) API versions per GCP service
  • Add deterministic schema file ordering (preferred before additional) and cross-version resource deduplication (preferred version wins)
  • Adds 167 new resources across 22 services from older API versions (admin, cloudbuild, connectors, dialogflow, drive, gkehub, jobs, monitoring, notebooks, osconfig, run, and others)

How it works

Fetch phase: For every API with multiple stable versions, non-preferred versions are fetched alongside the preferred one and saved as {name}-{version}.json.

Generation phase: Schema files are sorted so preferred versions load first. A seen-set keyed on service.resourcePath deduplicates across versions — preferred version resources always win, and older versions only contribute resources that don't exist in the preferred version.

Verification

  • IAM: all 16 resources present, 0 changed — no regression from removing ADDITIONAL_VERSIONS
  • Full generation: 2207 resources across 263 services
  • Idempotency: second generation run = 0 changed
  • deno check / deno lint / deno fmt all pass
  • Upgrade entries auto-generated for changed models
  • Manifest versions bumped for affected services

Test plan

  • Filtered IAM regeneration confirms no regression
  • Full regeneration confirms blast radius
  • Second regeneration confirms idempotency (zero diff)
  • deno check, deno lint, deno fmt pass on codegen/

Closes #561

🤖 Generated with Claude Code

## Summary - Replace manual `ADDITIONAL_VERSIONS` / `ADDITIONAL_VERSION_RESOURCE_FILTER` with automatic discovery of all stable (non-alpha/beta) API versions per GCP service - Add deterministic schema file ordering (preferred before additional) and cross-version resource deduplication (preferred version wins) - Adds 167 new resources across 22 services from older API versions (admin, cloudbuild, connectors, dialogflow, drive, gkehub, jobs, monitoring, notebooks, osconfig, run, and others) ## How it works **Fetch phase**: For every API with multiple stable versions, non-preferred versions are fetched alongside the preferred one and saved as `{name}-{version}.json`. **Generation phase**: Schema files are sorted so preferred versions load first. A seen-set keyed on `service.resourcePath` deduplicates across versions — preferred version resources always win, and older versions only contribute resources that don't exist in the preferred version. ## Verification - IAM: all 16 resources present, 0 changed — no regression from removing `ADDITIONAL_VERSIONS` - Full generation: 2207 resources across 263 services - Idempotency: second generation run = 0 changed - `deno check` / `deno lint` / `deno fmt` all pass - Upgrade entries auto-generated for changed models - Manifest versions bumped for affected services ## Test plan - [x] Filtered IAM regeneration confirms no regression - [x] Full regeneration confirms blast radius - [x] Second regeneration confirms idempotency (zero diff) - [x] `deno check`, `deno lint`, `deno fmt` pass on codegen/ Closes #561 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(gcp): auto-merge resources across API versions (#561)
Some checks failed
CI / kubernetes - fmt (pull_request) Has been skipped
CI / kubernetes - lockfile up to date (pull_request) Has been skipped
CI / workflows/gcs-bootstrap - check (pull_request) Has been skipped
CI / workflows/s3-bootstrap - check (pull_request) Has been skipped
CI / kubernetes - test (pull_request) Has been skipped
CI / workflows/gcs-bootstrap - fmt (pull_request) Has been skipped
CI / workflows/s3-bootstrap - fmt (pull_request) Has been skipped
CI / workflows/gcs-bootstrap - lint (pull_request) Has been skipped
CI / workflows/s3-bootstrap - lint (pull_request) Has been skipped
CI / workflows/gcs-bootstrap - test (pull_request) Has been skipped
CI / workflows/s3-bootstrap - test (pull_request) Has been skipped
CI / workflows/gcs-bootstrap - lockfile up to date (pull_request) Has been skipped
CI / cve/dirtyfrag - check (pull_request) Has been skipped
CI / workflows/s3-bootstrap - lockfile up to date (pull_request) Has been skipped
CI / cve/dirtyfrag - test (pull_request) Has been skipped
CI / cve/dirtyfrag - lint (pull_request) Has been skipped
CI / cve/dirtyfrag - fmt (pull_request) Has been skipped
CI / cve/mini-shai-hulud - check (pull_request) Has been skipped
CI / cve/mini-shai-hulud - fmt (pull_request) Has been skipped
CI / cve/dirtyfrag - lockfile up to date (pull_request) Has been skipped
CI / cve/mini-shai-hulud - lint (pull_request) Has been skipped
CI / cve/mini-shai-hulud - test (pull_request) Has been skipped
CI / cve/mini-shai-hulud - lockfile up to date (pull_request) Has been skipped
CI / CI Security Review (pull_request) Has been skipped
CI / cloudflare models - sample check (pull_request) Successful in 1m2s
CI / model/digitalocean - check (pull_request) Successful in 58s
CI / codegen - lockfile up to date (pull_request) Successful in 4m25s
CI / Claude Code Review (pull_request) Has been skipped
CI / Adversarial Code Review (pull_request) Has been skipped
CI / Merge Gate (pull_request) Failing after 30s
261710dada
Replace the manual ADDITIONAL_VERSIONS / ADDITIONAL_VERSION_RESOURCE_FILTER
pattern with automatic discovery and merging of all stable API versions.

The fetch phase now discovers every stable (non-alpha/beta) version per API
and saves non-preferred versions as {name}-{version}.json. The generation
phase sorts schema files deterministically (preferred before additional) and
applies cross-version resource deduplication so preferred-version resources
always win.

This adds 167 new resources across 22 services (admin, cloudbuild,
connectors, dialogflow, drive, gkehub, jobs, monitoring, notebooks,
osconfig, run, tpu, and others) that were previously only available in
older API versions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix: add missing deno.lock files for new GCP services
All checks were successful
CI / cve/dirtyfrag - check (pull_request) Has been skipped
CI / workflows/s3-bootstrap - lockfile up to date (pull_request) Has been skipped
CI / cve/dirtyfrag - fmt (pull_request) Has been skipped
CI / cve/dirtyfrag - lint (pull_request) Has been skipped
CI / cve/dirtyfrag - test (pull_request) Has been skipped
CI / cve/mini-shai-hulud - check (pull_request) Has been skipped
CI / cve/mini-shai-hulud - fmt (pull_request) Has been skipped
CI / cve/mini-shai-hulud - lint (pull_request) Has been skipped
CI / cve/mini-shai-hulud - test (pull_request) Has been skipped
CI / cve/dirtyfrag - lockfile up to date (pull_request) Has been skipped
CI / cve/mini-shai-hulud - lockfile up to date (pull_request) Has been skipped
CI / model/digitalocean - lockfile up to date (pull_request) Successful in 57s
CI / Dependency Audit (pull_request) Successful in 4m11s
CI / model/digitalocean - check (pull_request) Successful in 55s
CI / model/hetzner-cloud - check (pull_request) Successful in 1m18s
CI / gcp models - lockfiles up to date (pull_request) Successful in 1m13s
CI / model/hetzner-cloud - lockfile up to date (pull_request) Successful in 1m19s
CI / aws models - lockfiles up to date (pull_request) Successful in 1m28s
CI / cloudflare models - sample check (pull_request) Successful in 1m24s
CI / gcp models - sample check (pull_request) Successful in 1m45s
CI / CI Security Review (pull_request) Has been skipped
CI / aws models - sample check (pull_request) Successful in 1m56s
CI / cloudflare models - lockfiles up to date (pull_request) Successful in 48s
CI / codegen - fmt (pull_request) Successful in 51s
CI / codegen - lint (pull_request) Successful in 56s
CI / codegen - check (pull_request) Successful in 1m11s
CI / codegen - lockfile up to date (pull_request) Successful in 58s
CI / Adversarial Code Review (pull_request) Successful in 4m28s
CI / Claude Code Review (pull_request) Successful in 5m5s
CI / Merge Gate (pull_request) Successful in 23s
49972e9321
The chromewebstore, cloudtrace, and identitytoolkit services are new
directories created by the auto-merge pipeline. They need committed
lockfiles for the gcp-lockfile CI job to pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

Adversarial Review

Scope: codegen/gcp/pipeline.ts and codegen/designs/gcp.md (all model/ files are auto-generated and excluded per CLAUDE.md).

This PR replaces the manually curated ADDITIONAL_VERSIONS / ADDITIONAL_VERSION_RESOURCE_FILTER mechanism with automatic discovery and merging of all stable (non-alpha/beta) API versions. The cross-version deduplication uses a seenResourceKeys Set with deterministic sort order ensuring preferred versions always win.

Medium

  1. codegen/gcp/pipeline.ts:46 — Regex ADDITIONAL_VERSION_FILENAME_RE can misidentify preferred-version files as additional-version files.

    The regex /^(.+)-(v\d+)$/ matches any stem ending with -v\d+. If a GCP API's name field itself ends with a version-like suffix (hypothetical: my-v2), its preferred version file my-v2.json would be misidentified as an additional version of API my with version v2. This would cause it to be sorted after all non-additional files, so its resources would be processed as "additional" — meaning any resource keys already seen from an unrelated my.json would shadow its resources.

    Breaking example: If the GCP Discovery Directory ever adds an API named foo-v3, the preferred schema foo-v3.json would be classified as additional version v3 of API foo. If foo.json also exists, resources from foo-v3 that share a key with foo would be silently dropped.

    Current risk: No known GCP API name currently ends with -v\d+, so this is latent. But the auto-discovery nature of this change means new APIs added to the Discovery Directory could trigger it without any code changes.

    Suggested fix: Cross-reference against the known set of preferred-version filenames. During generation, after collecting schemaFiles, build a Set<string> of preferred stems (all files that don't match the regex). Then for each regex match, verify that group1 (the extracted base name) exists in the preferred set before treating the file as additional. Files whose extracted base doesn't correspond to a known preferred file should be treated as preferred themselves.

Low

  1. codegen/gcp/pipeline.ts:439 — APIs without a preferred version get no cross-version merging.

    When versions.find((v) => v.preferred) returns undefined, the additional-version loop continues, skipping the API entirely. selectBestVersion (used in the main loop) has its own fallback for no-preferred APIs (highest stable version). So these APIs get a single schema file with no cross-version merge — potentially missing resources from other stable versions.

    This matches the old behavior (which also required explicit listing), so it's not a regression. Noting it as a design choice.

  2. codegen/gcp/pipeline.ts:461 — Removed per-fetch log line for additional versions reduces debuggability.

    The old code logged each additional version fetch: Fetched additional version: iam v1. The new code only logs a final count. When investigating why a particular API version wasn't fetched, the summary Fetched 47 additional API version(s) is less useful than individual lines. Minor observability loss.

Verdict

PASS — The logic is sound. Sort-then-dedup correctly implements preferred-wins semantics, the service filter interaction with additional versions is correct (matching by base service name), and the auto-discovery approach is a clean simplification over the manual curation. The regex misidentification risk (Medium #1) is theoretical given current GCP API naming and doesn't warrant blocking.

## Adversarial Review **Scope**: `codegen/gcp/pipeline.ts` and `codegen/designs/gcp.md` (all `model/` files are auto-generated and excluded per CLAUDE.md). This PR replaces the manually curated `ADDITIONAL_VERSIONS` / `ADDITIONAL_VERSION_RESOURCE_FILTER` mechanism with automatic discovery and merging of all stable (non-alpha/beta) API versions. The cross-version deduplication uses a `seenResourceKeys` Set with deterministic sort order ensuring preferred versions always win. ### Medium 1. **`codegen/gcp/pipeline.ts:46` — Regex `ADDITIONAL_VERSION_FILENAME_RE` can misidentify preferred-version files as additional-version files.** The regex `/^(.+)-(v\d+)$/` matches any stem ending with `-v\d+`. If a GCP API's `name` field itself ends with a version-like suffix (hypothetical: `my-v2`), its preferred version file `my-v2.json` would be misidentified as an additional version of API `my` with version `v2`. This would cause it to be sorted *after* all non-additional files, so its resources would be processed as "additional" — meaning any resource keys already seen from an unrelated `my.json` would shadow its resources. **Breaking example**: If the GCP Discovery Directory ever adds an API named `foo-v3`, the preferred schema `foo-v3.json` would be classified as additional version `v3` of API `foo`. If `foo.json` also exists, resources from `foo-v3` that share a key with `foo` would be silently dropped. **Current risk**: No known GCP API name currently ends with `-v\d+`, so this is latent. But the auto-discovery nature of this change means new APIs added to the Discovery Directory could trigger it without any code changes. **Suggested fix**: Cross-reference against the known set of preferred-version filenames. During generation, after collecting `schemaFiles`, build a `Set<string>` of preferred stems (all files that don't match the regex). Then for each regex match, verify that `group1` (the extracted base name) exists in the preferred set before treating the file as additional. Files whose extracted base doesn't correspond to a known preferred file should be treated as preferred themselves. ### Low 2. **`codegen/gcp/pipeline.ts:439` — APIs without a `preferred` version get no cross-version merging.** When `versions.find((v) => v.preferred)` returns undefined, the additional-version loop `continue`s, skipping the API entirely. `selectBestVersion` (used in the main loop) has its own fallback for no-preferred APIs (highest stable version). So these APIs get a single schema file with no cross-version merge — potentially missing resources from other stable versions. This matches the old behavior (which also required explicit listing), so it's not a regression. Noting it as a design choice. 3. **`codegen/gcp/pipeline.ts:461` — Removed per-fetch log line for additional versions reduces debuggability.** The old code logged each additional version fetch: `Fetched additional version: iam v1`. The new code only logs a final count. When investigating why a particular API version wasn't fetched, the summary `Fetched 47 additional API version(s)` is less useful than individual lines. Minor observability loss. ### Verdict **PASS** — The logic is sound. Sort-then-dedup correctly implements preferred-wins semantics, the service filter interaction with additional versions is correct (matching by base service name), and the auto-discovery approach is a clean simplification over the manual curation. The regex misidentification risk (Medium #1) is theoretical given current GCP API naming and doesn't warrant blocking.
Author
Owner

Code Review

Blocking Issues

None.

Suggestions

  1. Sorting edge case for non-standard GCP version strings (codegen/gcp/pipeline.ts:500–509): The ADDITIONAL_VERSION_FILENAME_RE regex (/^(.+)-(v\d+)$/) only matches standard version suffixes like -v1, -v2. GCP APIs with non-standard version strings — such as admin whose additional versions are datatransfer_v1 and reports_v1 — produce filenames like admin-datatransfer_v1.json that don't match this regex. Those files are classified as non-additional in the sort, and since - (ASCII 45) sorts before . (ASCII 46), admin-datatransfer_v1.json ends up sorted before admin.json, reversing the intended "preferred version first" order for those APIs.

    In practice this is harmless today — resource paths across admin versions are disjoint, so seenResourceKeys dedup causes no conflicts regardless of order. But the invariant "preferred version always wins" silently doesn't hold for any API whose version suffix isn't v\d+. Worth tightening the regex or the sort comparator to handle the general case before this becomes observable.

  2. Design doc section numbering (codegen/designs/gcp.md): Section §10a ("Idempotent Create") and §13a ("List Factory Method") use a-suffixes that break the sequential numbering. Minor, but worth renumbering to keep the doc easy to navigate.

## Code Review ### Blocking Issues None. ### Suggestions 1. **Sorting edge case for non-standard GCP version strings** (`codegen/gcp/pipeline.ts:500–509`): The `ADDITIONAL_VERSION_FILENAME_RE` regex (`/^(.+)-(v\d+)$/`) only matches standard version suffixes like `-v1`, `-v2`. GCP APIs with non-standard version strings — such as `admin` whose additional versions are `datatransfer_v1` and `reports_v1` — produce filenames like `admin-datatransfer_v1.json` that don't match this regex. Those files are classified as non-additional in the sort, and since `-` (ASCII 45) sorts before `.` (ASCII 46), `admin-datatransfer_v1.json` ends up sorted *before* `admin.json`, reversing the intended "preferred version first" order for those APIs. In practice this is harmless today — resource paths across `admin` versions are disjoint, so `seenResourceKeys` dedup causes no conflicts regardless of order. But the invariant "preferred version always wins" silently doesn't hold for any API whose version suffix isn't `v\d+`. Worth tightening the regex or the sort comparator to handle the general case before this becomes observable. 2. **Design doc section numbering** (`codegen/designs/gcp.md`): Section §10a ("Idempotent Create") and §13a ("List Factory Method") use `a`-suffixes that break the sequential numbering. Minor, but worth renumbering to keep the doc easy to navigate.
stack72 deleted branch issue-561-auto-merge-gcp-versions 2026-06-05 22:51:56 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
swamp-club/swamp-extensions!38
No description provided.