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