Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/scripts/merge-gate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,16 @@ const HOLD = 'hold'
// (runs 39602546475, 39602806953, 39653640861, 39694988559, 39696278650 — all five failed with
// "cannot read a pull request from head_ref" before this prefix was accepted, so the gate never once
// judged a queue entry). Accept both spellings rather than depend on which one the event carries.
//
// The base branch is not a single segment: a queue built on `release/1.0` yields
// `gh-readonly-queue/release/1.0/pr-<N>-<sha>` (#655, run 39694988559's documented shape), so the base
// is matched greedily up to the final `/pr-…` and may contain slashes. Everything that made the old
// single-segment pattern refuse still refuses: a non-`gh-readonly-queue/` ref, a missing or
// non-numeric PR number, and a tail that is not 7–40 hex characters.
export function prFromHeadRef(ref) {
const branch = String(ref ?? '').trim().replace(/^refs\/heads\//i, '')
const m = /^gh-readonly-queue\/[^/]+\/pr-(\d+)-([0-9a-f]{7,40})$/i.exec(branch)
return m ? { pr: Number(m[1]), base: m[2].toLowerCase() } : null
const m = /^gh-readonly-queue\/(.+)\/pr-(\d+)-([0-9a-f]{7,40})$/i.exec(branch)
return m ? { pr: Number(m[2]), base: m[3].toLowerCase() } : null
}

const names = (labels) => (labels ?? []).map((l) => String(typeof l === 'string' ? l : l?.name ?? '').toLowerCase())
Expand Down
11 changes: 11 additions & 0 deletions .github/scripts/merge-gate.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ test('#652 follow-up: a head_ref that carries refs/heads/ still names the queue
assert.equal(prFromHeadRef('refs/tags/gh-readonly-queue/main/pr-566-' + HEAD), null, 'only a branch ref is a queue entry')
})

test('#655: a queue base that contains slashes still names the pull request', () => {
assert.deepEqual(prFromHeadRef('gh-readonly-queue/release/1.0/pr-652-abc1234'), { pr: 652, base: 'abc1234' })
assert.deepEqual(prFromHeadRef('refs/heads/gh-readonly-queue/release/1.0/pr-652-abc1234'), {
pr: 652,
base: 'abc1234',
})
assert.equal(prFromHeadRef('gh-readonly-queue/release/1.0/pr-652-not-a-sha'), null, 'a multi-segment base does not relax the hex tail')
assert.equal(prFromHeadRef('gh-readonly-queue//pr-652-abc1234'), null, 'an empty base names no entry')
assert.equal(prFromHeadRef('gh-readonly-queue/release/1.0/pr-abc1234'), null, 'the tail must carry a PR number')
})

test('a PASS at the merged head lets the entry through', () => {
const r = judgeAt()
assert.equal(r.ok, true)
Expand Down
Loading