Skip to content
Helix Docs

Deploy from CI

Generate a GitHub Actions workflow with helix ci init that deploys your project on merge or on demand, authenticated with a Tray API user token.

For developers Updated Sep 29, 2026
View as Markdown

helix ci init generates the CI pipeline that deploys your project, so a merge or a button press ships it instead of a laptop. It asks which CI service you use (GitHub Actions is the only option today) and how deploys should be triggered, writes the workflow file, and prints the one-time setup to do on GitHub. The workflow itself runs helix deploy --wait, so the job fails with the build errors when a deployment fails.

Generate the workflow

Run it from the project root, in a terminal:

helix ci init

You answer two questions. The first is the CI service. The second is how deploys should be triggered:

StrategyFiles writtenWhen it deploys
Manual production deploys (default)deploy-production.ymlOn demand only, from the Actions tab or gh workflow run deploy-production.yml
Deploy production on mergedeploy-production.ymlOn every push to your default branch, and on demand
Staging on merge, production manuallydeploy-staging.yml, deploy-production.ymlStaging on every push to your default branch; production on demand, behind an approval gate

The files land in .github/workflows/. The command asks before overwriting one that already exists.

Without a terminal, for example when an agent runs it, pass the answers as flags:

helix ci init --provider github --strategy manual-production

The strategy ids are manual-production, production-on-merge, and staging-on-merge. Add --force to overwrite existing files without asking.

What the command checks first

The command reads your project before it writes anything, and stops with the fix when a target isn’t ready:

  • A config file per target. The production target uses helix.production.config.ts when it exists, otherwise helix.config.ts. The staging strategy needs both helix.staging.config.ts and helix.production.config.ts, so a merge never deploys your development target by accident. See one config file per target.
  • A provisioned project. Every target the workflow deploys must already have a projectId and workspaceId in its config file. A first deploy writes the project ID it provisions back into the file, and a CI runner throws that write away, so an unprovisioned target would create a new project on every run. Deploy the target once from your machine, or set the ids with helix project set and helix workspace set, then run helix ci init again.
  • A lockfile. helix deploy needs package-lock.json or pnpm-lock.yaml; the workflow installs with the matching package manager.

The workflow pins @trayai/helix-cli to your project’s @trayai/helix-sdk version. The two are released together, and a CLI ahead of the SDK breaks deploys, so bump both at once.

Create the token

The workflow authenticates with a secret named TRAY_CLI_TOKEN: a Tray API user token for the workspace the target deploys to. Create one in Tray:

  1. Go to Account Settings, then Tokens, then Create API user. Organization admins can do this for any workspace; workspace admins can when an organization admin has allowed it.
  2. Name the API user, pick the workspace your target deploys to, and give it a workspace role.
  3. Name the token and set its expiry. Copy it when it’s shown: it isn’t shown again, and it’s deleted when it expires.

Tokens are scoped to one workspace. When staging and production are different workspaces, create one API user and token for each.

Check a token before saving it on GitHub:

TRAY_CLI_TOKEN=<token> helix whoami

When TRAY_CLI_TOKEN is set, every helix command uses it instead of a saved helix login session. Nothing is written to disk and the token is never refreshed. A rejected token is reported as such, rather than as an expired login.

Set up GitHub

For the single-workflow strategies, add TRAY_CLI_TOKEN as a repository secret (Settings, Secrets and variables, Actions). The recommended upgrade is a GitHub environment named Production with required reviewers, with the secret moved onto it and environment: Production added to the job, so every deploy waits for approval.

The staging strategy sets that up from the start: each job runs on its own environment, Staging or Production, and reads TRAY_CLI_TOKEN from that environment’s secrets. Add required reviewers on Production and a production deploy waits for one of them.

The exact steps are printed when helix ci init finishes, and repeated in a comment at the top of each generated file.

What the workflow does

Each generated workflow, in order:

  1. Checks out the repository.
  2. Sets up Node.js 24 and installs your dependencies from the lockfile.
  3. Installs @trayai/helix-cli at the pinned version.
  4. Runs helix deploy --wait (with --config <target file> for a named target), with TRAY_CLI_TOKEN supplied from the secret.

--wait keeps polling after the upload until the platform finishes rolling out. The job passes once the deployment is ready, and fails with the build errors printed in the log when it isn’t. A deployment still rolling out after 10 minutes fails the job with a “still deploying” message; check it later with helix deployment get <id>.

One deploy runs at a time per target, and a running deploy is never cancelled by a newer one. Each job has a 20 minute limit and read-only repository permissions.

Add your own steps, such as tests, before the deploy step. The generated file marks where.

Use another CI service

The generator writes GitHub Actions workflows today. On any other service, the same two pieces make a deploy job:

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

Supply TRAY_CLI_TOKEN from your service’s secret store as an environment variable on that step. Everything in Create the token applies unchanged.

Loading search…

Jump to a section

tab to move · esc to close