-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathgithub.js
More file actions
98 lines (87 loc) · 3.36 KB
/
github.js
File metadata and controls
98 lines (87 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
async function fetchProtectedBranchNames(context) {
let branches = await context.octokit.repos.listBranches(context.repo({protected : true, per_page : 100, request: { timeout: 120_000 }}))
return branches.data.map(branch => branch.name)
}
async function createPr(context, from, to, title) {
let pr = await context.octokit.pulls.create(context.repo({title: title, head: from, base: to}))
return pr
}
async function fetchOpenPr(context, from, to) {
let req = context.repo({base: to, state: "open"})
req.head = `${req.owner}:${from}`
let pr = await context.octokit.pulls.list(req)
if (pr.data.length == 1) {
return pr.data[0];
}
return null
}
async function setLabels(context, issueNumber, labels) {
await context.octokit.issues.setLabels(context.repo({issue_number: issueNumber, labels: labels}))
}
async function resolveAllComments(context, prNumber) {
try {
const { data: comments } = await context.octokit.request(
'GET /repos/{owner}/{repo}/pulls/{pull_number}/comments',
context.repo({pull_number: prNumber})
)
for (const comment of comments) {
if (comment.user.login !== 'cursor[bot]' || comment.user.login !== 'snyk-io[bot]') continue;
console.log("deleting comment : " + comment.id);
await context.octokit.request(
'DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}',
context.repo({comment_id: comment.id})
);
}
} catch(err) {
console.error(err);
}
}
async function mergePr(context, pr, onMergeFailure) {
const maxRetries = 5
let i = 0
let isMerged = false
while (i++ < maxRetries) {
try {
await context.octokit.pulls.merge(context.repo({pull_number : pr.number, commit_message : "\r\n\r\n skip-checks: true"}))
isMerged = true
break;
} catch (e) {
console.log(`Unable to merge the PR ${pr.number} due to ${e.message}.`);
if (i < maxRetries) {
console.log(` Retrying... sleeping for ${(i + 2)} minute(s)`)
await timeout(60 * (i + 1) * 1000);
}
}
}
if (!isMerged) {
await onMergeFailure(context, pr);
}
}
async function deleteBranch(context, branchName) {
await context.octokit.git.deleteRef(context.repo({ref : `heads/${branchName}`}))
}
function timeout(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
async function isMergeable (context, prNumber) {
const maxRetries = 5
let i = 0
while (i++ < maxRetries) {
await resolveAllComments(context, prNumber);
const pr = await context.octokit.pulls.get(context.repo({pull_number: prNumber}))
console.log(`PR Details of ${prNumber}`)
console.log(JSON.stringify(pr.data, null, 2));
// Merge Statuses: https://docs.github.com/en/graphql/reference/enums#mergestatestatus
if (typeof pr.data.mergeable === 'boolean' && pr.data.mergeable_state !== 'unknown') {
return pr.data.mergeable &&
(pr.data.mergeable_state === 'clean' || pr.data.mergeable_state === 'behind' || pr.data.mergeable_state === 'unstable' || pr.data.mergeable_state === 'blocked')
}
console.log(`sleeping for a minute`)
await timeout(60 * 1000)
}
return null
}
async function closePr(context, prNumber) {
await context.octokit.pulls.update(context.repo({pull_number: prNumber, state : "closed"}))
}
module.exports = {fetchProtectedBranchNames, createPr, setLabels, mergePr, deleteBranch, isMergeable, closePr, fetchOpenPr}