Skip to content

Commit c0db0b2

Browse files
authored
Merge pull request #5 from qweered/merge-bot/eligibility-check-run
test: merge-bot eligibility check run (DO NOT MERGE)
2 parents 3bcfffa + fb68242 commit c0db0b2

3 files changed

Lines changed: 97 additions & 12 deletions

File tree

.github/workflows/bot.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ concurrency:
3030
# This is used as fallback without app only.
3131
# This happens when testing in forks without setting up that app.
3232
permissions:
33+
checks: write # creating/updating the merge-bot eligibility check run
3334
issues: write # managing issue labels and comments
3435
pull-requests: write # managing pull request labels and comments
3536

@@ -63,6 +64,7 @@ jobs:
6364
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
6465
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
6566
permission-administration: read
67+
permission-checks: write
6668
permission-contents: write
6769
permission-issues: write
6870
permission-members: read

.github/workflows/pull-request-target.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ jobs:
9595
needs: [prepare, eval]
9696
uses: ./.github/workflows/bot.yml
9797
permissions:
98+
checks: write
9899
issues: write
99100
pull-requests: write
100101
secrets:

ci/github-script/merge.js

Lines changed: 94 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,83 @@ function runChecklist({
8989
}
9090
}
9191

92+
function renderChecklist(checklist) {
93+
return Object.entries(checklist).flatMap(([msg, res]) =>
94+
typeof res === 'boolean'
95+
? `- :${res ? 'white_check_mark' : 'x'}: ${msg}`
96+
: [
97+
`- :${Object.values(res).some(Boolean) ? 'white_check_mark' : 'x'}: ${msg}`,
98+
...Object.entries(res).map(
99+
([msg, res]) =>
100+
` - ${res ? ':white_check_mark:' : ':white_large_square:'} ${msg}`,
101+
),
102+
],
103+
)
104+
}
105+
106+
const ELIGIBILITY_CHECK_NAME = 'merge-bot eligibility'
107+
const ELIGIBILITY_DETAILS_URL =
108+
'https://github.com/NixOS/nixpkgs/blob/master/ci/README.md#nixpkgs-merge-bot'
109+
110+
async function upsertEligibilityCheck({
111+
github,
112+
context,
113+
core,
114+
dry,
115+
pull_request,
116+
result,
117+
checklist,
118+
eligibleUsers,
119+
}) {
120+
const summary = [
121+
'Requirements to merge this PR with `@NixOS/nixpkgs-merge-bot merge`:',
122+
...renderChecklist(checklist),
123+
]
124+
if (eligibleUsers.length > 0) {
125+
summary.push(
126+
'',
127+
'#### Maintainers eligible to merge',
128+
...eligibleUsers.map((login) => `- @${login}`),
129+
)
130+
}
131+
132+
const params = {
133+
...context.repo,
134+
name: ELIGIBILITY_CHECK_NAME,
135+
head_sha: pull_request.head.sha,
136+
status: 'completed',
137+
conclusion: result ? 'success' : 'neutral',
138+
details_url: ELIGIBILITY_DETAILS_URL,
139+
output: {
140+
title: result
141+
? 'PR is eligible to be merged by the merge-bot'
142+
: 'PR is not (yet) eligible for the merge-bot',
143+
summary: summary.join('\n'),
144+
},
145+
}
146+
147+
if (dry) {
148+
core.info(
149+
`Eligibility check (dry) on ${pull_request.head.sha}:\n${JSON.stringify(params, null, 2)}`,
150+
)
151+
return
152+
}
153+
154+
const existing = (
155+
await github.rest.checks.listForRef({
156+
...context.repo,
157+
ref: pull_request.head.sha,
158+
check_name: ELIGIBILITY_CHECK_NAME,
159+
})
160+
).data.check_runs[0]
161+
162+
if (existing) {
163+
await github.rest.checks.update({ ...params, check_run_id: existing.id })
164+
} else {
165+
await github.rest.checks.create(params)
166+
}
167+
}
168+
92169
// The merge command must be on a separate line and not within codeblocks or html comments.
93170
// Codeblocks can have any number of ` larger than 3 to open/close. We only look at code
94171
// blocks that are not indented, because the later regex wouldn't match those anyway.
@@ -280,17 +357,7 @@ async function handleMerge({
280357
`@${comment.user.login} wants to merge this PR.`,
281358
'',
282359
'Requirements to merge this PR with `@NixOS/nixpkgs-merge-bot merge`:',
283-
...Object.entries(checklist).flatMap(([msg, res]) =>
284-
typeof res === 'boolean'
285-
? `- :${res ? 'white_check_mark' : 'x'}: ${msg}`
286-
: [
287-
`- :${Object.values(res).some(Boolean) ? 'white_check_mark' : 'x'}: ${msg}`,
288-
...Object.entries(res).map(
289-
([msg, res]) =>
290-
` - ${res ? ':white_check_mark:' : ':white_large_square:'} ${msg}`,
291-
),
292-
],
293-
),
360+
...renderChecklist(checklist),
294361
'',
295362
]
296363

@@ -333,7 +400,7 @@ async function handleMerge({
333400
if (result) break
334401
}
335402

336-
const { result } = runChecklist({
403+
const { result, eligible, checklist } = runChecklist({
337404
committers,
338405
events,
339406
files,
@@ -342,6 +409,21 @@ async function handleMerge({
342409
maintainers,
343410
})
344411

412+
const eligibleUsers = await Promise.all(
413+
Array.from(eligible, async (id) => (await getUser(id)).login),
414+
)
415+
416+
await upsertEligibilityCheck({
417+
github,
418+
context,
419+
core,
420+
dry,
421+
pull_request,
422+
result,
423+
checklist,
424+
eligibleUsers,
425+
})
426+
345427
// Returns a boolean, which indicates whether the PR is merge-bot eligible in principle.
346428
// This is used to set the respective label in bot.js.
347429
return result

0 commit comments

Comments
 (0)