Manifest
Jobs
Your own commands, run on rollout steps, on a schedule or on demand.
jobs:
migrate: { service: web, command: npm run migrate, on: deploy }
seed: { service: web, command: npm run seed, on: seed }
warm: { service: web, command: npm run warm-cache, on: start }
digest: { service: worker, command: npm run digest, on: { schedule: "0 8 * * *" } }
backfill: { service: worker, command: npm run backfill }A job runs command in a fresh container of service, with its image and env. on is one event or a list.
on | When it runs |
|---|---|
deploy | When a sandbox is first set up, and on every update after (a changed manifest, new code, a retry). Migrations go here. |
seed | Once, when a sandbox is first set up. |
start | Once per sandbox, after deploy and seed. |
destroy | When the sandbox is deleted. |
{ schedule: "<cron>", time_zone: <zone> } | On a five-field cron schedule, or @hourly, @daily, @weekly, @monthly, @yearly. UTC unless time_zone names an IANA zone such as Europe/Paris. Paused in sandboxes: parity run <job> fires one. |
| omitted | Only on demand, with parity run <job>. |
- Order. Events are phases: all
deployjobs, thenseed, thenstart. A seed never meets an empty schema. Services take traffic once they're done. - Parallel unless ordered. Jobs of one phase run in parallel (up to 8 at once). A job that must run after another lists it in
depends_on, as in Buildkite. See Steps. - Failures. A failed job skips the jobs that depend on it, lets running ones finish, then fails the sandbox;
parity upprints its log tail. Rerunningparity upretries it. - Jobs wait for every managed entry. Services start after the setup jobs, so a job that needs one (a database you run as a service, such as MySQL) lists it:
depends_on: [mysql]. That service, and the services it depends on, then start before the setup jobs, and the job waits until its first port accepts connections (and itshealthcheck passes, if it has one). The job's variables still come from its own service. A service keeps no data across restarts, and a sandbox whose seed writes to one isn't restored from a snapshot. - In-app schedulers. Pausing covers the manifest's jobs only. A scheduler inside your own process keeps running.
parity scale <service> 0stops it. - HTTP jobs.
command: { http: GET /api/cron/digest }sends that request to the service's first port, instead of starting a container of it. It fails on an HTTP error status, and retries while the service isn't answering yet. If the service hasCRON_SECRET, the request carriesAuthorization: Bearer <CRON_SECRET>, as Vercel cron does, so existing cron routes work unchanged. HTTP jobs run on ascheduleor withparity run, since setup jobs run before services start. - Commands run through a shell when they need one. A command with
$VAR,&&, quotes or pipes runs assh -c, so$CRON_SECRETis the service's variable. A plainnpm run xruns directly.
Runners
runners:
tools: { image: ghcr.io/acme/deploy-tools:3 }
jobs:
purge: { service: web, runner: tools, command: ./scripts/purge-cdn.sh, on: deploy }A runner is an image that jobs run on instead of their service's: build tools and CLIs the app itself doesn't need. Define it once and pick it with runner:. The job still belongs to its service, so it gets that service's env and egress. The console's Runners page lists each runner, its jobs, and the hosts they were blocked from.
Steps
jobs:
init-db: { label: Create the database, service: web, command: npm run db:init, on: deploy }
migrate: { service: web, command: npm run migrate, depends_on: [init-db] }
assets: { service: web, runner: tools, command: ./scripts/upload-assets.sh, on: deploy }
release:
block: Release to customers
prompt: Check the canary dashboard and #support first.
depends_on: [migrate, assets]Every job on deploy, seed or start is a step of a sandbox's rollout. Your environments run the deploy steps.
labelis the name the console and CLI show: one line, up to 200 characters. The job's name stays its key.depends_onlists jobs as well as services. A job runs after the jobs it lists; jobs with nothing between them run in parallel. A job withoutonruns on the latest phase of the jobs it depends on. It can depend on jobs of the same or an earlier phase, never a later one or itself. Only steps depend on jobs: a scheduled or on-demand job can't.blockmakes a step that runs nothing and waits for a person to approve it:block: <label>, orblock: truewith an optionallabel.promptis optional text, up to 1,000 characters, that the approve dialog shows. A block always runs ondeploy, so every job it depends on must be adeploystep.- Sandboxes pass blocks. A sandbox is an agent's, and agents never approve. Environments wait on a block for a person (
environments.deploy, which Developers have);environments: [production]limits it to the environments it names. Approve lets the steps after it run; Reject fails the rollout; if nobody decides withintimeout(a duration such as4h; default24h, at most720h), the rollout fails. A newer rollout asks again.
How steps run, fail and report status: Steps and approvals.