carlos / platform Public

zdd-6 task 15: docs for apps set, the rollout watch, --swap, promote --retry, the migrations rule and sidecars

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 77d77b3a83cb513b92dd52181ffd3f42104674a5 parent 17cd0e4
1 file changed, +79 −4
  • docs/site/cli.md +79 −4
diff --git a/docs/site/cli.md b/docs/site/cli.md
index 08bf235a5..2cbf7587b 100644
--- a/docs/site/cli.md
+++ b/docs/site/cli.md
@@ -184,6 +184,22 @@ carlos apps ttl --app tmp-docs 5d
carlos apps keep --app tmp-docs
```
+<!-- TODO-COPY zdd.docs.apps-set -->
+`carlos apps set` changes how the app's running instances take a new build:
+
+```sh
+carlos apps set hello --swap hold
+carlos apps set hello --swap-concurrency 3
+```
+
+With `--swap overlap`, the default, the new build starts beside the old one
+and takes over once it answers its health check, so no request waits. With
+`--swap hold`, the old one stops first, and requests wait until the new one
+is up. `--swap-concurrency` is how many instances may swap at once on one
+box, after the first one has stayed up for ten seconds; it starts at 1. Any
+member of the app can change both, here or on the app's settings page in the
+console.
+
### carlos ship
Publishes a release. The artifact is hashed, stored under its content
@@ -236,7 +252,19 @@ Ship, promote, and then wait until the app's URL actually serves the new
build. Reach for this one by default; ship and promote separately when you
want the gap between them.
-What it watches is worth knowing, because the two answers differ. If the app
+<!-- TODO-COPY zdd.docs.deploy-watch -->
+Deploy then watches each box roll the build out. An awake instance counts
+once the new build has passed its health check and taken over; on each box
+the first one must also stay up for ten seconds before the rest follow. An
+asleep instance counts once its box has installed the build, and starts it on
+its next request. If the build fails on a box, that box stops rolling it out,
+its other instances stay on the build they were serving, and deploy names the
+failure and exits with an error.
+
+<!-- TODO-COPY zdd.docs.deploy-watch-lead -->
+Where a box does not report its rollout yet, deploy watches the app's URL
+instead, and what it watches there is worth knowing, because the two answers
+differ. If the app
declares a build probe, deploy asks the app's own process which build it is
running, and `live` means the process cycled. If it does not, deploy watches
the `X-Carlos-Version` header — and the edge stamps that from the route row
@@ -266,6 +294,22 @@ having no instances to resolve a channel from.
carlos deploy --app website --kind static --host www.example.com ./dist
```
+<!-- TODO-COPY zdd.docs.deploy-swap-and-retry -->
+`--swap hold` ships a release that stops each instance before starting the
+new build, for a migration the previous build cannot share the database
+with. It applies to that release only; `carlos apps set --swap hold` makes it
+the rule for the app.
+
+To try a build that failed again, once you have fixed what it depended on,
+promote it again with `--retry`. Every box where it failed tries it again:
+
+```sh
+carlos promote --app hello --retry a1b2c3d edge
+```
+
+Without `--retry`, promoting a build that is already on the channel does
+nothing.
+
When `carlos deploy` creates your first app, it sends your timezone so the
console can pick the region nearest you, and prints the choice. `--region
<code>` chooses instead. On an app that already exists, `--region` must
@@ -282,6 +326,23 @@ app is served only at its own platform address, so `--host` and
carlos deploy --temporary --ttl 3d ./dist
```
+<!-- TODO-COPY zdd.docs.migrations -->
+#### Two builds at once
+
+When a new build reaches an awake instance, it starts beside the old one,
+and for a few seconds both run. They share the instance's database and its
+scheduled work. The new build's migrations run while the old build is still
+serving, so both builds must work with the database in between:
+
+- Add in one release and remove in a later one. A new column, table or index
+ goes in one release; dropping the old one waits for the next.
+- Keep the names of scheduled work (`carlos schedule`) the same across the
+ two builds.
+
+When a release cannot follow these rules, ship it with `--swap hold`, or set
+the app to `hold` with `carlos apps set`. Each instance then stops before the
+new build starts, and requests wait until it is up.
+
#### Deploying one checkout to several places
When one project deploys to more than one console, or as more than one app,
@@ -668,6 +729,19 @@ every few minutes, and asleep instances are measured too. A dash means no box
has measured it: the instance is not running anywhere yet, it has not created
its database, or it keeps its data somewhere CARLOS does not manage.
+<!-- TODO-COPY zdd.docs.instances -->
+`carlos instances list` shows two builds for each instance: the one installed
+on its box, and the one serving its requests. They differ while a new build
+rolls out, while an asleep instance waits for its next request, and after a
+build has failed on that box. The REASON column says which.
+
+`carlos instances retry` clears the failure hold on one instance, so the
+build that failed there is tried again, as a canary:
+
+```sh
+carlos instances retry --app hello shop-1.hello.example.com
+```
+
`--environment <e>` on `create`, and `set-environment` on a route that
already exists, bind one instance to one of the app's named config bundles.
This matters most for a route standing **alongside** a live one. Config is
@@ -833,10 +907,11 @@ record asks for it, independently and on purpose: one is a fact about the
network, the other a requirement of the work. Where they disagree the more
restrictive reading wins.
+<!-- TODO-COPY zdd.docs.sidecars -->
Because a sidecar has no URL, there is no `X-Carlos-Version` header to read
-it back from, so `carlos sidecars ls` shows the version a sidecar reported
-for itself against the version its channel points at. One that has never
-reported reads as unknown rather than as current.
+it back from, so `carlos sidecars ls` shows the build its box last started
+for each sidecar, beside the version its channel points at. One that has not
+started on any box reads as unknown rather than as current.
### carlos steering