feat(dev-infra): show CI status of all active release trains (#39067)

As part of the ng-dev caretaker check command, show the status of the
lastest CircleCI run for each active release train.

PR Close #39067
This commit is contained in:
Joey Perrott 2020-09-30 13:16:33 -07:00
parent f4f1bcc997
commit f3150223da
2 changed files with 23 additions and 19 deletions

View File

@ -8,6 +8,7 @@ ts_library(
module_name = "@angular/dev-infra-private/caretaker",
visibility = ["//dev-infra:__subpackages__"],
deps = [
"//dev-infra/release/versioning",
"//dev-infra/utils",
"@npm//@types/node",
"@npm//@types/node-fetch",

View File

@ -7,52 +7,55 @@
*/
import fetch from 'node-fetch';
import {fetchActiveReleaseTrains} from '../../release/versioning/index';
import {bold, green, info, red} from '../../utils/console';
import {bold, debug, info} from '../../utils/console';
import {GitClient} from '../../utils/git';
/** The results of checking the status of CI. */
interface StatusCheckResult {
status: 'success'|'failed'|'canceled'|'infrastructure_fail'|'timedout'|'failed'|'no_tests';
timestamp: Date;
buildUrl: string;
status: 'success'|'failed';
}
/** Retrieve and log status of CI for the project. */
export async function printCiStatus(git: GitClient) {
const releaseTrains = await fetchActiveReleaseTrains({api: git.github, ...git.remoteConfig});
info.group(bold(`CI`));
// TODO(josephperrott): Expand list of branches checked to all active branches.
await printStatus(git, 'master');
for (const [trainName, train] of Object.entries(releaseTrains)) {
if (train === null) {
debug(`No active release train for ${trainName}`);
continue;
}
const status = await getStatusOfBranch(git, train.branchName);
await printStatus(`${trainName.padEnd(6)} (${train.branchName})`, status);
}
info.groupEnd();
info();
}
/** Log the status of CI for a given branch to the console. */
async function printStatus(git: GitClient, branch: string) {
const result = await getStatusOfBranch(git, branch);
const branchName = branch.padEnd(10);
if (result === null) {
async function printStatus(label: string, status: StatusCheckResult|null) {
const branchName = label.padEnd(16);
if (status === null) {
info(`${branchName} was not found on CircleCI`);
} else if (result.status === 'success') {
} else if (status.status === 'success') {
info(`${branchName}`);
} else {
info(`${branchName} (Ran at: ${result.timestamp.toLocaleString()})`);
info(`${branchName}`);
}
}
/** Get the CI status of a given branch from CircleCI. */
async function getStatusOfBranch(git: GitClient, branch: string): Promise<StatusCheckResult|null> {
const {owner, name} = git.remoteConfig;
const url = `https://circleci.com/api/v1.1/project/gh/${owner}/${name}/tree/${
branch}?limit=1&filter=completed&shallow=true`;
const result = (await fetch(url).then(result => result.json()))?.[0];
const url = `https://circleci.com/gh/${owner}/${name}/tree/${branch}.svg?style=shield`;
const result = await fetch(url).then(result => result.text());
if (result) {
if (result && !result.includes('no builds')) {
return {
status: result.outcome,
timestamp: new Date(result.stop_time),
buildUrl: result.build_url
status: result.includes('passing') ? 'success' : 'failed',
};
}
return null;