-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.js
More file actions
134 lines (126 loc) · 5.92 KB
/
index.js
File metadata and controls
134 lines (126 loc) · 5.92 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
/*
* This is the Azure Function backing the GitGitGadget GitHub App.
*
* As Azure Functions do not support Typescript natively yet, we implement it in
* pure Javascript and keep it as simple as possible.
*
* Note: while the Azure Function Runtime v1 supported GitHub webhooks natively,
* via the "webHookType", starting with v2, we have to do the payload
* validation "by hand".
*/
const { validateGitHubWebHook } = require('./validate-github-webhook');
const { triggerWorkflowDispatch, listWorkflowRuns } = require('./trigger-workflow-dispatch')
module.exports = async (context, req) => {
try {
validateGitHubWebHook(context);
} catch (e) {
context.log('Caught ' + e);
context.res = {
status: 403,
body: 'Not a valid GitHub webhook: ' + e,
};
return;
}
try {
const { readFileSync } = require('fs')
const config = JSON.parse(readFileSync(`${__dirname}/gitgitgadget-config.json`))
const orgs = config.repo.owners
const a = [context, undefined, config.workflowsRepo.owner, config.workflowsRepo.name]
const eventType = context.req.headers['x-github-event'];
context.log(`Got eventType: ${eventType}`);
const repositoryOwner = req.body.repository.owner.login;
if (!orgs.includes(repositoryOwner)) {
context.res = {
status: 403,
body: `Refusing to work on any repository outside of ${orgs.join(', ')}`,
};
} else if (eventType === 'pull_request') {
if (req.body.action !== 'opened' && req.body.action !== 'synchronize') {
context.res = {
body: `Ignoring pull request action: ${req.body.action}`,
};
} else {
const run = await triggerWorkflowDispatch(...a, 'handle-pr-push.yml', 'main', {
'pr-url': req.body.pull_request.html_url
})
context.res = { body: `Okay, triggered ${run.html_url}!` };
}
} else if ((new Set(['check_run', 'status']).has(eventType))) {
context.res = {
body: `Ignored event type: ${eventType}`,
};
} else if (eventType === 'push') {
if (config.mailrepo.mirrorURL === `https://github.com/${req.body.repository.full_name}`) {
context.res = { body: `push(${req.body.ref} in ${req.body.repository.full_name}): ` }
if (req.body.ref === config.mailrepo.mirrorRef) {
const queued = await listWorkflowRuns(...a, 'handle-new-mails.yml', 'queued')
if (queued.length) {
context.res.body += [
`skip triggering handle-new-emails, ${queued} already queued:`,
queued.map(e => `- ${e.html_url}`)
].join('\n')
} else {
const run = await triggerWorkflowDispatch(...a, 'handle-new-mails.yml', 'main')
context.res.body += `triggered ${run.html_url}`
}
} else context.res.body += `Ignoring non-default branches`
} else if (req.body.repository.full_name !== `${config.repo.baseOwner}/${config.repo.name}`) {
context.res = { body: `Ignoring pushes to ${req.body.repository.full_name}` }
} else {
const run = await triggerWorkflowDispatch(
...a,
'sync-ref.yml',
'main', {
ref: req.body.ref
}
)
const extra = []
if (config.repo.branches.map((name) => `refs/heads/${name}`).includes(req.body.ref)) {
for (const workflow of ['update-prs.yml', 'update-mail-to-commit-notes.yml']) {
if ((await listWorkflowRuns(...a, workflow, 'main', 'queued')).length === 0) {
const run = await triggerWorkflowDispatch(...a, workflow, 'main')
extra.push(` and ${run.html_url}`)
}
}
}
context.res = { body: `push(${req.body.ref}): triggered ${run.html_url}${extra.join('')}` }
}
} else if (eventType === 'issue_comment') {
const comment = req.body.comment;
const prNumber = req.body.issue.number;
if (!comment || !comment.id || !prNumber) {
context.log(`Invalid payload:\n${JSON.stringify(req.body, null, 4)}`);
throw new Error('Invalid payload');
}
/* GitGitGadget works on dscho/git only for testing */
if (repositoryOwner === config.repo.testOwner && comment.user.login !== config.repo.testOwner) {
throw new Error(`Ignoring comment from ${comment.user.login}`);
}
/* Only trigger the Pipeline for valid commands */
if (!comment.body || !comment.body.match(/^\/(submit|preview|allow|disallow|test|cc)\b/)) {
context.res = {
body: `Not a command: '${comment.body}'`,
};
return;
}
const run = await triggerWorkflowDispatch(...a, 'handle-pr-comment.yml', 'main', {
'pr-comment-url': comment.html_url
})
context.res = {
// status: 200, /* Defaults to 200 */
body: `Okay, triggered ${run.html_url}!`,
};
} else {
context.log(`Unhandled request:\n${JSON.stringify(req, null, 4)}`);
context.res = {
body: 'No idea what this is about, but okay.',
};
}
} catch (e) {
context.log('Caught exception ', e);
context.res = {
status: 500,
body: `Caught an error: ${e.message || JSON.stringify(e, null, 2)}`,
};
}
};