rover
rover copied to clipboard
'rover diff' to for changes between local versions of a schema
Description
Currently rover [sub]graph check
commands check for changes against a registry version of a schema. It might be useful to be able to check for breaking changes between two local version of schema. An API to consider:
rover [sub]graph diff ./schema_1.graphql ./schema_2.graphql
Because checks are done in the registry, this new command will require us to maintain code to do the checks ourselves which should be a consideration for when deciding to take up this issue. Another consideration to think about is whether a 'local' check and a 'registry' check should be under two different 'verbs' (so check
and diff
) or whether we should be combining the two. I am partial to having them separate for extra clarity to the user as to which functionality they are triggering.
Prior Art
@martinbonnin brought up that people currently use graphql-inspector for similar functionality, which I think we can use for inspiration.
This would be really cool functionality to have locally as well as in the cloud. We spent some time investigating what it would take to build out a "complete" diff algorithm that could be used both for rich user visibility as well as to power some features that are valuable atop the diff itself (like checks) and outlined some of the behavior in this card: https://apollographql.atlassian.net/browse/GM-1279
I think that if we plan to build out a diff
experience locally with Rover, we will want to ensure that the diff
experience is in alignment with what we build out in Studio as well, and there might be some benefits to letting the diff
be calculated server-side so that we can change it as GraphQL changes without needing users to update their clients. That said, I think if we can create something that's more complete to the schema language itself, it should be pretty stable and then we would just want to think about a code reuse solution to maintain alignment.
Pulling in @jsegaran and @alexandermann for their knowledge and awareness, too :)
I don't think we should have different commands for diffing a subgraph and graph. We are at diffing two schemas, so the diff should be based solely on the contents of the files rather than if this is a subgraph core schema or a graph core schema.
Initially having diffs be something built in studio would probably be the easiest thing to iterate, since we don't really know the ergonomics and format of the diff we want in studio at least and will probably be iterating on this for a while. I am somewhat hesitant to have the diff format from rover and studio start to diverge.
For studio at least we want to build a complete reversible diffing algorithm that we can use for checks, changelog, field history. I think there are still open questions for how we would want to treat renames, directive ordering/re-ordering, special handling for schemas with core features?
The rust graphql-parser is still missing some core features of graphql syntax. It doesn't currently allow interfaces implementing interfaces, but graphql validation and parsing rules have been changing over time (repeatable directives, interfaces on interfaces, arguments can be deprecated (validation not parsing)).
I think iterating on it our backends will make it so we can continue to change/improve on it without forcing people to upgrade or having a long tail of people seeing different diffs. Also I don't think it would be a big ask to require connection to studio to compute a diff. It could even be done with an un-authenticated root query field that just accepts two schema documents and returns some diff type.
Rather than focus on where the diff would run I'd recommend if and when we work on this we come up with the diff format, independent from a specific implementation, and accept that there may be multiple implementations over time. If the goal is to have a diff format that's useful to other tooling and not just for human readability the format itself needs to be stable enough to work with.