Skip to main content
Status: partly built (STA-72). The runway check in pnpm validate, core’s runway.yaml, the cloudflare-workers, npm and mintlify provider workflows, the supply-chain checks and pnpm runway are written; none has run yet (testing pass STA-597). The secrets and vars sync is designed here and not built (STA-606). Everything that needs the generated Encore app waits for gen: the Encore deploy spike (STA-136), the staging deploy, images and generated CI pipelines.
Runway is the deploy layer of Stackra: the runway files say what each member needs and where it runs (0296), and public reusable workflows in this repository deploy it (0168). Promotion, rollback and records follow 0170; secrets follow 0173.

Runway files

pnpm validate reads every one of them, checks it against the version 3 schema of its kind with @stackra/runway, and checks that a grouped topology places each service member exactly once (checkRunwayFiles). A runway.yaml anywhere else is a finding. The check uses the built package: the Quality Gate builds before it validates, and a local pnpm validate before a build prints a notice instead. Core’s root runway declares only dev and production: Stackra deploys only its own infrastructure, the static Worker, the docs and the npm packages (0170 decision 1). The docs member has its runway (0299 decision 6); workers/static gets one with gen, when its hand-written wrangler.jsonc goes (0284 decision 8).

Provider workflows

Each provider is a workflow_call workflow in .github/workflows/. Its job takes its GitHub environment from an input, so the environment’s protection, its OIDC subject and GitHub’s deployment record apply to every deploy. Each job reads one credential per step from Infisical /ci over GitHub OIDC, and without an identity id it builds, checks, prints a notice and deploys nothing. npm checks the calling workflow, not the reusable one, so each package’s trusted publisher names release.yml.

Calling a provider from another repository

A release of the providers is the tag runway-v<n> on a commit of main. Pin the commit, with the tag in a comment, as for every action (0019 D1):
The calling job grants the permissions the provider’s job asks for. zizmor fails any uses: that is not a full SHA.

The deploy command

pnpm runway is the one way to start a deploy, for people and CI alike (STA-268). It never builds or deploys on your machine: it checks the commit and dispatches the same caller workflow a merge runs.
  • plan [env] prints, as JSON, each target in build order with its caller workflows, the CI secret names the jobs read and the member secret and var names a deploy syncs. Names only.
  • deploy <target> needs a clean checkout at the head of origin/main; it prints that SHA and dispatches each caller workflow of the target.
  • promote <sha> needs a commit on origin/main; it dispatches every production caller that takes a sha input. That is also the rollback: promote the last good release’s SHA. A caller that only builds the head of main (Mintlify) is listed as skipped.
  • --dry-run prints the gh commands instead of running them. An agent’s deploy or promote without it asks the owner (the guard’s runway-deploy rule).

Secrets and vars sync

The sync is designed here and built in STA-606, once its targets exist.
  1. Source. Infisical holds every value (0173). Member runways name secrets; the root names the Infisical environment per runway environment (providers.infisical.environments) and the path (secrets.defaultPath in providers.infisical.paths). CI-only names are root secrets.ci and never reach a runtime.
  2. Who reads. The deploy job of each environment logs in with that environment’s own Infisical identity over OIDC, trusted only for that environment’s subject, so a staging job cannot read production.
  3. Plan first. Before writing, the job prints the names it will write and where (pnpm runway plan <env> shows the same list). A name the member declares and Infisical lacks fails the deploy before anything changes.
  4. Write from stdin only. A value never appears in argv, a file, GITHUB_ENV, an output, an artifact or a log:
  5. Vars. A member’s per-environment vars are public values. A ref:<path> value resolves from the stacks repository’s Pulumi config at deploy time (0171); a ${pr} value from the build environment.
  6. Drift. A name in the runtime that no runway declares is reported, never deleted, until a prune rule is decided.

What is not built yet

Owner steps

Agents cannot do these (STA-605):
  1. Restrict the static environment to main and schemas@* tags.
  2. Create the docs environment (main only), and add Infisical OIDC trusts for the docs and release environments.
  3. Put MINTLIFY_ADMIN_KEY into Infisical /ci through the secrets inbox, set the repository variable MINTLIFY_PROJECT_ID, and switch off the Mintlify GitHub-app deploy after the first CI deploy.
  4. Apply .github/rulesets/release-tags.json to the release-tags ruleset.
  5. After the merge, tag runway-v1 on the merge commit.
  6. The first npm publish (OP2): a 7-day publish-only token as NPM_BOOTSTRAP_TOKEN in /ci, dispatch release.yml with bootstrap, add a trusted publisher naming release.yml for each package, revoke the token.
See also Deploys, Release, Secrets and CI.