watchpr: start the conflict window at the arm
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful

The window ran from the first non-mergeable poll even while the rule was
disarmed, so the poll that armed it confirmed a run it played no part in.
Measure from the later of the run's start and the arm; re-arming stays a
no-op so a base moving under every poll still confirms.
This commit is contained in:
2026-09-26 22:14:25 +10:00
parent 7ffa123e3d
commit 5928233a97
6 changed files with 218 additions and 41 deletions
+14 -8
View File
@@ -94,15 +94,21 @@ watched, and the baseline line — written to stderr, as a JSON record under
Gitea reports `mergeable: false` both for a real conflict and while it
recomputes the merge base after a push, so a conflict is only reported once the
watch has seen a merge computation start (the PR was mergeable, or its head or
base commit moved) **and** the non-mergeable polls have then run unbroken for
two minutes. The debounce is a duration, not a poll count, because what it has
to outlast is Gitea's recompute and `--interval` ranges from seconds to hours.
base commit moved) **and** the non-mergeable polls have **then** run unbroken for
two minutes. The window runs from whichever came later, so the poll that starts
the merge computation never confirms a run of falses that predates it. The
debounce is a duration, not a poll count, because what it has to outlast is
Gitea's recompute and `--interval` ranges from seconds to hours.
One case is therefore never reported: a conflict introduced by the push
immediately before the watch started, on a PR whose head and base never move
again. Nothing in Gitea's payload separates that from a merge check still in
flight, so watchpr stays silent about it for as long as it runs — the baseline
line is how you see it.
So a conflict introduced by the push immediately before the watch started is not
reported while the commits stay put: nothing in Gitea's payload separates it from
a merge check still in flight, and the baseline line is the only notice of it.
That is a narrower gap than it looks, because `base.sha` is the base branch's
tip — it moves for every open PR whenever anything merges to the base branch, so
the commits rarely stay put for long. A move like that arms the rule, and the
move itself is silent: the window restarts from it, so what is eventually
reported is a conflict still standing two minutes after that fresh merge
computation began, never the run of falses that preceded it.
```bash
# Watch until something meaningful happens (default interval 60s)