Skip to content

fix: resolve OpenAPI $ref properties to strongly-typed Pulumi types - #901

Open
pierskarsenbarg wants to merge 2 commits into
mainfrom
fix/resolve-openapi-refs-to-typed-pulumi-types
Open

fix: resolve OpenAPI $ref properties to strongly-typed Pulumi types#901
pierskarsenbarg wants to merge 2 commits into
mainfrom
fix/resolve-openapi-refs-to-typed-pulumi-types

Conversation

@pierskarsenbarg

Copy link
Copy Markdown
Member

Summary

OpenAPI $ref properties on auto-generated REST resources were typed as any in all generated SDKs because the schema builder discarded the reference without resolving it. This fixes the root cause so that component schema types are properly resolved, registered, and referenced. Fixes #900.

Changes

  • provider/pkg/rest/schema.go: Introduces a typeBuilder struct that carries *Spec and the output types accumulator through the schema-building call chain. When a $ref is encountered, it resolves the component schema, builds a named Pulumi ComplexTypeSpec under {pkg}:api:{Name}, and returns a #/types/... reference. A placeholder is written before recursing to handle circular type references. Replaces the standalone openAPIToProperty/openAPIToType functions with methods on typeBuilder, threaded through buildResource, buildAttachmentResource, operationInputs, operationOutputs, and mergeEmitOnCreateOutputs.
  • provider/pkg/rest/schema_test.go: Adds TestRefPropertyResolvesToNamedType to verify that a $ref property produces a #/types/... ref and the type is registered in the types map.
  • provider/cmd/pulumi-resource-pulumiservice/schema.json: Regenerated — now includes a populated types section with all component schemas referenced by API resources.
  • sdk/: All language SDKs regenerated. For example, AuditLogExportConfiguration.newS3Configuration is now pulumi.Input<inputs.api.AuditLogsExportS3ConfigArgs> in TypeScript instead of any.

Test Plan

  • go test ./provider/pkg/rest/... -count=1 passes, including the new TestRefPropertyResolvesToNamedType test
  • mise exec -- make lint passes with 0 issues
  • make provider rebuilds successfully
  • All SDK types verified in NodeJS (inputs.api.AuditLogsExportS3ConfigArgs), Python (AuditLogsExportS3ConfigArgs), and Go (AuditLogsExportS3Config struct)

Previously, `openAPIToType` in the REST schema builder immediately
converted any OpenAPI `$ref` property to `pulumi.json#/Any`, causing
SDK inputs/outputs that reference component schemas to be typed as `any`
in all generated SDKs. For example, `AuditLogExportConfiguration.newS3Configuration`
was `any` in TypeScript instead of a typed `AuditLogsExportS3ConfigArgs` interface.

Introduces a `typeBuilder` struct that carries `*Spec` and the output
`types` accumulator through the schema-building call chain. When a `$ref`
is encountered, it resolves the component schema, builds a named Pulumi
`ComplexTypeSpec`, registers it under `{pkg}:api:{Name}`, and returns a
`#/types/...` reference. A placeholder is written before recursing to
handle circular type references. All previously standalone functions
(`openAPIToProperty`, `openAPIToType`) are replaced by methods on
`typeBuilder` and threaded through `buildResource`, `buildAttachmentResource`,
`operationInputs`, `operationOutputs`, and `mergeEmitOnCreateOutputs`.

Regenerates schema.json and all language SDKs to reflect the new types.

Fixes #900
@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Does the PR have any schema changes?

Found 62 breaking changes:

