Files
werkator/docs/plan/00-legacy-analysis.md
T
mhoennigandClaude Opus 5 35f06ec1ec Rename GitTally to Werkator
`gitTally` is the name of another product in the git space, so the
rename is a precaution; nothing about what the build system does changes.

The name follows one rule: `Werkator` where it is prose, capitalized
where it is a Kotlin type and its file, lowercase everywhere a machine
reads it — the command, packages, paths, configuration keys and values,
the Gitea check context. Environment variables keep their convention and
are uppercase throughout.

Every configuration file is still found under its pre-rename name
(`ConfigFiles`): `.gittally.yml` at the repository root, in a build
worktree and as committed on a branch, `.git/gittally/.gittally.yml` for
the machine layer. The current name wins where both exist, and the old
file is then ignored rather than merged — two files side by side are a
half-done rename, not a layering. Without the fallback an installation
that updated without renaming would not fail: a configuration that is
not found leaves every setting at its default, so it would come up
looking healthy while having forgotten its credentials and its builds.

`docs/werkator-migrationsplan.md` lists what the fallback does not
cover and has to be moved by hand — above all the state directory
`.git/werkator/`, which holds the build history, the control token and
the worktrees, and has no fallback of its own.

`docs/migration-from-legacy.md` is deleted with this: it mapped the
legacy script's environment variables, and every host it addressed has
long since moved to the YAML configuration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 19:39:55 +02:00

5.6 KiB
Raw Blame History

Legacy Werkator Analysis

Condensed analysis of legacy/werkator (bash, ~6000 lines) as input for the rewrite. Line numbers refer to the legacy script at the time of analysis (version 0.7.8).

What the Legacy System Does

A single bash daemon per repository that:

  1. Polls origin for changed local branches and recent new origin branches.
  2. Checks out and builds each changed branch (natively or in Docker), one at a time.
  3. Records results and publishes commit statuses to Gitea.
  4. Archives build logs and report directories as browsable artifacts.
  5. Serves a static-HTML web UI via an embedded Python HTTP server.
  6. Optionally manages an nginx+certbot Docker container for HTTPS.
  7. Installs itself as a systemd user service.

Persistent State (formats to replace)

All state lives in files; there is no database.

File Format Content
.git/git-watch-origin-and-test/build-results.tsv TSV branch, commit, status, timestamp, duration(MM:SS), artifact_key
.git/git-watch-origin-and-test/auto-builds.tsv TSV branch, date, time_slot — prevents double auto-builds
.git/git-watch-origin-and-test/build.lock flock file build mutex, holder found via fuser/lsof
.git/git-watch-origin-and-test/cancel-* touch/token files cancellation request/token/accepted handshake
$TMPDIR/git-watch-origin-and-test/<repo_key>/ HTML + files artifact root: generated pages, per-build artifact dirs
<artifact_root>/system.json + system_state.dat JSON + text system metrics snapshot and aggregation state

Build statuses: pending, running, success, failed, interrupted, cancelled (legacy alias passedsuccess).

Artifact key naming: sanitized branch + 12-char SHA256 prefix, plus sanitized timestamp + hash for per-build dirs.

External Interactions

Git (always via CLI): rev-parse, for-each-ref, fetch, switch, reset --hard, show -s --format=%cI, rev-list. HTTPS git auth uses a generated GIT_ASKPASS script feeding username + Gitea token.

Gitea API:

  • POST /api/v1/repos/{owner}/{repo}/statuses/{sha} — publish status; payload state, context, description, target_url.
  • GET /api/v1/repos/{owner}/{repo}/commits/{sha}/statuses?sort=recentupdate — read statuses, filtered by context.
  • GET /api/v1/user — resolve username from token.
  • State mapping: success→success; failed/interrupted/cancelled→failure; pending/running→pending.

Web control endpoints (Python handler):

  • GET /control/status?commit=<sha>&local_status=<s> — proxy Gitea status for a commit.
  • POST /control/cancel — cancel running build (CSRF-token protected).
  • POST /control/restart — append a new pending result row.
  • POST /control/delete — remove a result row and patch HTML files via regex.

Root Causes of the Known Bugs

Stuck loading animation (UI):

  • Status cells start as status-loading and each row fetches /control/status with a 15s timeout; failures leave the spinner forever (no error state).
  • Page auto-refresh re-fetches the page HTML and diffs #build-rows; HTML is regenerated server-side by regex-patching files, which fails silently when structure drifts.
  • "Current" and "System" nav views exist, but the page generator only implements latest/branches/history, so some views fall through.

No status changes observable during a build (control loop):

  • The main loop (lines ~49444966) is synchronous: checkout_and_build blocks until the build ends; only then is origin re-scanned.
  • retry_origin_change_check() is an uninterruptible internal retry loop with 10s sleeps.
  • The console spinner is cosmetic and runs independently of actual progress.

Behavior Worth Preserving

  • Startup recovery: mark stale running builds as interrupted; restart restartable builds; optional retry of failed builds.
  • New-branch age filter (newBranchMaxAge) to avoid building stale branches.
  • Auto-build time slots (UTC HH:MM) per branch with per-day/slot dedup.
  • Retention per branch by count or age, pruning both results and artifact dirs.
  • Per-branch build/clean command, artifact dirs, and log file names (now via branches: YAML config).
  • Cancellation with token handshake; process-tree termination (TERM, wait, KILL).
  • Build log capture: stdout/stderr to files plus a live "current build" log.
  • Gitea status published on every transition with target_url pointing at the artifact page.

Not Ported (decided)

  • nginx + certbot/Let's Encrypt container management — replaced by deployment documentation (step 12). Revised by ADR 0005: it IS needed for Hostsharing container hosts and returns as an opt-in feature (step 13).
  • Self-install (--install), self-update script generation — replaced by jar deployment plus systemd docs (step 12).
  • Legacy HSADMIN_NG_* environment fallbacks and env-file config — replaced by YAML config (done).
  • Regex-based in-place HTML patching — replaced by server-rendered pages/JSON endpoints.
  • Static HTML artifact index generation with embedded 900-line JavaScript — replaced by templates.
  • .aliases sourcing (line 731), impressum footer link handling stays optional/simple.

Orphaned or Dubious Legacy Config

Verify need before porting any of these:

  • WERKATOR_BUILD_DOCKER_PREFLIGHT_COMMAND, WERKATOR_BUILD_DOCKER_JAVA_TOOL_OPTIONS — highly hsadmin-ng-specific defaults.
  • WERKATOR_ARTIFACT_NGINX_*, WERKATOR_ARTIFACT_LETSENCRYPT_EMAIL — dropped with nginx management; revived as server.nginx.* by step 13 (ADR 0005).
  • WERKATOR_IMPRESSUM_URL — keep as optional simple footer link if wanted.
  • WERKATOR_INSTALL_DIR — dropped with self-install.