-
Notifications
You must be signed in to change notification settings - Fork 257
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
feat: Add the schema coordinate to all CompositionHints in composition-js #2658
feat: Add the schema coordinate to all CompositionHints in composition-js #2658
Conversation
|
Name | Link |
---|---|
🔨 Latest commit | 50861949f6ca810df97a8fa05fc60faffbe3693f |
🦋 Changeset detectedLatest commit: 187e036 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. |
a1f07fe
to
c56a570
Compare
@@ -390,6 +392,7 @@ export class ComposeDirectiveManager { | |||
this.pushHint(new CompositionHint( | |||
HINTS.DIRECTIVE_COMPOSITION_WARN, | |||
`Composed directive "@${name}" is named differently in a subgraph that doesn't export it. Consistent naming will be required to export it.`, | |||
name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this also be prepended with an @
?
composition-js/src/merging/merge.ts
Outdated
const name = dest instanceof NamedSchemaElement ? `Element "${dest.coordinate}"` : 'The schema definition'; | ||
const coordinate = dest instanceof NamedSchemaElement ? dest.coordinate : undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're already computing this value, we can just reuse it.
const name = dest instanceof NamedSchemaElement ? `Element "${dest.coordinate}"` : 'The schema definition'; | |
const coordinate = dest instanceof NamedSchemaElement ? dest.coordinate : undefined; | |
const coordinate = dest instanceof NamedSchemaElement ? dest.coordinate : undefined; | |
const name = coordinate ? `Element "${coordinate}"` : 'The schema definition'; |
composition-js/src/merging/merge.ts
Outdated
@@ -2468,6 +2489,7 @@ class Merger { | |||
this.mismatchReporter.pushHint(new CompositionHint( | |||
HINTS.MERGED_NON_REPEATABLE_DIRECTIVE_ARGUMENTS, | |||
`Directive @${name} is applied to "${(dest as any)['coordinate'] ?? dest}" in multiple subgraphs with different arguments. Merging strategies used by arguments: ${info.argumentsMerger}`, | |||
name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need an @
here as well?
@@ -2468,6 +2489,7 @@ class Merger { | |||
this.mismatchReporter.pushHint(new CompositionHint( | |||
HINTS.MERGED_NON_REPEATABLE_DIRECTIVE_ARGUMENTS, | |||
`Directive @${name} is applied to "${(dest as any)['coordinate'] ?? dest}" in multiple subgraphs with different arguments. Merging strategies used by arguments: ${info.argumentsMerger}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can compute the coordinate like this instead (and reuse it here and below where we're doing the other as any
cast)?
const coordinate = `${'coordinate' in dest && dest.coordinate ? dest.coordinate : dest}`;
@@ -143,6 +143,7 @@ export class ComposeDirectiveManager { | |||
this.pushHint(new CompositionHint( | |||
HINTS.DIRECTIVE_COMPOSITION_INFO, | |||
`Non-composed core feature "${coreIdentity}" has major version mismatch across subgraphs`, | |||
coreIdentity, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like our testing story is a bit inconsistent, which is not your fault.
i.e. if I change this to, say, undefined
, tests still pass. But if I remove the this.pushHint(...)
there is a test that fails (which doesn't use the toRaiseHint
matcher.
I'd like it if we addressed these inconsistencies so there's coverage for all of your additions. Let me know if you'd like me to help with that, since I think that's an "us" problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: this is the only one I checked, so for now I'm not checking the others or leaving comments on them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure if we get the testing story consistent it'll reveal the directive name errors that I pointed out above (or reveal that we're just lacking coverage on those particular hints altogether).
Please add a |
@@ -174,6 +175,7 @@ export class ComposeDirectiveManager { | |||
this.pushHint(new CompositionHint( | |||
HINTS.DIRECTIVE_COMPOSITION_INFO, | |||
`Directive "@${directive.name}" should not be explicitly manually composed since it is a federation directive composed by default`, | |||
`@${directive.name}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should avoid manually crafting any coordinate when the coordinate
property exists.
In fact, see my suggestion on the ctor of CompositionHint
which would pretty much guarantee this by design.
composition-js/src/hints.ts
Outdated
@@ -235,6 +235,7 @@ export class CompositionHint { | |||
constructor( | |||
readonly definition: HintCodeDefinition, | |||
readonly message: string, | |||
readonly coordinate: string | undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest changing this argument to be the (main) element that is the target of the hint, so something like:
export class CompositionHint {
public readonly nodes?: readonly SubgraphASTNode[];
public readonly coordinate?: string;
constructor(
readonly definition: HintCodeDefinition,
readonly message: string,
element: NamedSchemaElement | undefined,
) {
this.coordinate = element?.coordinate;
....
}
...
}
Imo this has a bunch of advantages:
- this is more precisely typed.
string
is not the most helpful type: it's really easy to pass something that isn't a valid coordinate and have this go undetected. PassingNamedSchemaElement
makes it less error prone and guaranteed we will get a valid coordinate at the end of the day. - practically, this avoid having to repeat
.coodinate
on almost all callsite, which feel kinda nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review! This makes sense to me, I will make this change and post a new revision
@@ -112,6 +113,7 @@ export class MismatchReporter { | |||
message: string, | |||
supergraphElement: TMismatched, | |||
subgraphElements: (TMismatched | undefined)[], | |||
coordinate: string | undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same remarks as in CompositionHint
: we should imo pass element: NamedSchemaElement | undefined
.
In fact, it's worth double checking, but I suspect we can avoid the need of that argument, at least in most case, as supergraphElement
is usually what we want here (when it is a NamedSchemaElement
at least; and when it isn't, we want undefined
). From a quick look, it seems that there is 2 special cases where that's not quite true, for hints on enum values and union members where supergraphElement
is the type itself, but we ideally would want to pass the value/member itself. But I'd personally suggest adding an optional argument (say, targetedElement?: NamedSchemaElement
and only pass it when it's not equal to supergraphElement
(and default to the later when targetedElement
is not provided).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You were correct, I noticed that while going through and fixing unit tests. I have added the targetedElement?: NamedSchemaElement
to this function and filled in it for the Enum value cases.
Co-authored-by: Samuel Collard <[email protected]>
Overview
As part of pulling Composition Hints and all build messages into Apollo Studio and GraphOS we want to align on specifying errors, warnings, and lint errors around the schema coordinate. The easiest way to start aligning all those would be to include the schema coordinate in the Composition Hint. This PR adds the optional String to the CompositionHint class and implements setting the coordinate in all instances where CompositionHint objects are constructed.
Changes
coordinate
Testing
Expanded existing unit tests to also verify the coordinate is correct