Skip to content

fix(module-ci): create a module's intent, or the first one of a kind 404s - #16

Merged
anujhydrabadi merged 1 commit into
masterfrom
fix/module-ci-auto-create-intent
Sep 10, 2026
Merged

anujhydrabadi merged 1 commit into
masterfrom
fix/module-ci-auto-create-intent

Conversation

@anujhydrabadi

Copy link
Copy Markdown
Contributor

A modules repo could not carry a module whose intent the Control Plane had never seen. The upload failed outright:

Error: upload failed with status 404: {"message":"Intent gcs not found","code":"404"}

Nothing else creates an intent — raptor create resource-type-mapping rejects one it does not know — so there was no way through from CI at all. A repo bootstrapped against one Control Plane could not be published to another.

Hit for real: vibe-modules carries gcs, firestore, service_account and artifact_registry; all four failed preview registration this way, and a direct raptor create iac-module failed identically.

The fix

raptor already has the flag. This passes --auto-create on the two steps that upload:

Step Call
Preview modules (pull request) raptor create iac-module -f "$dir" $AUTO_CREATE --feature-branch --git-ref …
Publish modules (push) raptor create iac-module -f "$dir" $AUTO_CREATE

It is deliberately not passed to the --dry-run validation, which never touches the intent — confirmed by dry-runs passing while the intent was absent.

Why it is behind an input

--auto-create does two things, and the second is shared state:

Create the intent if it doesn't exist, and update an existing intent's metadata from intentDetails in facets.yaml.

An intent is shared by every flavor under it. Two flavors that disagree will fight, and the last module published wins. That is not hypothetical — it is already true in vibe-modules:

intent flavor intentDetails.displayName
cloud_account gcp_provider Cloud Account
cloud_account gcp_org_provider GCP Org Cloud Account

So auto-create-intents (default true) can be set to false to freeze intent metadata, at the cost of failing on any new intent. The README gains an Intents section explaining the shared-object model and saying plainly that keeping intentDetails identical across a flavor set is the right answer, and a difference is a repo bug.

Default is true because without it the action simply cannot bootstrap a fresh Control Plane, which is the bug being fixed.

Verification

  • Against a live Control Plane: with the flag, gcs/standard/1.0 uploaded and registered the gcs intent. Re-running without the flag then succeeded, proving the intent persisted.
  • Toggle logic checked for true, false, and unset (unset defaults to on).
  • The repo's own gate run locally: action.yml parses, 12 inputs, 0 shellcheck findings across all embedded scripts.

Not in scope

Two further gaps in the same area, both needing work outside this action:

  1. Output types are never created. A module referencing an output type the Control Plane lacks fails the same way. A working round-trip exists (raptor module get-output-type -o yamlraptor create output-type -f), but the repo carries no output-type files — ModulesRepoBootstrapService.exportModules and raptor module sync-repo both export modules only, and the generated workflow filters on modules/**. Needs control-plane work first.
  2. Deletions never reach the Control Plane. A module directory removed from the repo maps to no facets.yaml, so the publish loop skips it and the module stays published.

🤖 Generated with Claude Code

…404s

A modules repo could not carry a module whose intent the Control Plane had
never seen. The upload failed outright:

  Error: upload failed with status 404: {"message":"Intent gcs not found"}

Nothing else creates an intent. raptor create resource-type-mapping rejects
one it does not know, so there was no way through from CI at all — a repo
bootstrapped against one Control Plane could not be published to another.

raptor already has the flag. Pass --auto-create on the two steps that
upload: preview registration and publish. It is deliberately NOT passed to
the --dry-run validation, which never touches the intent.

Gated behind a new auto-create-intents input, default true, because the flag
does two things and the second is shared state. Besides creating a missing
intent, --auto-create rewrites an existing intent's metadata from the
uploading module's intentDetails. An intent is shared by all its flavors, so
two flavors that disagree fight, and the last module published wins. A real
example from vibe-modules: cloud_account/gcp_provider says displayName
"Cloud Account" while cloud_account/gcp_org_provider says "GCP Org Cloud
Account", for the same intent.

Keeping intentDetails identical across the flavors of one intent is the
right answer, and the README now says so. auto-create-intents: 'false'
freezes the metadata instead, at the cost of failing on any new intent.

Verified against a live Control Plane: with the flag, gcs/standard/1.0
uploaded and registered the gcs intent; re-running without it then succeeded,
which proves the intent persisted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@anujhydrabadi
anujhydrabadi merged commit ca526fc into master Sep 10, 2026
1 check passed
@anujhydrabadi
anujhydrabadi deleted the fix/module-ci-auto-create-intent branch September 10, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant