`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>
54 lines
3.0 KiB
Markdown
54 lines
3.0 KiB
Markdown
# Step 03: Gitea Client
|
|
|
|
Prerequisites: step 01 (for `BuildStatus`).
|
|
Read `README.md` and `00-legacy-analysis.md` first.
|
|
|
|
## Goal
|
|
|
|
A tested client for the Gitea commit-status API.
|
|
|
|
## Design
|
|
|
|
Create package `de.hoennig.werkator.gitea`:
|
|
|
|
- `GiteaClient` using Spring's `RestClient`.
|
|
- `publishStatus(sha, state, description, targetUrl)` → `POST /api/v1/repos/{owner}/{repo}/statuses/{sha}` with header `Authorization: token <git.token>`; body fields `state`, `context`, `description`, `target_url`.
|
|
- `readStatus(sha)` → `GET /api/v1/repos/{owner}/{repo}/commits/{sha}/statuses?sort=recentupdate`; pick the newest entry matching `gitea.statusContext`.
|
|
- `resolveUsername()` → `GET /api/v1/user` (used as fallback for `git.account`).
|
|
- State mapping in both directions (`BuildStatus` ↔ Gitea `success|failure|pending|error`), as in the legacy analysis.
|
|
- `isEnabled()` — true only when `gitea.baseUrl`, `gitea.owner`, `gitea.repo`, and `git.token` are configured.
|
|
All callers must treat a disabled or failing client as non-fatal (log and continue); the legacy behaved the same but failed silently.
|
|
|
|
Configuration comes from `WerkatorConfig` (`gitea.*`, `git.token`).
|
|
|
|
## Out of Scope
|
|
|
|
- No callers yet; the build executor (step 04) wires status publishing.
|
|
- No webhook receiving; Werkator remains poll-based.
|
|
|
|
## Tests
|
|
|
|
WireMock (already a test dependency, see `WireMockSmokeTest`):
|
|
|
|
- Publish: correct URL, auth header, JSON body per status.
|
|
- Read: filtering by context, newest-first, empty result, malformed JSON → error status, HTTP 4xx/5xx → non-fatal error result.
|
|
- State-mapping unit tests.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- `./gradlew ktlintFormat` then `./gradlew build` is green.
|
|
- No call path throws when Gitea is unconfigured or down.
|
|
|
|
## Execution Notes (2026-07-07)
|
|
|
|
Implemented as designed; deviations and decisions:
|
|
|
|
- Added `org.springframework:spring-web` as a dependency; `RestClient` lives there and `spring-boot-starter` alone does not provide it.
|
|
- `publishStatus` takes a `BuildStatus` and maps it internally instead of a raw Gitea state string.
|
|
The forward mapping never produces `error` because the `BuildStatus` enum is exhaustive; legacy emitted `error` only for unknown status strings.
|
|
- `readStatus` returns a sealed `GiteaStatusResult` (`Found`/`None`/`Disabled`/`Error`) so callers get explicit non-fatal error states instead of exceptions.
|
|
- `resolveUsername` only requires `gitea.baseUrl` and `git.token`; legacy gated it on the full status-enabled check including owner/repo, which the `/api/v1/user` endpoint does not need.
|
|
- Responses are read as strings and parsed with a dedicated Jackson `ObjectMapper` instead of RestClient message converters, keeping malformed-JSON handling explicit and independent of converter auto-detection.
|
|
- The legacy "Build status deleted" description marker is not ported; it belongs to the result-delete feature of later steps.
|
|
- No config changes were needed: `gitea.*` and `git.token` already exist in `WerkatorConfig`, the `init` templates, and `docs/configuration.md`.
|