Graph Environment Best Practices

Best practices and examples when using graph variants for multiple deployment environments


Learn CI/CD best practices and examples for using graph variants for multiple deployment environments.

In a typical deployment architecture, organizations set up multiple environments—such as development, pre-prod, and prod—with each having a separate Kubernetes cluster and database. They create separate CI/CD jobs for each environment or configure them to behave differently based on environment-specific variables. They use in GraphOS a dedicated graph variant for each environment, with each variant representing a specific copy of the graph for that environment.

The setup for a typical deployment architecture begins with code and schemas in source control. A CI/CD system both deploys code to a target deployment environment and publishes schemas to GraphOS, which then provides the schemas to a deployment environment:

💡 tip
The purpose of publishing your subgraph schemas to GraphOS is so that they can be composed into a supergraph which is consumed by the router. Each router will be configured to consume a specific variant via a fixed graph reference. As a result, it's important that graph references/variant names are fixed, such as aligning them with each environment as demonstrated in this article.

Source control branches for variants

The source control branching model you use affects the branch in which the code for a graph variant is developed. Let's go over examples for a few common branching models.

Git flow (feature, develop, main)

In Git Flow, you typically have a develop branch and a main branch, where develop contains the code under-development that hasn't necessarily been deployed to a production environment, and main contains the production code.

In this setup, you can create two variants, mygraph@develop and mygraph@main, that correspond directly to the develop and main branches.

A feature/* branch contains the code for a particular feature.

When a pull request is opened to merge feature/* into develop, a set of schema checks is executed to ensure this set of changes will not break the supergraph upon composing or publishing the changes.

Once the code is merged from feature/* into develop, a CI/CD job runs to deploy the changes to the development environment and publish the subgraph to the mygraph@develop variant.

When the code in the develop branch is ready for production, it is merged into main, triggering a CI/CD job to deploy the changes to the production environment and publish the subgraph to the mygraph@main variant.

In the deployment environments, your subgraphs and the GraphOS Router run with the router configured to pull from a specific variant.

Simplified feature branch flow (feature, main)

A branching model similar to Git Flow uses feature and main branches but doesn't use develop. Instead, new features are branched directly off the main branch, and when the code is completed, each feature branch is merged directly into main. In this model, main represents the latest code but not necessarily what is deployed to production.

In this setup, you can still have two variants, mygraph@develop and mygraph@main, but the timing of when they are published differs slightly from Git Flow.

A feature/* branch contains the code for a particular feature.

When a pull request is opened to merge feature/* into main, a set of schema checks is executed to ensure this set of changes will not break the supergraph upon composing or publishing the changes.

Once the code is merged from feature/* into main, a CI/CD job runs to deploy the changes to the development environment and publish the subgraph to the mygraph@develop variant.

When the code in the main branch is ready for production, a CI/CD job runs to deploy the changes to the production environment and publish the subgraph to the mygraph@main variant.

In the deployment environments, your subgraphs and the GraphOS Router run with the router configured to pull from a specific variant.

Multi-branch flow (feature, develop, preprod, main)

In some cases, you might need multiple branches to accommodate multiple non-production environments. This can be achieved by expanding the Git Flow setup with additional variants tied to various branches.

In this setup, you would likely have a variant for each deployment environment (mygraph@develop, mygraph@preprod, mygraph@main), each linked directly to the appropriate Git branches.

A feature/* branch contains the code for a particular feature.

When a pull request is opened to merge feature/* into develop, a set of schema checks is executed to ensure these changes won't break the supergraph upon composing or publishing.

Once the code is merged from feature/* into develop, a CI/CD job runs to deploy the changes to the development environment and publish the subgraph to the mygraph@develop variant.

When the code in the develop branch is ready for pre-production verification, such as user acceptance testing, the code is merged into preprod. Subsequently, a CI/CD job is run to deploy the changes to the pre-prod environment and publish the subgraph to the mygraph@preprod variant.

Finally, when the code in the preprod branch is ready for production, it is merged into main, and a CI/CD job is run to deploy the changes to the production environment and publish the subgraph to the mygraph@main variant.

In the deployment environments, your subgraphs and Router run with the router configured to pull from a specific variant.

Running subgraph checks

Using rover subgraph check to run checks when opening a merge request is a great tool for ensuring that changes won't cause problems with the composition of your supergraph. Setting this up requires a CI/CD job to run against pull request events and execute the rover command on the updated schema.

Here is an example using GitHub Actions:

yml
1name: Pull Request Check Code
2
3on: pull_request
4
5env:
6  APOLLO_KEY: ${{ secrets.APOLLO_KEY }}
7  APOLLO_VCS_COMMIT: ${{ github.event.pull_request.head.sha }}
8
9jobs:
10  npm-build:
11    runs-on: ubuntu-latest
12    steps:
13      - uses: actions/checkout@v3
14
15      - uses: actions/setup-node@v3
16        with:
17          node-version: 18.x
18          cache: 'npm'
19
20      - run: npm ci
21
22      - run: npm run build
23  checks:
24    name: Rover Subgraph Check
25    runs-on: ubuntu-latest
26
27    steps:
28      - name: Checkout
29        uses: actions/checkout@v3
30
31      - name: Install Rover
32        run: |
33          curl -sSL https://rover.apollo.dev/nix/v0.8.1 | sh
34          echo "$HOME/.rover/bin" >> $GITHUB_PATH
35
36      - name: Rover Subgraph Check
37        run: |
38          rover subgraph check ${{ secrets.APOLLO_GRAPH_ID }}@develop \ # Specifying the variant here. This might also come from an environment variable, input, etc
39            --name subgraph-a \
40            --schema ./src/schema.graphql
💡 tip
For a more comprehensive example of deployment, Kubernetes setup, CI/CD, etc., check out our Reference Architecture .

Publishing schemas

To publish a schema from your CI/CD jobs to a GraphOS variant, you can use the rover subgraph publish command.

Here is an example using GitHub Actions:

yml
1name: Manual Deploy
2
3on: workflow_dispatch
4
5env:
6  APOLLO_KEY: ${{ secrets.APOLLO_KEY }}
7  APOLLO_VCS_COMMIT: ${{ github.event.pull_request.head.sha }}
8
9jobs:
10  deploy:
11    # Your deployment steps would go here!
12  publish:
13    name: Rover Subgraph Publish
14    runs-on: ubuntu-latest
15
16    steps:
17      - name: Checkout
18        uses: actions/checkout@v3
19
20      - name: Install Rover
21        run: |
22          curl -sSL https://rover.apollo.dev/nix/v0.8.1 | sh
23          echo "$HOME/.rover/bin" >> $GITHUB_PATH
24
25      - name: Rover Subgraph Publish
26        run: |
27          rover subgraph publish ${{ secrets.APOLLO_GRAPH_ID }}@develop \ # Specifying the variant here. This might also come from an environment variable, input, etc
28            --name subgraph-a \
29            --routing-url http://graphql.mygraph.svc.cluster.local:4000 \
30            --schema ./src/schema.graphql