Skip to content

fix(github): reuse an existing repo-docs branch ref instead of failing (#8310)#8481

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
galuis116:fix/repo-doc-branch-ref-reuse
Jul 24, 2026
Merged

fix(github): reuse an existing repo-docs branch ref instead of failing (#8310)#8481
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
galuis116:fix/repo-doc-branch-ref-reuse

Conversation

@galuis116

Copy link
Copy Markdown
Contributor

Summary

Closes #8310.

openRepoDocPullRequest always targets the fixed loopover/repo-docs branch (deliberately stable, per the file's header comment, so repeat runs update one PR instead of piling up duplicates). But it only checks for an open PR on that branch before deciding to create the ref:

// src/github/repo-doc-pr.ts:167
const existingOpenPrs = await octokit.request("GET /repos/{owner}/{repo}/pulls", { ..., state: "open", ... });

When a maintainer closes the repo-doc PR without deleting its branch -- GitHub offers a "Delete branch" button but never forces it, and a PR closed via the API or a bot deletes nothing -- the ref survives. The open-only lookup then finds nothing, the function proceeds, and POST /git/refs 422s "Reference already exists". The outer try/catch turns that into { opened: false, reason }, so every subsequent refresh for that repo fails permanently -- both the scheduled sweep and the on-demand loopover_refresh_repo_docs tool.

Change

When the create reports that specific failure, fall back to PATCH /repos/{owner}/{repo}/git/refs/{ref} with { sha: commitSha, force: true }, then continue into the existing PR-open path unchanged. This branch is exclusively owned by this feature and never shared with contributor work, so force-updating it to the freshly built commit is safe.

Deliberately narrow, matching the issue's constraints:

  • Only a 422 whose message matches Reference already exists recovers. Any other create-ref failure (e.g. an invalid sha) still propagates to the outer catch's fail-safe, so nothing is silently force-pushed over.
  • The "reuse only an OPEN PR" behaviour at line 167 is untouched -- a closed PR still results in a new pull request (reused: false); only the underlying ref is reused.
  • Reuses the module's existing githubErrorStatus helper and the shared errorMessage helper rather than hand-rolling status/message extraction.

Tests

  • the 422 path force-updates the ref (asserting the PATCH body carries { sha, force: true }) and still opens a fresh PR with reused: false
  • an unrelated create-ref 422 issues no PATCH and degrades to opened: false, pinning the fail-safe

Scope

  • The PR title follows type(scope): short summary Conventional Commit format.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves (Closes #8310).

Validation

  • git diff --check
  • npm run actionlint - no workflow files touched.
  • npm run typecheck
  • npx vitest run test/unit/repo-doc-pr.test.ts - 33 pass (was 31).
  • Changed-line coverage verified locally with the v8 provider: no uncovered statements and no partial branches on the diff (both arms of the new isRefAlreadyExistsError guard are exercised by the two tests above).
  • npm run test:coverage (full) / test:workers / build:mcp / ui:* - not run: this is a scoped change to one backend module plus its unit test, touching no worker, MCP, or UI surface.
  • npm audit --audit-level=moderate - no dependency changes.
  • New or changed behavior has unit tests for new branches and fallback paths.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests - no auth logic changes; the write still goes through the same makeInstallationOctokit / withInstallationTokenRetry chokepoint, and the unrelated-failure test is the negative path.
  • API/OpenAPI/MCP behavior is updated and tested where needed - no contract change; loopover_refresh_repo_docs simply stops failing on this case.
  • UI changes use live API data or real empty/error/loading states - n/a, no UI change.
  • Visible UI changes include a UI Evidence section - n/a: no visible UI/frontend/docs/extension change.
  • Public docs/changelogs are updated where needed - n/a.

Notes

  • The force-update is confined to loopover/repo-docs. Because the recovery is gated on both the 422 status and the "Reference already exists" message, an unrelated 422 can never reach the force: true call.

Reopened from #8474, which was auto-closed because its branch received an additional commit (a rebase onto latest main) after opening - this repo reviews one-shot and treats that as a restart. No code changed: same diff, rebased and re-verified (33/33 tests; 0 uncovered statements and 0 partial branches on the diff).

JSONbored#8310)

openRepoDocPullRequest always targets the fixed loopover/repo-docs branch, but
only looks for an OPEN pull request on it before deciding to create the ref. A
maintainer who closes the repo-doc PR without deleting its branch (GitHub never
forces that, and an API/bot close deletes nothing) leaves the ref behind: the
open-only lookup finds nothing, POST /git/refs then 422s "Reference already
exists", and the outer catch turns every later refresh into
{ opened: false }, permanently.

When the create reports that specific failure, fall back to
PATCH /git/refs/{ref} with { sha, force: true } and continue into the existing
PR-open path unchanged. The branch is owned solely by this feature (per the
file's own header comment), never shared with contributor work, so force-
updating it to the freshly built commit is safe.

Deliberately narrow:
- Only a 422 whose message says "Reference already exists" recovers; any other
  create-ref failure still propagates to the outer catch's fail-safe, so a bad
  sha is never force-pushed over.
- The "reuse only an OPEN PR" behaviour is untouched -- a closed PR still
  results in a NEW pull request, only the underlying ref is reused.
- Reuses the existing githubErrorStatus and errorMessage helpers rather than
  hand-rolling status/message extraction.

Adds two tests: the 422 path force-updates the ref and still opens a fresh PR
(reused: false), and an unrelated create-ref 422 issues no PATCH and degrades
to opened: false.
@galuis116
galuis116 requested a review from JSONbored as a code owner July 24, 2026 15:00
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 24, 2026
@loopover-orb

loopover-orb Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-24 15:27:35 UTC

2 files · 1 AI reviewer · no blockers · readiness 93/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This fixes a real bug: when a repo-doc PR is closed without deleting its branch, the open-only PR lookup misses it and the subsequent create-ref call 422s forever, permanently breaking refreshes for that repo. The fix narrowly catches only the 'Reference already exists' 422 and recovers via a force-update PATCH to the same feature-owned branch, leaving all other failures to propagate through the existing fail-safe. The two added tests correctly exercise both the recovery path and the non-recovery (unrelated 422) path against the real code path, not a fabricated scenario.

Nits — 3 non-blocking
  • src/github/repo-doc-pr.ts:64-67 hardcodes the 422 status inline; a named constant would make the intent slightly clearer, though this is purely stylistic.
  • The PR description mentions 'the 422 path f...' (truncated) implying more test detail than shown; worth confirming the full test suite covers the PATCH failure path too (e.g., if the PATCH itself 422s, it still propagates to the outer catch — not tested explicitly but likely fine given the existing fail-safe).
  • Consider extracting the magic number 422 in isRefAlreadyExistsError (src/github/repo-doc-pr.ts:64) into a named constant like HTTP_UNPROCESSABLE_ENTITY for readability, though this is optional given the function name already documents intent.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #8310
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 1895 registered-repo PR(s), 1231 merged, 56 issue(s).
Contributor context ✅ Confirmed Gittensor contributor galuis116; Gittensor profile; 1895 PR(s), 56 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The diff adds a try/catch around POST /git/refs that detects the specific 422 "Reference already exists" error and falls back to PATCH .../git/refs/{ref} with force:true before proceeding to open a fresh PR, exactly matching the issue's requested recovery path, while other errors still propagate to the outer fail-safe. New tests cover both the recovered ref-exists case (asserting opened:true, reus

Review context
  • Author: galuis116
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: JavaScript, Python, TypeScript, Dart, HTML, MDX, Rust, C++
  • Official Gittensor activity: 1895 PR(s), 56 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Triage stale or unlinked PRs.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit f50d010 into JSONbored:main Jul 24, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(github): repo-doc PR refresh permanently breaks after the loopover/repo-docs branch is closed without deleting it

1 participant