Skip to content

Commit 2bc3a00

Browse files
committed
tc
1 parent 851c0ad commit 2bc3a00

File tree

8 files changed

+120
-17
lines changed

8 files changed

+120
-17
lines changed
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
{
22
"params": {
33
"repo": "String",
4-
"sha": "String"
4+
"sha": "String",
5+
"workflowId": "Int64"
56
},
67
"tests": [
78
{
89
"repo": "pytorch/pytorch",
9-
"sha": "85df746892d9b0e87e7a5dfa78ef81a84aec6de0"
10+
"sha": "85df746892d9b0e87e7a5dfa78ef81a84aec6de0",
11+
"workflow_id": 0
1012
}
1113
]
1214
}

torchci/clickhouse_queries/commit_jobs_query/query.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ WITH job AS (
4646
AND workflow.event != 'workflow_run' -- Filter out workflow_run-triggered jobs, which have nothing to do with the SHA
4747
AND workflow.event != 'repository_dispatch' -- Filter out repository_dispatch-triggered jobs, which have nothing to do with the SHA
4848
AND workflow.id in (select id from materialized_views.workflow_run_by_head_sha where head_sha = {sha: String})
49+
AND (
50+
{workflowId: Int64} = 0
51+
OR workflow.id = {workflowId: Int64} -- If a specific workflow ID is provided, filter by it
52+
)
4953
AND job.id in (select id from materialized_views.workflow_job_by_head_sha where head_sha = {sha: String})
5054
AND workflow.repository. 'full_name' = {repo: String } -- UNION
5155
AND workflow.name != 'Upload test stats while running' -- Continuously running cron job that cancels itself to avoid running concurrently
@@ -84,6 +88,10 @@ WITH job AS (
8488
workflow.event != 'workflow_run' -- Filter out workflow_run-triggered jobs, which have nothing to do with the SHA
8589
AND workflow.event != 'repository_dispatch' -- Filter out repository_dispatch-triggered jobs, which have nothing to do with the SHA
8690
AND workflow.id in (select id from materialized_views.workflow_run_by_head_sha where head_sha = {sha: String})
91+
AND (
92+
{workflowId: Int64} = 0
93+
OR workflow.id = {workflowId: Int64} -- If a specific workflow ID is provided, filter by it
94+
)
8795
AND workflow.repository.full_name = {repo: String }
8896
AND workflow.name != 'Upload test stats while running' -- Continuously running cron job that cancels itself to avoid running concurrently
8997
)

torchci/components/commit/CommitStatus.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,12 @@ function getBoxOrdering(jobs: JobData[], wideBoxes: Set<string>) {
5454
function WorkflowsContainer({
5555
jobs,
5656
unstableIssues,
57+
workflowIdsByName,
5758
repoFullName,
5859
}: {
5960
jobs: JobData[];
6061
unstableIssues: IssueData[];
62+
workflowIdsByName: Record<string, number[]>;
6163
repoFullName: string;
6264
}) {
6365
useScrollTo();
@@ -81,6 +83,7 @@ function WorkflowsContainer({
8183
repoFullName={repoFullName}
8284
key={workflowName}
8385
workflowName={workflowName}
86+
allWorkflowIds={workflowIdsByName[workflowName] || []}
8487
jobs={jobs}
8588
unstableIssues={unstableIssues}
8689
wide={wideBoxes.has(workflowName)}
@@ -106,13 +109,15 @@ export default function CommitStatus({
106109
repoName,
107110
commit,
108111
jobs,
112+
workflowIdsByName,
109113
isCommitPage,
110114
unstableIssues,
111115
}: {
112116
repoOwner: string;
113117
repoName: string;
114118
commit: CommitData;
115119
jobs: JobData[];
120+
workflowIdsByName: Record<string, number[]>;
116121
isCommitPage: boolean;
117122
unstableIssues: IssueData[];
118123
}) {
@@ -174,6 +179,7 @@ export default function CommitStatus({
174179
/>
175180
<WorkflowsContainer
176181
jobs={jobs}
182+
workflowIdsByName={workflowIdsByName}
177183
unstableIssues={unstableIssues}
178184
repoFullName={`${repoOwner}/${repoName}`}
179185
/>

torchci/components/commit/WorkflowBox.tsx

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Button, styled } from "@mui/material";
1+
import { Button, Stack, styled, Tooltip, Typography } from "@mui/material";
22
import { TestInfo } from "components/additionalTestInfo/TestInfo";
33
import styles from "components/commit/commit.module.css";
44
import LogViewer, { SearchLogViewer } from "components/common/log/LogViewer";
@@ -14,7 +14,10 @@ import {
1414
ListUtilizationMetadataInfoAPIResponse,
1515
UtilizationMetadataInfo,
1616
} from "lib/utilization/types";
17+
import { CommitApiResponse } from "pages/api/[repoOwner]/[repoName]/commit/[sha]";
1718
import React, { useEffect, useState } from "react";
19+
import { FaInfoCircle } from "react-icons/fa";
20+
import useSWR from "swr";
1821
import useSWRImmutable from "swr/immutable";
1922

2023
function sortJobsByConclusion(jobA: JobData, jobB: JobData): number {
@@ -140,16 +143,32 @@ export default function WorkflowBox({
140143
unstableIssues,
141144
wide,
142145
setWide,
146+
allWorkflowIds,
143147
repoFullName,
144148
}: {
145149
workflowName: string;
146150
jobs: JobData[];
147151
unstableIssues: IssueData[];
148152
wide: boolean;
153+
allWorkflowIds: number[];
149154
setWide: any;
150155
repoFullName: string;
151156
}) {
152-
const workflowId = jobs[0].workflowId;
157+
const [selectedWorkflowId, setSelectedWorkflowId] = useState<
158+
string | undefined
159+
>(undefined);
160+
const workflowId = selectedWorkflowId || jobs[0].workflowId;
161+
162+
const { data: jobsFromSelectedWorkflowId } = useSWR<CommitApiResponse>(
163+
selectedWorkflowId &&
164+
`/api/${repoFullName}/commit/${jobs[0].sha}?workflowId=${selectedWorkflowId}`,
165+
fetcher
166+
);
167+
168+
if (selectedWorkflowId) {
169+
jobs = jobsFromSelectedWorkflowId?.jobs || [];
170+
}
171+
153172
const isFailed = jobs.some(isFailedJob) !== false;
154173
const workflowClass = isFailed
155174
? styles.workflowBoxFail
@@ -163,6 +182,7 @@ export default function WorkflowBox({
163182
const { artifacts, error } = useArtifacts(jobs.map((job) => job.workflowId));
164183
const [artifactsToShow, setArtifactsToShow] = useState(new Set<string>());
165184
const groupedArtifacts = groupArtifacts(jobs, artifacts);
185+
166186
const [searchString, setSearchString] = useState("");
167187
const [searchRes, setSearchRes] = useState<{
168188
results: Map<string, LogSearchResult>;
@@ -184,11 +204,33 @@ export default function WorkflowBox({
184204
>
185205
<h3>{workflowName}</h3>
186206
<div>
187-
<div
188-
// Similar styling to an h4
189-
style={{ float: "left", marginBottom: "1.33em", fontWeight: "bold" }}
190-
>
191-
Job Status
207+
<div style={{ float: "left" }}>
208+
<div
209+
// Similar styling to an h4
210+
style={{ marginBottom: "0.5em", fontWeight: "bold" }}
211+
>
212+
Job Status
213+
</div>
214+
<Stack direction="row" spacing={1}>
215+
<select
216+
value={selectedWorkflowId}
217+
onChange={(e) => {
218+
setSelectedWorkflowId(e.target.value);
219+
}}
220+
>
221+
<option value={""}>Select Workflow ID</option>
222+
{allWorkflowIds.sort().map((id) => (
223+
<option key={id} value={id}>
224+
{id}
225+
</option>
226+
))}
227+
</select>
228+
<Tooltip title="By default the box will show what it believes to be the latest jobs. Use this to select a specific workflow ID if it's wrong.">
229+
<Typography>
230+
<FaInfoCircle />
231+
</Typography>
232+
</Tooltip>
233+
</Stack>
192234
</div>
193235
<div style={{ float: "right" }}>
194236
<div style={{ margin: ".5em 0em" }}>

torchci/lib/fetchCommit.ts

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
import _ from "lodash";
22
import { Octokit } from "octokit";
3+
import { CommitApiResponse } from "pages/api/[repoOwner]/[repoName]/commit/[sha]";
34
import { queryClickhouseSaved } from "./clickhouse";
45
import { commitDataFromResponse, getOctokit } from "./github";
56
import { removeCancelledJobAfterRetry } from "./jobUtils";
6-
import { CommitData, JobData } from "./types";
7+
import { JobData } from "./types";
78

8-
async function fetchDatabaseInfo(owner: string, repo: string, sha: string) {
9+
async function fetchDatabaseInfo(
10+
owner: string,
11+
repo: string,
12+
sha: string,
13+
workflowId: number
14+
) {
915
const response = await queryClickhouseSaved("commit_jobs_query", {
1016
repo: `${owner}/${repo}`,
1117
sha: sha,
18+
workflowId,
1219
});
1320

1421
for (const row of response) {
@@ -20,21 +27,53 @@ async function fetchDatabaseInfo(owner: string, repo: string, sha: string) {
2027
return response;
2128
}
2229

30+
/**
31+
* Get a mapping of workflow names to all workflow IDs from a list of job data.
32+
* @param jobs
33+
* @returns
34+
*/
35+
function getWorkflowIdsByName(jobs: JobData[]): Record<string, number[]> {
36+
return _(jobs)
37+
.groupBy((job) => job.workflowName)
38+
.map((jobs, key) => {
39+
const workflowIds = _(jobs)
40+
.map((job) => job.workflowId)
41+
.filter((id) => id !== null && id !== undefined)
42+
.uniq()
43+
.value();
44+
return [key, workflowIds];
45+
})
46+
.fromPairs()
47+
.value();
48+
}
49+
50+
/**
51+
*
52+
* @param owner
53+
* @param repo
54+
* @param sha
55+
* @param workflowId Optional workflow ID to filter jobs by. If not provided,
56+
* all jobs for the commit will be returned.
57+
* @returns
58+
*/
2359
export default async function fetchCommit(
2460
owner: string,
2561
repo: string,
26-
sha: string
27-
): Promise<{ commit: CommitData; jobs: JobData[] }> {
62+
sha: string,
63+
workflowId: number = 0
64+
): Promise<CommitApiResponse> {
2865
// Retrieve commit data from GitHub
2966
const octokit = await getOctokit(owner, repo);
3067

3168
const [githubResponse, response] = await Promise.all([
3269
octokit.rest.repos.getCommit({ owner, repo, ref: sha }),
33-
await fetchDatabaseInfo(owner, repo, sha),
70+
await fetchDatabaseInfo(owner, repo, sha, workflowId),
3471
]);
3572

3673
let jobs = response as any[];
3774

75+
const workflowIdsByName = getWorkflowIdsByName(jobs);
76+
3877
// Subtle: we need to unique jobs by name, taking the most recent job. This is
3978
// because there might be many periodic jobs with the same name, and we want
4079
// to avoid noising up the display with many duplicate jobs.
@@ -65,6 +104,7 @@ export default async function fetchCommit(
65104
return {
66105
commit: commitDataFromResponse(githubResponse.data),
67106
jobs: _.concat(filteredJobs, badWorkflows),
107+
workflowIdsByName,
68108
};
69109
}
70110

torchci/pages/[repoOwner]/[repoName]/commit/[sha].tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export function CommitInfo({
4343
return <div>Loading...</div>;
4444
}
4545

46-
const { commit, jobs } = commitData;
46+
const { commit, jobs, workflowIdsByName } = commitData;
4747

4848
return (
4949
<div>
@@ -53,6 +53,7 @@ export function CommitInfo({
5353
repoName={repoName}
5454
commit={commit}
5555
jobs={jobs}
56+
workflowIdsByName={workflowIdsByName}
5657
isCommitPage={true}
5758
unstableIssues={unstableIssuesData ?? []}
5859
/>

torchci/pages/[repoOwner]/[repoName]/pull/[prNumber].tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ function CommitInfo({
4848
if (commitData === undefined) {
4949
return <div>Loading...</div>;
5050
}
51-
const { commit, jobs } = commitData;
51+
const { commit, jobs, workflowIdsByName } = commitData;
5252

5353
return (
5454
<CommitStatus
5555
repoOwner={repoOwner}
5656
repoName={repoName}
5757
commit={commit}
5858
jobs={jobs}
59+
workflowIdsByName={workflowIdsByName}
5960
isCommitPage={false}
6061
unstableIssues={unstableIssuesData ?? []}
6162
/>

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,22 @@ import type { NextApiRequest, NextApiResponse } from "next";
55
export type CommitApiResponse = {
66
commit: CommitData;
77
jobs: JobData[];
8+
workflowIdsByName: Record<string, number[]>;
89
};
910

1011
export default async function handler(
1112
req: NextApiRequest,
1213
res: NextApiResponse<CommitApiResponse>
1314
) {
15+
const workflowId = parseInt(req.query.workflowId as string, 10) || 0;
1416
res
1517
.status(200)
1618
.json(
1719
await fetchCommit(
1820
req.query.repoOwner as string,
1921
req.query.repoName as string,
20-
req.query.sha as string
22+
req.query.sha as string,
23+
workflowId
2124
)
2225
);
2326
}

0 commit comments

Comments
 (0)