apollographql / rover

The CLI for Apollo GraphOS
https://rover.apollo.dev
Other
404 stars 84 forks source link

`supergraph compose` works from URL but doesn't work from file #1566

Closed maxkomarychev closed 3 weeks ago

maxkomarychev commented 1 year ago

Description

Describe the issue that you're seeing.

I am trying to compose a supergraph (for now just with one subgraph) from a dummy service.

Steps to reproduce

  1. clone repo https://github.com/maxkomarychev/rover-compose-problem-demo
  2. npm i
  3. npm run start:dev
  4. install rover 0.13.0

When creating a supergraph with the following config it works fine:

federation_version: '=2.3.2'
subgraphs:
  users:
    routing_url: http://localhost:4001/graphql
    schema:
      subgraph_url: http://localhost:4001/graphql

However if I download file from http://localhost:4001/graphql and try to run rover with this config:

federation_version: '=2.3.2'
subgraphs:
  users:
    routing_url: http://localhost:4001/graphql
    schema:
      file: ./users.graphql
users.graphql ```graphql directive @link( url: String as: String for: link__Purpose import: [link__Import] ) on SCHEMA directive @key( fields: federation__FieldSet! resolvable: Boolean = true ) on OBJECT | INTERFACE directive @requires(fields: federation__FieldSet!) on FIELD_DEFINITION directive @provides(fields: federation__FieldSet!) on FIELD_DEFINITION directive @external(reason: String) on OBJECT | FIELD_DEFINITION directive @tag( name: String! ) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION | SCHEMA directive @extends on OBJECT | INTERFACE directive @shareable on OBJECT | FIELD_DEFINITION directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION directive @override(from: String!) on FIELD_DEFINITION directive @composeDirective(name: String) on SCHEMA directive @interfaceObject on OBJECT type User { id: ID! name: String! dob: String! } type Query { users: [User!]! user(id: ID!): User! _entities(representations: [_Any!]!): [_Entity]! _service: _Service! } type Mutation { createUser(name: String!): User! } enum link__Purpose { # `SECURITY` features provide metadata necessary to securely resolve fields. SECURITY # `EXECUTION` features provide metadata necessary for operation execution. EXECUTION } scalar link__Import scalar federation__FieldSet scalar _Any type _Service { sdl: String } union _Entity = User ```

it fails with the following errors

⌛ resolving SDL for subgraphs defined in supergraph.yaml
🎶 composing supergraph with Federation v2.3.2
error[E029]: Encountered 4 build errors while trying to build a supergraph.

Caused by:
    UNKNOWN: [users] Invalid definition for directive "@key": argument "fields" should have type "_FieldSet!" but found type "federation__FieldSet!"
    UNKNOWN: [users] Invalid definition for directive "@requires": argument "fields" should have type "_FieldSet!" but found type "federation__FieldSet!"
    UNKNOWN: [users] Invalid definition for directive "@provides": argument "fields" should have type "_FieldSet!" but found type "federation__FieldSet!"
    UNKNOWN: [users] Invalid definition for directive "@tag": "@tag" should have locations FIELD_DEFINITION, OBJECT, INTERFACE, UNION, ARGUMENT_DEFINITION, SCALAR, ENUM, ENUM_VALUE, INPUT_OBJECT, INPUT_FIELD_DEFINITION, but found (non-subset) FIELD_DEFINITION, OBJECT, INTERFACE, UNION, ARGUMENT_DEFINITION, SCALAR, ENUM, ENUM_VALUE, INPUT_OBJECT, INPUT_FIELD_DEFINITION, SCHEMA

Expected result

Composition should work equally well with both URL and file-based schemas.

Actual result

Error when attempting to compose from a file

⌛ resolving SDL for subgraphs defined in supergraph.yaml
🎶 composing supergraph with Federation v2.3.2
error[E029]: Encountered 4 build errors while trying to build a supergraph.

Caused by:
    UNKNOWN: [users] Invalid definition for directive "@key": argument "fields" should have type "_FieldSet!" but found type "federation__FieldSet!"
    UNKNOWN: [users] Invalid definition for directive "@requires": argument "fields" should have type "_FieldSet!" but found type "federation__FieldSet!"
    UNKNOWN: [users] Invalid definition for directive "@provides": argument "fields" should have type "_FieldSet!" but found type "federation__FieldSet!"
    UNKNOWN: [users] Invalid definition for directive "@tag": "@tag" should have locations FIELD_DEFINITION, OBJECT, INTERFACE, UNION, ARGUMENT_DEFINITION, SCALAR, ENUM, ENUM_VALUE, INPUT_OBJECT, INPUT_FIELD_DEFINITION, but found (non-subset) FIELD_DEFINITION, OBJECT, INTERFACE, UNION, ARGUMENT_DEFINITION, SCALAR, ENUM, ENUM_VALUE, INPUT_OBJECT, INPUT_FIELD_DEFINITION, SCHEMA

Environment

Rover Info:
Version: 0.13.0
Install Location: /Users/<username>/.rover/bin/rover
OS: Mac OS 12.6.3 [64-bit]
Shell: /bin/zsh
gabrielbahniuk commented 4 months ago

Does anyone know how to make this work? @maxkomarychev did you workaround this?

I have the same scenario where using file doesn't work but remote works just fine.

I'm using rover 0.23.0

p.s. in my case I must use file, not subgraph_url.

jonathanrainer commented 1 month ago

Hi @maxkomarychev,

Thanks so much for raising this, can I just ask, is there a reason you're using the output of introspection as a schema file to watch? I think the issue here arises from the fact that the schema that comes out of introspection is perfectly fine to read but has undergone some transformations that mean it is harder for rover to use for composition.

By way of example, following your instructions above you do indeed get the errors stated. However, if you transform the users schema into the following

extend schema
@link(url: "https://specs.apollo.dev/federation/v2.8",
  import: ["@key", "@shareable"])

type User @key(fields: "id") {
  id: ID!
  name: String!
  dob: String!
}

type Query {
  users: [User!]!
  user(id: ID!): User!
}

type Mutation {
  createUser(name: String!): User!
}

You can then run this in rover dev (and by extensions supergraph compose) with no problems. In general if you're maintaining a schema that is in a file it tends to have a different format to what would come back via introspection for lots of technical reasons. This is alluded to in the docs but I appreciate this isn't amazingly clear. Would it be possible to massage the schema of the subgraph if you wanted to watch a file, or is there some context I'm missing?

jonathanrainer commented 3 weeks ago

Hi @maxkomarychev , thanks again for raising this, since it's been over a month I'm going to close this issue. If you're having more problems please feel free to re-open the issue and we can take another look. Thanks!