Skip to content

New spec validation: Subscriptions root field must not contain @skip nor @include on root selection set #3871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 1, 2025

Conversation

dondonz
Copy link
Member

@dondonz dondonz commented Mar 29, 2025

Fixes #3868 and implements graphql/graphql-spec#860

We had an existing validation for subscription root fields. This adds on a new requirement that subscription root fields can't contain the @include nor @skip directives. See the spec link for more.

This could be considered a "breaking change" but it is more correctly a new validation requirement.

@@ -27,7 +27,7 @@
import graphql.validation.rules.PossibleFragmentSpreads;
import graphql.validation.rules.ProvidedNonNullArguments;
import graphql.validation.rules.ScalarLeaves;
import graphql.validation.rules.SubscriptionUniqueRootField;
import graphql.validation.rules.SubscriptionRootField;
Copy link
Member Author

Choose a reason for hiding this comment

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

I changed this rule name to be more generic, reflecting that it does 2 checks on the root field

@@ -39,16 +47,24 @@ public void checkOperationDefinition(OperationDefinition operationDef) {

GraphQLObjectType subscriptionType = getValidationContext().getSchema().getSubscriptionType();

// This coercion takes into account default values for variables
Copy link
Member Author

Choose a reason for hiding this comment

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

This is fixing an edge case - this check previously didn't take into account default variable values because there was previously no coercion.

That caused my tests to fail (see later) because I had set a default boolean value for include and skip.

.objectType(subscriptionType)
.graphQLContext(getValidationContext().getGraphQLContext())
.build();

MergedSelectionSet fields = fieldCollector.collectFields(collectorParameters, operationDef.getSelectionSet());
List<Selection> subscriptionSelections = operationDef.getSelectionSet().getSelections();
Copy link
Member Author

Choose a reason for hiding this comment

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

Unused variable


private boolean hasSkipOrIncludeDirectives(MergedField field) {
List<Directive> directives = field.getSingleField().getDirectives();
for (Directive directive : directives) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Given recent performance improvements I am using plain for loops

@@ -68,9 +68,8 @@ ScalarLeaves.subselectionOnLeaf=Validation error ({0}) : Subselection not allowe
ScalarLeaves.subselectionRequired=Validation error ({0}) : Subselection required for type ''{1}'' of field ''{2}''
#
SubscriptionUniqueRootField.multipleRootFields=Validation error ({0}) : Subscription operation ''{1}'' must have exactly one root field
SubscriptionUniqueRootField.multipleRootFieldsWithFragment=Validation error ({0}) : Subscription operation ''{1}'' must have exactly one root field with fragments
Copy link
Member Author

Choose a reason for hiding this comment

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

Unused messages

Copy link
Contributor

github-actions bot commented Mar 29, 2025

Test Results

  312 files    312 suites   45s ⏱️
3 583 tests 3 577 ✅ 6 💤 0 ❌
3 672 runs  3 666 ✅ 6 💤 0 ❌

Results for commit 0219c47.

♻️ This comment has been updated with latest results.

SubscriptionIntrospectionRootField.introspectionRootField=Validierungsfehler ({0}) : Subscription operation ''{1}'' root field ''{2}'' kann kein introspection field sein
SubscriptionIntrospectionRootField.introspectionRootFieldWithFragment=Validierungsfehler ({0}) : Subscription operation ''{1}'' fragment root field ''{2}'' kann kein introspection field sein
SubscriptionRootField.forbidSkipAndIncludeOnSubscriptionRoot=Validierungsfehler ({0}) : Subscription operation ''{1}'' root field ''{2}'' darf weder @skip noch @include directive in top level selection
#
Copy link
Member Author

Choose a reason for hiding this comment

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

Check my German please

def "valid subscription with @skip and @include directives on subfields"() {
given:
def query = """
subscription MySubscription(\$bool: Boolean = true) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is what I mean by default values. When an empty coerced variables map is passed, this test fails

SubscriptionIntrospectionRootField.introspectionRootField=Validatiefout ({0}) : Subscription operation ''{1}'' root field ''{2}'' kan geen introspectieveld zijn
SubscriptionIntrospectionRootField.introspectionRootFieldWithFragment=Validatiefout ({0}) : Subscription operation ''{1}'' fragment root field ''{2}'' kan geen introspectieveld zijn
SubscriptionRootField.forbidSkipAndIncludeOnSubscriptionRoot=Validation error ({0}) : Subscription operation ''{1}'' root field ''{2}'' must not use @skip nor @include directives in top level selection
Copy link
Member Author

Choose a reason for hiding this comment

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

Add English placeholder

@dondonz dondonz added the spec-change Tracking GraphQL specification changes label Mar 29, 2025
@dondonz dondonz added the breaking change requires a new major version to be relased label Apr 1, 2025
@dondonz dondonz merged commit 12273f4 into master Apr 1, 2025
2 checks passed
@dondonz dondonz deleted the subscriptions-root-field branch April 1, 2025 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change requires a new major version to be relased spec-change Tracking GraphQL specification changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tracking spec change: Prevent @skip and @include on root subscription selection set
2 participants