GitHub Actions

Beta

The Catalyst CLI runs without a browser, so you can deploy from CI instead of from a developer’s machine. This page covers two workflows you can add to a Catalyst repository: one that deploys your storefront when a branch merges, and one that deploys a preview for each pull request and comments the URL on it.

Both workflows use the Catalyst CLI from your own repository, so the CLI version stays under your control and upgrades with your project.

The Catalyst CLI is generally available, but Native Hosting is currently in closed beta. There may be breaking changes to the Native Hosting APIs as we finalize them. To express interest in gaining access, fill out the Native Hosting Closed Beta Interest Form.

Before you begin

You need the following:

  • A Catalyst storefront in a GitHub repository, with @bigcommerce/catalyst 1.2.0 or newer installed. Check with pnpm catalyst --version.
  • A hosting project to deploy into. Create one with catalyst projects create, then copy its UUID from catalyst projects list.
  • Permission to add secrets and variables to the repository.

Deploying from CI needs credentials that a browser login does not provide, so start by creating an API account for it.

Create an API account for CI

In your BigCommerce control panel, go to Settings → API accounts → Create API account and choose Store API account. Grant these scopes:

  • Infrastructure Projects — modify
  • Infrastructure Deployments — modify
  • Infrastructure Logs — read-only

Save the access token. You also need your storefront token, which is the same one your storefront build already uses.

Treat this token as a deployment credential. It can create and replace deployments on your store, so store it as a GitHub secret and never commit it.

Understand the two sets of variables

The Catalyst CLI reads two separate sets of variables, and mixing them up is the most common cause of a failed CI deploy:

  • CLI configuration tells the CLI which store and project to act on, and how to authenticate. In CI, supply CATALYST_ACCESS_TOKEN and CATALYST_PROJECT_UUID as environment variables. There is no CATALYST_STORE_HASH to set — it falls back to BIGCOMMERCE_STORE_HASH. These are never read from .env files, so putting them in .env.local does not authenticate CI.
  • Storefront build variables (BIGCOMMERCE_* and AUTH_SECRET) are read by the Next.js build.

There is a third case that catches people out. A build variable feeds the build running on the runner; it does not reach the deployed application. The deployed worker gets its own environment, which is populated only by --secret flags on catalyst deploy or by values stored with catalyst env add. A deployment that builds successfully but returns a runtime configuration error is usually missing a --secret.

For the full resolution order, see Configuration.

Deploy on merge to your default branch

In your GitHub repository, go to Settings → Secrets and variables → Actions. On the Variables tab, add BIGCOMMERCE_STORE_HASH, BIGCOMMERCE_CHANNEL_ID, and CATALYST_PROJECT_UUID. On the Secrets tab, add BIGCOMMERCE_ACCESS_TOKEN, BIGCOMMERCE_STOREFRONT_TOKEN, and AUTH_SECRET.

Then create .github/workflows/deploy.yml:

