-
Notifications
You must be signed in to change notification settings - Fork 6
/
cascading-runs.js
144 lines (125 loc) · 5.66 KB
/
cascading-runs.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
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
const getToken = (() => {
const tokens = {}
const get = async (context, owner, repo) => {
const getInstallationIdForRepo = require('./get-installation-id-for-repo')
const installationId = await getInstallationIdForRepo(context, owner, repo)
const getInstallationAccessToken = require('./get-installation-access-token')
return await getInstallationAccessToken(context, installationId)
}
return async (context, owner, repo) => tokens[[owner, repo]] || (tokens[[owner, repo]] = await get(context, owner, repo))
})()
const triggerGitArtifactsRuns = async (context, checkRunOwner, checkRunRepo, tagGitCheckRun) => {
const commitSHA = tagGitCheckRun.head_sha
const conclusion = tagGitCheckRun.conclusion
const text = tagGitCheckRun.output.text
if (conclusion !== 'success') {
throw new Error(`tag-git run ${tagGitCheckRun.id} completed with ${conclusion}: ${tagGitCheckRun.html_url}`)
}
const match = text.match(/For details, see \[this run\]\(https:\/\/github.com\/([^/]+)\/([^/]+)\/actions\/runs\/(\d+)\)/)
if (!match) throw new Error(`Unhandled 'text' attribute of tag-git run ${tagGitCheckRun.id}: ${tagGitCheckRun.url}`)
const owner = match[1]
const repo = match[2]
const workflowRunId = Number(match[3])
if (owner !== 'git-for-windows' || repo !== 'git-for-windows-automation') {
throw new Error(`Unexpected repository ${owner}/${repo} for tag-git run ${tagGitCheckRun.id}: ${tagGitCheckRun.url}`)
}
const gitVersionMatch = tagGitCheckRun.output.summary.match(/^Tag Git (\S+) @([0-9a-f]+)$/)
if (!gitVersionMatch) {
throw new Error(`Could not parse Git version from summary '${tagGitCheckRun.output.summary}' of tag-git run ${tagGitCheckRun.id}: ${tagGitCheckRun.url}`)
}
if (commitSHA !== gitVersionMatch[2]) {
throw new Error(`Expected ${commitSHA} in summary '${tagGitCheckRun.output.summary}' of tag-git run ${tagGitCheckRun.id}: ${tagGitCheckRun.url}`)
}
const gitVersion = gitVersionMatch[1]
let res = ''
const architecturesToTrigger = []
const { listCheckRunsForCommit, queueCheckRun } = require('./check-runs')
for (const architecture of ['x86_64', 'i686']) {
const workflowName = `git-artifacts-${architecture}`
const runs = await listCheckRunsForCommit(
context,
await getToken(context, checkRunOwner, checkRunRepo),
checkRunOwner,
checkRunRepo,
commitSHA,
workflowName
)
const latest = runs
.filter(run => run.output.summary.endsWith(`(tag-git run #${workflowRunId})`))
.sort((a, b) => a.id - b.id)
.pop()
if (latest && (latest.status !== 'completed' || latest.conclusion === 'success')) {
// It either succeeded or is still running
res = `${res}${workflowName} run already exists at ${latest.html_url}.\n`
} else {
architecturesToTrigger.push(architecture)
}
}
if (architecturesToTrigger.length === 0) return `${res}No workflows need to be run!\n`
for (const architecture of architecturesToTrigger) {
const workflowName = `git-artifacts-${architecture}`
const title = `Build Git ${gitVersion} artifacts`
const summary = `Build Git ${gitVersion} artifacts from commit ${commitSHA} (tag-git run #${workflowRunId})`
await queueCheckRun(
context,
await getToken(context, checkRunOwner, checkRunRepo),
checkRunOwner,
checkRunRepo,
commitSHA,
workflowName,
title,
summary
)
}
const triggerWorkflowDispatch = require('./trigger-workflow-dispatch')
for (const architecture of architecturesToTrigger) {
const run = await triggerWorkflowDispatch(
context,
await getToken(context, owner, repo),
owner,
repo,
'git-artifacts.yml',
'main', {
architecture,
tag_git_workflow_run_id: workflowRunId.toString()
}
)
res = `${res}The \`git-artifacts-${architecture}\` workflow run [was started](${run.html_url}).\n`
}
return res
}
const cascadingRuns = async (context, req) => {
const action = req.body.action
const checkRunOwner = req.body.repository.owner.login
const checkRunRepo = req.body.repository.name
const checkRun = req.body.check_run
const name = checkRun.name
if (action === 'completed') {
if (name === 'tag-git') {
if (checkRunOwner !== 'git-for-windows' || checkRunRepo !== 'git') {
throw new Error(`Refusing to handle cascading run in ${checkRunOwner}/${checkRunRepo}`)
}
const comment = await triggerGitArtifactsRuns(context, checkRunOwner, checkRunRepo, checkRun)
const token = await getToken(context, checkRunOwner, checkRunRepo)
const { getGitArtifactsCommentID, appendToIssueComment } = require('./issues')
const gitArtifactsCommentID = await getGitArtifactsCommentID(
context,
token,
checkRunOwner,
checkRunRepo,
req.body.check_run.head_sha,
checkRun.details_url,
)
if (gitArtifactsCommentID) {
await appendToIssueComment(context, token, checkRunOwner, checkRunRepo, gitArtifactsCommentID, comment)
}
return comment
}
return `Not a cascading run: ${name}; Doing nothing.`
}
return `Unhandled action: ${action}`
}
module.exports = {
triggerGitArtifactsRuns,
cascadingRuns
}