mirror of
https://gh-proxy.org/https://github.com/klinsmaya/portal-template-default.git
synced 2026-11-08 00:57:57 +08:00
64 lines
2.2 KiB
JavaScript
64 lines
2.2 KiB
JavaScript
// Finding and creating a task's build PR. publish-pr.mjs is a script that
|
|
// runs on import; these helpers live apart so they can be tested.
|
|
|
|
// The open PR of this work branch into the target branch, if any.
|
|
export async function findOpenPull(
|
|
client,
|
|
{ owner, workBranch, targetBranch },
|
|
) {
|
|
const open = await client.request('GET', '/pulls', {
|
|
query: { state: 'open', head: `${owner}:${workBranch}`, per_page: 100 },
|
|
});
|
|
return open.find((candidate) => candidate.base?.ref === targetBranch) ?? null;
|
|
}
|
|
|
|
// POST /pulls is not idempotent, so GitHubClient never retries it. A lost
|
|
// response (a timeout, a dropped connection, a 5xx) may still have created the
|
|
// PR, and a second POST then answers 422 "A pull request already exists":
|
|
// after any failure the open PR is looked up first, and the POST is repeated
|
|
// only while none exists and the failure could be transient.
|
|
export const CREATE_PULL_RETRY_DELAYS_MS = [5000, 15000];
|
|
export async function createPull(
|
|
client,
|
|
{ owner, workBranch, targetBranch, body },
|
|
{
|
|
delays = CREATE_PULL_RETRY_DELAYS_MS,
|
|
sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
} = {},
|
|
) {
|
|
for (let attempt = 0; ; attempt++) {
|
|
try {
|
|
return await client.request('POST', '/pulls', { body });
|
|
} catch (error) {
|
|
let existing = null;
|
|
try {
|
|
existing = await findOpenPull(client, {
|
|
owner,
|
|
workBranch,
|
|
targetBranch,
|
|
});
|
|
} catch (lookup) {
|
|
console.warn(
|
|
`Cannot look up the pull request after a failed create: ${lookup.message}`,
|
|
);
|
|
}
|
|
if (existing) {
|
|
console.warn(
|
|
`Creating the pull request failed (${error.message}); it exists, using it.`,
|
|
);
|
|
return existing;
|
|
}
|
|
const status = Number(/ failed \((\d{3})\)/.exec(error.message)?.[1]);
|
|
const transient =
|
|
!status ||
|
|
status >= 500 ||
|
|
(status === 422 && /already exists/i.test(error.message));
|
|
if (!transient || attempt >= delays.length) throw error;
|
|
console.warn(
|
|
`Creating the pull request failed (${error.message}); retrying.`,
|
|
);
|
|
await sleep(delays[attempt]);
|
|
}
|
|
}
|
|
}
|