Skip to content

Report queued builds as "queued", drive one check run through its full lifecycle - #374

Merged
alexreinking merged 2 commits into
masterfrom
fix-orphaned-pending-check-runs
Sep 4, 2026
Merged

Report queued builds as "queued", drive one check run through its full lifecycle#374
alexreinking merged 2 commits into
masterfrom
fix-orphaned-pending-check-runs

Conversation

@alexreinking

@alexreinking alexreinking commented Sep 4, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes the bug observed live on halide/Halide PR #9400: builds showed "in progress" immediately, but with text "Build pending" and a details link to a /buildrequests/... page (a queued request, not an actual build).
  • Root cause: GitHubStatusPush's default generators include both a BuildRequestGenerator (fires when a build is queued, before any worker picks it up) and a BuildStartEndStatusGenerator (fires on actual start/end). Both produce state == "pending" in the inherited sendMessage(), so GitHubAppCheckPush.createStatus() was creating a separate check run for each -- but unlike statuses (where a new post for the same context just overwrites the display), check runs are persistent objects with their own id, so the queued-request one was never touched again and sat forever stuck "in progress".
  • We still want the queued state reported (a static dot while waiting for a worker is useful, distinct from actively running) -- the fix is to stop creating a second check run for it. createStatus() now always looks up the existing check run by name first and PATCHes it, falling back to POST only when none exists yet. The queued report's target_url points at a buildrequest page rather than an actual build (getURLForBuildrequest vs. getURLForBuild produce structurally different paths), which is enough to tell "queued" from "in progress" apart despite both arriving as state == "pending".
  • Net effect: one check run per build, transitioning queued -> in_progress -> completed cleanly.

Test plan

  • pre-commit run --files master/github_app_check_push.py -- all hooks pass
  • buildbot checkconfig passes
  • Drove createStatus() directly against a fake HTTP session through all three stages (queued report with a buildrequest URL, started report with a build URL, completed report) and asserted exactly one check run existed throughout, with status transitioning queued -> in_progress -> completed and the right conclusion on completion
  • After deploy, confirm a fresh PR build shows a static queued dot, then a spinner, then resolves -- all as one check run

GitHubStatusPush's default generators report both a build-request-queued
event and the actual build start/end. Both produce state == "pending" in
sendMessage() (build['complete'] is False for a queued request too), so
createStatus() was creating a check run for the queued-but-not-yet-started
event as well as the real one for build start -- but unlike statuses, check
runs are persistent objects with their own id, so the queued-request one
was never completed and sat forever as "in progress" pointing at a
buildrequest page instead of a build.
…fecycle

The previous commit dropped BuildRequestGenerator entirely, losing the
queued-but-not-started feedback (a static dot, distinct from an actively
running build) that we actually want. The real bug wasn't reporting the
queued state -- it was creating a brand new check run for it instead of
reusing the one for the build's later start/completion.

Both the queued (BuildRequestGenerator) and started (BuildStartEndStatus-
Generator) reports produce state == "pending" in the inherited sendMessage(),
but their target_url differs -- a buildrequest page vs. an actual build page
-- which is enough to tell "queued" from "in progress" apart. createStatus()
now always looks up the existing check run by name first and PATCHes it,
falling back to POST only when none exists yet, so a build's queued,
started, and completed reports all update the same check run.

Verified against a fake HTTP session driving createStatus() through all
three stages: exactly one check run exists throughout, transitioning
queued -> in_progress -> completed.
@alexreinking alexreinking changed the title Drop BuildRequestGenerator from GitHubAppCheckPush's default generators Report queued builds as "queued", drive one check run through its full lifecycle Sep 4, 2026
@alexreinking
alexreinking merged commit 996b348 into master Sep 4, 2026
9 checks passed
@alexreinking
alexreinking deleted the fix-orphaned-pending-check-runs branch September 4, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant