Skip to content

Commit f315022

Browse files
committed
feat(dev-infra): show CI status of all active release trains (angular#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 angular#39067
1 parent f4f1bcc commit f315022

File tree

2 files changed

+23
-19
lines changed

2 files changed

+23
-19
lines changed

dev-infra/caretaker/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ ts_library(
88
module_name = "@angular/dev-infra-private/caretaker",
99
visibility = ["//dev-infra:__subpackages__"],
1010
deps = [
11+
"//dev-infra/release/versioning",
1112
"//dev-infra/utils",
1213
"@npm//@types/node",
1314
"@npm//@types/node-fetch",

dev-infra/caretaker/check/ci.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,55 @@
77
*/
88

99
import fetch from 'node-fetch';
10+
import {fetchActiveReleaseTrains} from '../../release/versioning/index';
1011

11-
import {bold, green, info, red} from '../../utils/console';
12+
import {bold, debug, info} from '../../utils/console';
1213
import {GitClient} from '../../utils/git';
1314

1415

1516
/** The results of checking the status of CI. */
1617
interface StatusCheckResult {
17-
status: 'success'|'failed'|'canceled'|'infrastructure_fail'|'timedout'|'failed'|'no_tests';
18-
timestamp: Date;
19-
buildUrl: string;
18+
status: 'success'|'failed';
2019
}
2120

2221
/** Retrieve and log status of CI for the project. */
2322
export async function printCiStatus(git: GitClient) {
23+
const releaseTrains = await fetchActiveReleaseTrains({api: git.github, ...git.remoteConfig});
24+
2425
info.group(bold(`CI`));
25-
// TODO(josephperrott): Expand list of branches checked to all active branches.
26-
await printStatus(git, 'master');
26+
for (const [trainName, train] of Object.entries(releaseTrains)) {
27+
if (train === null) {
28+
debug(`No active release train for ${trainName}`);
29+
continue;
30+
}
31+
const status = await getStatusOfBranch(git, train.branchName);
32+
await printStatus(`${trainName.padEnd(6)} (${train.branchName})`, status);
33+
}
2734
info.groupEnd();
2835
info();
2936
}
3037

3138
/** Log the status of CI for a given branch to the console. */
32-
async function printStatus(git: GitClient, branch: string) {
33-
const result = await getStatusOfBranch(git, branch);
34-
const branchName = branch.padEnd(10);
35-
if (result === null) {
39+
async function printStatus(label: string, status: StatusCheckResult|null) {
40+
const branchName = label.padEnd(16);
41+
if (status === null) {
3642
info(`${branchName} was not found on CircleCI`);
37-
} else if (result.status === 'success') {
43+
} else if (status.status === 'success') {
3844
info(`${branchName} ✅`);
3945
} else {
40-
info(`${branchName} (Ran at: ${result.timestamp.toLocaleString()})`);
46+
info(`${branchName} ❌`);
4147
}
4248
}
4349

4450
/** Get the CI status of a given branch from CircleCI. */
4551
async function getStatusOfBranch(git: GitClient, branch: string): Promise<StatusCheckResult|null> {
4652
const {owner, name} = git.remoteConfig;
47-
const url = `https://circleci.com/api/v1.1/project/gh/${owner}/${name}/tree/${
48-
branch}?limit=1&filter=completed&shallow=true`;
49-
const result = (await fetch(url).then(result => result.json()))?.[0];
53+
const url = `https://circleci.com/gh/${owner}/${name}/tree/${branch}.svg?style=shield`;
54+
const result = await fetch(url).then(result => result.text());
5055

51-
if (result) {
56+
if (result && !result.includes('no builds')) {
5257
return {
53-
status: result.outcome,
54-
timestamp: new Date(result.stop_time),
55-
buildUrl: result.build_url
58+
status: result.includes('passing') ? 'success' : 'failed',
5659
};
5760
}
5861
return null;

0 commit comments

Comments
 (0)