Skip to content

ci: fix pr-queue-hygiene mergeable check to use per-PR API fetch - #240

Merged
mrbobbytables merged 2 commits into
mainfrom
fix-pr-queue-hygiene-mergeable-unknown
Sep 21, 2026
Merged

mrbobbytables merged 2 commits into
mainfrom
fix-pr-queue-hygiene-mergeable-unknown

Conversation

@mrbobbytables

Copy link
Copy Markdown
Member

Summary

Fixes #217: the mergeability check for the GOVERNANCE.md merge-queue
hygiene rule (issue #58) needs to re-fetch each PR individually rather
than trust gh pr list's mergeable field, which GitHub computes
asynchronously and frequently returns UNKNOWN on list responses —
silently letting conflicting PRs evade the 48h flagging check.

This PR adds:

  • scripts/pr-queue-hygiene.mjs — fetches all open PRs (paginated past
    gh pr list's default --limit 30), then re-checks mergeability
    per-PR via GET /repos/{owner}/{repo}/pulls/{number} (which forces a
    fresh computation) before deciding a PR is conflicting. Persists a
    first-conflict-observed marker comment so the 48h window is measured
    from when the PR actually started conflicting, not from updatedAt
    (which changes on any commit/label/comment).
  • tests/pr-queue-hygiene.test.mjs — unit tests for the marker
    parsing, age calculation, and conflict-detection logic.
  • pr-queue-hygiene npm script for manual/local runs.
  • A GOVERNANCE.md "Operational status" note under Merge-queue hygiene.

Context: related, still-open PR #115

PR #115 proposed this same feature but shipped it as inline bash in
.github/workflows/pr-queue-hygiene.yml using gh pr list's
mergeable field directly — the exact bug #217 reports. A later
revision to #115 extracted the logic into a script
(scripts/pr-queue-hygiene.mjs) that fixes it correctly, but the
workflow file itself was never updated to call that script, so the
bug remained live in the step that actually runs. The PR's author
noted its fork's credentials lack the workflow OAuth scope needed to
push the one-line wiring change to .github/workflows/*.

This PR is in the same boat: this environment's push credentials
also lack the workflow scope
, so .github/workflows/pr-queue-hygiene.yml
itself could not be pushed here. A maintainer with that scope will
need to add it directly — the full contents are below (also mirrors
what #115 needed):

name: PR queue hygiene

# Operationalizes the GOVERNANCE.md merge-queue hygiene rule (see issue #58):
# "Agent PRs that conflict with the base branch for more than 48 hours should
# be rebased by their author agent or closed as superseded." This workflow
# does not close PRs automatically — deciding whether a conflicting PR is
# superseded requires judgment a scheduled job shouldn't make. Instead it
# flags them (label + comment) so a maintainer or the author agent can act
# quickly, keeping the queue from silently rotting.
#
# The actual check lives in scripts/pr-queue-hygiene.mjs, which re-fetches
# each PR's mergeability individually rather than trusting the list
# endpoint's `mergeable` field (frequently `UNKNOWN`/stale there -- see
# issue #217), and paginates past `gh pr list`'s default 30-PR limit.

on:
  schedule:
    - cron: '0 */6 * * *'
  workflow_dispatch:

permissions:
  contents: read
  pull-requests: write

jobs:
  flag-stale-conflicts:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Ensure hygiene label exists
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPO: ${{ github.repository }}
        run: |
          gh label create "needs-rebase-or-close" \
            --repo "$REPO" \
            --color "d93f0b" \
            --description "Conflicting with base >48h per GOVERNANCE.md merge-queue hygiene" \
            2>/dev/null || true

      - name: Flag PRs conflicting with base for more than 48h
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPO: ${{ github.repository }}
        run: node scripts/pr-queue-hygiene.mjs

Once this workflow file is added (either by a maintainer here, or by
rebasing/merging #115 with its workflow step updated to run: node scripts/pr-queue-hygiene.mjs), #115 could likely be closed as
superseded, since this PR delivers the corrected script + tests it was
trying to add.

Testing

  • node --test — full suite passes (63 tests, including the 8 new
    ones in tests/pr-queue-hygiene.test.mjs).
  • npx prettier --check — passes on all changed files.
  • Manually validated the workflow YAML with js-yaml.

— hive: backend=copilot

@mrbobbytables

Copy link
Copy Markdown
Member Author

Per the merge-order decision in #318: this PR is canonical for the script/tests/GOVERNANCE.md fix (it correctly resolves #217, unlike #115's copy). #115's unique remaining value — its two workflow files — has been preserved as a comment on #318 for a maintainer to apply once this merges.

— hive: backend=copilot model=claude-sonnet-5

🐝 Hive Agent: contributor | SHA: 60ddab0

@castrojo

Copy link
Copy Markdown
Member

Closing as superseded: PR #240 has unresolvable merge conflicts against current main, and its pr-queue-hygiene workflow changes are superseded by subsequent workflow updates on main.

@castrojo castrojo closed this Sep 21, 2026
@castrojo

Copy link
Copy Markdown
Member

Reopening: verifying actual conflict state against origin/main. The pr-queue-hygiene script is not present on main, investigating resolution.

@castrojo castrojo reopened this Sep 21, 2026
Fixes #217: scripts/pr-queue-hygiene.mjs re-fetches each
PR's mergeability individually via GET /repos/{owner}/{repo}/pulls/{number}
instead of relying on the pulls-list endpoint's 'mergeable' field, which
GitHub computes asynchronously and frequently returns as UNKNOWN on list
responses.

Adds bounded retry polling for pending mergeable states and skips PRs
carrying hold labels per GOVERNANCE.md. The workflow file is tracked in
issue #318 per the Hive App workflow-permission gap policy.

Signed-off-by: Jorge Castro <jorge.castro@gmail.com>
@castrojo
castrojo force-pushed the fix-pr-queue-hygiene-mergeable-unknown branch from b5615fe to 5dfdc3f Compare September 21, 2026 16:49
@castrojo

Copy link
Copy Markdown
Member

Rebased onto latest main (incorporating #398):

Awaiting independent review.

@mrbobbytables
mrbobbytables added this pull request to the merge queue Sep 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Sep 21, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

[scanner] PR#115: pr-queue-hygiene.yml reads mergeable from 'gh pr list' (often UNKNOWN) — conflicting PRs silently skipped

2 participants