fix(codegen/gcp): read path params from where the resource keeps them (swamp-club #2669) #464

Merged
stack72 merged 1 commit from 2669 into main 2026-10-06 20:20:49 +00:00
Owner

Fixes swamp-club #2669.

Problem

Generated GCP update methods read the resource id back out of stored state from a field guessed from the path parameter's name. When no mapping matched, they fell back to name, and there was no fallback to globalArgs. BigQuery datasets have no name field: the id is in datasetReference.datasetId. So @swamp/gcp/bigquery/datasets update always failed with Missing required path parameter: datasetId. The same flaw affected every resource whose id lives somewhere other than name.

Fix (codegen/gcp)

  • resolveStateIdentifierPaths (pipeline.ts) works out where each path parameter lives in the raw GET response and stores it as stateIdentifierPaths. Lookup order:

    1. name, when the identifier is described as "Name of…" / "The name of…"
    2. id, when it is described as an "ID"
    3. a top-level field named like the parameter
    4. the field inside a *Reference object
    5. the primary identifier, then <singular>Id, then name, then id

    Only the resource's own GET (or update/patch/delete) defines the identifier. A collection-level action ending in {region} or {bucket} does not.

  • Generated methods (extensionModelGenerator.ts): update, sync and action methods read that path, using optional chaining for nested fields. The globalArgs fallback always uses a flat key.

  • update now falls back to globalArgs like sync does. When no id is found it throws No identifier found in existing state or globalArgs instead of sending an empty path parameter.

  • Design doc: codegen/designs/gcp.md documents the lookup order.

Regenerated models

567 files across 104 GCP services. Each file gets a version bump, the update fallback, and, where it was wrong, a corrected id read. Examples:

Resource Before After
BigQuery datasets, tables, models, routines read name, which doesn't exist read the id inside datasetReference, tableReference and so on
Drive files read name (the filename) read id
Tag Manager read name (display name) read path
DNS record sets (sync) sent name as type send type
Vault, dfareporting, Calendar, admin, … various wrong fields the real id fields

I audited by hand every id read that moved off name, onto name, or off id. Compute addresses, compute regional resources, Storage buckets and objects, and compute autoscalers keep their working reads.

Not regenerated here: cloudlocationfinder, dataproc, displayvideo, integrations, looker, networksecurity and osconfig. The discovery schemas I fetched for these 7 services have drifted from main, so I reverted them to keep upstream changes out of this diff. The scheduled regenerate-models job will carry both the drift and this fix. Only dataproc (2 files) and displayvideo (33 files) are affected by the fix.

Testing

  • Unit tests for each resolver rule, including a BigQuery discovery-doc round trip.

  • Generator tests for the nested reads, the flat globalArgs key, unchanged output for name-keyed resources, and the clear error.

  • referenceIdentifier_integration_test.ts: runs a generated dataset-shaped model against a Deno.serve mock and covers:

    • create → update → sync
    • get → update
    • update after a delete, using the globalArgs fallback
    • the clear error when no id exists

    With the fix removed, the two scenarios from the issue fail.

  • Idempotency: a second generate:gcp run produces zero diff outside the 7 excluded services.

  • Verification: verify-build passed 14/14, including the upgrade path test for every touched published extension. verify-reviews passed (code-review and adversarial-review). Attestation 8015cc67-fbed-4b81-b272-aa4d446fada5.

🤖 Generated with Claude Code

Fixes swamp-club #2669. ## Problem Generated GCP `update` methods read the resource id back out of stored state from a field guessed from the path parameter's name. When no mapping matched, they fell back to `name`, and there was no fallback to globalArgs. BigQuery datasets have no `name` field: the id is in `datasetReference.datasetId`. So `@swamp/gcp/bigquery/datasets` `update` always failed with `Missing required path parameter: datasetId`. The same flaw affected every resource whose id lives somewhere other than `name`. ## Fix (codegen/gcp) - **`resolveStateIdentifierPaths`** (`pipeline.ts`) works out where each path parameter lives in the raw GET response and stores it as `stateIdentifierPaths`. Lookup order: 1. `name`, when the identifier is described as "Name of…" / "The name of…" 2. `id`, when it is described as an "ID" 3. a top-level field named like the parameter 4. the field inside a `*Reference` object 5. the primary identifier, then `<singular>Id`, then `name`, then `id` Only the resource's own GET (or update/patch/delete) defines the identifier. A collection-level action ending in `{region}` or `{bucket}` does not. - **Generated methods** (`extensionModelGenerator.ts`): `update`, `sync` and action methods read that path, using optional chaining for nested fields. The globalArgs fallback always uses a flat key. - **`update`** now falls back to globalArgs like `sync` does. When no id is found it throws `No identifier found in existing state or globalArgs` instead of sending an empty path parameter. - **Design doc:** `codegen/designs/gcp.md` documents the lookup order. ## Regenerated models 567 files across 104 GCP services. Each file gets a version bump, the `update` fallback, and, where it was wrong, a corrected id read. Examples: | Resource | Before | After | | --- | --- | --- | | BigQuery datasets, tables, models, routines | read `name`, which doesn't exist | read the id inside `datasetReference`, `tableReference` and so on | | Drive files | read `name` (the filename) | read `id` | | Tag Manager | read `name` (display name) | read `path` | | DNS record sets (`sync`) | sent `name` as `type` | send `type` | | Vault, dfareporting, Calendar, admin, … | various wrong fields | the real id fields | I audited by hand every id read that moved off `name`, onto `name`, or off `id`. Compute addresses, compute regional resources, Storage buckets and objects, and compute autoscalers keep their working reads. **Not regenerated here:** cloudlocationfinder, dataproc, displayvideo, integrations, looker, networksecurity and osconfig. The discovery schemas I fetched for these 7 services have drifted from `main`, so I reverted them to keep upstream changes out of this diff. The scheduled regenerate-models job will carry both the drift and this fix. Only dataproc (2 files) and displayvideo (33 files) are affected by the fix. ## Testing - **Unit tests** for each resolver rule, including a BigQuery discovery-doc round trip. - **Generator tests** for the nested reads, the flat globalArgs key, unchanged output for name-keyed resources, and the clear error. - **`referenceIdentifier_integration_test.ts`**: runs a generated dataset-shaped model against a `Deno.serve` mock and covers: - `create → update → sync` - `get → update` - `update` after a delete, using the globalArgs fallback - the clear error when no id exists With the fix removed, the two scenarios from the issue fail. - **Idempotency:** a second `generate:gcp` run produces zero diff outside the 7 excluded services. - **Verification:** `verify-build` passed 14/14, including the upgrade path test for every touched published extension. `verify-reviews` passed (code-review and adversarial-review). Attestation `8015cc67-fbed-4b81-b272-aa4d446fada5`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(codegen/gcp): read path params from where the resource keeps them (swamp-club #2669)
All checks were successful
CI / Review Integrity (pull_request) Successful in 1m9s
CI / Validate Attestation (pull_request) Successful in 1m10s
6000810214
Generated GCP update methods read the resource id from stored state via a
field guessed from the path param name (default `name`) with no globalArgs
fallback. Resources whose id lives elsewhere could not be updated: BigQuery
datasets keep it in datasetReference.datasetId, so update failed with
"Missing required path parameter: datasetId" after create, get or list.

The pipeline now resolves where each path param lives in the raw GET
response (resolveStateIdentifierPaths -> stateIdentifierPaths): a "Name of"
identifier keeps `name`, an "ID" identifier reads `id`, then a same-named
field, a `*Reference` object, and the primary identifier / <singular>Id /
name / id. update, sync and action methods read that path with optional
chaining; globalArgs fallbacks stay flat keys. update now falls back to
globalArgs like sync and throws a clear error instead of sending an empty
path param.

Regenerated GCP models (567 files, 104 services). Seven services whose
fetched schemas drifted from main (cloudlocationfinder, dataproc,
displayvideo, integrations, looker, networksecurity, osconfig) are left for
the scheduled regeneration.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
stack72 deleted branch 2669 2026-10-06 20:20: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!464
No description provided.