# 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 … 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 … 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 … 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 … 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.