forked from check-mergeable/check-mergeable
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
109 lines (97 loc) · 3.33 KB
/
app.js
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
99
100
101
102
103
104
105
106
107
108
109
module.exports = (app) => {
app.on([
'pull_request.opened',
'pull_request.edited',
'pull_request.labeled',
'pull_request.unlabeled',
'pull_request.synchronize',
], async (context) => {
const octokit = context.octokit
const logger = app.log
logger.info(`Got an event '${context.name}' from '${context.payload.repository.owner.login}/${context.payload.repository.name}'.`)
const repository = {
owner: context.payload.repository.owner.login,
repo: context.payload.repository.name,
}
const pullRequest = context.payload.pull_request
const { isMergeable, isDependent } = getMergeable({ logger, pullRequest })
await Promise.all([
updateStatus({ octokit, logger, repository, pullRequest, isMergeable }),
updateLabel({ octokit, logger, repository, pullRequest, isMergeable, isDependent }),
])
})
}
const getMergeable = ({ logger, pullRequest }) => {
const targetBranch = pullRequest.base.ref
const labels = pullRequest.labels.map(label => label.name)
logger.info(`Target branch is ${targetBranch}.`)
const isAllowedTargetBranch = (
targetBranch === 'main' ||
targetBranch === 'develop' ||
targetBranch.startsWith('release/') ||
targetBranch.startsWith('hotfix/')
)
const hasPendingLabels = (
!labels.includes('status: pending') &&
!labels.includes('status: in-progress') &&
labels.findIndex(label => label.startsWith('status: in-review')) === -1
)
const isMergeable = isAllowedTargetBranch && hasPendingLabels
logger.info(`This pull request is ${isMergeable ? '' : 'not '}mergeable.`)
return { isMergeable, isDependent: !isAllowedTargetBranch, hasPendingLabels }
}
const updateStatus = async ({ octokit, logger, repository, pullRequest, isMergeable }) => {
const state = isMergeable ? 'success' : 'pending'
logger.info(`Updating status to '${state}'.`)
try {
await octokit.request('POST /repos/:owner/:repo/statuses/:sha', {
...repository,
sha: pullRequest.head.sha,
context: 'Can I merge this PR?',
description: isMergeable ? 'Let\'s go!' : 'Wait...',
state,
})
logger.info(`Updated status.`)
} catch (error) {
logger.error(`Failed to update status. ${error}`)
}
}
const updateLabel = async ({ isMergeable, isDependent, ...params }) => {
const label = 'status: dependent'
if (!isMergeable && isDependent) {
await addLabel({ ...params, label })
} else {
await removeLabel({ ...params, label })
}
}
const addLabel = async ({ octokit, logger, repository, pullRequest, label }) => {
logger.info(`Adding label '${label}'.`)
const exists = pullRequest.labels.find(x => x.name === label)
if (exists) {
logger.info(`Label '${label}' already exists. Skip.`)
return
}
try {
await octokit.issues.addLabels({
...repository,
issue_number: pullRequest.number,
labels: [label],
})
logger.info(`Added label.`)
} catch (error) {
logger.error(`Failed to add label. ${error}`)
}
}
const removeLabel = async ({ octokit, logger, repository, pullRequest, label }) => {
logger.info(`Removing label '${label}'.`)
try {
await octokit.issues.removeLabel({
...repository,
issue_number: pullRequest.number,
name: label,
})
logger.info(`Removed label.`)
} catch (error) {
logger.error(`Failed to remove label. ${error}`)
}
}