Rover graph Commands

Publish and retrieve your API schema


These Rover commands are primarily for interacting with monographs that do not use federation. However, you can also use them to fetch a federated graph's API schema from GraphOS or via introspection.

note

Fetching a schema

graph fetch

This command requires authenticating Rover with GraphOS.

You can use Rover to fetch the current schema of any GraphOS graph and variant it has access to.

Run the graph fetch command, like so:

Bash
1rover graph fetch my-graph@my-variant

The argument my-graph@my-variant in the example above specifies the ID of the Studio graph you're fetching from, along with which variant you're fetching.

If you omit @ and the variant name, Rover uses the supergraph's default variant, named current.

graph introspect

If you need to obtain the schema of a running GraphQL server or federated gateway, you can use Rover to execute an introspection query on it. This is especially helpful if you're developing a GraphQL server that doesn't define its schema via SDL, such as graphql-kotlin.

Use the graph introspect command, like so:

shell
1rover graph introspect http://example.com/graphql

The server must be reachable by Rover and it must have introspection enabled.

Watching for schema changes

If you pass --watch to rover graph introspect, Rover introspects your GraphQL endpoint continuously. Whenever the returned schema differs from the previously returned schema, Rover outputs the updated schema.

Including headers

If the endpoint you're trying to reach requires HTTP headers, you can use the --header (-H) flag to pass key:value pairs of headers. If you have multiple headers to pass, use the header multiple times. If the header includes any spaces, the pair must be quoted.

shell
1rover graph introspect http://example.com/graphql --header "Authorization: Bearer token329r"

Introspection JSON output

By default, graph introspect outputs the schema as SDL. Use --format json to get machine-readable GraphQL introspection JSON. In the JSON envelope, data.introspection_response is the { "__schema": ... } object. This matches the format produced by legacy Apollo CLI commands such as apollo service:download and apollo schema:download, and is useful when migrating workflows that expect introspection JSON (for example, tools that consumed output from apollo client:download-schema against a running endpoint).

shell
1rover graph introspect http://localhost:4000 --format json
2rover graph introspect http://localhost:4000 --format json | jq '.data.introspection_response' > schema.json

