Skip to content

Commit 9d914b1

Browse files
authored
Merge pull request #29 from dscho/switch-/git-artifacts-and-/release-to-actions
Switch `/git-artifacts` and `/release` to trigger GitHub workflows instead
2 parents 4064d75 + 9aeb564 commit 9d914b1

7 files changed

Lines changed: 518 additions & 19 deletions

File tree

.vscode/launch.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
{
22
"version": "0.2.0",
33
"configurations": [
4+
{
5+
"type": "node",
6+
"request": "launch",
7+
"name": "Debug Tests",
8+
"program": "${workspaceRoot}/node_modules/.bin/jest",
9+
"cwd": "${workspaceRoot}",
10+
"args": ["--runInBand", "--config", "jest.config.js"],
11+
"windows": {
12+
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
13+
}
14+
},
415
{
516
"name": "Attach to Node Functions",
617
"type": "node",
@@ -9,4 +20,4 @@
920
"preLaunchTask": "func: host start"
1021
}
1122
]
12-
}
23+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
const getToken = (() => {
2+
const tokens = {}
3+
4+
const get = async (context, owner, repo) => {
5+
const getInstallationIdForRepo = require('./get-installation-id-for-repo')
6+
const installationId = await getInstallationIdForRepo(context, owner, repo)
7+
const getInstallationAccessToken = require('./get-installation-access-token')
8+
return await getInstallationAccessToken(context, installationId)
9+
}
10+
11+
return async (context, owner, repo) => tokens[[owner, repo]] || (tokens[[owner, repo]] = await get(context, owner, repo))
12+
})()
13+
14+
const triggerGitArtifactsRuns = async (context, checkRunOwner, checkRunRepo, tagGitCheckRun) => {
15+
const commitSHA = tagGitCheckRun.head_sha
16+
const conclusion = tagGitCheckRun.conclusion
17+
const text = tagGitCheckRun.output.text
18+
19+
if (conclusion !== 'success') {
20+
throw new Error(`tag-git run ${tagGitCheckRun.id} completed with ${conclusion}: ${tagGitCheckRun.html_url}`)
21+
}
22+
23+
const match = text.match(/For details, see \[this run\]\(https:\/\/github.com\/([^/]+)\/([^/]+)\/actions\/runs\/(\d+)\)/)
24+
if (!match) throw new Error(`Unhandled 'text' attribute of tag-git run ${tagGitCheckRun.id}: ${tagGitCheckRun.url}`)
25+
const owner = match[1]
26+
const repo = match[2]
27+
const workflowRunId = Number(match[3])
28+
if (owner !== 'git-for-windows' || repo !== 'git-for-windows-automation') {
29+
throw new Error(`Unexpected repository ${owner}/${repo} for tag-git run ${tagGitCheckRun.id}: ${tagGitCheckRun.url}`)
30+
}
31+
32+
const gitVersionMatch = tagGitCheckRun.output.summary.match(/^Tag Git (\S+) @([0-9a-f]+)$/)
33+
if (!gitVersionMatch) {
34+
throw new Error(`Could not parse Git version from summary '${tagGitCheckRun.output.summary}' of tag-git run ${tagGitCheckRun.id}: ${tagGitCheckRun.url}`)
35+
}
36+
if (commitSHA !== gitVersionMatch[2]) {
37+
throw new Error(`Expected ${commitSHA} in summary '${tagGitCheckRun.output.summary}' of tag-git run ${tagGitCheckRun.id}: ${tagGitCheckRun.url}`)
38+
}
39+
const gitVersion = gitVersionMatch[1]
40+
41+
let res = ''
42+
43+
const architecturesToTrigger = []
44+
const { listCheckRunsForCommit, queueCheckRun } = require('./check-runs')
45+
for (const architecture of ['x86_64', 'i686']) {
46+
const workflowName = `git-artifacts-${architecture}`
47+
const runs = await listCheckRunsForCommit(
48+
context,
49+
await getToken(context, checkRunOwner, checkRunRepo),
50+
checkRunOwner,
51+
checkRunRepo,
52+
commitSHA,
53+
workflowName
54+
)
55+
const latest = runs
56+
.filter(run => run.output.summary.endsWith(`(tag-git run #${workflowRunId})`))
57+
.sort((a, b) => a.id - b.id)
58+
.pop()
59+
if (latest && (latest.status !== 'completed' || latest.conclusion === 'success')) {
60+
// It either succeeded or is still running
61+
res = `${res}${workflowName} run already exists at ${latest.html_url}.\n`
62+
} else {
63+
architecturesToTrigger.push(architecture)
64+
}
65+
}
66+
67+
if (architecturesToTrigger.length === 0) return `${res}No workflows need to be run!\n`
68+
69+
for (const architecture of architecturesToTrigger) {
70+
const workflowName = `git-artifacts-${architecture}`
71+
const title = `Build Git ${gitVersion} artifacts`
72+
const summary = `Build Git ${gitVersion} artifacts from commit ${commitSHA} (tag-git run #${workflowRunId})`
73+
await queueCheckRun(
74+
context,
75+
await getToken(context, checkRunOwner, checkRunRepo),
76+
checkRunOwner,
77+
checkRunRepo,
78+
commitSHA,
79+
workflowName,
80+
title,
81+
summary
82+
)
83+
}
84+
85+
const triggerWorkflowDispatch = require('./trigger-workflow-dispatch')
86+
for (const architecture of architecturesToTrigger) {
87+
const run = await triggerWorkflowDispatch(
88+
context,
89+
await getToken(context, owner, repo),
90+
owner,
91+
repo,
92+
'git-artifacts.yml',
93+
'main', {
94+
architecture,
95+
tag_git_workflow_run_id: workflowRunId
96+
}
97+
)
98+
res = `${res}The \`git-artifacts-${architecture}\` workflow run [was started](${run.html_url}).\n`
99+
}
100+
101+
return res
102+
}
103+
104+
const cascadingRuns = async (context, req) => {
105+
const action = req.body.action
106+
const checkRunOwner = req.body.repository.owner.login
107+
const checkRunRepo = req.body.repository.name
108+
const checkRun = req.body.check_run
109+
const name = checkRun.name
110+
111+
if (action === 'completed') {
112+
if (name === 'tag-git') {
113+
if (checkRunOwner !== 'git-for-windows' || checkRunRepo !== 'git') {
114+
throw new Error(`Refusing to handle cascading run in ${checkRunOwner}/${checkRunRepo}`)
115+
}
116+
117+
return await triggerGitArtifactsRuns(context, checkRunOwner, checkRunRepo, checkRun)
118+
}
119+
return `Not a cascading run: ${name}; Doing nothing.`
120+
}
121+
return `Unhandled action: ${action}`
122+
}
123+
124+
module.exports = {
125+
triggerGitArtifactsRuns,
126+
cascadingRuns
127+
}

