Skip to content

Commit 233d2be

Browse files
authored
[HUD] Add workflow run attempt to the elector for workflow id in commit and PR pages (#7142)
This is a continuation of #6919 There can be multiple attempts per workflow, this makes it so you can select which one. This is mostly so I can get the TD info easier in the UI since TD info is per workflow and run attempt #6919 (comment) Old: <img width="262" height="97" alt="image" src="https://github.com/user-attachments/assets/7dce3d30-cb06-4eb9-adca-8b405721f2ab" /> New: <img width="279" height="108" alt="image" src="https://github.com/user-attachments/assets/8c541a41-d53f-4202-a515-6d90b88b4a6d" />
1 parent b6d478f commit 233d2be

7 files changed

Lines changed: 93 additions & 31 deletions

File tree

torchci/clickhouse_queries/commit_jobs_query/params.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
"params": {
33
"repo": "String",
44
"sha": "String",
5-
"workflowId": "Int64"
5+
"workflowId": "Int64",
6+
"runAttempt": "Int64"
67
},
78
"tests": [
89
{
910
"repo": "pytorch/pytorch",
1011
"sha": "85df746892d9b0e87e7a5dfa78ef81a84aec6de0",
11-
"workflow_id": 0
12+
"workflow_id": 0,
13+
"run_attempt": 0
1214
}
1315
]
1416
}