Resources

  • 🟡 "pulumiservice:api/agents:Pool": properties: "agents": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:DeploymentAgentMetadata"
  • "pulumiservice:api/agents:Task":
    • inputs:
      • 🟡 "cliIntegrations": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:CLIIntegrationRef"
      • 🟡 "enabledIntegrations": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AgentTaskIntegrationRef"
      • 🟡 "message" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AgentUserEventMessage"
    • 🟡 properties: "createdBy" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:UserInfo"
  • "pulumiservice:api/auth:OidcIssuer":
    • 🟡 inputs: "jwks" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:JSONWebKeySet"
    • 🟡 properties: "jwks" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:JSONWebKeySet"
  • "pulumiservice:api/auth:Policy":
    • 🟡 inputs: "policies": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AuthPolicyDefinition"
    • 🟡 properties: "policies": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AuthPolicyDefinition"
  • 🟡 "pulumiservice:api/auth:SAML": properties: "organization" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:Organization"
  • 🟡 "pulumiservice:api/deployments:ScheduledDeployment": inputs: "request" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:CreateDeploymentRequest"
  • "pulumiservice:api/deployments:Settings":
    • inputs:
      • 🟡 "cacheOptions" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:CacheOptionsRequest"
      • 🟡 "executorContext" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:ExecutorSettingsRequest"
      • 🟡 "gitHub" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:DeploymentSettingsGitHubRequest"
      • 🟡 "operationContext" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:OperationContextRequest"
      • 🟡 "sourceContext" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:SourceContextRequest"
    • properties:
      • 🟡 "cacheOptions" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:CacheOptions"
      • 🟡 "executorContext" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:ExecutorContext"
      • 🟡 "gitHub" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:DeploymentSettingsGitHub"
      • 🟡 "operationContext" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:OperationContext"
      • 🟡 "sourceContext" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:SourceContext"
  • 🟡 "pulumiservice:api/esc:EnvironmentSchedule": inputs: "secretRotationRequest" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:CreateEnvironmentSecretRotationScheduleRequest"
  • "pulumiservice:api/insights:Account": properties:
    • 🟡 "ownedBy" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:UserInfo"
    • 🟡 "scanStatus" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:ScanStatus"
  • "pulumiservice:api/integrations:AzureDevOpsIntegration": properties:
    • 🟡 "authUser" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:User"
    • 🟡 "organization" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AzureDevOpsOrganization"
    • 🟡 "project" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AzureDevOpsProject"
  • 🟡 "pulumiservice:api/integrations:BitBucketIntegration": properties: "authUser" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:User"
  • 🟡 "pulumiservice:api/integrations:CustomVCSIntegration": properties: "repositories": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:CustomVCSRepository"
  • "pulumiservice:api/integrations:GitHubEnterpriseIntegration": properties:
    • 🟡 "ghUrls" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:GitHubAppURLs"
    • 🟡 "neoGitHubAppPermissionRequirements": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:GitHubAppPermissionRequirement"
  • "pulumiservice:api/integrations:GitHubIntegration": properties:
    • 🟡 "ghUrls" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:GitHubAppURLs"
    • 🟡 "neoGitHubAppPermissionRequirements": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:GitHubAppPermissionRequirement"
  • "pulumiservice:api/integrations:GitLabIntegration": properties:
    • 🟡 "authUser" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:User"
    • 🟡 "gitLabOrg" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:GitLabAppOrganization"
  • "pulumiservice:api/services:Item":
    • 🟡 inputs: "items": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AddServiceItem"
    • properties:
      • 🟡 "items": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:ServiceItem"
      • 🟡 "service" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:Service"
  • "pulumiservice:api/services:Service":
    • inputs:
      • 🟡 "items": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AddServiceItem"
      • 🟡 "properties": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:ServiceProperty"
    • 🟡 properties: "items": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:ServiceItem"
  • "pulumiservice:api/stacks:Stack":
    • inputs:
      • 🟡 "config" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AppStackConfig"
      • 🟡 "state" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AppUntypedDeployment"
    • properties:
      • 🟡 "config" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AppStackConfig"
      • 🟡 "currentOperation" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AppOperationStatus"
  • "pulumiservice:api/teams:Team": properties:
    • 🟡 "accounts": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:TeamAccountPermission"
    • 🟡 "environments": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:TeamEnvironmentSettings"
    • 🟡 "members": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:TeamMemberInfo"
    • 🟡 "stacks": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:TeamStackPermission"
  • "pulumiservice:api:AuditLogExportConfiguration":
    • 🟡 inputs: "newS3Configuration" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AuditLogsExportS3Config"
    • properties:
      • 🟡 "lastResult" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AuditLogExportResult"
      • 🟡 "s3Config" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AuditLogsExportS3Config"
  • 🟡 "pulumiservice:api:DefaultOrganization": properties: "Messages": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AppMessage"
  • "pulumiservice:api:Gate":
    • 🟡 inputs: "target" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:ChangeGateTargetInput"
    • 🟡 properties: "target" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:ChangeGateTargetOutput"
  • "pulumiservice:api:OrgTemplateCollection":
    • 🟡 inputs: "destination" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:TemplateDestination"
    • 🟡 properties: "destination" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:TemplateDestination"
  • "pulumiservice:api:OrganizationMember": properties:
    • 🟡 "fgaRole" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:FGARole"
    • 🟡 "links" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:MemberLinks"
    • 🟡 "user" type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:UserInfo"
  • "pulumiservice:api:PolicyGroup": properties:
    • 🟡 "appliedPolicyPacks": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AppPolicyPackMetadata"
    • 🟡 "stacks": items type changed from "pulumi.json#/Any" to "#/types/pulumiservice:api:AppPulumiStackReference"
      No new resources/functions.

