> **WARNING:** This document describes only the change applied in this PR. > It may already be outdated once the next PR is merged. > Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation. ## The Problem Werkator works on branches; the pull requests in Gitea do not show anywhere in its pages. A reviewer who sees a red build on a branch has to look up the pull request of that branch in Gitea by hand. The branch name alone often says little; `PR#12` is the name the work is discussed under. ## Non-Goals - No builds of pull requests or of merge results; Werkator still builds branches. - No pull requests from forks: their head branch belongs to another repository. - No closed or merged pull requests; the link shows while a pull request is open. - No other forge than Gitea, and nothing without a token. - No change to the pull-request gate (`requirePullRequest`); it keeps reading `refs/pull/*/head` without a token. ## The Scenarios ### Feature: the open pull request beside every branch name #### Background - A branch *heads* a pull request when the pull request's head is that branch of the repository itself. - The Gitea connection is `gitea.baseUrl`, `gitea.owner`, `gitea.repo` and `git.token` — the one the statuses are published with. #### Scenario#81.01: Werkator knows the open pull requests of each repository So that the pages can show them without asking Gitea on every request. - **Given** a repository with a Gitea connection and a token - **When** the watcher's poll cycle reaches origin - **Then** it reads the open pull requests from Gitea, keyed by head branch - **and** a pull request from a fork is left out - **and** of several pull requests from one branch, the newest wins - **and** a list longer than one page is read page by page - **And** nothing is read before the first poll cycle, so CLI runs and tests never ask Gitea ##### Verified by - [GiteaClientTest](../../src/test/kotlin/de/hoennig/werkator/gitea/GiteaClientTest.kt) — `readOpenPullRequests`: own branches only, the newest wins, paging, token header - [PullRequestIndexTest](../../src/test/kotlin/de/hoennig/werkator/gitea/PullRequestIndexTest.kt) — nothing known before the first refresh, a refresh replaces one repository's list - [WatcherTest](../../src/test/kotlin/de/hoennig/werkator/watcher/WatcherTest.kt) — every poll cycle that reached origin refreshes the pull requests #### Scenario#81.02: Every branch name carries its pull request So that a reader gets from a build to the discussion of its work in one click. - **Given** a branch that heads an open pull request - **When** the Latest, Branches, History or Current Builds view, the build page, the Repositories page or the home page shows the branch - **Then** `PR#` stands beside the branch name, linked to the pull request in Gitea - **and** on a home card it is plain text, because the card is a link already - **And** the JSON API carries it as `pullRequest` with `number` and `url`, so every poll renders it too ##### Verified by - [BuildsApiControllerTest](../../src/test/kotlin/de/hoennig/werkator/server/BuildsApiControllerTest.kt) — `latest`, `history` and `current` carry the pull request - [BranchListingTest](../../src/test/kotlin/de/hoennig/werkator/server/BranchListingTest.kt) — a branch row and its named pools carry it - [RepoOverviewsTest](../../src/test/kotlin/de/hoennig/werkator/server/RepoOverviewsTest.kt) — the newest build of an overview carries it - [UiControllerTest](../../src/test/kotlin/de/hoennig/werkator/server/UiControllerTest.kt) — the pages render the `PR#12` link, the Repositories page too - [UiViewsTest](../../src/test/kotlin/de/hoennig/werkator/server/UiViewsTest.kt) — a link on the Repositories page, plain text on a home card #### Scenario#81.03: A pull request is content So that a private repository still gives out no content (RFC 0003, D8). - **Given** a private repository and a visitor without the control token - **When** a page or the API shows its builds - **Then** no pull request is shown, like the branch name it belongs to - **And** a build whose branch is gone from origin shows no pull request either ##### Verified by - [BuildsApiControllerTest](../../src/test/kotlin/de/hoennig/werkator/server/BuildsApiControllerTest.kt) — a private repository and a gone branch carry no pull request - [RepoOverviewsTest](../../src/test/kotlin/de/hoennig/werkator/server/RepoOverviewsTest.kt) — a hidden repository's newest build carries none #### Scenario#81.04: Without Gitea nothing changes, and a Gitea outage does not blink So that the feature costs nothing where it cannot work. - **Given** no Gitea connection or no token, **then** no request is made and no pull request is shown - **Given** Gitea fails or answers garbage, **then** the last known pull requests stay - **and** the failure is logged once, not once per poll cycle, and so is the recovery ##### Verified by - [GiteaClientTest](../../src/test/kotlin/de/hoennig/werkator/gitea/GiteaClientTest.kt) — `Disabled` without a request, `Error` instead of an exception - [PullRequestIndexTest](../../src/test/kotlin/de/hoennig/werkator/gitea/PullRequestIndexTest.kt) — a failed read keeps the list, a disabled client drops it ## The Solution `GiteaClient.readOpenPullRequests` lists `GET /api/v1/repos/{owner}/{repo}/pulls?state=open`, 50 per page, at most ten pages. It keeps a pull request only when `head.repo_id` equals `base.repo_id`, and it takes the link from Gitea's own `html_url`. `PullRequestIndex` holds the result per `RepoContext`. The watcher refreshes it at the end of each repository's poll cycle, after a successful fetch: an unreachable origin most likely means an unreachable forge, and the last list stays. The pages and the API only read from the index. A page is polled every few seconds by every open browser; a slow forge must never slow a page down. The DTOs `BuildResultDto`, `BranchDto` and `CurrentBuildDto` carry `pullRequest` (`number`, `url`). `BuildResultDto.from` drops it for a gone branch, and `Redaction` drops it with the branch. The views take it from the DTO, so the first paint and every poll say the same. `werkator.js` renders the same link with `pullRequestLink`, and `UiFormats.pullRequest` writes the home card's text like the script does. ## Additional Changes - `docs/configuration.md` explains the links under the `gitea` notes; `docs/llms.md` and the architecture skill name them. - Version 1.23.0 with its release note. 1.22.0 is taken by the open branch of RFC 0006.