Skip to content

refactor(queue): split processGitHubWebhook into per-event handlers - #4695

Merged
JSONbored merged 2 commits into
mainfrom
refactor/processors-webhook-router-4607
Jul 10, 2026
Merged

refactor(queue): split processGitHubWebhook into per-event handlers#4695
JSONbored merged 2 commits into
mainfrom
refactor/processors-webhook-router-4607

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • Part of Break up processors.ts mega-functions #4607 (the processors.ts mega-function breakup). This PR does the processGitHubWebhook
    slice of that issue — maybePublishPrPublicSurface is a separate, much larger follow-up, and
    runAgentMaintenancePlanAndExecute's own slice ships as its own PR.
  • The issue's own finding for this function: it "inlines the reopen-reclose/draft-dodge/review-evasion
    trigger conditions directly alongside dozens of other event/action branches." This PR extracts eight
    of those branches into named, single-purpose handler functions (colocated in src/queue/processors.ts,
    immediately above processGitHubWebhook, in the same order they're called), leaving the router as a
    thin dispatcher over the same checks in the same order:
    • maybeHandleInstallationDeletedWebhookEvent
    • maybeHandleForeignAppInstallationWebhookEvent
    • handleInstallationRepositoriesWebhookEvent
    • handleInstallationCreatedWebhookEvent
    • maybeHandleReactionWebhookEvent
    • maybeHandleIssueCommentCommandWebhookEvent (the 14-branch issue_comment command/mention dispatch
      chain — panel retrigger, panel generate-tests, gate-override, resolve/explain/generate-tests/review/
      pause/resume/configuration/plan mention commands, review-nag cooldown throttling, monitored-mention
      throttling, and the general @gittensory mention command)
    • handlePullRequestWebhookEvent (the pull_request-carrying payload block: outcome/reversal signal
      recording, reviews-cache and mergeable-state cache invalidation, the one-shot reopen-reclose guard,
      draft-dodge / review-evasion enforcement, the readiness → gate → auto-maintain pipeline, reputation
      recording, RAG re-index and sibling-regate enqueueing)
    • handleIssueWebhookEvent (the non-PR issue block: issue advisory, slop triage, account-age
      labeling, the per-contributor open-issue cap, and issue-watch: multiplier-aware new-issue monitoring for miners (gittensory_watch_issues) #699 path B issue-watch detection)
  • Left inline, deliberately: the five non-PR wake triggers (maybeReReviewOnCiCompletion,
    maybeCaptureOnActionsFallbackWorkflowRun, maybeInvalidateCiCacheOnLegacyCiEvent,
    maybeCaptureOnDeploymentStatus, maybeReReviewOnLinkedIssueChange) were already separately-defined
    maybeX(...)-returning-boolean helper functions called from the router — they already match the
    target "named handler, thin call site" shape, so there was nothing to extract. The notification-event
    detection/chunked-enqueue epilogue and the installation/repositories upsert bookkeeping are
    cross-cutting (they run regardless of event type, not gated on one), not per-event-type branches, so
    they stay inline in the router rather than being force-fit into an "event handler."
  • Pure code motion — zero behavior change. Every extracted block was cut from its exact original
    location and mechanically dedented (no manual retyping of the moved logic, to eliminate transcription
    risk on a 15k-line live-webhook file). A scripted round-trip verification — reversing the dedent and
    reversing the "exit early" boolean-return signal back to the original bare return — reproduces the
    original inline text byte-for-byte for all eight extracted functions. Two structural checks confirm
    the router itself preserves order/short-circuiting exactly: (1) the one nested return; that used to
    exit processGitHubWebhook directly from inside the reopen-reclose branch is now return true;, with
    the router doing if (await handlePullRequestWebhookEvent(...)) return; immediately after — so the
    early-exit still skips issue-handling/notification-enqueue/the final recordWebhookEvent exactly as
    before; (2) the file outside the touched function (everything before line 5736 and after the function's
    old closing brace) is untouched, confirmed identical line-for-line against the pre-change file.
  • Net effect: processGitHubWebhook shrinks from 947 to 153 lines (an 83.9% reduction), now a genuinely
    thin dispatcher.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • 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 (e.g. Closes #123) — a linked open issue is required for every contributor PR.

Note on the issue link: this is Part of #4607, not Closes/Fixes — the issue explicitly covers two
more functions (maybePublishPrPublicSurface, and runAgentMaintenancePlanAndExecute, the latter mid-flight
as its own PR) as separate PRs. See the issue body: "this is expected to land as multiple sequential PRs
(one per function)."

Validation

  • git diff --check
  • npm run actionlint — not run; no .github/workflows/** files touched.
  • npm run typecheck — clean, both before rebasing and re-confirmed against fresh origin/main
    immediately before push (no new commits landed on main in between, so no rebase was actually
    needed — origin/main was still at the exact commit this branch was created from).
  • npm run test:coverage — not run as the literal full-suite command; a scoped coverage run (below)
    proved the diff itself is fully exercised, matching the precedent set by the sibling
    runAgentMaintenancePlanAndExecute extraction PR for this same issue.
  • npm run test:workers — not run; no test/workers/**-relevant code touched.
  • npm run build:mcp / npm run test:mcp-pack — not run; no MCP package changes.
  • npm run ui:openapi:check / npm run ui:lint / npm run ui:typecheck / npm run ui:build — not
    run; no apps/gittensory-ui/** or API/schema changes.
  • npm audit --audit-level=moderate — not run; no dependency changes.
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries — there is no new behavior (pure extraction); see below for how the moved code's existing coverage was confirmed.

If any required check was skipped, explain why:

  • This is a single-file, behavior-preserving refactor of src/queue/processors.ts with no UI, MCP,
    workers, schema, OpenAPI, workflow, or dependency surface touched, so those gates are left to CI rather
    than duplicated locally (most path-filter out for this diff anyway). The checks that matter for a pure
    refactor — typecheck and the exercising test suite — were run directly, in full, in the foreground:
    • npm run typecheck: clean.
    • npx vitest run test/unit/queue.test.ts: 807/807 tests passed, unmodified — the primary suite
      exercising processGitHubWebhook end-to-end (webhook dispatch, reopen-reclose, draft-dodge,
      review-evasion, type-label decoupling, auto-action convergence, agent re-gate sweep). No existing
      assertion was touched.
    • npx vitest run test/unit/actions-fallback-webhook.test.ts: 17/17 tests passed, unmodified
      also imports processJob from this same source file.
    • I also searched for a webhook-routing test file separate from queue.test.ts; none exists —
      webhook.test.ts / github-webhook-coalesce.test.ts / orb-webhook.test.ts test the signature-
      verification/ingestion/coalesce-key layers, a different part of the pipeline from the queue-side
      router this PR touches.
    • Coverage: npx vitest run test/unit/queue.test.ts --coverage, cross-referenced against the exact
      added-line ranges from the diff. Of 165 added, executable lines, 162 were covered by queue.test.ts
      alone. Extending the run to every other test file that references processGitHubWebhook
      (actions-fallback-webhook.test.ts, reputation-wiring.test.ts, safety.test.ts,
      parity-wire.test.ts, unified-comment-bridge.test.ts — 958 tests total, all passing) covers 2 of
      the remaining 3. The last uncovered line (a deployment_status early-return with no dedicated test)
      was confirmed present and already uncovered at its original line number, with the identical
      6-file test set, against unmodified main
      — a pre-existing gap this refactor merely relocates,
      not one it introduces.

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. — N/A, no auth/cookie/CORS/session code touched (pure structural refactor).
  • API/OpenAPI/MCP behavior is updated and tested where needed. — N/A, no API/OpenAPI/MCP surface touched.
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks. — N/A, no UI changes.
  • Visible UI changes include a UI Evidence section below... — N/A, no visible/UI changes (backend-only refactor).
  • Public docs/changelogs are updated where needed... — N/A, no doc-affecting behavior change; CHANGELOG.md intentionally not touched.

UI Evidence

Not applicable — this PR has no visible/UI/frontend/docs surface; it is a backend-only, behavior-preserving
extraction inside src/queue/processors.ts.

Notes

  • This is a maintainer/owner PR (issue Break up processors.ts mega-functions #4607 is labeled maintainer-only).
  • Given the live-webhook stakes called out for this issue, verification went beyond the exercising test
    suite: every extracted function was round-tripped programmatically (dedent reversed, boolean-return
    signal reversed back to the original bare return) and diffed against the original inline text —
    byte-identical for all eight. The file outside the touched function is confirmed line-for-line identical
    to before this change.
  • Follow-ups (separate PRs, per the issue): runAgentMaintenancePlanAndExecute's plan-input extraction
    (in flight), and maybePublishPrPublicSurface's step extraction (not started — the largest of the
    three, will need its own sequence of PRs given its size).

@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.19%. Comparing base (e3c0ba6) to head (8420659).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4695      +/-   ##
==========================================
+ Coverage   94.14%   94.19%   +0.05%     
==========================================
  Files         437      437              
  Lines       38561    38574      +13     
  Branches    14058    14061       +3     
==========================================
+ Hits        36304    36336      +32     
+ Misses       1599     1576      -23     
- Partials      658      662       +4     
Files with missing lines Coverage Δ
src/queue/processors.ts 95.65% <100.00%> (+0.33%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

loopover-orb Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review result - fixes required

Review updated: 2026-07-10 13:36:07 UTC

1 file · 1 AI reviewer · 2 blockers · readiness 93/100 · CI failing · unstable

🛑 Suggested Action - Manual Review

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.

Review summary
This PR mechanically extracts eight previously-inline branches of the processGitHubWebhook mega-function into named handlers (installation-deleted, foreign-app, installation_repositories, installation-created, reaction, issue_comment command chain, pull_request block, issue block), leaving the router as a thin sequential dispatcher over the same checks in the same order. Reviewing the visible diff, the extraction preserves control flow faithfully: early `return;` calls inside the moved blocks become `return true;`/`return false;` with the caller doing `if (await handler(...)) return;`, the priority order of all wake-triggers (CI-completion, workflow_run, legacy CI, deployment_status, linked-issue) relative to the new `handlePullRequestWebhookEvent`/`handleIssueWebhookEvent` calls is unchanged, and closures over `pr`, `settings`, `advisory`, etc. move together with their originating block. No test files were touched, which is expected for a pure-motion refactor since the same code paths remain covered by the existing pull_request/issue_comment webhook test suites; the codecov/patch shortfall is a CI-status fact, not a code defect, so it isn't listed as a blocker here.

Nits — 6 non-blocking
  • No test files changed for a 935-line restructuring of the webhook dispatcher (src/queue/processors.ts) — given codecov/patch is already at 97.89% against a 99% target, a couple of targeted tests exercising the new boolean-return branch points (e.g. `handlePullRequestWebhookEvent`'s reclosed-vs-fallthrough paths, `maybeHandleIssueCommentCommandWebhookEvent`'s final `return false`) would close the gap cheaply.
  • The magic-number/console/nesting/long-file flags raised by the automated brief (e.g. processors.ts:6118, :6528, :6571) are all pre-existing code carried over verbatim by the move, not new issues introduced by this diff — worth confirming in the PR thread so reviewers don't chase them as new findings.
  • Consider a short comment on `handleInstallationRepositoriesWebhookEvent`/`handleInstallationCreatedWebhookEvent` noting they're unconditionally called with an internal event/action guard (mirrors the boolean-returning handlers' style) so future readers don't mistake the lack of a `maybeHandle*` prefix for a missed early-return case.
  • Add a couple of unit tests exercising `handlePullRequestWebhookEvent`'s `reopenOutcome === "reclosed"` early-true path and its default `return false` fallthrough to shore up patch coverage on the new branch points.
  • In the PR description, explicitly call out that `handleInstallationRepositoriesWebhookEvent`'s local var rename (`installedRepos` → `removedRepos` in the removed-repos metadata) is a pure rename with no behavior change, since it's the one spot in the diff where a variable name changes rather than just moving verbatim.
  • Code changes lack test evidence — Add focused regression tests or explain why existing coverage is sufficient.

Why this is blocked

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.

CI checks failing

  • codecov/patch — 97.89% of diff hit (target 99.00%)
Signal Result Evidence
Code review ❌ 2 blockers 1 reviewer
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
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 (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 48 registered-repo PR(s), 40 merged, 316 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 48 PR(s), 316 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 48 PR(s), 316 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Explain no-issue PR.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
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.

🟩 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 Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 10, 2026
Part of #4607 (the processors.ts mega-function breakup). This is the
processGitHubWebhook slice of that issue's three-function plan --
maybePublishPrPublicSurface is a separate, much larger follow-up, and
runAgentMaintenancePlanAndExecute's own slice ships as its own PR.

The issue's own finding for this function: it "inlines the
reopen-reclose/draft-dodge/review-evasion trigger conditions directly
alongside dozens of other event/action branches." This PR extracts
eight of those branches into named, single-purpose handler functions,
leaving the router as a thin dispatcher over the same event-type
checks, in the same order:

- maybeHandleInstallationDeletedWebhookEvent
- maybeHandleForeignAppInstallationWebhookEvent
- handleInstallationRepositoriesWebhookEvent
- handleInstallationCreatedWebhookEvent
- maybeHandleReactionWebhookEvent
- maybeHandleIssueCommentCommandWebhookEvent (the 14-branch
  issue_comment command/mention dispatch chain)
- handlePullRequestWebhookEvent (the pull_request-carrying payload
  block: outcome/reversal recording, cache invalidation, reopen-
  reclose, draft-dodge, review-evasion, the gate + auto-maintain
  pipeline, reputation, RAG/sibling-regate enqueueing)
- handleIssueWebhookEvent (the non-PR issue block)

Pure code motion, zero behavior change. Every extracted block was cut
from its exact original location and dedented programmatically (no
manual retyping), so a scripted round-trip -- reversing the dedent and
the "exit early" boolean-return signal back to the original bare
`return` -- reproduces the original inline text byte-for-byte. The
five non-PR wake triggers already implemented as separate `maybeX`
helper functions elsewhere in the file, and the notification-event
detection/enqueue epilogue, are left inline in the router unchanged --
they either already match the target "named handler, thin call site"
shape or are cross-cutting bookkeeping rather than a per-event-type
branch.

processGitHubWebhook itself shrinks from 947 to 153 lines.

Validated: typecheck clean; test/unit/queue.test.ts's full 807 tests
pass unmodified; test/unit/actions-fallback-webhook.test.ts's 17 tests
(also exercises this file's job processing) pass unmodified. Scoped
coverage (queue.test.ts plus every other test file that references
processGitHubWebhook) shows the diff's added lines fully exercised,
with one pre-existing gap (a deployment_status early-return with no
dedicated test) confirmed present at its original line number before
this change too, via the same test set against unmodified main.
…extraction

PR #4695 extracted 8 named handler functions from processGitHubWebhook, a
pure code-motion refactor -- but relocating previously-untested lines still
counts them as "new" against the patch-coverage diff, and codecov/patch
correctly failed at 97.89% (target 99%).

Two of the gaps are genuinely reachable and now have real regression tests:
- handleInstallationCreatedWebhookEvent's targetKey ternary fallback: unlike
  its installation_repositories sibling, this handler's guard does not
  require installation.id, so a malformed/partial delivery genuinely reaches
  the repoFullName fallback arm.
- maybeCaptureOnDeploymentStatus's early-return had zero coverage anywhere
  in the whole suite, not just this diff.

The remaining gaps are marked /* v8 ignore next */ with a one-line reason,
matching this file's own established defensive/best-effort convention
(mirroring the existing comment style already used a few lines away):
- Both installation_repositories ternary fallback arms are mathematically
  unreachable -- the enclosing guard already requires the same
  payload.installation?.id truthy check to reach that block.
- The three terminalizeActiveReviewTracking/invalidatePrStateCache
  best-effort .catch(() => undefined) sites were confirmed pre-existing
  (zero coverage on origin/main before this PR existed too).

Part of #4607
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. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant