werkator build succeeded after 01:04
Co-authored-by: claude-code <claude-code@javagil.de>
107 lines
5.3 KiB
Markdown
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
|
|
|
|
… 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.
|