3.0 KiB
3.0 KiB
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.gittally.gitea:
GiteaClientusing Spring'sRestClient.publishStatus(sha, state, description, targetUrl)→POST /api/v1/repos/{owner}/{repo}/statuses/{sha}with headerAuthorization: token <git.token>; body fieldsstate,context,description,target_url.readStatus(sha)→GET /api/v1/repos/{owner}/{repo}/commits/{sha}/statuses?sort=recentupdate; pick the newest entry matchinggitea.statusContext.resolveUsername()→GET /api/v1/user(used as fallback forgit.account).- State mapping in both directions (
BuildStatus↔ Giteasuccess|failure|pending|error), as in the legacy analysis. isEnabled()— true only whengitea.baseUrl,gitea.owner,gitea.repo, andgit.tokenare 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 GitTallyConfig (gitea.*, git.token).
Out of Scope
- No callers yet; the build executor (step 04) wires status publishing.
- No webhook receiving; GitTally 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 ktlintFormatthen./gradlew buildis 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-webas a dependency;RestClientlives there andspring-boot-starteralone does not provide it. publishStatustakes aBuildStatusand maps it internally instead of a raw Gitea state string. The forward mapping never produceserrorbecause theBuildStatusenum is exhaustive; legacy emittederroronly for unknown status strings.readStatusreturns a sealedGiteaStatusResult(Found/None/Disabled/Error) so callers get explicit non-fatal error states instead of exceptions.resolveUsernameonly requiresgitea.baseUrlandgit.token; legacy gated it on the full status-enabled check including owner/repo, which the/api/v1/userendpoint does not need.- Responses are read as strings and parsed with a dedicated Jackson
ObjectMapperinstead 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.*andgit.tokenalready exist inGitTallyConfig, theinittemplates, anddocs/configuration.md.