From 91e1dd47a384af1c85655b5558c6a4c9c4c2e650 Mon Sep 17 00:00:00 2001 From: mhoennig Date: Thu, 3 Sep 2026 13:41:26 +0200 Subject: [PATCH] docs(deployment): wie eine Instanz mehrere Repositories bedient MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der aus Sitzung C nach E übertragene Doku-Punkt: docs/deployment.md beschreibt die Registry jetzt betrieblich — klonen, vorbereiten, in ~/.werkator.yml eintragen, neu starten. Dazu die Regeln, die beim Eintragen weh tun, wenn man sie nicht kennt: Der Name ist Routen-Segment und Umschalter-Eintrag und muss eindeutig sein (ein Doppel bricht den Start ab, ebenso ein Eintrag, der kein git-Repository ist), eine unlesbare Konfiguration überspringt nur ihr Repository, geteilte Zugangsdaten können einmal im defaults-Block liegen, und die Unit behält ihren Namen — sie gehört der Instanz, nicht einem Repository. Dazu, was die Adressen tun: mit einem Repository bleibt jede URL, wie sie war; mit mehreren tragen Seiten und API das Repository, und die unscoped Pfade meinen weiterhin das bediente. Co-Authored-By: Claude Opus 5 --- docs/deployment.md | 44 ++++++++++++++++++++++++++++++++++++++ docs/plan/22-multi-repo.md | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/docs/deployment.md b/docs/deployment.md index f4f5809..af37bd1 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -81,6 +81,50 @@ User services stop at logout unless lingering is enabled once per user: loginctl enable-linger "$USER" ``` +## Serving Several Repositories + +One instance serves a *set* of repositories (ADR 0009): one service, one port, one UI, one watcher loop, one control token. +Adding a repository is editing a registry entry — never a data migration, because everything repository-specific already lives inside the repository (`.git/werkator/`: machine config with secrets, build results, auto-build slots, worktrees). + +1. **Clone it** on the host, next to the ones already served: + + ```bash + git clone https://github.com//.git ~/repos/ + ``` + +2. **Prepare it** like any watched repository — the machine config with the git credentials, and the sandbox policy if the host needs one: + + ```bash + cd ~/repos/ && java -jar ~/bin/werkator.jar init + # fill in git.account and git.token in .git/werkator/.werkator.yml + ``` + + Credentials shared by every repository of the same forge can live once in the instance file's `defaults` block instead (`docs/configuration.md`); they merge below each repository's own layers, so a repository may still override them. + The repository's own `.werkator.yml` — its builds — is committed and comes with the clone. + +3. **Register it** in `~/.werkator.yml` of the user running the service: + + ```yaml + repositories: + - path: ~/repos/werkator + - path: ~/repos/ + name: # optional; default is the directory basename + ``` + + The name is the route segment (`/repos//…`) 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. + +4. **Restart** the service; startup recovery re-enqueues what was in flight: + + ```bash + systemctl --user restart werkator-.service + ``` + +The service unit keeps the name it was installed with — it is the instance's unit, not one repository's. +With one registered repository every URL stays what it was; with several, the pages and the API carry the repository (`/repos//…`, `/api/repos//…`), the unscoped paths keep meaning the repository the instance was started in, and the navigation shows a switcher. +The watcher polls every repository in its own guard: an unreachable origin is that repository's report in the health banner, and the others are polled regardless. +`executor.maxConcurrent` is the global cap across all of them, and builds take slots in enqueue order (FIFO). + ## Operating the Service ```bash diff --git a/docs/plan/22-multi-repo.md b/docs/plan/22-multi-repo.md index 9bf7449..da96d02 100644 --- a/docs/plan/22-multi-repo.md +++ b/docs/plan/22-multi-repo.md @@ -68,7 +68,7 @@ The pinning model is untouched: pinned keys still come from each repo's machine - ~~Latest/branches/history views group by repo or gain a repo column; one instance-wide metrics page; one control token.~~ — done 2026-09-03, decided against the column: the pages stay per repository and the navigation gains a **repository switcher** (a row's actions need the repository anyway, branches come from one origin, artifacts from one store — and with one repository a column is noise). Metrics page and control token stay instance-wide as planned. - Gitea status links use the repo-scoped URLs — the permanent artifact links do (`BranchPermalinks.permanentUrl` takes the prefix, because the key is a hash of the build name alone and two repositories both having `main` would otherwise share one URL); the commit-status target URLs posted by `GiteaStatusPublisher` are carried over to session E, where the instance actually serves two repositories. - Also done: `RunningBuild` carries its `RepoContext` (the carry-over from session C), so the current-builds views and the watcher's worktree pruning tell repositories apart, and `cancel` refuses a key that is not recorded in the named repository. -- Carried over to session E: the commit-status URLs; `docs/deployment.md` gets the registry setup. +- Carried over to session E: the commit-status URLs. ~~`docs/deployment.md` gets the registry setup~~ — done 2026-09-03: section "Serving Several Repositories" (clone, prepare, register, restart) with the name rules, the per-repository guard, and what the URLs look like with one repository and with several. ### E — Rollout on mih34: Werkbaum joins