-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
111 lines (97 loc) · 3.76 KB
/
index.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
110
111
const createScheduler = require('probot-scheduler')
const Bottleneck = require('bottleneck')
const Pull = require('./lib/pull')
const getConfig = require('./lib/get-config')
const configureLogging = require('./lib/logging')
const configureRoutes = require('./lib/router')
module.exports = async (app) => {
app.CONFIG_FILENAME = process.env.CONFIG_FILENAME || 'pull.yml'
app.limiter = new Bottleneck({
maxConcurrent: parseInt(process.env.MAX_CONCURRENT, 10) || 10,
highWater: parseInt(process.env.MAX_IN_QUEUE, 10) || 1000,
strategy: Bottleneck.strategy.OVERFLOW,
trackDoneStatus: false
})
configureLogging(app)
configureRoutes(app)
app.scheduler = createScheduler(app, {
delay: !process.env.DISABLE_DELAY,
interval: (parseInt(process.env.PULL_INTERVAL, 10) || 3600) * 1000
})
app.on('schedule.repository', routineCheck)
app.on('push', handlePush)
app.on('pull_request_review', checkPRStatus)
async function handlePush (context) {
if (context.payload.commits.filter(c => [...c.added, ...c.removed, ...c.modified].filter(f => f.indexOf(app.CONFIG_FILENAME) > -1).length > 0).length > 0) {
await routineCheck(context, { noCache: true })
}
}
async function routineCheck (context, opts = {}) {
const jobId = `${context.payload.repository.full_name}${context.payload.manual ? '-manual' : ''}`
if (!app.limiter.jobStatus(jobId)) {
await app.limiter.schedule({
expiration: (parseInt(process.env.JOB_TIMEOUT, 10) || 60) * 1000,
id: jobId,
priority: context.payload.manual ? 1 : 9
}, () => processRoutineCheck(context, opts))
}
}
async function processRoutineCheck (context, opts = {}) {
const pull = await forRepository(context, opts)
if (pull) {
await pull.routineCheck()
}
}
async function checkPRStatus (context) {
switch (context.event) {
case 'pull_request_review':
if (context.payload.action !== 'submitted' || context.payload.review.state !== 'approved') {
return
}
break
default:
return
}
const pull = await forRepository(context)
if (pull) await pull.checkAutoMerge(context.payload.pull_request)
}
async function forRepository (context, opts = {}) {
if (context.payload.repository.archived) {
app.log.debug(`[${context.payload.repository.full_name}] Not an active repo, unscheduled`)
app.scheduler.stop(context.payload.repository)
return null
}
let config
try {
config = await getConfig.getLiveConfig(context, app.CONFIG_FILENAME, { noCache: !!opts.noCache })
if (!context.payload.repository.fork && !config) {
app.log.debug(`[${context.payload.repository.full_name}] Not a forked repo and has no pull.yml, unscheduled`)
app.scheduler.stop(context.payload.repository)
return null
}
if (!config) {
config = await getConfig.getDefaultConfig(context, { noCache: !!opts.noCache })
}
} catch (e) {
if (e && e.code >= 500) {
app.log.warn(e, `[${context.payload.repository.full_name}] Repo access failed with server error ${e.code}`)
} else {
app.log.debug(e, `[${context.payload.repository.full_name}] Repo is blocked, unscheduled`)
app.scheduler.stop(context.payload.repository)
}
return null
}
if (!config) {
app.log.debug(`[${context.payload.repository.full_name}] Unable to get config, unscheduled`)
app.scheduler.stop(context.payload.repository)
return null
}
try {
return new Pull(context.github, context.repo({ logger: app.log }), config)
} catch (e) {
app.log.warn(e, `[${context.payload.repository.full_name}] Pull initialization failed`)
app.scheduler.stop(context.payload.repository)
return null
}
}
}