161 lines
8.5 KiB
Markdown
161 lines
8.5 KiB
Markdown
# PR#78: The Merges per Day, Week and Month of the Configured Authors
|
|
|
|
> **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.
|
|
|
|
## Problem
|
|
|
|
The human wants to see how many pull requests reach the default branch per day, week and month:
|
|
those of the human and those of `claude-code`, on git.javagil.de and on dev.hostsharing.net.
|
|
|
|
The dashboard reads only the open pull requests and the last 50 activities of the token user;
|
|
it keeps no history of merges.
|
|
Gitea has the data: its issue search finds the closed pull requests of an author (`created_by`),
|
|
each with `merged` and `merged_at`, and the pull request itself names its base branch and the default branch of its repository.
|
|
|
|
## Non-Goals
|
|
|
|
- No pull requests of all authors; only the configured ones count.
|
|
- No other measures, e.g. the time from opening to merge.
|
|
- No storage of its own; Gitea holds the history.
|
|
- No merges in the public demo; see Follow-up PRs.
|
|
|
|
## Specification
|
|
|
|
### Feature: the merges per day, week and month of the configured authors
|
|
|
|
#### Scenario#78.01: a merge of a configured author counts on its day
|
|
|
|
… so that the human sees how many pull requests reach the default branch.
|
|
|
|
- **Given** a Gitea with `mergeAuthors: [mi, claude-code]`
|
|
and a pull request of `claude-code`, merged into the default branch today
|
|
- **When** the human opens the dashboard
|
|
- **Then** the merge chart of that Gitea counts it today for `claude-code`
|
|
|
|
##### Verified by
|
|
|
|
- [MergeHistoryTest "the merges of each configured author, oldest first, in seconds since the epoch"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt)
|
|
- manual check in the browser, see "Solution"
|
|
- [DashboardTest "carries the load, the costs and the merges the sources report"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/DashboardTest.kt)
|
|
|
|
#### Scenario#78.02: the authors stack in each bar
|
|
|
|
… so that the human sees the share of each author.
|
|
|
|
- **Given** a Gitea with `mergeAuthors: [mi, claude-code]`, and on one day 2 merges of `mi` and 3 of `claude-code`
|
|
- **When** the human opens the dashboard
|
|
- **Then** the bar of that day stacks 2 for `mi` on 3 for `claude-code`, each in its own colour,
|
|
and the legend names the authors
|
|
|
|
##### Verified by
|
|
|
|
- [MergeHistoryTest "the merges of each configured author, oldest first, in seconds since the epoch"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt)
|
|
- manual check in the browser, see "Solution"
|
|
|
|
#### Scenario#78.03: the human switches between days, weeks and months
|
|
|
|
… so that the human sees the pace over a short and a long time.
|
|
|
|
- **Given** the merge chart, showing the last 30 days
|
|
- **When** the human selects "Wochen"
|
|
- **Then** the chart shows the last 12 weeks, from Monday to Sunday, and keeps this choice on the next visit
|
|
|
|
##### Verified by
|
|
|
|
- [MergeHistoryTest "the search starts a day before the first of the oldest month shown, for a time zone ahead of UTC"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt)
|
|
- manual check in the browser, see "Solution"
|
|
|
|
#### Scenario#78.04: only a merge into the default branch counts
|
|
|
|
… so that a stacked pull request does not count twice.
|
|
|
|
- **Given** a pull request of a configured author, merged into the branch of another pull request
|
|
- **When** the human opens the dashboard
|
|
- **Then** the merge chart does not count it
|
|
|
|
##### Verified by
|
|
|
|
- [MergeHistoryTest "only a merge into the default branch counts, and a closed pull request without a merge not at all"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt)
|
|
- [MergeHistoryTest "a pull request without a base or a default branch does not base on the default branch"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt)
|
|
|
|
#### Scenario#78.05: a closed pull request without a merge does not count
|
|
|
|
… so that the chart counts delivered work only.
|
|
|
|
- **Given** a pull request of a configured author, closed without a merge
|
|
- **When** the human opens the dashboard
|
|
- **Then** the merge chart does not count it
|
|
|
|
##### Verified by
|
|
|
|
- [MergeHistoryTest "only a merge into the default branch counts, and a closed pull request without a merge not at all"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt)
|
|
|
|
#### Scenario#78.06: without `mergeAuthors` the token user counts
|
|
|
|
… so that an existing configuration shows the merges of its user without a change.
|
|
|
|
- **Given** a Gitea without `mergeAuthors`, with the token of `hsh-michaelhoennig`
|
|
- **When** the human opens the dashboard
|
|
- **Then** the merge chart of that Gitea counts the merges of `hsh-michaelhoennig`
|
|
|
|
##### Verified by
|
|
|
|
- [GiteaSourceFetchTest "without mergeAuthors the merges of the token's user count, with an empty list none"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/GiteaSourceFetchTest.kt)
|
|
|
|
## Solution
|
|
|
|
- `GiteaConfig.mergeAuthors`: the logins whose merges count; without it the token user, an empty list shows no chart.
|
|
- Each 10 minutes, `GiteaSource` searches the closed pull requests of each author, updated since the start of the
|
|
oldest month shown, and keeps those with a `merged_at` in that range;
|
|
[MergeHistoryTest "a merge before the oldest period does not count, though the pull request was updated later"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt).
|
|
It runs in a thread of its own, so that the first read after a start does not hold up the open pull requests.
|
|
For each of them it asks the pull request once whether its base is the default branch of its repository,
|
|
and keeps the answer, as a merged pull request no longer changes.
|
|
- The snapshot carries the time of each merge in seconds since the epoch;
|
|
the page counts them by the days, weeks from Monday and months of the browser's time zone.
|
|
The server would need `journal.zone` from `Main.kt`, whose old methods are above a Mutation-CRAP of 15
|
|
and would fail the gate of this branch; the human chose the time zone of the browser.
|
|
The search starts a day before the first of the oldest month in UTC, so that a zone ahead of UTC gets its first day too.
|
|
- The page shows a tile per Gitea next to the review costs:
|
|
a bar per period, the authors stacked, a switch between 30 days, 12 weeks and 12 months.
|
|
- Each merged pull request is asked once, so the first read after a start costs a request per merge;
|
|
the search reads at most 20 pages of 50 per author.
|
|
[MergeHistoryTest "the search reads page after page until one is not full"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt) and
|
|
["each merged pull request is asked once for its base, a failed answer again"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MergeHistoryTest.kt) verify both.
|
|
- Version 0.49.0.
|
|
|
|
### Manual Check
|
|
|
|
On 2026-10-14, a local dashboard with `mergeAuthors: [mi, claude-code]` for git.javagil.de
|
|
and without `mergeAuthors` for dev.hostsharing.net counted:
|
|
|
|
| Gitea | Author | 12 months | 30 days |
|
|
|----------------------|----------------------|-----------|---------|
|
|
| git.javagil.de | `mi` | 188 | 127 |
|
|
| git.javagil.de | `claude-code` | 247 | 247 |
|
|
| dev.hostsharing.net | `hsh-michaelhoennig` | 122 | 53 |
|
|
|
|
The tile showed the bars stacked by author in desktop width, and in phone width in the dark theme;
|
|
the switch to months stayed after a reload.
|
|
|
|
## Open Questions
|
|
|
|
- [x] In which time zone do the days begin?
|
|
In the browser's; see Solution.
|
|
|
|
## Additional Changes
|
|
|
|
- `stateDir` of `Config.kt` takes `XDG_STATE_HOME` as a parameter and gets a test,
|
|
as this branch changes `Config.kt` and the method was at a Mutation-CRAP of 72:
|
|
[ConfigLoaderTest "the state directory: the configured one, with ~ for the home directory, else the user's XDG state"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/ConfigLoaderTest.kt).
|
|
- The example configurations name `mergeAuthors`.
|
|
|
|
## Follow-up PRs
|
|
|
|
- The demo data get merges, so that the public demo shows the chart.
|
|
`Demo.kt` stays unchanged: its method `snapshot` is above a Mutation-CRAP of 15.
|
|
- A test framework for the JavaScript of `index.html`, e.g. for the counting by day, week and month of `mergeSeries`.
|
|
werkregie has none yet; it is a new technology and needs the consent of the human.
|