diff --git a/dev-infra/caretaker/BUILD.bazel b/dev-infra/caretaker/BUILD.bazel index f3afe19c7e..d8d8b058da 100644 --- a/dev-infra/caretaker/BUILD.bazel +++ b/dev-infra/caretaker/BUILD.bazel @@ -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", diff --git a/dev-infra/caretaker/check/ci.ts b/dev-infra/caretaker/check/ci.ts index 2e568e14d5..ff32fe052c 100644 --- a/dev-infra/caretaker/check/ci.ts +++ b/dev-infra/caretaker/check/ci.ts @@ -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 { 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;