Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/azure-pipelines/github-check-run.js
13379 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
// @ts-check
7
8
const crypto = require('crypto');
9
const https = require('https');
10
11
/**
12
* @param {string} appId
13
* @param {string} privateKey
14
* @returns {string}
15
*/
16
function createJwt(appId, privateKey) {
17
const now = Math.floor(Date.now() / 1000);
18
const header = Buffer.from(JSON.stringify({ alg: 'RS256', typ: 'JWT' })).toString('base64url');
19
const payload = Buffer.from(JSON.stringify({ iat: now - 60, exp: now + 600, iss: appId })).toString('base64url');
20
const signature = crypto.sign('sha256', Buffer.from(`${header}.${payload}`), privateKey).toString('base64url');
21
return `${header}.${payload}.${signature}`;
22
}
23
24
/**
25
* @param {import('https').RequestOptions} options
26
* @param {object} [body]
27
* @returns {Promise<any>}
28
*/
29
function request(options, body) {
30
return new Promise((resolve, reject) => {
31
const req = https.request(options, res => {
32
let data = '';
33
res.on('data', chunk => data += chunk);
34
res.on('end', () => {
35
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
36
resolve(JSON.parse(data));
37
} else {
38
reject(new Error(`HTTP ${res.statusCode}: ${data}`));
39
}
40
});
41
});
42
req.on('error', reject);
43
if (body) {
44
req.write(JSON.stringify(body));
45
}
46
req.end();
47
});
48
}
49
50
/**
51
* @param {string} jwt
52
* @param {string} installationId
53
* @returns {Promise<string>}
54
*/
55
async function getInstallationToken(jwt, installationId) {
56
/** @type {{ token: string }} */
57
const result = await request({
58
hostname: 'api.github.com',
59
path: `/app/installations/${encodeURIComponent(installationId)}/access_tokens`,
60
method: 'POST',
61
headers: {
62
'Authorization': `Bearer ${jwt}`,
63
'Accept': 'application/vnd.github+json',
64
'User-Agent': 'VSCode-ADO-Pipeline',
65
'X-GitHub-Api-Version': '2022-11-28'
66
}
67
});
68
return result.token;
69
}
70
71
/**
72
* @param {string} token
73
* @param {string} checkRunId
74
* @param {string} conclusion
75
* @param {string} detailsUrl
76
*/
77
function updateCheckRun(token, checkRunId, conclusion, detailsUrl) {
78
return request({
79
hostname: 'api.github.com',
80
path: `/repos/microsoft/vscode/check-runs/${encodeURIComponent(checkRunId)}`,
81
method: 'PATCH',
82
headers: {
83
'Authorization': `token ${token}`,
84
'Accept': 'application/vnd.github+json',
85
'User-Agent': 'VSCode-ADO-Pipeline',
86
'X-GitHub-Api-Version': '2022-11-28'
87
}
88
}, {
89
status: 'completed',
90
conclusion,
91
completed_at: new Date().toISOString(),
92
details_url: detailsUrl
93
});
94
}
95
96
async function main() {
97
const appId = process.env.GITHUB_APP_ID;
98
const privateKey = process.env.GITHUB_APP_PRIVATE_KEY;
99
const installationId = process.env.GITHUB_APP_INSTALLATION_ID;
100
const checkRunId = process.env.CHECK_RUN_ID;
101
const jobStatus = process.env.AGENT_JOBSTATUS;
102
const detailsUrl = `${process.env.SYSTEM_COLLECTIONURI}${process.env.SYSTEM_TEAMPROJECT}/_build/results?buildId=${process.env.BUILD_BUILDID}`;
103
104
if (!appId || !privateKey || !installationId || !checkRunId) {
105
throw new Error('Missing required environment variables');
106
}
107
108
const jwt = createJwt(appId, privateKey);
109
const token = await getInstallationToken(jwt, installationId);
110
111
/** @type {string} */
112
let conclusion;
113
switch (jobStatus) {
114
case 'Succeeded':
115
case 'SucceededWithIssues':
116
conclusion = 'success';
117
break;
118
case 'Canceled':
119
conclusion = 'cancelled';
120
break;
121
default:
122
conclusion = 'failure';
123
break;
124
}
125
126
await updateCheckRun(token, checkRunId, conclusion, detailsUrl);
127
console.log(`Updated check run ${checkRunId} with conclusion: ${conclusion}`);
128
}
129
130
main().catch(err => {
131
console.error(err);
132
process.exit(1);
133
});
134
135