lifeos handbook
Operations

Deploying

The single gated path, and the two switches that must stay off.

One path

push to main
   └── .github/workflows/ci.yml
         ├── job: affected   Biome · ./gradlew build · nx affected -t build
         └── job: deploy     needs: affected, main + push only
               ├── nx affected -t deploy   → Cloudflare Workers (wrangler, per web project)
               └── POST application.deploy → Dokploy, per affected backend, then verified

Two switches that must stay off, permanently

SettingWhereMust be
Workers Builds / git integrationCloudflare → Workers → each Worker → Settings → Builddisconnected
Auto DeployDokploy → each application → Generaloff

Either one, turned on, creates a second path to production that skips the test gate and knows nothing about the Nx affected set (ADR-0005).

Cloudflare cannot compute affected — a change in @lifeos/ui fans out, and only the Nx graph knows how far. Git integration gives you either every-project-every-push or hand-maintained path filters that go stale on the first import change.

If you ever see a deploy this workflow did not run, check those two settings before anything else.

A 200 is not a deploy

Dokploy's application.deploy answers 200 the moment the request is accepted, long before anything is rebuilt. Treating that as success is a real incident from the reference estate.

So CI does three things and fails if any of them does not happen:

Trigger the deploy.
Wait for the application to visibly enter a running build. Never seeing running means nothing was rebuilt — that is a failure, not a fast deploy.
Wait for the public health endpoint to come back UP. done means the image built and the container started; it does not mean Spring finished booting.

The same discipline applies to tools/deploy/infra/deploy.sh for the shared services.

Docs-only pushes

docs/ is in .nxignore, so editing it affects no project and a docs-only push produces a deliberate NO-OP DEPLOY banner in the job summary. That banner is the workflow saying it decided to do nothing — not a deploy that quietly failed.

The handbook's own MDX lives in apps/docs/web/content/, not in docs/. Editing it is a real change to a real project and does trigger a deploy, which is the point.

On this page