To save the bare introspection JSON file (without Rover's envelope), pipe through jq as shown above. No field or value transformation is needed beyond traversing the envelope.

SDL remains the default output format and is still recommended when publishing schemas to GraphOS.

For example, for an endpoint whose schema is a single Query type, the default text output is the SDL:

terminal
type Query {
  hello: String
}

With --format json, the same schema is returned as introspection JSON inside the envelope (the ... stands for the rest of the introspection payload, which is much longer for a real schema):

JSON
1{
2  "json_version": "1",
3  "data": {
4    "introspection_response": {
5      "__schema": {
6        "queryType": { "name": "Query" },
7        ...
8      }
9    },
10    "success": true
11  },
12  "error": null
13}

Output format

By default, graph fetch and graph introspect output fetched SDL to stdout. This is useful for providing the schema as input to other Rover commands:

shell
1rover graph introspect http://localhost:4000 | rover graph publish my-graph@dev --schema -

You can also save SDL output to a local .graphql file like so:

Bash
1# Creates prod-schema.graphql or overwrites if it already exists
2rover graph fetch my-graph@my-variant --output prod-schema.graphql

To save introspection JSON instead of SDL, use --format json with graph introspect. See Introspection JSON output for details.

For more on passing values via stdout, see Conventions.

Publishing a schema to GraphOS

graph publish

This command requires authenticating Rover with GraphOS.

You can use Rover to publish schema changes to one of your GraphOS monographs.

Use the graph publish command, like so:

shell
1rover graph publish my-graph@my-variant --schema ./schema.graphql

The argument my-graph@my-variant in the example above specifies the ID of the GraphOS graph you're publishing to, along with which variant you're publishing to.

If the graph exists in GraphOS but the variant doesn't, Rover creates a new variant on publish.

Pass --changelog-message to attach a message to this publish in the GraphOS Studio changelog:

shell
1rover graph publish my-graph@my-variant --schema ./schema.graphql \
2  --changelog-message "Add the Product.reviews field"

After publishing, Rover waits for the launch the publish triggers to finish. For details, see Waiting for launches.

Providing the schema

You provide your schema to Rover commands via the --schema option. The value is usually the path to a local .graphql or .gql file in SDL format.

If your schema isn't stored in a compatible file, you can provide - as the value of the --schema flag to instead accept an SDL string from stdin. This enables you to pipe the output of another Rover command (such as graph introspect), like so:

shell
1rover graph introspect http://localhost:4000 | rover graph publish my-graph@dev --schema -

Whenever possible, we recommend publishing a .graphql file directly instead of using introspection. An introspection result omits schema comments and most uses of directives.

For more on accepting input via stdin, see Conventions.

Running checks before publishing

Use the --check flag to run all configured schema checks and then publish in a single command. If any checks fail, the publish is aborted and no schema changes are pushed to the registry.

Running check and publish as two separate commands introduces two risks:

  • Human error — You must type or paste both commands with identical arguments. A mismatched --schema path or graph ref means you could publish a schema that was never actually checked.

  • Race conditions — Another team member could publish a change between your check and your publish, so the check result no longer reflects the state of the graph at publish time.

--check eliminates both risks by treating the check and publish as one atomic operation.

The --check flag honors all schema check settings configured for your graph variant in GraphOS Studio—including linting rules, operation checks, and any other check configurations—exactly as a standalone rover graph check would.

To exemplify the difference, here is the previous two-step approach:

shell
1# Step 1: check
2rover graph check my-graph@current --schema ./schema.graphql
3
4# Step 2: publish (only safe if nothing changed between the two commands)
5rover graph publish my-graph@current --schema ./schema.graphql

With --check, both steps happen in one command:

shell
1rover graph publish my-graph@current --schema ./schema.graphql --check

If all checks pass, Rover publishes the schema and then waits for the launches it triggers. If any check fails, Rover prints the check output and exits without publishing. A failed check fails with error E043, as it does for graph check, with the message Schema checks must pass before publishing. Fix the check failures above and try again. With --format json, data is the check result, in the same shape as graph check's, and json_version is "3".

--include-contract-checks applies to the check that --check runs, as it does for graph check, and also to the launches the publish waits for.

--background doesn't apply to a publish, because --check always waits for the check: the check decides whether the publish happens. graph publish accepts --background for compatibility with earlier versions of Rover, ignores it, and warns:

Text
1Warning: `--background` has moved to `rover graph check --background`, and will be removed from `rover graph publish` in a future version. It has no effect here: `publish --check` always waits for the check, because the check decides whether the publish happens.

For details on configuring checks (time range, operation thresholds, and linting rules), see the graph check section. The --query-count-threshold, --query-percentage-threshold, and --validation-period options override the check configuration for the checks that --check runs, as they do for graph check.

Waiting for launches

When a publish changes the schema, it triggers a launch on the variant, and the launch can trigger launches on downstream contract variants. Rover waits for the triggered launch and every downstream contract-variant launch to finish before it exits. The wait is bounded by --checks-timeout (or the APOLLO_CHECKS_TIMEOUT_SECONDS environment variable), which defaults to 300 seconds. With --check, the check and the launch each get their own wait. If the launch wait times out, Rover fails with error E065. The schema is already published and the launch may still finish in GraphOS. With --format json, data still includes the publish response, with launch_status null, because Rover stopped waiting before it learned the outcome.

If the publish triggered downstream launches, Rover reports them on stderr:

Text
1Triggered downstream launches for 2 contract variants: mobile, partner-api.
2View launch details at: https://studio.apollographql.com/graph/my-graph/launches/launch-1

When it prints this report, Rover first prints this note:

Text
1Note: a future version of `rover graph publish` will include this report in its stdout output. If you need to reliably parse just the schema hash, use `--format json` and read `.data.api_schema_hash`.

If a downstream contract-variant launch fails, Rover prints a warning and exits successfully:

Text
1Warning: The publish succeeded, but a downstream contract launch failed: mobile. Pass --include-contract-checks to make this fail the command.
2View launch details at: https://studio.apollographql.com/graph/my-graph/launches/launch-2

With --format json, the failed launch's status is FAILED in downstream_launches, and error is null.

If the variant's own launch fails, or a downstream launch fails and you passed --include-contract-checks, Rover reports which one failed and exits with error E047:

Text
1The publish succeeded, but downstream contract launches failed: mobile, partner-api.
2View launch details at: https://studio.apollographql.com/graph/my-graph/launches/launch-2

The schema is still published. With --format json, data keeps the full publish response alongside the E047 error.

With --format json, data includes the launch results. For example, a publish that triggered a launch and one downstream contract-variant launch, both completed:

JSON
1{
2  "json_version": "1",
3  "data": {
4    "api_schema_hash": "123456",
5    "field_changes": { "additions": 0, "removals": 0, "edits": 0 },
6    "type_changes": { "additions": 0, "removals": 0, "edits": 0 },
7    "total_type_count": 1,
8    "launch_url": "https://studio.apollographql.com/graph/my-graph/launches/launch-1",
9    "launch_status": "COMPLETED",
10    "launch_superseded": false,
11    "downstream_launches": [
12      {
13        "graph_id": "my-graph",
14        "variant_name": "mobile",
15        "status": "COMPLETED",
16        "superseded": false,
17        "url": "https://studio.apollographql.com/graph/my-graph/launches/launch-2"
18      }
19    ],
20    "success": true
21  },
22  "error": null
23}

The launch fields are:

  • launch_url: the Studio URL of the triggered launch, or null if the publish triggered none

  • launch_status: the launch's final status, such as COMPLETED or FAILED, or null

  • launch_superseded: true if a later publish to the same variant superseded the launch

  • downstream_launches: one entry per triggered contract-variant launch, with graph_id, variant_name, status, superseded, and url

With --include-contract-checks, a failed downstream contract-variant launch fails the publish with E047, and data keeps the full publish response:

JSON
1{
2  "json_version": "1",
3  "data": {
4    "api_schema_hash": "123456",
5    "field_changes": { "additions": 0, "removals": 0, "edits": 0 },
6    "type_changes": { "additions": 0, "removals": 0, "edits": 0 },
7    "total_type_count": 1,
8    "launch_url": "https://studio.apollographql.com/graph/my-graph/launches/launch-1",
9    "launch_status": "COMPLETED",
10    "launch_superseded": false,
11    "downstream_launches": [
12      {
13        "graph_id": "my-graph",
14        "variant_name": "mobile",
15        "status": "FAILED",
16        "superseded": false,
17        "url": "https://studio.apollographql.com/graph/my-graph/launches/launch-2"
18      }
19    ],
20    "success": false
21  },
22  "error": {
23    "message": "The publish to 'my-graph@current' succeeded, but a triggered launch did not complete successfully. See the launch report above for details.",
24    "code": "E047"
25  }
26}

For how this differs from earlier versions of Rover, see Upgrading to Rover 1.0.

Validating schema changes

graph check

This command requires authenticating Rover with GraphOS.

Before you publish schema changes to GraphOS, you can check those changes to confirm that you aren't introducing breaking changes to your application clients.

To do so, you can run the graph check command:

shell
1# Using a schema file
2rover graph check my-graph@my-variant --schema ./schema.graphql
3
4# Using piped input to stdin
5rover graph introspect http://localhost:4000 | rover graph check my-graph --schema -

As shown, arguments and options are similar to graph publish.

To configure the behavior of schema checks (such as the time range of past operations to check against), see the documentation for schema checks.

If you don't want to wait for the check to complete, you can run the command with the --background flag. You can then look up the check's result in GraphOS Studio on the Checks tab.

If your graph has contract variants, pass --include-contract-checks to also fail the check when a blocking contract variant's own check has failed, even if the overall GraphOS result for the check says it passed. See Check output.

Check output

Rover prints a section for each check task that ran, such as Operation Check [PASSED]:. The Operation Check section appears even when the check found no schema changes.

If your graph has contract variants, the output ends with a Downstream Check section that summarizes the contract variants checked:

Text
1Downstream Check [PASSED]:
2Checked 2 contract variants, all passed.
3View downstream check details at: https://studio.apollographql.com/graph/my-graph/checks/downstream

The summary line is one of:

  • No contract variants configured for this graph.

  • Checked N contract variants, all passed.

  • Checked N contract variants. (when not every contract variant passed)

A contract variant can be configured to block its source variant's checks. If a blocking contract variant's check fails, the summary names it. By default, graph check passes or fails with the overall GraphOS result for the check, and fails with error E043 when that result is a failure. Pass --include-contract-checks to fail with E043 whenever a blocking contract variant's own check has failed, even if the overall GraphOS result says the check passed:

Text
1Downstream Check [FAILED]:
2The downstream check task has encountered check failures for at least this blocking downstream variant: mobile.
3View downstream check details at: https://studio.apollographql.com/graph/my-graph/checks/downstream

A failed check on a non-blocking contract variant appears in the output but doesn't fail the command.

Without --include-contract-checks, a blocking contract variant's failed check can appear under a passing Downstream Check [PASSED]: heading, when the overall GraphOS result is a pass. The command then exits successfully.

With --format json, check output uses json_version "3". The downstream task lists each contract variant in variants, with graph_id, variant_name, blocking, fails_upstream_workflow, and status:

JSON
1{
2  "json_version": "3",
3  "data": {
4    "tasks": {
5      "downstream": {
6        "task_status": "FAILED",
7        "target_url": "https://studio.apollographql.com/graph/my-graph/checks/downstream",
8        "variants": [
9          {
10            "graph_id": "my-graph",
11            "variant_name": "mobile",
12            "blocking": true,
13            "fails_upstream_workflow": null,
14            "status": "FAILED"
15          }
16        ]
17      }
18    },
19    "success": false
20  },
21  "error": {
22    "message": "The changes in the schema you proposed caused downstream checks to fail.",
23    "code": "E043"
24  }
25}

For what changed from json_version "2", see Upgrading to Rover 1.0.

Running checks in CI

If you're running schema checks in CI, you might want to pass the --background flag to rover graph check. This flag instructs Rover to initiate schema checks but not await their result. If you've connected GraphOS to your GitHub repository, the integration detects the checks execution and adds a status to the associated pull request.

graph lint

This command requires authenticating Rover with GraphOS.

You can run the GraphOS schema linter against your local schema to identify any violations of formatting and naming best practices:

Bash
Example command
1rover graph lint --schema ./schema.graphql my-graph@my-variant

The argument my-graph@my-variant in the example above is a graph ref that specifies the ID of the graph you're comparing your schema changes against, along with which variant you're comparing against.

Schema linting also runs as one of the checks included in graph check. Use this command to perform one-off linting.

Options include:

Name Description
--schema
Required. The path to a local .graphql or .gql file, in SDL format.Alternatively, you can provide -, in which case the command uses an SDL string piped to stdin instead (see Using stdin).
--ignore-existing-lint-violations
If provided, the linter only flags violations that are present in the diff between your local schema and your published schema.By default, this command flags all violations in your local schema.

Deleting a variant

graph delete

This command requires authenticating Rover with GraphOS.

You can delete a single variant of a graph by running rover graph delete:

Bash
1# ⚠️ This action is irreversible!
2rover graph delete my-graph@variant-to-delete

This command prompts you for confirmation because the action is irreversible. You can bypass confirmation by passing the --confirm flag.

If you delete a federated variant with this command, it also deletes all of that variant's subgraphs. To delete a single subgraph while preserving the variant, see Deleting a subgraph.