diff --git a/docs/runbooks/gitea-actions-gotchas.md b/docs/runbooks/gitea-actions-gotchas.md index e41c5cd..4e47136 100644 --- a/docs/runbooks/gitea-actions-gotchas.md +++ b/docs/runbooks/gitea-actions-gotchas.md @@ -15,6 +15,7 @@ those containers share a filesystem — or a `localhost` — breaks. | `pg_isready` passes before PostGIS is ready | add a `PostGIS_Version()` probe | the db healthchecks | | `upload-artifact@v4` fails ("not supported on GHES") | pin `@v3` | `.gitea/workflows/ci.yaml` (`mutation` job) | | `upload-artifact@v3` fails with "Artifact service responded with 500" | mark the upload `continue-on-error: true` (server-side; issue #62) | `.gitea/workflows/ci.yaml` (`mutation` job) | +| PR says "out-of-date" but *Update branch* fails ("Unable to update pull request") | push a new head SHA (`commit --amend --no-edit` + `push --force-with-lease`) | §10, server-side | --- @@ -289,3 +290,41 @@ re-run hides the failed one, so keep the failing job id from the original report - Remember `concurrency.cancel-in-progress: true` in `ci.yaml`: a new push to the same ref, or a re-run, kills the in-flight run the same way. Check `run_attempt` before concluding a job hung. + +--- + +## 10. A retargeted stacked PR says "out-of-date" but *Update branch* fails + +**Symptom** — the PR shows *This branch is out-of-date with the base branch* and +*This pull request is blocked because it's outdated* (branch protection +`block_on_outdated_branch` on `main`), yet **Update branch** answers *Unable to update +pull request* (API: `HeadBranch of PR NN is up to date`). `git merge-base` confirms the +branch sits on the tip of `main`. Seen on #194 (#195). + +**Why** — Gitea 1.27 keeps two answers to "is it behind?": + +- The banner and the merge block read a **stored** `pull_request.commits_behind` + (`MergeBlockedByOutdatedBranch`: `CommitsBehind > 0`). +- *Update branch* recomputes it **live** from git (`services/pull/update.go`) and refuses + when nothing is behind. + +The stored count is only refreshed by a push to the head or base branch, or by a +retarget. #194 was stacked on #193; its rebased branch was force-pushed in the **same +second** that merging #193 deleted the parent branch and Gitea retargeted #194 to `main`. +The retarget compared `main` against `refs/pull/194/head` before the push queue had +updated that ref (the old head missed the squash commit → `CommitsBehind = 1`); the push +handler's own resync ran against the deleted old base and failed. Nothing pushed +afterwards, so the stale `1` stuck. Close/reopen does not recompute it. + +**Fix** — give the head a new SHA with the same content; the push resyncs the count: + +```bash +git commit --amend --no-edit # new committer date → new SHA +git push --force-with-lease origin +``` + +PR CI re-runs on the new SHA (the old statuses don't carry over). + +**Avoid it** — when the parent of a stacked PR merges, let Gitea finish retargeting the +child to `main` (its timeline shows *changed target branch*) **before** pushing the +rebased child branch.