feat(server): Routen, Seiten und Artefakte tragen das Repository — /repos/<name>/… (Sitzung D)
Zweite Hälfte von Sitzung D (docs/plan/22-multi-repo.md, PR #13): Der Server bediente bisher genau ein Repository der Registry. Jede Route — API, Seiten, Artefakt-Dateien — arbeitete auf `registry.current()`; ein zweites registriertes Repository wurde gebaut und gepollt, war aber unsichtbar und unerreichbar. Jeder Controller löst sein Repository jetzt je Anfrage auf, statt das bediente als Bohne zu halten; jede Route ist zweimal gemappt. Die unscoped Form ist kein Übergangs-Alias, sondern dauerhaft die Art zu sagen „das bediente Repository" — Lesezeichen und die nach Gitea geposteten Links kennen kein Segment. Entschieden gegen die Repo-Spalte: Die Seiten bleiben je Repository, die Navigation bekommt einen Umschalter. Die Aktionen einer Zeile brauchen das Repository ohnehin, Branches kommen von einem origin und Artefakte aus einem Store — und bei dem einen Repository, das die meisten Installationen haben, wäre eine Spalte nur Rauschen. Das Link-Präfix folgt der ZAHL der bedienten Repositories, nicht dem Weg, über den eine Seite erreicht wurde: mit einem behält die Installation ihre bisherigen URLs (Abnahmekriterium der Sitzung), mit mehreren benennt jeder Link sein Repository. werkator.js liest das Präfix einmal aus einem `werkator-repo-base`-Meta. `BranchPermalinks.permanentUrl` bekommt es ebenfalls — der permanente Schlüssel ist ein Hash des Build-Namens allein, zwei Repositories mit `main` teilten sich sonst eine permanente URL. Fünf neue Tests, Gegenprobe per Mutation gezogen (Präfix fest auf leer → genau der Mehr-Repo-Test fällt). 498 Tests grün, ktlint sauber. PR-Dokument docs/prs/2026-09-03-PR#13-…, Plan, Architektur-Skill und AGENTS.md nachgezogen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4304dd7c4b
commit
c82f2a965c
@@ -63,7 +63,7 @@ Three places must stay in sync when config keys change: the `WerkatorConfig` dat
|
||||
|
||||
## Repository Context
|
||||
|
||||
Everything repository-scoped goes through a `RepoContext` (`repo` package, ADR 0009): the primary checkout (`workingDir`), the repository's `BuildResultRepository` (`.git/werkator/build-results.json`), its `ArtifactStore` (keyed by the repository path), and a short `name` defaulting to the directory basename — the future route segment. `RepoContexts.open(dir)` builds one (running the pre-rename state-dir migration for that repository on the way); `RepoRegistry` opens one per entry of the instance configuration's `repositories` — or the current directory without a registry — lazily on first use and loudly: a non-repository entry or a duplicate name aborts the start naming the home file, a repository whose config must not be read (`ConfigException`) is skipped with an error. `RepoConfiguration` provides `registry.current()` (the cwd when served, else the first entry) as the `RepoContext` bean for the still-unscoped controllers, and the `BuildResultRepository`/`ArtifactStore` beans are that context's. The `--repo` mixin (`RepoOption`) selects by name in `build`, `retry`, and `status`. Git access and config loading stay path-based services taking `repo.workingDir`; the instance configuration (`~/.werkator.yml`, `ConfigLoader.homeDir`/`WERKATOR_HOME`, bound as `InstanceConfig`) is folded in by `ConfigLoader.loadRaw` itself — its `defaults` below every repository layer, its `server`/`executor`/`watcher.pollInterval` overlaid on top and stripped from the repository files with one warning — so every consumer of `load(dir)` sees the instance values without knowing the file. The context object is the identity (executor pools, watcher memory are keyed by it), so exactly one is opened per repository — `RunningBuild` carries it too, so `currentBuilds()` says which repository a running build belongs to: the current-builds view and API serve only the served repository's builds, and the watcher's worktree pruning is protected by its own repository's builds alone. Not yet repository-scoped: the routes and the UI, which still serve `registry.current()` only (session D).
|
||||
Everything repository-scoped goes through a `RepoContext` (`repo` package, ADR 0009): the primary checkout (`workingDir`), the repository's `BuildResultRepository` (`.git/werkator/build-results.json`), its `ArtifactStore` (keyed by the repository path), and a short `name` defaulting to the directory basename — the future route segment. `RepoContexts.open(dir)` builds one (running the pre-rename state-dir migration for that repository on the way); `RepoRegistry` opens one per entry of the instance configuration's `repositories` — or the current directory without a registry — lazily on first use and loudly: a non-repository entry or a duplicate name aborts the start naming the home file, a repository whose config must not be read (`ConfigException`) is skipped with an error. `RepoConfiguration` provides `registry.current()` (the cwd when served, else the first entry) as the `RepoContext` bean; the controllers no longer take it — they resolve per request from the `{repo}` path segment, and `registry.current()` is what the unscoped routes mean. The `--repo` mixin (`RepoOption`) selects by name in `build`, `retry`, and `status`. Git access and config loading stay path-based services taking `repo.workingDir`; the instance configuration (`~/.werkator.yml`, `ConfigLoader.homeDir`/`WERKATOR_HOME`, bound as `InstanceConfig`) is folded in by `ConfigLoader.loadRaw` itself — its `defaults` below every repository layer, its `server`/`executor`/`watcher.pollInterval` overlaid on top and stripped from the repository files with one warning — so every consumer of `load(dir)` sees the instance values without knowing the file. The context object is the identity (executor pools, watcher memory are keyed by it), so exactly one is opened per repository — `RunningBuild` carries it too, so `currentBuilds()` says which repository a running build belongs to: the current-builds view and API serve only the served repository's builds, and the watcher's worktree pruning is protected by its own repository's builds alone. Routes, pages, and artifact files are repository-scoped (session D): every mapping exists twice, `/api/repos/<name>/…` and `/repos/<name>/…` beside the unscoped form, an unknown name is a 404, and the link prefix follows the number of served repositories — one repository keeps its existing URLs, several make every link name its repository and show the switcher in the navigation.
|
||||
|
||||
## Build Execution
|
||||
|
||||
|
||||
Reference in New Issue
Block a user