GitForWindowsHelper/check-runs.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,23 @@ const cancelWorkflowRun = async (context, token, owner, repo, workflowRunId) =>
7171
console.log(answer)
7272
}
7373

74+
const listCheckRunsForCommit = async (context, token, owner, repo, rev, checkRunName) => {
75+
const githubApiRequest = require('./github-api-request')
76+
77+
const answer = await githubApiRequest(
78+
context,
79+
token,
80+
'GET',
81+
`/repos/${owner}/${repo}/commits/${rev}/check-runs?per_page=100${
82+
checkRunName ? `&check_name=${checkRunName}` : ''
83+
}`
84+
)
85+
return answer.check_runs
86+
}
87+
7488
module.exports = {
7589
queueCheckRun,
7690
updateCheckRun,
77-
cancelWorkflowRun
91+
cancelWorkflowRun,
92+
listCheckRunsForCommit
7893
}

GitForWindowsHelper/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ module.exports = async function (context, req) {
4444
return withStatus(500, undefined, e.toString('utf-8'))
4545
}
4646

47+
try {
48+
const { cascadingRuns } = require('./cascading-runs.js')
49+
if (req.headers['x-github-event'] === 'check_run'
50+
&& req.body.repository.full_name === 'git-for-windows/git'
51+
&& req.body.action === 'completed') return ok(await cascadingRuns(context, req))
52+
} catch (e) {
53+
context.log(e)
54+
return withStatus(500, undefined, e.toString('utf-8'))
55+
}
56+
4757
context.log("Got headers")
4858
context.log(req.headers)
4959
context.log("Got body")

GitForWindowsHelper/issues.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,21 @@ const createReactionForIssueComment = async (context, token, owner, repo, commen
5252
return answer.id
5353
}
5454

55+
const getPRCommitSHA = async (context, token, owner, repo, pullRequestNumber) => {
56+
const answer = await sendGitHubAPIRequest(
57+
context,
58+
token,
59+
'GET',
60+
`/repos/${owner}/${repo}/pulls/${pullRequestNumber}`
61+
)
62+
return answer.head.sha
63+
}
64+
5565
module.exports = {
5666
addIssueComment,
5767
getIssue,
5868
getIssueComment,
5969
appendToIssueComment,
60-
createReactionForIssueComment
70+
createReactionForIssueComment,
71+
getPRCommitSHA
6172
}

0 commit comments

Comments
 (0)