.github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
# A project serves one deployment at a time, so let one deploy finish before
# the next starts rather than racing.
concurrency:
group: catalyst-deploy
cancel-in-progress: false
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
env:
# Tells the CLI which project to deploy to, and how to authenticate.
# The store hash comes from BIGCOMMERCE_STORE_HASH below.
CATALYST_PROJECT_UUID: ${{ vars.CATALYST_PROJECT_UUID }}
CATALYST_ACCESS_TOKEN: ${{ secrets.BIGCOMMERCE_ACCESS_TOKEN }}
# Read by the Next.js build on the runner.
BIGCOMMERCE_STORE_HASH: ${{ vars.BIGCOMMERCE_STORE_HASH }}
BIGCOMMERCE_CHANNEL_ID: ${{ vars.BIGCOMMERCE_CHANNEL_ID }}
BIGCOMMERCE_STOREFRONT_TOKEN: ${{ secrets.BIGCOMMERCE_STOREFRONT_TOKEN }}
AUTH_SECRET: ${{ secrets.AUTH_SECRET }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
# The --secret flags populate the deployed application's environment.
# The env block above only feeds the build.
- name: Deploy
run: |
pnpm catalyst deploy \
--secret "BIGCOMMERCE_STORE_HASH=$BIGCOMMERCE_STORE_HASH" \
--secret "BIGCOMMERCE_STOREFRONT_TOKEN=$BIGCOMMERCE_STOREFRONT_TOKEN" \
--secret "BIGCOMMERCE_CHANNEL_ID=$BIGCOMMERCE_CHANNEL_ID" \
--secret "AUTH_SECRET=$AUTH_SECRET"

To store the runtime secrets on the project instead of repeating them on every run, add them once with catalyst env add and drop the --secret flags. The CLI then sends the stored values on each deploy.

If customers reach your storefront on a hostname other than the one Auth.js derives from the request, sign-in can fail host validation. Pass --secret "AUTH_TRUST_HOST=true" for deployments served on a hostname you control but have not configured as the canonical site URL.

Deploy a preview for each pull request

BigCommerce publishes a GitHub Action that deploys pull request code to a hosting project and comments the URL on the pull request.

Preview deployments are an early version of this feature

A hosting project has one hostname, not one per deployment. A repository therefore shares one preview project and one preview URL, and it serves one pull request at a time. Deploying a preview for a second pull request replaces the first. This behavior may change as the feature develops.

How the shared preview works

The newest open pull request deploys automatically when it receives a push. Any other open pull request claims the preview by commenting redeploy preview on it. When a pull request takes the preview over, the one that previously held it gets a comment explaining that the URL no longer reflects its changes, so no thread is left advertising a stale preview.

Previews do not run for pull requests from forks. The workflow builds and deploys pull request code with your store credentials in scope, so it only runs for branches in your own repository. Only users with write access can run the command.

Create a preview project

Previews need a project of their own. Every preview overwrites the last deployment in it, so do not point previews at the project serving your storefront.

pnpm catalyst projects create
pnpm catalyst projects list

Copy the UUID of the project you created.

Add configuration

In your GitHub repository, go to Settings → Secrets and variables → Actions and add the following. The project UUID, store hash, and channel ID are configuration rather than credentials, so add those on the Variables tab and the rest on the Secrets tab.

NameKindValue
BIGCOMMERCE_PREVIEW_PROJECT_UUIDVariableThe preview project UUID
BIGCOMMERCE_STORE_HASHVariableYour store hash
BIGCOMMERCE_CHANNEL_IDVariableThe channel the preview storefront serves
BIGCOMMERCE_ACCESS_TOKENSecretThe access token from the API account above
BIGCOMMERCE_STOREFRONT_TOKENSecretYour storefront token
AUTH_SECRETSecretGenerate a new value with openssl rand -hex 32

Generate an AUTH_SECRET for previews rather than reusing the one your storefront uses. Sessions then do not carry between a preview and your live storefront.

If BIGCOMMERCE_PREVIEW_PROJECT_UUID is absent, the workflow skips instead of failing, so the feature stays switched off until you configure it.

Add the workflow

Create .github/workflows/preview-deployment.yml:

.github/workflows/preview-deployment.yml
name: Preview Deployment
on:
pull_request:
types: [opened, reopened, synchronize]
issue_comment:
types: [created]
jobs:
preview:
uses: bigcommerce/catalyst/.github/workflows/deployment-preview.yml@preview-action-v1
secrets:
access-token: ${{ secrets.BIGCOMMERCE_ACCESS_TOKEN }}
storefront-token: ${{ secrets.BIGCOMMERCE_STOREFRONT_TOKEN }}
auth-secret: ${{ secrets.AUTH_SECRET }}

That is the whole file. The reusable workflow sets the permissions it needs and serializes deploys across the repository, because all previews share one project.

preview-action-v1 is a moving major tag that tracks the newest 1.x release, so fixes arrive without editing the workflow. To upgrade by hand instead, pin an exact version such as @preview-action-v1.1.0.

A job that calls a reusable workflow cannot declare environment:, and GitHub does not expose environment-scoped secrets to a job that does not. Keep these three secrets at repository level. To scope them to a GitHub Environment, call the action directly instead of the reusable workflow, in a job that declares the environment itself.

Merge the workflow to your default branch

GitHub reads issue_comment workflows from the default branch only. Until this file is merged, commenting redeploy preview does nothing — including on the pull request that adds the file. Pull request previews run from the branch, but the comment command does not.

Use the preview

Open a pull request. If it is the newest open one, it deploys and the action comments the preview URL and the commit it built.

On an older pull request, the action comments that the preview is reserved for the newest one. Comment redeploy preview to claim it. The command gets an eyes reaction while it runs and a rocket when it finishes, and a check named Preview Deployment (redeploy) appears in the pull request’s checks so you can follow progress.

Configuration reference

Pass any of these in the with: block of the reusable workflow.

InputDefaultDescription
project-uuidReads BIGCOMMERCE_PREVIEW_PROJECT_UUIDHosting project every preview deploys into
store-hashReads BIGCOMMERCE_STORE_HASHStore hash
channel-idReads BIGCOMMERCE_CHANNEL_IDChannel the preview storefront serves
environmentNoneGitHub Environment holding your variables
command-phraseredeploy previewComment prefix that claims the preview
auto-deploy-newesttrueSet to false to require the command every time
working-directory.Directory holding the Catalyst project
node-version24Node version used for the build
pnpm-version10The Catalyst CLI shells out to pnpm to build
api-hostapi.bigcommerce.comOverride only for non-production stores
check-namePreview Deployment (redeploy)Check row a redeploy reports against

The workflow also exposes outputs: deployed is "true" when the run deployed, and url holds the preview URL.

Troubleshooting

What you seeCauseFix
The workflow reports as skipped and posts no commentBIGCOMMERCE_PREVIEW_PROJECT_UUID is unset, so previews are switched offAdd the variable, and check the spelling
Missing configuration: naming a secret or variableThe value is scoped to a GitHub Environment that the job does not declareMove it to repository level, or call the action directly from a job that declares the environment
redeploy preview does nothing at allThe workflow is not on your default branchMerge it, then comment again
Client configuration must include a channelId at runtimeA runtime secret did not reach the deployed applicationPass BIGCOMMERCE_CHANNEL_ID with --secret, or store it with catalyst env add
Previews are not available for pull requests from forksWorking as intendedPush the branch to the repository itself
Your access token is invalid or has expiredThe store API token was revoked or expiredCreate a new token and update BIGCOMMERCE_ACCESS_TOKEN
A 403 naming store_infrastructure_projects_manageThe API account is missing a scopeRecreate it with the scopes listed above
@bigcommerce/catalyst@<version> is older than the required 1.2.0The project’s CLI is too old for the actionUpgrade @bigcommerce/catalyst in your project
The preview URL shows another pull request’s changesAnother pull request claimed the shared previewComment redeploy preview to claim it back

To inspect a failed deployment, stream the project’s logs with catalyst logs.