Skip to content

Merge queue DCO check not reported for merge groups #303

Description

@tykeal

Follow-up to #199, which was closed when merge queue support shipped in #292. @llucax reported in #199 (comment) that the DCO check still does not appear for merge groups, so the merge queue stalls and eventually ejects the PR.

Opening this as its own issue so the discussion isn't buried on a closed one.

Report

Repro: frequenz-floss/frequenz-client-common-python#259 (Remove dummy DCO check for the merge queue — the repo had been satisfying the required DCO check in the merge queue with a placeholder GitHub Actions job, and removing it exposed the problem).

Timeline from the PR timeline API:

Time (UTC) Event
2026-07-23T07:40:12Z auto_merge_enabled
2026-07-23T08:33:16Z added_to_merge_queue
2026-07-23T09:36:38Z removed_from_merge_queue by github-merge-queue[bot]

That is roughly an hour sitting in the queue with DCO reported as Expected — Waiting for status to be reported, then ejection.

What has been ruled out

  • The code was deployed. f9dc6849 (the Feat: Add Merge Group support #292 merge) reached the Production environment at 2026-07-22T13:06:49Z, about 19 hours before the PR was queued.
  • The event is subscribed. GET /apps/dco reports merge_queue_entry in events, with the app record last updated 2026-07-22T14:15:18Z — also before the attempt.
  • No missing permission. GitHub's OpenAPI description for merge_group (both checks_requested and destroyed) declares no required permission; it is simply app-only. So this is not a repeat of the issues: read gating problem from @dcoapp recheck doesn't work. DCO is still stuck #289.
    This was wrong — see the correction below. The merge_group event does require the Merge queues repository permission at read level, which the app does not currently hold. The OpenAPI document does not encode webhook permission gating; only the prose documentation does. This is the root cause.
  • Webhook library supports the event. The deployed lockfile resolves @octokit/webhooks@14.2.0, which handles merge_group.
  • The app is healthy for that installation. The same PR's head commit has DCO | completed | success from the dco app, so pull request events are being delivered and processed normally.

The merge group ref and its check runs are long gone, so the failure cannot be reconstructed from the public API.

Hypotheses

Resolved: the root cause is hypothesis 4, added below. The hypotheses that follow are retained for the record.

  1. The delivery failed at the app. Any exception inside check() currently results in nothing being reported rather than a failing check — this is the same silent-failure class documented in DCO step stuck even though the review comment with a recheck request exists #302. If the merge-group code path throws (or the function cold-starts past its time limit), the merge queue sees silence and stalls exactly as observed. The fix in progress for DCO step stuck even though the review comment with a recheck request exists #302 adds a safety net that would make this self-diagnosing.
  2. The required check is pinned to a different integration. Required status checks can be bound to a specific app. If the ruleset still pins DCO to GitHub Actions (from the placeholder-job era), a check run published by the dco app would not satisfy it. This would explain why the PR-level check passes while the merge group never clears.
  3. A silent early return in the handler. merge_group.checks_requested returns without reporting anything if the head_ref regex does not match, or if pulls.get returns 404/403. In a merge queue, returning silently is indistinguishable from being down: the queue waits, then ejects. These paths arguably should publish a check run explaining themselves rather than staying quiet.

Next steps

  • Inspect the app's Recent Deliveries for merge_group around 2026-07-23T08:33Z to establish whether a delivery occurred and what status it returned.
  • Confirm with the reporter whether the required DCO check in their ruleset is pinned to a specific app.
  • Get a fresh reproduction now that more of the picture is understood.
  • Regardless of root cause, reconsider the silent return paths in the merge_group handler (hypothesis 3) — stalling a merge queue for an hour is a poor failure mode.

cc @llucax @bramwelt


Root cause (resolved)

  1. The app lacks the merge_queues permission. GitHub gates delivery of merge_group on the Merge queues repository permission (read is sufficient), independently of whether the event is subscribed. The subscription was enabled and appears in GET /apps/dco, but no events were ever delivered. Identified by @bramwelt in Merge queue DCO check not reported for merge groups #303 (comment).

Fix requires both adding merge_queues: read to app.yml (for new installations) and adding the permission to the live app registration (which triggers per-installation admin approval).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions