Files
werkregie/doc/prs/2026-10-14-PR#69-werkator-deploy.md
claude-code 1ee7a87150
werkator build succeeded after 01:04
Werkator deploys a green main to mih09 (#69)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-14 14:07:19 +02:00

107 lines
5.3 KiB
Markdown

# PR#69: Werkator Deploys a Green main to mih09
> **WARNING:** This document describes only the change applied in this PR.
> It may already be outdated once the next PR is merged.
> Historic PR documentation is not maintained along with new PRs; treat it as a snapshot.
## Related Links
- Werkator's [docs/configuration.md](https://git.javagil.de/mi/werkator/src/branch/main/docs/configuration.md),
"Follow-up builds": a deployment is a build with `afterSuccessOf`;
the repository says what it does, the host when, where and with which key.
- werkrevisor PR#70: Hostsharing refuses ssh connections that follow too quickly.
## Problem
So far a coding agent deployed the server on mih09 by hand, with `scp` and `ssh` after each merge.
The auto mode of Claude Code now refuses such a production deploy, so 0.41.1 and 0.42.0 were merged but not deployed.
A deploy that depends on the rights of an agent session is not reliable.
## Non-Goals
- No deploy of the relays; they run on the user's machines.
- No deploy of a branch other than `main`.
- No change to how the server runs: unit, port, configuration and `.htaccess` stay.
## Specification
### Feature: Werkator deploys a green main to mih09
#### Scenario#69.01: a green main build deploys its commit
&hellip; so that what runs on mih09 is the last green `main`, without an agent or the human.
- **Given** the host part of the build `deploy` on mih09 and a green build `default` of `main` at version 0.43.0
- **When** Werkator runs the build `deploy`
- **Then** https://werkregie.javagil.de serves version 0.43.0, and the previous runtime stays as `werkregie-dashboard.prev`
##### Verified by
- [DeployReceiveTest: a bundle replaces the runtime and the service answers with its version](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/DeployReceiveTest.kt)
- manual: the first deploy after the merge, see "Solution"
#### Scenario#69.02: a runtime that does not answer is rolled back
&hellip; so that a broken deploy leaves the previous version running.
- **Given** a bundle whose service does not answer with its version within the waiting time
- **When** the receiver installs it
- **Then** the previous runtime runs again, and the build `deploy` fails
##### Verified by
- [DeployReceiveTest: a service that does not answer with the new version gets the previous runtime back](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/DeployReceiveTest.kt)
#### Scenario#69.03: a bundle whose launcher fails does not stop the service
&hellip; so that a JRE that does not start on the host costs no downtime.
- **Given** a bundle whose launcher fails
- **When** the receiver checks it
- **Then** the service keeps running unchanged, and the build `deploy` fails
##### Verified by
- [DeployReceiveTest: a bundle whose launcher fails leaves the service untouched](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/DeployReceiveTest.kt)
#### Scenario#69.04: the deploy key can only deploy
&hellip; so that a stolen deploy key gives no shell on the server.
- **Given** the deploy key of Werkator on the server
- **When** a connection with this key asks for a shell command
- **Then** the server does not run the command, only the deploy of a bundle
##### Verified by
- manual: after the setup on mih09, `ssh werkregie-deploy whoami < /dev/null` as Werkator's user
ran the receiver, which failed on the empty bundle with exit 2; `whoami` did not run.
## Solution
- `.werkator.yml` defines the build `deploy`: `dashboard/packaging/werkregie-deploy`, status `werkator/deploy`, no artifacts.
It has no trigger in the repository; the host part on mih09 sets `afterSuccessOf: default` on `main` and pins it,
so that no branch deploys itself (Werkator's docs/configuration.md, "Follow-up builds").
- `werkregie-deploy` builds the runtime bundle of the tested commit
and pipes it over one ssh connection to the alias `werkregie-deploy`.
The host names the server and the key under this alias in the ssh configuration of the build's home,
since a native build of Werkator has no `env` of its own.
It tries a refused connection again, 4 times in all, as werkrevisor's `tools/deploy-rootfs` does since werkrevisor PR#70.
- `werkregie-deploy-receive` is the forced command of the key on the server, installed once by the human:
it unpacks the bundle beside the running one, runs `bin/werkregie-dashboard version`, stops the service,
keeps the running runtime as `werkregie-dashboard.prev`, swaps, starts,
and waits up to 120 s until `/api/dashboard` answers with the new version; otherwise it puts the previous runtime back.
The demo answer of `/api/dashboard` carries the version and needs no token.
- The human set up the host part before the merge, as in the README of the dashboard, except the trigger:
a trigger without the definition of `main` would run the build command of `default` as `deploy`.
mih09 offers an RSA host key only, so `ssh-keyscan -t ed25519` found none.
- `DeployReceiveTest` runs the receiver against a temporary directory, with `systemctl` and `curl` as stubs.
- The README of the dashboard holds the setup of the human, `AGENTS.md` says that the agent only checks the deploy,
and the risk analysis names the deploy key.
- Version 0.43.0; the deploy of this PR is the first one.
It installs 0.43.0, which holds the changes of PR#66 and PR#68, merged but never deployed.
## Open Questions
None.