Skip to content

fix: read the PR number from the event payload, not only from GITHUB_REF - #6

Merged
Ostico merged 1 commit into
mainfrom
fix/pr-number-from-event-payload
Aug 12, 2026
Merged

fix: read the PR number from the event payload, not only from GITHUB_REF#6
Ostico merged 1 commit into
mainfrom
fix/pr-number-from-event-payload

Conversation

@Ostico

@Ostico Ostico commented Aug 12, 2026

Copy link
Copy Markdown
Owner

The failure

A pull_request run whose GITHUB_REF is not refs/pull/<number>/merge aborts with

::error::Could not determine PR number from GITHUB_REF.

and exit 1 — before Layer 1 measures anything. From the author's side that is indistinguishable from a coverage verdict: the required check goes red having never looked at the diff.

Observed 2026-08-12 on Ostico/bruno-mcp-studio#180. Editing the PR body fired the edited activity type, which produced a second run on a head sha whose earlier run was green. That second run failed this way, and because GitHub surfaces the latest run per check name, the merge button showed a red required gate for a commit that had already passed.

The change

.pull_request.number is present in every pull_request payload, for every activity type. GITHUB_REF carries the number only while GitHub has a merge ref to point the run at.

So parse_config now reads the payload at GITHUB_EVENT_PATH first and keeps GITHUB_REF as the fallback — every case that worked before still works.

_pr_number_from_event returns None rather than raising for anything unexpected: no GITHUB_EVENT_PATH, an unreadable or malformed file, a payload for another event, or a number that is not an int. That last one is not paranoia — true is valid JSON in that position and bool is an int subclass, so a plain isinstance(number, int) would accept it and pass True downstream as PR number 1. Each of these cases still has GITHUB_REF to fall back on, and raising would turn a recoverable run into a failed one.

main.py's message now names both sources it tried and states that nothing was measured. As written it pointed the reader at GITHUB_REF even once the payload was being consulted.

One existing test changed, deliberately

test_pr_number_from_env set GITHUB_REF and asserted 42. This suite runs inside Actions, where GITHUB_EVENT_PATH points at a real payload naming a real PR — so reading the payload first would have made that test measure CI's own PR number. It would have passed locally and failed in CI. It now unsets GITHUB_EVENT_PATH explicitly, with a comment saying why.

Verification

12 tests added (47 in test_config.py, 455 in the suite). ruff check src/ tests/ clean.

Mutation-checked — each of these turns the suite red:

Mutation Result
never consult the payload 2 failed
let the ref win over the payload 1 failed
accept a non-int number 2 failed
let a malformed payload raise 2 failed

What this does not do

Consumers pin ostico/test-guard@v2, so merging changes nothing for them. The fix reaches bruno-mcp-studio only when the v2 tag moves to include this commit — a deliberate act, not done here.

A pull_request run whose GITHUB_REF is not refs/pull/<number>/merge aborted with
"Could not determine PR number from GITHUB_REF" and exit 1, before Layer 1 had
measured anything. To the author that is indistinguishable from a coverage verdict:
the check goes red having never looked at the diff.

Observed on 2026-08-12 in Ostico/bruno-mcp-studio#180. Editing the PR body fired the
`edited` activity type, which produced a second run on a head sha whose earlier run
was green; that run failed this way, and because GitHub surfaces the latest run per
check name, the merge button showed a red required gate for a commit that had passed.

Every pull_request payload carries `.pull_request.number`, for every activity type.
GITHUB_REF carries it only while GitHub has a merge ref to point the run at. So the
payload at GITHUB_EVENT_PATH is now consulted first and GITHUB_REF remains the
fallback, which keeps every case that worked before working.

`_pr_number_from_event` returns None rather than raising for anything unexpected — no
GITHUB_EVENT_PATH, an unreadable or malformed file, a payload for another event, a
number that is not an int (`true` is valid JSON in that position, and bool is an int
subclass). Each of those still has GITHUB_REF to fall back on, and raising would turn
a recoverable run into a failed one.

main.py's message now names both sources it tried and says outright that nothing was
measured. As written it sent the reader to GITHUB_REF even once the payload was being
consulted.

One existing test needed a change for a reason worth stating: test_pr_number_from_env
set GITHUB_REF and asserted 42, and this suite runs inside Actions, where
GITHUB_EVENT_PATH points at a real payload naming a real PR. Reading the payload first
means that test would have measured the CI run's own PR — passing locally and failing
in CI. It now unsets GITHUB_EVENT_PATH explicitly.

Twelve tests added. Each of the four ways to break this — never consulting the
payload, letting the ref win, accepting a non-int number, letting a malformed payload
raise — was verified to turn the suite red.
@github-actions

Copy link
Copy Markdown

🧪 Test-Guard Report

✅ PASS — All changed source files have adequate test coverage.

Coverage Analysis: ✅ PASS

Changed lines: 100.0% covered (threshold: 100%)

📋 2 files: 2 ✅ pass
File Verdict Reason
src/config.py ✅ pass 100% diff coverage ≥ 100% threshold
src/main.py ✅ pass 100% diff coverage ≥ 100% threshold

Result: ✅ PASS

@Ostico
Ostico marked this pull request as ready for review August 12, 2026 19:01
@Ostico
Ostico merged commit e683c08 into main Aug 12, 2026
2 checks passed
@Ostico
Ostico deleted the fix/pr-number-from-event-payload branch August 12, 2026 19:02
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