-
Notifications
You must be signed in to change notification settings - Fork 2
[AS-222] Tech note: Ephemeral environments with GraphOS #39
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
Open
ilan-bel
wants to merge
2
commits into
main
Choose a base branch
from
docs/as-222-ephemeral-environments
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| # Ephemeral environments with GraphOS | ||
|
|
||
| > Spin up a fully composed supergraph per PR (and tear it down on merge or close), without manual GraphOS plumbing. Tracks [AS-222](https://apollographql.atlassian.net/browse/AS-222). | ||
|
|
||
| Ephemeral envs let a reviewer hit a real Router + subgraph URL that reflects exactly the change in a PR. The Apollo-native primitive that makes this work is the [GraphOS variant](https://www.apollographql.com/docs/graphos/graphs#variants) β each variant has its own composed supergraph schema, its own Router config, and its own usage stats. | ||
|
|
||
| ## Topology | ||
|
|
||
| ``` | ||
| ββββββββββββββββββββββββββββββββββββ | ||
| β GraphOS β | ||
| PR #142 push βββΊ β variant: pr-142 ββββ β | ||
| β variant: main β rover β | ||
| β variant: prod β publish β | ||
| ββββββββββββββββββ¬βββββββ β | ||
| β β | ||
| CI βΌ β | ||
| βββΊ spin up Router pointed at variant pr-142 β | ||
| deploy subgraph services on pr-142.example β | ||
| comment PR with the env URL β | ||
| β | ||
| PR merged / closed βββΊ tear down namespace βββΊ rover graph delete my-graph@pr-142 | ||
| ``` | ||
|
|
||
| One variant per PR, one short-lived Router + subgraph deployment per PR, automatic cleanup on PR close. | ||
|
|
||
| ## Step 1 β Variant lifecycle in CI | ||
|
|
||
| On `pull_request: [opened, synchronize, reopened]`: | ||
|
|
||
| ```bash | ||
| # Create the variant by publishing one subgraph against it. The variant is | ||
| # implicitly created on first publish; no separate "create variant" call. | ||
| rover subgraph publish my-graph@pr-${PR_NUMBER} \ | ||
| --name products \ | ||
| --schema ./subgraphs/products/schema.graphql \ | ||
| --routing-url https://pr-${PR_NUMBER}.products.example.com | ||
| ``` | ||
|
|
||
| On `pull_request: [closed]`: | ||
|
|
||
| ```bash | ||
| # Delete the variant and all its subgraphs β wipes the composed supergraph, | ||
| # usage data, checks history, and any contracts. `rover graph delete` exits | ||
| # non-zero if the variant doesn't exist, so guard the step with `|| true` | ||
| # (or skip it if the variant was never created on this PR). | ||
| rover graph delete my-graph@pr-${PR_NUMBER} --confirm || true | ||
| ``` | ||
|
|
||
| The variant key (`pr-<number>`) is the contract between CI and infrastructure. Use the GitHub-provided `PR_NUMBER`, not a sha or branch name, so re-pushes still target the same variant. | ||
|
|
||
| ## Step 2 β Subgraph deployment | ||
|
|
||
| Same pattern as your prod deploy, parameterized by PR number. On Kubernetes, that's a per-PR namespace; on Fly.io / Render, it's per-PR apps named `pr-<n>-products`, `pr-<n>-reviews`, etc. | ||
|
|
||
| The only Apollo-specific config: each subgraph's `routing-url` published to GraphOS must resolve from the Router pod. For Kubernetes, that's the in-cluster service DNS; for Fly.io/Cloud Run, the public HTTPS URL. | ||
|
|
||
| ## Step 3 β Router pointing at the variant | ||
|
|
||
| The Router fetches its supergraph schema and config from Apollo Uplink based on `APOLLO_GRAPH_REF`. Set it to the per-PR variant: | ||
|
|
||
| ```yaml | ||
| env: | ||
| - name: APOLLO_GRAPH_REF | ||
| value: my-graph@pr-142 | ||
| - name: APOLLO_KEY | ||
| valueFrom: | ||
| secretKeyRef: { name: apollo-key, key: APOLLO_KEY } | ||
| ``` | ||
|
|
||
| Router automatically refetches when the variant's supergraph schema changes (every re-push during the PR's life). No restart needed. | ||
|
|
||
| ## Step 4 β PR comment with the URL | ||
|
|
||
| After the deploy completes, post a comment with the ephemeral URL. Use a deduped marker so re-pushes update the comment instead of creating new ones β the pattern in [`apollosolutions/proposal-pr-bot`](https://github.com/apollosolutions/proposal-pr-bot) works here. | ||
|
|
||
| ## Permissions | ||
|
|
||
| Use a [GraphOS service account API key](https://www.apollographql.com/docs/graphos/api-keys/) scoped to one graph. The key needs: | ||
|
|
||
| - `graph admin` or `graph contributor` to publish subgraphs to new variants | ||
| - `graph admin` to delete variants | ||
|
|
||
| Store it as a GitHub Actions secret. Rotate quarterly. | ||
|
|
||
| ## Cost / quota awareness | ||
|
|
||
| - **Variants are unlimited** on enterprise plans but each one counts as an active variant on usage-based plans. Tear them down promptly on PR close. | ||
| - **Usage reporting** from PR Routers is real usage data. Filter it out of dashboards by `graph.variant_id` to avoid polluting prod metrics. | ||
| - **Checks** against ephemeral variants don't carry forward to prod β the validity of a `pr-142` check expires when the variant is deleted. | ||
|
|
||
| ## See also | ||
|
|
||
| - [Apollo Connectors and Router on each variant](https://www.apollographql.com/docs/graphos/graphs/federated-graphs) | ||
| - [Service accounts and API keys](https://www.apollographql.com/docs/graphos/api-keys/) | ||
| - [`apollosolutions/proposal-pr-bot`](https://github.com/apollosolutions/proposal-pr-bot) β companion tooling for keeping PR β proposal in sync (AS-89) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
rover variant deleteis not a real command. Userover graph delete my-graph@pr-${PR_NUMBER} --confirm(deletes the variant and all its subgraphs). Also, the comment above says this is idempotent/safe when the variant was never created, butrover graph deleteexits non-zero on a missing variant and will fail the CI teardown step; guard it (e.g.|| true) or remove the idempotency claim.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.
Verified at 81f0912: Step 1 teardown now uses
rover graph delete my-graph@pr-${PR_NUMBER} --confirm || true, and the surrounding comment correctly states the command exits non-zero on a missing variant and is guarded with|| truerather than claiming idempotency. This thread can be resolved.