-
-
Notifications
You must be signed in to change notification settings - Fork 135
Expand file tree
/
Copy pathtrigger-jenkins-build.js
More file actions
180 lines (150 loc) · 5.04 KB
/
trigger-jenkins-build.js
File metadata and controls
180 lines (150 loc) · 5.04 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
'use strict'
const request = require('request')
const githubClient = require('../lib/github-client')
const botUsername = require('../lib/bot-username')
const jenkinsApiCredentials = process.env.JENKINS_API_CREDENTIALS || ''
function ifBotWasMentionedInCiComment (commentBody, cb) {
botUsername.resolve((err, username) => {
if (err) {
return cb(err)
}
const atBotName = new RegExp(`^@${username} run CI`, 'mi')
const wasMentioned = commentBody.match(atBotName) !== null
cb(null, wasMentioned)
})
}
// URL to the Jenkins job should be triggered for a given repository
function buildUrlForRepo (repo) {
// e.g. JENKINS_JOB_URL_CITGM = https://ci.nodejs.org/job/citgm-continuous-integration-pipeline
const jobUrl = process.env[`JENKINS_JOB_URL_${repo.toUpperCase()}`] || ''
return jobUrl ? `${jobUrl}/build` : ''
}
// Authentication token configured per Jenkins job needed when triggering a build,
// this is set per job in Configure -> Build Triggers -> Trigger builds remotely
function buildTokenForRepo (repo) {
// e.g. JENKINS_BUILD_TOKEN_CITGM
return process.env[`JENKINS_BUILD_TOKEN_${repo.toUpperCase()}`] || ''
}
function buildParametersForRepo (options, repo) {
if (repo === 'citgm') {
return [{
name: 'GIT_REMOTE_REF',
value: `refs/pull/${options.number}/head`
}]
} else {
return [{
name: 'CERTIFY_SAFE',
value: 'true'
},
{
name: 'TARGET_GITHUB_ORG',
value: 'nodejs'
},
{
name: 'TARGET_REPO_NAME',
value: 'node'
},
{
name: 'PR_ID',
value: options.number
}
]
}
}
function triggerBuild (options, cb) {
const { repo } = options
const base64Credentials = new Buffer(jenkinsApiCredentials).toString('base64')
const authorization = `Basic ${base64Credentials}`
const payload = JSON.stringify({ parameter: buildParametersForRepo(options, repo) })
const uri = buildUrlForRepo(repo)
const buildAuthToken = buildTokenForRepo(repo)
if (!uri) {
return cb(new TypeError(`Will not trigger Jenkins build because $JENKINS_JOB_URL_${repo.toUpperCase()} is not set`))
}
if (!buildAuthToken) {
return cb(new TypeError(`Will not trigger Jenkins build because $JENKINS_BUILD_TOKEN_${repo.toUpperCase()} is not set`))
}
options.logger.debug('Triggering Jenkins build')
request.post({
uri,
headers: { authorization },
qs: { token: buildAuthToken },
form: { json: payload }
}, (err, response) => {
if (err) {
return cb(err)
} else if (response.statusCode !== 201) {
return cb(new Error(`Expected 201 from Jenkins, got ${response.statusCode}`))
}
cb(null, response.headers.location)
})
}
function createPrComment ({ owner, repo, number, logger }, body) {
githubClient.issues.createComment({
owner,
repo,
number,
body
}, (err) => {
if (err) {
logger.error(err, 'Error while creating comment to reply on CI run comment')
}
})
}
module.exports = (app) => {
app.on('issue_comment.created', function handleCommentCreated (event, owner, repo) {
const { number, logger, comment } = event
const commentAuthor = comment.user.login
const options = {
owner,
repo,
number,
logger
}
function replyToCollabWithBuildStarted (err, buildUrl) {
if (err) {
logger.error(err, 'Error while triggering Jenkins build')
return createPrComment(options, `@${commentAuthor} sadly an error occured when I tried to trigger a build :(`)
}
createPrComment(options, `@${commentAuthor} build started: ${buildUrl}`)
logger.info({ buildUrl }, 'Jenkins build started')
}
function triggerBuildWhenCollaborator (err) {
if (err) {
return logger.debug(`Ignoring comment to me by @${commentAuthor} because they are not a repo collaborator`)
}
triggerBuild(options, replyToCollabWithBuildStarted)
}
ifBotWasMentionedInCiComment(comment.body, (err, wasMentioned) => {
if (err) {
return logger.error(err, 'Error while checking if the bot username was mentioned in a comment')
}
if (!wasMentioned) return
githubClient.repos.checkCollaborator({ owner, repo, username: commentAuthor }, triggerBuildWhenCollaborator)
})
})
app.on('pull_request.opened', function handlePullCreated (event, owner, repo) {
const { number, logger, pull_request } = event
const pullRequestAuthor = pull_request.user.login
const options = {
owner,
repo,
number,
logger
}
function logBuildStarted (err) {
if (err) {
logger.error(err, 'Error while triggering Jenkins build')
} else {
logger.info('Jenkins build started')
}
}
function triggerBuildWhenCollaborator (err) {
if (err) {
return logger.debug(`Ignoring comment to me by @${pullRequestAuthor} because they are not a repo collaborator`)
}
triggerBuild(options, replyToCollabWithBuildStarted)
}
githubClient.repos.checkCollaborator({ owner, repo, username: pullRequestAuthor }, triggerBuildWhenCollaborator)
})
}