The three steps
- Install the CLI in the job, or call the API directly. The installer is
curl -fsSL https://levelrail.com/install-cli.sh | sh. SetLEVELRAIL_CLI_INSTALL_DIRto a directory you can write to (the default is/usr/local/binfor root and~/.local/binotherwise) andLEVELRAIL_VERSION=vX.Y.Zto pin a release. - Authenticate with environment variables only.
LEVELRAIL_API_URLis your control plane URL andLEVELRAIL_TOKENis an API token with at least thedeployability.LEVELRAIL_PROFILEpicks a saved profile and is not needed in CI. The CLI also readsCI=true(orLEVELRAIL_CI=true) and then never prompts, and it does so by itself when stdin or stdout is not a terminal. - Deploy by image, then wait.
apps deployreturns as soon as the deploy is accepted.apps waitis what tells you whether the rollout worked.
apps deploy requires --image here; add --confirm to deploy into a protected environment. apps wait also takes --attempt-id and --poll-interval (default 3s).
Create the token once and store it in your CI’s secret store:
Exit codes
Branch on these in scripts.
A job running
apps deploy then apps wait fails on any non-zero code, which is what you want.
Safe retries
apps deploy sends an Idempotency-Key, so re-running the same job applies the deploy once and replays the first result. The CLI derives the key from the app, the image and the run id. It reads only two sets of run variables: GITHUB_RUN_ID with GITHUB_RUN_ATTEMPT, and CI_PIPELINE_ID (set by GitLab CI). On any other CI it falls back to the current minute, so pass your own key from the CI’s build id:
Retry-After. LEVELRAIL_RETRY_MAX (default 3, 0 turns retry off) and LEVELRAIL_RETRY_MAX_WAIT (default 60s) bound it. See Deploy from your computer.
OIDC support
Deploy without a stored secret works on GitHub Actions only. The control plane accepts identity tokens only fromhttps://token.actions.githubusercontent.com and matches them by GitHub repository, ref and environment (internal/api/ci_oidc.go). GitLab ID tokens, CircleCI OIDC and Buildkite OIDC are not accepted today, so the templates below use an API token. Supporting another CI would need a verifier for that issuer and a mapping from its claims to repository, ref and environment.
GitLab CI
StoreLEVELRAIL_API_URL and LEVELRAIL_TOKEN under Settings > CI/CD > Variables, masked, and protected if you deploy only from protected branches.
CI_PIPELINE_ID is read for the idempotency key, so no extra flag is needed. The control plane must be able to pull $IMAGE, so add the registry credentials to the app first.
CircleCI
Store both variables in Project Settings > Environment Variables or in a context.Jenkins
Create two Secret text credentials with the idslevelrail-api-url and levelrail-token under Manage Jenkins > Credentials.
sh strings keep Groovy from interpolating the secrets into the command line, and Jenkins masks the credential values in the log.
Buildkite
Keep the secrets in your agent environment hook, a secrets manager plugin, or Pipeline Settings. Do not put them inpipeline.yml.
$$ stops Buildkite from expanding the variable at upload time. LEVELRAIL_API_URL and LEVELRAIL_TOKEN must already be in the step’s environment.
Troubleshooting
Next steps
- Deploying from GitHub Actions: the OIDC, no stored secret path.
- CLI reference:
apps deployandapps waitin full. - Identity and access: token abilities and presets.