Maintainer note: consult the runbook for dealing with any breaking changes.

@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.52941% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.05%. Comparing base (d99674c) to head (e5b2009).

Files with missing lines Patch % Lines
provider/pkg/rest/schema.go 83.52% 9 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #901      +/-   ##
==========================================
+ Coverage   53.93%   54.05%   +0.11%     
==========================================
  Files          82       82              
  Lines        9537     9570      +33     
==========================================
+ Hits         5144     5173      +29     
- Misses       3946     3948       +2     
- Partials      447      449       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One blocking finding inline: CHANGELOG.md was not updated despite the 69 user-facing schema/SDK changes this PR generates.

Reviewed by Internal Trusted PR Reviewer

Add this agentic workflows to your repo

To install this agentic workflow, run

gh aw add pulumi-labs/gh-aw-internal/.github/workflows/gh-aw-pr-review.md@8a92f53fac170563f7727cacab2dbedb5d5b9e29


// typeBuilder accumulates Pulumi named types discovered while converting
// OpenAPI $ref properties, and resolves them recursively.
type typeBuilder struct {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CHANGELOG.md is not updated. Per CLAUDE.md: "Always update CHANGELOG.md when making code changes that affect users." The schema-check bot reported 69 user-facing schema changes here (properties moving from pulumi.json#/Any to typed #/types/... refs), which alter SDK type signatures across every language SDK (e.g. AuditLogExportConfiguration.newS3Configuration is now AuditLogsExportS3ConfigArgs instead of any). Add an entry under ## Unreleased — either ### Improvements (strengthens types on the api: Preview surface) or ### Breaking Changes (existing user code typed against any may need updates), matching the precedent of other pulumiservice:api:* entries.

The discriminator-based schema fix caused PermissionDescriptor (and other
discriminated union types) to revert to `pulumi.json#/Any`, while other
OpenAPI $ref types became strongly-typed named types. This required updating
all language examples in examples/api/ to use the new typed inputs and
correct field names.

Changes in provider/pkg/rest/schema.go: detect OpenAPI discriminator fields
and fall back to Any rather than generating an unusable named type whose Go
struct has an unexported __type field that callers cannot set.

Regenerated schema.json and all SDKs to remove PermissionDescriptor* types
and update fields that changed from any to typed objects (e.g. executorImage
is now DockerImageRequest instead of a plain string).

Updated all six language examples for audit-log-export (fix s3BucketName /
iamRoleArn field names), auth-policy (fix authorizedPermissions array, add
rules), service (fix type/name fields on items, add type/order on properties),
and deployment-settings (wrap executorImage in DockerImageRequest object).
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.

Non-primitive inputs are not strongly typed

1 participant