Deploy Blueprints from CI
How to deploy your Blueprint automatically from any CI system using a deploy token and environment variables.
There may be instances where you want to deploy your Blueprint automatically from CI, without using our official GitHub Action. This page explains the flow step by step so you can run it on any CI system.
In CI, the deploy process involves four steps:
- Install the Sanity runtime CLI.
- Authenticate with a deploy token.
- Set the project (or organization) and Stack to target.
- Run blueprints deploy.
The sections below walk through each prerequisites and steps. Read on to understand the flow or to run your own deploy in another CI system.
How CI differs from local development
On your own machine, two things work automatically that aren't available in CI:
- Authentication. You've run sanity login, so the CLI reads your credentials from disk. CI has no logged-in user.
- Scope and Stack. When you run sanity blueprints init, the CLI saves your project (or organization) and Stack IDs to .sanity/blueprint.config.json. That file is gitignored by default, so it isn't in a fresh CI checkout.
In CI you supply both explicitly: a token for authentication, and a few environment variables for your scope and Stack.
Before you get started
This section assumes you have a Sanity project with a Blueprint initialized locally.
The Blueprints CLI commands require an authenticated token to run in CI. Create a deploy token with sanity blueprints mint-deploy-token, described below. It's the only credential your CI pipeline needs.
The deploy token can deploy your Stack, but it can't create a Stack or mint further tokens. Keep init and mint-deploy-token as local admin steps.
Create a deploy token
Mint a deploy token with the CLI:
sanity blueprints mint-deploy-token --print
This prints the token to your terminal. Add it to your CI system as a secret, and don't commit it to your repository. Your CI job exposes it to the CLI as the SANITY_AUTH_TOKEN environment variable, which the CLI reads before any credentials on disk.
Minting a token requires admin access to the Stack's scope: project admin for a project-scoped Stack, or organization admin for an organization-scoped Stack. The minted token automatically carries the permissions needed to plan, deploy, and destroy Blueprints in that scope.
Set your scope and Stack
Because .sanity/blueprint.config.json isn't in your CI, provide its values as environment variables. The CLI reads the following:
RequiredSANITY_AUTH_TOKEN
The deploy token you created above.
SANITY_PROJECT_IDstring
Required for project-scoped Stacks. Set this when your config has a projectId.
SANITY_ORGANIZATION_IDstring
Required for org-scoped Stacks. Set this when your config has an organizationId.
RequiredSANITY_BLUEPRINT_STACK_ID
The Stack to deploy (your ST-… ID).
A Stack has a single scope, recorded in .sanity/blueprint.config.json. Open that file (or run sanity blueprints info) and set the matching variable in your CI settings: if it contains a projectId, set SANITY_PROJECT_ID; if it contains an organizationId, set SANITY_ORGANIZATION_ID. Set one, never both.
Run the deploy
With the token and scope variables in your environment, the deploy is a single command. Substitute your package manager commands as needed.
npm ci npx -y sanity blueprints deploy
npm ci pnpm dlx -y sanity blueprints deploy
npm ci yarn dlx -y sanity blueprints deploy
npm ci bunx -y sanity blueprints deploy
deploy waits for the deployment to finish and exits with a non-zero status if it fails, so your CI job fails when the deployment fails.
This is everything the GitHub Action does, run by hand.
Plan on pull requests
sanity blueprints plan is read-only. It previews the changes a deploy would make without applying them. A common pattern is to run blueprints plan on pull requests so reviewers can see the intended change, and blueprints deploy when changes merge to your main branch. The plan command uses the same scope and Stack variables as deploy.
Example: CircleCI
Because the steps are a combination of environment variables and a CLI command, the same flow works on any platform. Here it is end to end in CircleCI (.circleci/config.yml):
version: 2.1
jobs:
deploy-blueprints:
docker:
- image: cimg/node:lts
environment:
# Non-secret values, safe to commit:
SANITY_PROJECT_ID: "1234xyz"
SANITY_BLUEPRINT_STACK_ID: "ST-1234xyz"
# SANITY_AUTH_TOKEN is set as a project environment variable in
# CircleCI (Project Settings > Environment Variables), not committed here.
steps:
- checkout
- run: npm ci
- run: npx -y sanity blueprints deploy
workflows:
deploy:
jobs:
- deploy-blueprints:
filters:
branches:
only: mainSet SANITY_AUTH_TOKEN as a project environment variable in CircleCI (Project Settings > Environment Variables). CircleCI injects it into the job automatically and the CLI reads it, so the token is never committed to your config file. Unlike GitHub Actions, there's no secret to reference in the config: the variable is simply present in the job's environment.
The pattern is the same everywhere: store the token as a secret, set your scope and Stack variables, and run deploy.
Troubleshooting
Start with diagnostics
sanity blueprints doctor reports what the CLI resolved in your CI environment: whether it found a valid token, which scope and Stack it resolved, and where each value came from (environment variable or config file). Run it as a step in your pipeline, or after a failed deploy, to see why a deploy failed.
Deploys failing with a permissions error after promoting a Stack
A deploy token is scoped to a single project or organization. Promoting a Stack from project to organization scope does not re-scope the token. Your existing project-scoped token can no longer deploy the now organization-scoped Stack. To fix it:
- Mint a new organization-scoped token:
sanity blueprints mint-deploy-token --organization-id your-org-id(requires organization admin access). - Update your CI secret with the new token.
- Replace
SANITY_PROJECT_IDwithSANITY_ORGANIZATION_ID.
The Stack ID doesn't change when you promote, so SANITY_BLUEPRINT_STACK_ID stays the same.
Missing scope: provide --project-id or --organization-id
The CLI couldn't determine your target project or organization. In CI this is expected: .sanity/blueprint.config.json is gitignored and isn't in your checkout. Set SANITY_PROJECT_ID or SANITY_ORGANIZATION_ID (or pass the matching flag), as described in the Set your scope and Stack section above.
Missing stack: provide --stack…
With no .sanity/ config in the checkout, the CLI doesn't know which Stack to deploy. Set SANITY_BLUEPRINT_STACK_ID (or pass --stack).
Authentication failures
Check that SANITY_AUTH_TOKEN is set in your job environment, and that the token has the right deploy permission for your scope.