Deploy

Deploy from your CI pipeline

Run helix ci init and Helix writes a GitHub Actions workflow into your repo. Merge to your default branch, or start it by hand, and the job deploys your project and waits until the new version is live.

Available in
Every Helix edition, with Helix CLI 1.3.0 or later.
Shipped
29 September 2026
Read more

Your pipeline

  1. Your repoMerge to the default branch

    Waiting for a mergeMerged to main

  2. GitHub ActionsOr any CI with the same command
    • Check out the repo
    • Install from the lockfile
    • Install the pinned helix-cli
    • helix deploy --wait
  3. helix deploy --waitWaits until the rollout is done
    staging
    Not startedRolling outReady
    production
    Not startedWaiting for a reviewerRolling outReady

Tray Helix

  • staging
  • production

Deploy

  • Deploys as a Tray API user, attributed to CI
  • A failed build fails the job
  • One deploy per target at a time

Run

  • Managed runtime and a live URL
  • Credential broker for every API
  • Built-in storage

Govern

  • Token scoped to one workspace
  • Lowest workspace role that deploys
  • Every deploy in the Deployments tab

In short

Tray Helix can deploy from CI. In Helix CLI 1.3.0, helix ci init writes a GitHub Actions workflow that deploys the project on demand, on every merge to the default branch, or to staging on merge with production waiting for a reviewer in GitHub. CI signs in as a Tray API user through a TRAY_CLI_TOKEN secret, the job waits for the rollout and passes only when the new version is ready. Any other CI service can run the same deploy command.

Until now a Helix deploy ran from someone’s machine, signed in as them. With Helix CLI 1.3.0 it can run from your CI pipeline instead. helix ci init writes the GitHub Actions workflow for you, CI signs in as a Tray API user, and helix deploy --wait keeps the job open until the new version is live, so the check on your commit tells you whether it shipped.

An example

A team has a Helix project with a staging target and a production target, each deployed once by hand from a laptop. They want staging to follow main and production to ship only when someone signs it off. Here is the setup, start to finish.

1. Generate the workflows

From the project root, pick the CI service and how deploys should start:

helix ci init --provider github --strategy staging-on-merge

There are three setups. manual-production, the default, deploys production only when you start it. production-on-merge deploys production on every push to the default branch, and on demand. staging-on-merge deploys staging on every push and production on demand, behind an approval. Run helix ci init with no flags to choose in a prompt.

This team gets two files, deploy-staging.yml and deploy-production.yml. Before writing them, the command checks three things: that helix.staging.config.ts and helix.production.config.ts both exist, that each already has a projectId and workspaceId, and that the repo has a package-lock.json or pnpm-lock.yaml. It also pins the CLI in the workflow to the version of @trayai/helix-sdk the project uses, since the two are released together.

2. Give CI its own sign-in

CI needs a Tray API user, not a person’s session. In Tray, go to Account Settings, then Tokens, then Create API user. Pick the workspace the project deploys to and the lowest workspace role that can deploy, then create a token with an expiry and copy it, because it is shown once. Check it works before you store it:

TRAY_CLI_TOKEN=<token> helix whoami

In GitHub, the staging-on-merge setup reads the secret from two environments, Staging and Production. Save the token as TRAY_CLI_TOKEN in each, and add required reviewers to Production.

3. Merge to main

The next push to the default branch runs deploy-staging.yml. Every generated workflow does the same four things: checks out the repo, sets up Node.js 24 and installs dependencies from the lockfile, installs the pinned Helix CLI, and runs:

helix deploy --config helix.staging.config.ts --wait

--wait keeps polling after the upload until Helix has finished rolling out. The job passes when the deployment is ready.

4. Ship to production

Start deploy-production.yml from the Actions tab, or from a terminal:

gh workflow run deploy-production.yml

GitHub holds the job until a reviewer on the Production environment approves it, then runs the same steps against helix.production.config.ts.

What follows from how it works

  • The check on your commit is the truth. A failed build fails the job and prints the build errors. If the rollout takes longer than 10 minutes, the job fails with a “still deploying” message, and helix deployment wait <id> picks up a deploy that is still going.
  • Merges close together don’t trip over each other. Only one deploy runs per target at a time, and a newer one never cancels a deploy that is already running.
  • Deploys are attributed to CI, not to whoever merged. When TRAY_CLI_TOKEN is set, every helix command uses it and never writes a session to disk, so the same variable works on any machine.
  • Tests go before the deploy. The generated file is yours. Add test or lint steps above the deploy step and a failure stops the deploy.
  • The approval is GitHub’s. The production reviewer is a GitHub environment rule, so who can approve is set in GitHub.

What to watch for

The token opens the whole workspace. A Tray API user token is scoped to one workspace but reaches everything in it across Tray, including workflows and authentications. Treat it as a production credential: keep it in your CI secret store only, give the API user the lowest role that deploys, set an expiry, use a separate token per workspace, and delete the API user if the token leaks.

Deploy by hand once first. helix ci init refuses to write a workflow for a target with no projectId and workspaceId in its config. Deploy it once from your machine, or set both with helix project set and helix workspace set.

Staging needs both config files. The staging setup checks for helix.staging.config.ts and helix.production.config.ts before it writes anything, so a staging pipeline can never fall back to deploying production.

Other CI services

helix ci init writes GitHub Actions workflows only. Any other CI service needs two commands, with TRAY_CLI_TOKEN supplied from its secret store:

npm install -g @trayai/helix-cli@<your @trayai/helix-sdk version>
helix deploy --config helix.production.config.ts --wait

Quick answers

Which CI services does it work with?

helix ci init writes GitHub Actions workflows. Any other CI service can deploy by installing the Helix CLI at your Helix SDK version and running helix deploy with the wait option, with TRAY_CLI_TOKEN supplied from its secret store.

Does a deploy from CI use someone's login?

No. CI signs in as a Tray API user through the TRAY_CLI_TOKEN secret, so the deploy is attributed to CI rather than to a person. When the variable is set, the CLI uses it for every command and saves nothing to disk.

What happens when the build fails?

The deploy step exits with an error and prints the build errors, so the job fails. A red check means the new version did not ship.

Can production deploys wait for an approval?

Yes, through GitHub. The staging-on-merge setup puts production in a GitHub environment, and adding required reviewers to it holds each production deploy until someone approves it in GitHub.

More from What's new

Try it on your own app

Deploy an app you built with your AI assistant, and see what Helix does with it.

Want to talk to someone first? Contact us