Skip to content

Commit d072223

Browse files
authored
fix: race condition with check runs (#283)
1 parent a352928 commit d072223

File tree

3 files changed

+60
-58
lines changed

3 files changed

+60
-58
lines changed

src/index.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -110,26 +110,28 @@ const probotHandler: ApplicationFunction = async (robot, { getRouter }) => {
110110
if (!label.name.startsWith(PRStatus.TARGET)) continue;
111111
const targetBranch = labelToTargetBranch(label, PRStatus.TARGET);
112112
const runName = `${CHECK_PREFIX}${targetBranch}`;
113-
const existing = checkRuns.find((run) => run.name === runName);
114-
if (existing) {
115-
if (existing.conclusion !== 'neutral') continue;
113+
let checkRun = checkRuns.find((run) => run.name === runName);
114+
if (checkRun) {
115+
if (checkRun.conclusion !== 'neutral') continue;
116116

117117
await context.octokit.checks.update(
118118
context.repo({
119-
name: existing.name,
120-
check_run_id: existing.id,
119+
name: checkRun.name,
120+
check_run_id: checkRun.id,
121121
status: 'queued' as 'queued',
122122
}),
123123
);
124124
} else {
125-
await context.octokit.checks.create(
125+
const response = await context.octokit.checks.create(
126126
context.repo({
127127
name: runName,
128128
head_sha: pr.head.sha,
129129
status: 'queued' as 'queued',
130130
details_url: 'https://github.com/electron/trop',
131131
}),
132132
);
133+
134+
checkRun = response.data;
133135
}
134136

135137
await backportImpl(
@@ -138,6 +140,7 @@ const probotHandler: ApplicationFunction = async (robot, { getRouter }) => {
138140
pr,
139141
targetBranch,
140142
BackportPurpose.Check,
143+
checkRun,
141144
);
142145
}
143146

src/operations/backport-to-location.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const createOrUpdateCheckRun = async (
1212
pr: WebHookPR,
1313
targetBranch: string,
1414
) => {
15-
const check = await getCheckRun(context, pr, targetBranch);
15+
let check = await getCheckRun(context, pr, targetBranch);
1616

1717
if (check) {
1818
if (check.conclusion === 'neutral') {
@@ -25,15 +25,19 @@ const createOrUpdateCheckRun = async (
2525
);
2626
}
2727
} else {
28-
await context.octokit.checks.create(
28+
const response = await context.octokit.checks.create(
2929
context.repo({
3030
name: `${CHECK_PREFIX}${targetBranch}`,
3131
head_sha: pr.head.sha,
3232
status: 'queued' as 'queued',
3333
details_url: 'https://github.com/electron/trop',
3434
}),
3535
);
36+
37+
check = response.data;
3638
}
39+
40+
return check;
3741
};
3842

3943
/**
@@ -74,7 +78,7 @@ export const backportToLabel = async (
7478
return;
7579
}
7680

77-
await createOrUpdateCheckRun(context, pr, targetBranch);
81+
const checkRun = await createOrUpdateCheckRun(context, pr, targetBranch);
7882

7983
const labelToRemove = label.name;
8084
const labelToAdd = label.name.replace(PRStatus.TARGET, PRStatus.IN_FLIGHT);
@@ -84,6 +88,7 @@ export const backportToLabel = async (
8488
pr,
8589
targetBranch,
8690
BackportPurpose.ExecuteBackport,
91+
checkRun,
8792
labelToRemove,
8893
labelToAdd,
8994
);
@@ -108,7 +113,7 @@ export const backportToBranch = async (
108113
`Executing backport to branch '${targetBranch}'`,
109114
);
110115

111-
await createOrUpdateCheckRun(context, pr, targetBranch);
116+
const checkRun = await createOrUpdateCheckRun(context, pr, targetBranch);
112117

113118
const labelToRemove = undefined;
114119
const labelToAdd = PRStatus.IN_FLIGHT + targetBranch;
@@ -118,6 +123,7 @@ export const backportToBranch = async (
118123
pr,
119124
targetBranch,
120125
BackportPurpose.ExecuteBackport,
126+
checkRun,
121127
labelToRemove,
122128
labelToAdd,
123129
);

src/utils.ts

+41-48
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ export const backportImpl = async (
450450
pr: WebHookPR,
451451
targetBranch: string,
452452
purpose: BackportPurpose,
453+
checkRun: NonNullable<Awaited<ReturnType<typeof getCheckRun>>>,
453454
labelToRemove?: string,
454455
labelToAdd?: string,
455456
) => {
@@ -485,16 +486,13 @@ export const backportImpl = async (
485486
`backport-${pr.head.sha}-${targetBranch}-${purpose}`,
486487
async () => {
487488
log('backportImpl', LogLevel.INFO, `Executing ${bp} for "${slug}"`);
488-
const checkRun = await getCheckRun(context, pr, targetBranch);
489-
if (checkRun) {
490-
await context.octokit.checks.update(
491-
context.repo({
492-
check_run_id: checkRun.id,
493-
name: checkRun.name,
494-
status: 'in_progress' as 'in_progress',
495-
}),
496-
);
497-
}
489+
await context.octokit.checks.update(
490+
context.repo({
491+
check_run_id: checkRun.id,
492+
name: checkRun.name,
493+
status: 'in_progress' as 'in_progress',
494+
}),
495+
);
498496

499497
const repoAccessToken = await getRepoToken(robot, context);
500498

@@ -679,20 +677,18 @@ export const backportImpl = async (
679677
log('backportImpl', LogLevel.INFO, 'Backport process complete');
680678
}
681679

682-
if (checkRun) {
683-
context.octokit.checks.update(
684-
context.repo({
685-
check_run_id: checkRun.id,
686-
name: checkRun.name,
687-
conclusion: 'success' as 'success',
688-
completed_at: new Date().toISOString(),
689-
output: {
690-
title: 'Clean Backport',
691-
summary: `This PR was checked and can be backported to "${targetBranch}" cleanly.`,
692-
},
693-
}),
694-
);
695-
}
680+
context.octokit.checks.update(
681+
context.repo({
682+
check_run_id: checkRun.id,
683+
name: checkRun.name,
684+
conclusion: 'success' as 'success',
685+
completed_at: new Date().toISOString(),
686+
output: {
687+
title: 'Clean Backport',
688+
summary: `This PR was checked and can be backported to "${targetBranch}" cleanly.`,
689+
},
690+
}),
691+
);
696692

697693
await fs.remove(createdDir);
698694
},
@@ -759,30 +755,27 @@ export const backportImpl = async (
759755
]);
760756
}
761757

762-
const checkRun = await getCheckRun(context, pr, targetBranch);
763-
if (checkRun) {
764-
const mdSep = '``````````````````````````````';
765-
const updateOpts = context.repo({
766-
check_run_id: checkRun.id,
767-
name: checkRun.name,
768-
conclusion: 'neutral' as 'neutral',
769-
completed_at: new Date().toISOString(),
770-
output: {
771-
title: 'Backport Failed',
772-
summary: `This PR was checked and could not be automatically backported to "${targetBranch}" cleanly`,
773-
text: diff
774-
? `Failed Diff:\n\n${mdSep}diff\n${rawDiff}\n${mdSep}`
775-
: undefined,
776-
annotations: annotations ? annotations : undefined,
777-
},
778-
});
779-
try {
780-
await context.octokit.checks.update(updateOpts);
781-
} catch (err) {
782-
// A GitHub error occurred - try to mark it as a failure without annotations.
783-
updateOpts.output!.annotations = undefined;
784-
await context.octokit.checks.update(updateOpts);
785-
}
758+
const mdSep = '``````````````````````````````';
759+
const updateOpts = context.repo({
760+
check_run_id: checkRun.id,
761+
name: checkRun.name,
762+
conclusion: 'neutral' as 'neutral',
763+
completed_at: new Date().toISOString(),
764+
output: {
765+
title: 'Backport Failed',
766+
summary: `This PR was checked and could not be automatically backported to "${targetBranch}" cleanly`,
767+
text: diff
768+
? `Failed Diff:\n\n${mdSep}diff\n${rawDiff}\n${mdSep}`
769+
: undefined,
770+
annotations: annotations ? annotations : undefined,
771+
},
772+
});
773+
try {
774+
await context.octokit.checks.update(updateOpts);
775+
} catch (err) {
776+
// A GitHub error occurred - try to mark it as a failure without annotations.
777+
updateOpts.output!.annotations = undefined;
778+
await context.octokit.checks.update(updateOpts);
786779
}
787780
},
788781
);

0 commit comments

Comments
 (0)