feat(remote): repo-add bereitet ein weiteres Repository für die Registry vor

`tools/remote` konnte genau ein beobachtetes Repository einrichten
(`repo-init`, fest auf $WERKATOR_PATH/werkator). Für eine Instanz, die eine
Registry bedient (ADR 0009), fehlte der Weg, ein zweites hinzuzunehmen —
und das braucht der Rollout unabhängig davon, welche Repositories es am Ende
sind.

`repo-add <url> [name]` klont daneben, führt `init` darin aus und PRÜFT, ob
die Registry den Pfad schon nennt — geschrieben wird sie nicht. `~/.werkator.yml`
ist die Datei der Instanz: Port, globale Nebenläufigkeit, womöglich geteilte
Zugangsdaten. Ein Skript, das sie in place umschreibt, verändert die
Konfiguration des Betreibers hinter dessen Rücken. Klonen und Initialisieren
ist mechanisch, Registrieren ist eine Entscheidung — also druckt es den
Eintrag und sagt, dass die Registry beim Start gelesen wird.

Der Name muss ein Pfadsegment sein: Er wird das Routen-Segment /repos/<name>.
docs/deployment.md verweist im Registry-Abschnitt darauf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-09-03 13:59:24 +02:00
co-authored by Claude Opus 5
parent 80a14a7467
commit c1629cace3
2 changed files with 62 additions and 0 deletions
+10
View File
@@ -114,6 +114,16 @@ Adding a repository is editing a registry entry — never a data migration, beca
The name is the route segment (`/repos/<name>/…`) and the UI's switcher entry, so it must be unique: a duplicate aborts the start naming this file, and so does an entry that is no git repository.
A repository whose configuration Werkator must not read (a version violation) is skipped with an error — the others keep building.
Steps 1 and 2 are mechanical and can be done from the workstation:
```bash
tools/remote --env-file .env.<instance> werkator repo-add https://github.com/<owner>/<repo>.git [<name>]
```
It clones the repository next to the ones already served, runs `init` in it, and **prints** the registry entry.
It does not write `~/.werkator.yml`: that file is the instance's own — port, global concurrency, possibly shared credentials — and a script editing it in place would rewrite the operator's configuration behind their back.
Cloning and initialising is mechanical; registering is a decision.
4. **Restart** the service; startup recovery re-enqueues what was in flight:
```bash
+52
View File
@@ -19,6 +19,8 @@
# tools/remote [--env-file FILE] werkator instance-update redeploy bundle + werkdock, restart the service
# tools/remote [--env-file FILE] werkator instance-start apply fragment, Apache proxy, systemd unit
# tools/remote [--env-file FILE] werkator repo-init clone the watched repo, init --apply, rootfs
# tools/remote [--env-file FILE] werkator repo-add URL [NAME] clone and init ANOTHER repository for the
# registry, then print the entry to add to ~/.werkator.yml
# tools/remote [--env-file FILE] werkator control-token
# tools/remote [--env-file FILE] port-forward start background tunnel to the Werkator UI
# tools/remote [--env-file FILE] port-forward stop
@@ -273,6 +275,53 @@ repo_init() {
echo " then tools/remote werkator instance-start"
}
# Prepare a SECOND (third, …) repository for the registry of an installed
# instance (ADR 0009): clone it next to the others and run `init` in it, so it
# has its own machine config. The registry entry itself is only PRINTED, never
# written: `~/.werkator.yml` is the instance's own file — it carries the port,
# the global concurrency and possibly shared credentials, and a script that
# edits it in place would rewrite the operator's own configuration behind their
# back. Cloning and initialising is mechanical, registering is a decision.
repo_add() {
local url="${1:-}"
[ -n "$url" ] || die "usage: tools/remote [--env-file FILE] werkator repo-add <clone-url> [name]"
local name="${2:-$(basename "$url" .git)}"
case "$name" in
*/*|"") die "the repository name is one path segment (it becomes the route segment /repos/<name>)" ;;
esac
ensure_ssh
ssh "$HOST" "test -x '$WERKATOR_BIN'" || die "no instance on $HOST — run instance-install first"
echo "==> Cloning $url as '$name'"
if ssh "$HOST" "test -d '$TARGET_DIR/$name/.git'"; then
echo " (already cloned, skipping)"
else
ssh "$HOST" "git clone '$url' '$TARGET_DIR/$name'"
fi
echo "==> Running werkator init in $name"
ssh "$HOST" "cd '$TARGET_DIR/$name' && '$WERKATOR_BIN' init"
echo "==> Checking the registry"
if ssh "$HOST" "grep -q -- '$TARGET_DIR/$name' ~/.werkator.yml 2>/dev/null"; then
echo " (~/.werkator.yml already names this path)"
else
echo " not registered yet — add this entry to ~/.werkator.yml on $HOST:"
echo
echo " repositories:"
echo " - path: $TARGET_DIR/$name"
echo " name: $name"
echo
fi
echo "==> Repository prepared."
echo " Repo: $TARGET_DIR/$name"
echo " Next: fill git.account/git.token in $TARGET_DIR/$name/.git/werkator/.werkator.yml if the origin is private"
echo " (or once for all repositories in the 'defaults' block of ~/.werkator.yml),"
echo " then restart the service — the registry is read at start."
}
# Start the server as a systemd user unit behind the managed Apache. All
# configuration comes from the instance fragment (server.port, publicBaseUrl,
# systemd limits); init generates the units AND the .htaccess — this script
@@ -384,6 +433,9 @@ case "$REPO" in
repo-init)
repo_init
;;
repo-add)
repo_add "${3:-}" "${4:-}"
;;
control-token)
control_token
;;