fix: detecting requires on interface members#1295
Conversation
WalkthroughExtends interface selection rewrite logic to consider requires-configuration on implementing types when no fragments are present, potentially triggering a rewrite. Adds federation-aware tests covering interface fields with @requires on implementations, both with and without explicit fragments. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Pre-merge checks (2 passed, 1 warning)❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
v2/pkg/engine/plan/abstract_selection_rewriter.go (2)
475-482: Scope the requires-check to entities lacking fragments to avoid unnecessary rewritesUsing entityNames here can trigger rewrites even when only types that already have concrete fragments require extra selections. Check only entitiesWithoutFragment.
- // check if any implementing type has requiresConfiguration for one of the requested fields - if slices.ContainsFunc(entityNames, func(entityName string) bool { + // check if any implementing type without its own fragment has requiresConfiguration for one of the requested fields + if slices.ContainsFunc(entitiesWithoutFragment, func(entityName string) bool { return r.hasRequiresConfigurationForField(entityName, selectionSetInfo.fields) }) { return true }
434-446: Micro-opt: guard the no-fragment requires scan behind hasFieldsIf there are no shared fields (e.g., only __typename), there’s nothing to attach requires to; skip the scan.
- // when we do not have fragments - if !selectionSetInfo.hasInlineFragmentsOnInterfaces && + // when we do not have fragments + if !selectionSetInfo.hasInlineFragmentsOnInterfaces && !selectionSetInfo.hasInlineFragmentsOnUnions && !selectionSetInfo.hasInlineFragmentsOnObjects { - // check that all types implementing the interface have a root node with the requested fields + if !selectionSetInfo.hasFields { + return false + } + // check that all types implementing the interface have a root node with the requested fields if !r.allEntitiesHaveFieldsAsRootNode(entityNames, selectionSetInfo.fields) { return true } return slices.ContainsFunc(entityNames, func(entityName string) bool { return r.hasRequiresConfigurationForField(entityName, selectionSetInfo.fields) }) }v2/pkg/engine/plan/abstract_selection_rewriter_test.go (1)
4023-4076: Add a coverage hole: when only types with @requires already have concrete fragments, no rewrite should be neededTo prevent regressions from over-rewriting, add a case where only Admin.name has @requires and the query already includes an Admin fragment.
@@ { + name: "requires only on Admin; Admin has fragment — no rewrite", + definition: definitionC, + upstreamDefinition: ` + interface Named { name: String! } + type User implements Named @key(fields: "id") { + id: ID!, name: String!, fullName: String! @external, surname: String! + } + type Admin implements Named @key(fields: "id") { + id: ID!, name: String! @requires(fields: "fullName"), fullName: String! @external, title: String! + } + type Query { user: Named! } + `, + dsBuilder: func() *dsBuilder { + return dsb(). + RootNode("Query", "user"). + RootNode("User", "id", "name", "surname"). + AddRootNodeExternalFieldNames("User", "fullName"). + RootNode("Admin", "id", "name", "title"). + AddRootNodeExternalFieldNames("Admin", "fullName"). + ChildNode("Named", "name"). + WithMetadata(func(m *FederationMetaData) { + m.Requires = []FederationFieldConfiguration{ + { TypeName: "Admin", FieldName: "name", SelectionSet: "fullName" }, + } + m.Keys = []FederationFieldConfiguration{ + { TypeName: "User", SelectionSet: "id" }, + { TypeName: "Admin", SelectionSet: "id" }, + } + }) + }(), + fieldName: "user", + operation: ` + query { + user { + name + ... on Admin { title } + } + }`, + expectedOperation: ` + query { + user { + name + ... on Admin { title } + } + }`, + shouldRewrite: false, + },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
v2/pkg/engine/plan/abstract_selection_rewriter.go(1 hunks)v2/pkg/engine/plan/abstract_selection_rewriter_test.go(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
v2/pkg/engine/plan/abstract_selection_rewriter_test.go (1)
v2/pkg/engine/plan/federation_metadata.go (2)
FederationMetaData(10-16)FederationFieldConfiguration(73-82)
🔇 Additional comments (2)
v2/pkg/engine/plan/abstract_selection_rewriter_test.go (2)
222-297: Nice, focused federation fixture for @requires on interface implementationsThe Named/User/Admin setup plus dsBuilderC cleanly models the requires/external scenario and keeps tests readable. LGTM.
4049-4076: Tests correctly assert rewriting for @requires on interface membersBoth no-fragment and mixed-fragment paths validate the new behavior. Nicely done.
🤖 I have created a release *beep* *boop* --- ## [2.0.0-rc.226](v2.0.0-rc.225...v2.0.0-rc.226) (2025-09-12) ### Bug Fixes * detecting requires on interface members ([#1295](#1295)) ([70bd5d5](70bd5d5)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Correctly detect "requires" on interface members, improving accuracy in dependency/interface validation scenarios. * **Documentation** * Updated changelog with entry for version 2.0.0-rc.226 detailing the bug fix. * **Chores** * Bumped release version to 2.0.0-rc.226. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary by CodeRabbit
Bug Fixes
Tests
Checklist