Developer Docs

Deployment

How DevStride actually ships to dev and prod — entirely CI-driven via Seed, with no local deploy command.

Deployment

DevStride has no local deploy command. There is no ds deploy, no pulumi up, nothing you run from your laptop to ship code to a shared environment. Deploys are entirely CI-driven, triggered by pushing to a tracked branch, and orchestrated by Seed — not by GitHub Actions.

Seed (seed.run) drives every deploy

The repo's seed.yml defines the build hooks that Seed runs on every push to a tracked branch. The two hooks that matter most:

before_deploy:
  - bash ds -ru script set-config
  - bash ds -ru script delete-orphan-stacks
  - bash ds -ru script check-orphan-stacks
after_deploy:
  - bash ds -ru migrations run-sql
  • before_deploy runs ds script set-config, which pushes the environment's config values up into the SST DEVSTRIDE_CONFIG secret binding so the freshly-deployed Lambdas can read them at runtime, then cleans up (and guards against) orphaned CloudFormation stacks left behind by stacks removed from sst.config.ts.
  • after_deploy runs ds migrations run-sql — the SQL migrations only apply after the new code has shipped, as a separate Seed build process on a cold cache.

Seed also runs ds script generate-api-docs in a before_build hook to keep the published OpenAPI spec in sync with the deployed routes. None of this happens on your machine — it's the exact sequence Seed executes on every deploy.

GitHub Actions: CI checks, not deploys

It's easy to assume .github/workflows/ is where deploys live, since that's the conventional place for them. In this repo, it isn't. All six workflow files run checks against pull requests (or are manual-only) — none of them deploy anything:

WorkflowTriggerWhat it does
backend-tests.yamlpull_requestRuns the sharded backend vitest suite
lint-backend.yamlpull_requestType-checks the backend (pnpm run check:ts)
lint-frontend.yamlpull_requestType-checks the frontend (pnpm run check:ts)
ui-tests.yamlpull_requestRuns the frontend test suite
golden-republish.yamlworkflow_dispatch onlyManually-triggered rebuild of the canonical golden dataset source; explicitly never runs automatically
claude.ymlIssue/PR comment containing @claudeThe Claude Code PR-comment bot

Deploy workflow files did exist here once, but they were deleted years ago — they're simply gone, not present-but-defunct. Today, GitHub Actions is purely a PR gate (plus the two manual/bot workflows above); the deploy pipeline lives entirely in Seed's own infrastructure.

Branch → stage mapping

By convention:

  • Push/merge to develop → deploys the dev stage, served at app.devstride.dev
  • Push/merge to master → deploys the prod stage, served at app.devstride.com

The frontend ships with the backend

The frontend isn't deployed by a separate pipeline. It ships as part of the same SST deploy, via the sst.StaticSite construct (stacks/ui/app-ui.stack.ts) — built with pnpm run build:ui and pushed to S3/CloudFront in the same sst deploy that ships the backend Lambdas.

That stack is gated off when you're running locally: sst.config.ts only registers the SiteStack when !app.local, so ds run backend (which runs pnpm exec sst dev) never tries to build or deploy the frontend — for local frontend work you run ds run ui separately, which just points a local Vite dev server at your bound stage's API.

Manual escape hatch (advanced, narrow)

There are exactly two documented cases for invoking the SST CLI directly instead of going through CI. The first is scoped to the packages/mcp package specifically:

DEVSTRIDE_STAGE=prod pnpm exec sst deploy

packages/mcp/README.md documents this to ship the MCP server, noting explicitly that it's part of the same SST deployment with no separate pipeline of its own — this is a raw sst invocation, not wrapped by any ds command. Treat it as an advanced, narrow escape hatch for that package, not a general-purpose way to deploy the app. Similarly, the root README.md documents raw sst remove for tearing down your own personal stage — again a direct SST CLI call, not a ds subcommand.

Outside of these two narrow, explicitly-documented cases, the only supported path to a deployed dev or prod environment is: merge to develop or master and let Seed do the rest.

Next Steps