torchci/clickhouse_queries/commit_jobs_query/query.sql

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ WITH job AS (
3636
job.torchci_classification_kg.'line_num' as line_num,
3737
job.torchci_classification_kg.'context' as context,
3838
job.runner_name AS runner_name,
39-
workflow.head_commit. 'author'.'email' AS authorEmail
39+
workflow.head_commit. 'author'.'email' AS authorEmail,
40+
job.run_attempt AS run_attempt
4041
FROM
4142
workflow_job job final
4243
INNER JOIN workflow_run workflow final ON workflow.id = job.run_id
@@ -51,6 +52,10 @@ WITH job AS (
5152
{workflowId: Int64} = 0
5253
OR workflow.id = {workflowId: Int64} -- If a specific workflow ID is provided, filter by it
5354
)
55+
AND (
56+
{runAttempt: Int64} = 0
57+
OR job.run_attempt = {runAttempt: Int64} -- If a specific run attempt
58+
)
5459
AND job.id in (select id from materialized_views.workflow_job_by_head_sha where head_sha = {sha: String})
5560
AND workflow.repository. 'full_name' = {repo: String } -- UNION
5661
AND workflow.name != 'Upload test stats while running' -- Continuously running cron job that cancels itself to avoid running concurrently
@@ -82,7 +87,8 @@ WITH job AS (
8287
0 as line_num,
8388
[ ] as context,
8489
'' AS runner_name,
85-
workflow.head_commit.author.email AS authorEmail
90+
workflow.head_commit.author.email AS authorEmail,
91+
workflow.run_attempt as run_attempt
8692
FROM
8793
workflow_run workflow final
8894
WHERE
@@ -94,6 +100,10 @@ WITH job AS (
94100
{workflowId: Int64} = 0
95101
OR workflow.id = {workflowId: Int64} -- If a specific workflow ID is provided, filter by it
96102
)
103+
AND (
104+
{runAttempt: Int64} = 0
105+
OR workflow.run_attempt = {runAttempt: Int64} -- If a specific run attempt is provided, filter by it
106+
)
97107
AND workflow.repository.full_name = {repo: String }
98108
AND workflow.name != 'Upload test stats while running' -- Continuously running cron job that cancels itself to avoid running concurrently
99109
)
@@ -118,6 +128,7 @@ SELECT
118128
runner_name AS runnerName,
119129
authorEmail,
120130
time,
131+
run_attempt AS runAttempt
121132
FROM
122133
job
123134
ORDER BY

torchci/components/commit/CommitStatus.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import { CommitData, IssueData, JobData } from "lib/types";
88
import useScrollTo from "lib/useScrollTo";
99
import _ from "lodash";
10+
import { WorkflowRunInfo } from "pages/api/[repoOwner]/[repoName]/commit/[sha]";
1011
import { useState } from "react";
1112
import { linkIt, UrlComponent, urlRegex } from "react-linkify-it";
1213
import { getConclusionSeverityForSorting } from "../../lib/JobClassifierUtil";
@@ -59,7 +60,7 @@ function WorkflowsContainer({
5960
}: {
6061
jobs: JobData[];
6162
unstableIssues: IssueData[];
62-
workflowIdsByName: Record<string, number[]>;
63+
workflowIdsByName: Record<string, [WorkflowRunInfo]>;
6364
repoFullName: string;
6465
}) {
6566
useScrollTo();
@@ -117,7 +118,7 @@ export default function CommitStatus({
117118
repoName: string;
118119
commit: CommitData;
119120
jobs: JobData[];
120-
workflowIdsByName: Record<string, number[]>;
121+
workflowIdsByName: Record<string, [WorkflowRunInfo]>;
121122
isCommitPage: boolean;
122123
unstableIssues: IssueData[];
123124
}) {

torchci/components/commit/WorkflowBox.tsx

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import {
1414
ListUtilizationMetadataInfoAPIResponse,
1515
UtilizationMetadataInfo,
1616
} from "lib/utilization/types";
17-
import { CommitApiResponse } from "pages/api/[repoOwner]/[repoName]/commit/[sha]";
17+
import {
18+
CommitApiResponse,
19+
WorkflowRunInfo,
20+
} from "pages/api/[repoOwner]/[repoName]/commit/[sha]";
1821
import React, { useEffect, useState } from "react";
1922
import { FaInfoCircle } from "react-icons/fa";
2023
import useSWR from "swr";
@@ -154,18 +157,18 @@ export default function WorkflowBox({
154157
jobs: JobData[];
155158
unstableIssues: IssueData[];
156159
wide: boolean;
157-
allWorkflowIds: number[];
160+
allWorkflowIds: [WorkflowRunInfo];
158161
setWide: any;
159162
repoFullName: string;
160163
}) {
161164
const [selectedWorkflowId, setSelectedWorkflowId] = useState<
162-
string | undefined
165+
WorkflowRunInfo | undefined
163166
>(undefined);
164-
const workflowId = selectedWorkflowId || jobs[0].workflowId;
167+
const workflowId = selectedWorkflowId?.id || jobs[0].workflowId;
165168

166169
const { data: jobsFromSelectedWorkflowId } = useSWR<CommitApiResponse>(
167170
selectedWorkflowId &&
168-
`/api/${repoFullName}/commit/${jobs[0].sha}?workflowId=${selectedWorkflowId}`,
171+
`/api/${repoFullName}/commit/${jobs[0].sha}?workflowId=${selectedWorkflowId.id}&runAttempt=${selectedWorkflowId.attempt}`,
169172
fetcher
170173
);
171174

@@ -180,7 +183,7 @@ export default function WorkflowBox({
180183

181184
const anchorName = encodeURIComponent(workflowName.toLowerCase());
182185

183-
const { utilMetadataList } = useUtilMetadata(workflowId);
186+
const { utilMetadataList } = useUtilMetadata(workflowId?.toString());
184187
const groupUtilMetadataList = groupMetadataByJobId(utilMetadataList);
185188

186189
const { artifacts, error } = useArtifacts(jobs.map((job) => job.workflowId));
@@ -219,20 +222,30 @@ export default function WorkflowBox({
219222
<Typography fontWeight="bold" paddingBottom={2}>
220223
Job Status
221224
</Typography>
222-
</Stack>
225+
</Stack>{" "}
223226
<Stack direction="column" spacing={1}>
224227
<Stack direction="row" spacing={1}>
225228
<select
226-
value={selectedWorkflowId}
229+
value={
230+
selectedWorkflowId
231+
? `${selectedWorkflowId?.id} ${selectedWorkflowId?.attempt}`
232+
: ""
233+
}
227234
onChange={(e) => {
228-
setSelectedWorkflowId(e.target.value);
235+
const split = e.target.value.split(" ");
236+
setSelectedWorkflowId({
237+
id: parseInt(split[0]),
238+
attempt: parseInt(split[1]),
239+
});
229240
}}
230-
style={{ width: "100%" }}
231241
>
232242
<option value={""}>Select Workflow ID</option>
233243
{allWorkflowIds.sort().map((id) => (
234-
<option key={id} value={id}>
235-
{id}
244+
<option
245+
key={`${id.id} ${id.attempt}`}
246+
value={`${id.id} ${id.attempt}`}
247+
>
248+
{id.id} (Attempt {id.attempt})
236249
</option>
237250
))}
238251
</select>
@@ -275,7 +288,15 @@ export default function WorkflowBox({
275288
</Stack>
276289
</Stack>
277290
{wide && (
278-
<TestInfo workflowId={workflowId!} runAttempt={"1"} jobs={jobs} />
291+
<TestInfo
292+
workflowId={workflowId!.toString()}
293+
runAttempt={
294+
selectedWorkflowId?.attempt?.toString() ||
295+
jobs[0].runAttempt?.toString() ||
296+
"1"
297+
}
298+
jobs={jobs}
299+
/>
279300
)}
280301
<>
281302
{jobs.sort(sortJobsByConclusion).map((job) => (

torchci/lib/fetchCommit.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import _ from "lodash";
22
import { Octokit } from "octokit";
3-
import { CommitApiResponse } from "pages/api/[repoOwner]/[repoName]/commit/[sha]";
3+
import {
4+
CommitApiResponse,
5+
WorkflowRunInfo,
6+
} from "pages/api/[repoOwner]/[repoName]/commit/[sha]";
47
import { queryClickhouseSaved } from "./clickhouse";
58
import { commitDataFromResponse, getOctokit } from "./github";
69
import { removeCancelledJobAfterRetry } from "./jobUtils";
@@ -10,12 +13,14 @@ async function fetchDatabaseInfo(
1013
owner: string,
1114
repo: string,
1215
sha: string,
13-
workflowId: number
16+
workflowId: number,
17+
runAttempt: number
1418
) {
1519
const response = await queryClickhouseSaved("commit_jobs_query", {
1620
repo: `${owner}/${repo}`,
1721
sha: sha,
1822
workflowId,
23+
runAttempt,
1924
});
2025

2126
for (const row of response) {
@@ -32,16 +37,29 @@ async function fetchDatabaseInfo(
3237
* @param jobs
3338
* @returns
3439
*/
35-
function getWorkflowIdsByName(jobs: JobData[]): Record<string, number[]> {
40+
function getWorkflowIdsByName(
41+
jobs: JobData[]
42+
): Record<string, [WorkflowRunInfo]> {
3643
return _(jobs)
3744
.groupBy((job) => job.workflowName)
3845
.map((jobs, key) => {
39-
const workflowIds = _(jobs)
40-
.map((job) => job.workflowId)
41-
.filter((id) => id !== null && id !== undefined)
42-
.uniq()
46+
const idAndAttempts = _(jobs)
47+
.map((job) => {
48+
return {
49+
id: job.workflowId,
50+
attempt: job.runAttempt,
51+
};
52+
})
53+
.filter(
54+
(id) =>
55+
id.id !== null &&
56+
id.id !== undefined &&
57+
id.attempt !== null &&
58+
id.attempt !== undefined
59+
)
60+
.uniqBy((id) => `${id.id}-${id.attempt}`)
4361
.value();
44-
return [key, workflowIds];
62+
return [key, idAndAttempts];
4563
})
4664
.fromPairs()
4765
.value();
@@ -60,14 +78,15 @@ export default async function fetchCommit(
6078
owner: string,
6179
repo: string,
6280
sha: string,
63-
workflowId: number = 0
81+
workflowId: number = 0,
82+
runAttempt: number = 0
6483
): Promise<CommitApiResponse> {
6584
// Retrieve commit data from GitHub
6685
const octokit = await getOctokit(owner, repo);
6786

6887
const [githubResponse, response] = await Promise.all([
6988
octokit.rest.repos.getCommit({ owner, repo, ref: sha }),
70-
await fetchDatabaseInfo(owner, repo, sha, workflowId),
89+
await fetchDatabaseInfo(owner, repo, sha, workflowId, runAttempt),
7190
]);
7291

7392
let jobs = response as any[];

torchci/lib/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface JobData extends BasicJobData {
3030
repo?: string;
3131
failureAnnotation?: string;
3232
failedPreviousRun?: boolean;
33+
runAttempt?: number;
3334
}
3435

3536
// Used by Dr.CI

torchci/pages/api/[repoOwner]/[repoName]/commit/[sha].ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,32 @@ import fetchCommit from "lib/fetchCommit";
22
import { CommitData, JobData } from "lib/types";
33
import type { NextApiRequest, NextApiResponse } from "next";
44

5+
export type WorkflowRunInfo = {
6+
id: number;
7+
attempt: number;
8+
};
9+
510
export type CommitApiResponse = {
611
commit: CommitData;
712
jobs: JobData[];
8-
workflowIdsByName: Record<string, number[]>;
13+
workflowIdsByName: Record<string, [WorkflowRunInfo]>;
914
};
1015

1116
export default async function handler(
1217
req: NextApiRequest,
1318
res: NextApiResponse<CommitApiResponse>
1419
) {
1520
const workflowId = parseInt(req.query.workflowId as string, 10) || 0;
21+
const runAttempt = parseInt(req.query.runAttempt as string, 10) || 0;
1622
res
1723
.status(200)
1824
.json(
1925
await fetchCommit(
2026
req.query.repoOwner as string,
2127
req.query.repoName as string,
2228
req.query.sha as string,
23-
workflowId
29+
workflowId,
30+
runAttempt
2431
)
2532
);
2633
}

0 commit comments

Comments
 (0)