Linked pipeline autoselect
This commit is contained in:
parent
90d9bc3fcc
commit
f17c7e01f5
9 changed files with 312 additions and 40 deletions
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
- [x] Initial Skeleton
|
- [x] Initial Skeleton
|
||||||
- [x] Frontend Drafts
|
- [x] Frontend Drafts
|
||||||
- [ ] Frontend Core
|
- [x] Frontend Core
|
||||||
- [ ] Frontend Pages
|
- [ ] Frontend Pages
|
||||||
|
|
||||||
## v0.0.2
|
## v0.0.2
|
||||||
|
|
|
@ -17,7 +17,7 @@ const testsMock = () => {
|
||||||
name: "single",
|
name: "single",
|
||||||
class: "single.js",
|
class: "single.js",
|
||||||
image: "node:latest",
|
image: "node:latest",
|
||||||
isCompound: false,
|
isPipeline: false,
|
||||||
type: "api",
|
type: "api",
|
||||||
description: "This is a single test",
|
description: "This is a single test",
|
||||||
tags: ["cron_1hour", "reg_us", "env_ci", "proj_core", "skip_alt"],
|
tags: ["cron_1hour", "reg_us", "env_ci", "proj_core", "skip_alt"],
|
||||||
|
@ -30,7 +30,7 @@ const testsMock = () => {
|
||||||
name: "failing",
|
name: "failing",
|
||||||
class: "failing.js",
|
class: "failing.js",
|
||||||
image: "node:latest",
|
image: "node:latest",
|
||||||
isCompound: false,
|
isPipeline: false,
|
||||||
type: "ui",
|
type: "ui",
|
||||||
description: "This is a failing test",
|
description: "This is a failing test",
|
||||||
tags: ["cron_1hour", "reg_us", "env_ci", "proj_core"],
|
tags: ["cron_1hour", "reg_us", "env_ci", "proj_core"],
|
||||||
|
@ -43,7 +43,7 @@ const testsMock = () => {
|
||||||
name: "primary",
|
name: "primary",
|
||||||
class: "primary.js",
|
class: "primary.js",
|
||||||
image: "node:latest",
|
image: "node:latest",
|
||||||
isCompound: true,
|
isPipeline: true,
|
||||||
type: "api",
|
type: "api",
|
||||||
description: "This is a primary test",
|
description: "This is a primary test",
|
||||||
tags: [
|
tags: [
|
||||||
|
@ -51,7 +51,7 @@ const testsMock = () => {
|
||||||
"reg_us",
|
"reg_us",
|
||||||
"proj_core",
|
"proj_core",
|
||||||
"skip_alt",
|
"skip_alt",
|
||||||
"compound_secondary",
|
"pipeline_secondary1",
|
||||||
],
|
],
|
||||||
path: "tests/assets/suite/primary.js",
|
path: "tests/assets/suite/primary.js",
|
||||||
created: Date.now(),
|
created: Date.now(),
|
||||||
|
@ -59,27 +59,72 @@ const testsMock = () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: "secondary",
|
name: "secondary1",
|
||||||
class: "secondary.js",
|
class: "secondary1.js",
|
||||||
image: "node:latest",
|
image: "node:latest",
|
||||||
isCompound: true,
|
isPipeline: true,
|
||||||
type: "api",
|
type: "api",
|
||||||
description: "This is a secondary test",
|
description: "This is a secondary test",
|
||||||
tags: ["cron_1hour", "reg_us", "proj_core", "compound_tertiary"],
|
tags: [
|
||||||
path: "tests/assets/suite/secondary.js",
|
"cron_1hour",
|
||||||
|
"reg_us",
|
||||||
|
"proj_core",
|
||||||
|
"compound_tertiary1",
|
||||||
|
"compound_tertiary2",
|
||||||
|
],
|
||||||
|
path: "tests/assets/suite/secondary1.js",
|
||||||
created: Date.now(),
|
created: Date.now(),
|
||||||
mergeRequest: "https://example.com",
|
mergeRequest: "https://example.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
name: "tertiary",
|
name: "secondary2",
|
||||||
class: "tertiary.js",
|
class: "secondary2.js",
|
||||||
image: "node:latest",
|
image: "node:latest",
|
||||||
isCompound: true,
|
isPipeline: true,
|
||||||
type: "api",
|
type: "api",
|
||||||
description: "This is a single test",
|
description: "This is a secondary2 test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "proj_core", "compound_tertiary3"],
|
||||||
|
path: "tests/assets/suite/secondary2.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "tertiary1",
|
||||||
|
class: "tertiary1.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a third test",
|
||||||
tags: ["cron_1hour", "reg_us", "proj_core"],
|
tags: ["cron_1hour", "reg_us", "proj_core"],
|
||||||
path: "tests/assets/suite/tertiary.js",
|
path: "tests/assets/suite/tertiary1.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "tertiary2",
|
||||||
|
class: "tertiary2.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a third2 test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "proj_core"],
|
||||||
|
path: "tests/assets/suite/tertiary2.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "tertiary3",
|
||||||
|
class: "tertiary3.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a third3 test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "proj_core"],
|
||||||
|
path: "tests/assets/suite/tertiary3.js",
|
||||||
created: Date.now(),
|
created: Date.now(),
|
||||||
mergeRequest: "https://example.com",
|
mergeRequest: "https://example.com",
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,12 +22,12 @@ const failingMock = () => {
|
||||||
dailyFails: 12,
|
dailyFails: 12,
|
||||||
screenshot: "https://picsum.photos/1920/1080",
|
screenshot: "https://picsum.photos/1920/1080",
|
||||||
recentResults: [1, 0, 0, 1, 0],
|
recentResults: [1, 0, 0, 1, 0],
|
||||||
isCompound: false,
|
isPipeline: false,
|
||||||
failedMessage: `Some Test FailureMessage`,
|
failedMessage: `Some Test FailureMessage`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "secondary",
|
name: "secondary1",
|
||||||
class: "secondary.js",
|
class: "secondary1.js",
|
||||||
timestamp: new Date().toJSON(),
|
timestamp: new Date().toJSON(),
|
||||||
method: "FAKEMETHOD",
|
method: "FAKEMETHOD",
|
||||||
cron: "1hour",
|
cron: "1hour",
|
||||||
|
@ -35,8 +35,8 @@ const failingMock = () => {
|
||||||
dailyFails: 1,
|
dailyFails: 1,
|
||||||
screenshot: "https://picsum.photos/1920/1080",
|
screenshot: "https://picsum.photos/1920/1080",
|
||||||
recentResults: [1, 0, 0, 1, 0],
|
recentResults: [1, 0, 0, 1, 0],
|
||||||
isCompound: true,
|
isPipeline: true,
|
||||||
failedMessage: `Some Test FailureMessage from Secondary`,
|
failedMessage: `Some Test FailureMessage from Secondary1`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
164
src/Queries.jsx
164
src/Queries.jsx
|
@ -10,7 +10,126 @@ const fetchApi = (subPath) => async () =>
|
||||||
fetch(`${QUALITEER_URL}${subPath}`).then((res) => res.json());
|
fetch(`${QUALITEER_URL}${subPath}`).then((res) => res.json());
|
||||||
|
|
||||||
export const useCatalogTests = () =>
|
export const useCatalogTests = () =>
|
||||||
useMock ? asMock([]) : useQuery(["catalogTests"], fetchApi("/catalog/tests"));
|
useMock
|
||||||
|
? asMock([
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: "single",
|
||||||
|
class: "single.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: false,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a single test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "env_ci", "proj_core", "skip_alt"],
|
||||||
|
path: "tests/assets/suite/single.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "failing",
|
||||||
|
class: "failing.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: false,
|
||||||
|
type: "ui",
|
||||||
|
description: "This is a failing test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "env_ci", "proj_core"],
|
||||||
|
path: "tests/assets/suite/failing.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "primary",
|
||||||
|
class: "primary.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a primary test",
|
||||||
|
tags: [
|
||||||
|
"cron_1hour",
|
||||||
|
"reg_us",
|
||||||
|
"proj_core",
|
||||||
|
"skip_alt",
|
||||||
|
"pipeline_secondary1",
|
||||||
|
],
|
||||||
|
path: "tests/assets/suite/primary.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "secondary1",
|
||||||
|
class: "secondary1.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a secondary test",
|
||||||
|
tags: [
|
||||||
|
"cron_1hour",
|
||||||
|
"reg_us",
|
||||||
|
"proj_core",
|
||||||
|
"compound_tertiary1",
|
||||||
|
"compound_tertiary2",
|
||||||
|
],
|
||||||
|
path: "tests/assets/suite/secondary1.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "secondary2",
|
||||||
|
class: "secondary2.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a secondary2 test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "proj_core", "compound_tertiary3"],
|
||||||
|
path: "tests/assets/suite/secondary2.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "tertiary1",
|
||||||
|
class: "tertiary1.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a third test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "proj_core"],
|
||||||
|
path: "tests/assets/suite/tertiary1.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "tertiary2",
|
||||||
|
class: "tertiary2.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a third2 test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "proj_core"],
|
||||||
|
path: "tests/assets/suite/tertiary2.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "tertiary3",
|
||||||
|
class: "tertiary3.js",
|
||||||
|
image: "node:latest",
|
||||||
|
isPipeline: true,
|
||||||
|
type: "api",
|
||||||
|
description: "This is a third3 test",
|
||||||
|
tags: ["cron_1hour", "reg_us", "proj_core"],
|
||||||
|
path: "tests/assets/suite/tertiary3.js",
|
||||||
|
created: Date.now(),
|
||||||
|
mergeRequest: "https://example.com",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
: useQuery(["catalogTests"], fetchApi("/catalog/tests"));
|
||||||
|
|
||||||
export const usePipelineMappings = () =>
|
export const usePipelineMappings = () =>
|
||||||
useMock
|
useMock
|
||||||
|
@ -22,7 +141,46 @@ export const usePipelineMappings = () =>
|
||||||
: useQuery(["pipelineMappings"], fetchApi("/catalog/pipeline-mappings"));
|
: useQuery(["pipelineMappings"], fetchApi("/catalog/pipeline-mappings"));
|
||||||
|
|
||||||
export const useSilencedAlerts = () =>
|
export const useSilencedAlerts = () =>
|
||||||
useMock ? asMock([]) : useQuery(["silenced"], fetchApi("/alerting/silenced"));
|
useMock
|
||||||
|
? asMock([
|
||||||
|
{
|
||||||
|
name: `failing`,
|
||||||
|
class: `failing.js`,
|
||||||
|
method: "FAKEMETHOD",
|
||||||
|
id: 0,
|
||||||
|
silencedUntil: new Date().toJSON(),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
: useQuery(["silenced"], fetchApi("/alerting/silenced"));
|
||||||
|
|
||||||
export const useCurrentlyFailing = () =>
|
export const useCurrentlyFailing = () =>
|
||||||
useMock ? asMock([]) : useQuery(["failing"], fetchApi("/results/failing"));
|
useMock
|
||||||
|
? asMock([
|
||||||
|
{
|
||||||
|
name: "failing",
|
||||||
|
class: "failing.js",
|
||||||
|
timestamp: new Date().toJSON(),
|
||||||
|
method: "FAKEMETHOD",
|
||||||
|
cron: "1hour",
|
||||||
|
type: "api",
|
||||||
|
dailyFails: 12,
|
||||||
|
screenshot: "https://picsum.photos/1920/1080",
|
||||||
|
recentResults: [1, 0, 0, 1, 0],
|
||||||
|
isPipeline: false,
|
||||||
|
failedMessage: `Some Test FailureMessage`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "secondary1",
|
||||||
|
class: "secondary1.js",
|
||||||
|
timestamp: new Date().toJSON(),
|
||||||
|
method: "FAKEMETHOD",
|
||||||
|
cron: "1hour",
|
||||||
|
type: "api",
|
||||||
|
dailyFails: 1,
|
||||||
|
screenshot: "https://picsum.photos/1920/1080",
|
||||||
|
recentResults: [1, 0, 0, 1, 0],
|
||||||
|
isPipeline: true,
|
||||||
|
failedMessage: `Some Test FailureMessage from Secondary1`,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
: useQuery(["failing"], fetchApi("/results/failing"));
|
||||||
|
|
|
@ -151,11 +151,13 @@ export const JobProvider = ({ children }) => {
|
||||||
const { pipelines } = state;
|
const { pipelines } = state;
|
||||||
pipelines.push(pipeline);
|
pipelines.push(pipeline);
|
||||||
updatePipelines([...pipelines]);
|
updatePipelines([...pipelines]);
|
||||||
return pipelineComponentJob(pipeline, pipelineReq);
|
pipelineComponentJob(pipeline, pipelineReq);
|
||||||
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pipelineCancel(pipelineId) {
|
function pipelineCancel(pipelineId) {
|
||||||
const pipeline = state.pipelines.find((p) => p.id === pipelineId);
|
const pipeline = state.pipelines.find((p) => p.id === pipelineId);
|
||||||
|
pipeline.isCanceled = true;
|
||||||
pipeline.pendingTriggers.forEach((t) => clearTimeout(t));
|
pipeline.pendingTriggers.forEach((t) => clearTimeout(t));
|
||||||
const jobs = state.jobs.filter(
|
const jobs = state.jobs.filter(
|
||||||
(j) => j.isPipeline && j.pipelineId === pipelineId
|
(j) => j.isPipeline && j.pipelineId === pipelineId
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState, useContext } from "react";
|
import React, { useState, useContext } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { usePipelineMappings } from "../../Queries.jsx";
|
||||||
import StoreContext from "../../ctx/StoreContext.jsx";
|
import StoreContext from "../../ctx/StoreContext.jsx";
|
||||||
import JobContext from "../../ctx/JobContext.jsx";
|
import JobContext from "../../ctx/JobContext.jsx";
|
||||||
|
|
||||||
|
@ -13,6 +14,12 @@ import PlayArrowIcon from "@mui/icons-material/PlayArrow";
|
||||||
|
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Stack from "@mui/material/Stack";
|
import Stack from "@mui/material/Stack";
|
||||||
|
import {
|
||||||
|
selectBranch,
|
||||||
|
asTree,
|
||||||
|
asBranches,
|
||||||
|
as1d,
|
||||||
|
} from "../../../lib/jobs/pipelines.js";
|
||||||
|
|
||||||
export default function CatalogBox(props) {
|
export default function CatalogBox(props) {
|
||||||
const { catalogTest } = props;
|
const { catalogTest } = props;
|
||||||
|
@ -21,12 +28,12 @@ export default function CatalogBox(props) {
|
||||||
name: testName,
|
name: testName,
|
||||||
class: testClass,
|
class: testClass,
|
||||||
repo: testRepo,
|
repo: testRepo,
|
||||||
isCompound,
|
isPipeline,
|
||||||
type: testType,
|
type: testType,
|
||||||
} = catalogTest;
|
} = catalogTest;
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { data: pipelineMappings, isLoading } = usePipelineMappings();
|
||||||
const { state: store, updateStore } = useContext(StoreContext);
|
const { state: store, updateStore } = useContext(StoreContext);
|
||||||
|
|
||||||
const { state: jobState, jobFactory } = useContext(JobContext);
|
const { state: jobState, jobFactory } = useContext(JobContext);
|
||||||
|
@ -38,10 +45,24 @@ export default function CatalogBox(props) {
|
||||||
const runTest = (e) => {
|
const runTest = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
console.log(catalogTest);
|
||||||
|
if (isPipeline) return runPipelineTest();
|
||||||
const jobId = jobFactory({ testNames: [testName] });
|
const jobId = jobFactory({ testNames: [testName] });
|
||||||
if (store.focusJob) navigate(`/qualiteer/jobs#${jobId}`);
|
if (store.focusJob) navigate(`/qualiteer/jobs#${jobId}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const runPipelineTest = () => {
|
||||||
|
const primaries = pipelineMappings.filter((m) => m.includes(testName));
|
||||||
|
const builderCache = {
|
||||||
|
branches: asBranches(primaries),
|
||||||
|
tree: asTree(primaries),
|
||||||
|
selectedBranches: as1d(primaries),
|
||||||
|
isTriage: true,
|
||||||
|
};
|
||||||
|
const pipeline = jobFactory(builderCache);
|
||||||
|
if (store.focusJob) navigate(`/qualiteer/jobs#p${pipeline.id}`);
|
||||||
|
};
|
||||||
|
|
||||||
function Actions() {
|
function Actions() {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
|
|
@ -59,16 +59,30 @@ export default function Failing() {
|
||||||
const failingTestsWithJobs = () => {
|
const failingTestsWithJobs = () => {
|
||||||
const silences = silencedAlerts ?? [];
|
const silences = silencedAlerts ?? [];
|
||||||
for (var test of failing) {
|
for (var test of failing) {
|
||||||
if (test.isCompound) continue;
|
|
||||||
const job = jobState.jobs.find((j) =>
|
|
||||||
j.builderCache.testNames.includes(test.name)
|
|
||||||
);
|
|
||||||
if (job) test.job = job;
|
|
||||||
const silence = silences.find(
|
const silence = silences.find(
|
||||||
(s) => s.name === test.name || s.class === test.class
|
(s) => s.name === test.name || s.class === test.class
|
||||||
);
|
);
|
||||||
|
|
||||||
if (silence) test.silencedUntil = silence;
|
if (silence) test.silencedUntil = silence;
|
||||||
|
if (test.isPipeline) {
|
||||||
|
const pipeline = jobState.pipelines.find((p) =>
|
||||||
|
p.selectedBranches.includes(test.name)
|
||||||
|
);
|
||||||
|
if (!pipeline) continue;
|
||||||
|
const pipelineJob = jobState.jobs.find(
|
||||||
|
(j) =>
|
||||||
|
j.isPipeline &&
|
||||||
|
j.pipelineId === pipeline.id &&
|
||||||
|
j.branchId === test.name
|
||||||
|
);
|
||||||
|
if (!pipelineJob) test.pipeline = pipeline;
|
||||||
|
test.job = pipelineJob;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const job = jobState.jobs.find(
|
||||||
|
(j) => !j.isPipeline && j.builderCache.testNames.includes(test.name)
|
||||||
|
);
|
||||||
|
if (job) test.job = job;
|
||||||
}
|
}
|
||||||
return failing;
|
return failing;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState, useContext } from "react";
|
import React, { useState, useContext } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { usePipelineMappings } from "../../Queries.jsx";
|
||||||
import StoreContext from "../../ctx/StoreContext.jsx";
|
import StoreContext from "../../ctx/StoreContext.jsx";
|
||||||
import JobContext, { jobStatus } from "../../ctx/JobContext.jsx";
|
import JobContext, { jobStatus } from "../../ctx/JobContext.jsx";
|
||||||
|
|
||||||
|
@ -32,6 +33,13 @@ import Badge from "@mui/material/Badge";
|
||||||
import Stack from "@mui/material/Stack";
|
import Stack from "@mui/material/Stack";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
|
import {
|
||||||
|
selectBranch,
|
||||||
|
asTree,
|
||||||
|
asBranches,
|
||||||
|
as1d,
|
||||||
|
} from "../../../lib/jobs/pipelines.js";
|
||||||
|
|
||||||
const stopPropagation = (e) => e.stopPropagation() && e.preventDefault();
|
const stopPropagation = (e) => e.stopPropagation() && e.preventDefault();
|
||||||
|
|
||||||
export default function FailingBox(props) {
|
export default function FailingBox(props) {
|
||||||
|
@ -46,14 +54,15 @@ export default function FailingBox(props) {
|
||||||
screenshot: screenshotUrl,
|
screenshot: screenshotUrl,
|
||||||
recentResults,
|
recentResults,
|
||||||
failedMessage,
|
failedMessage,
|
||||||
isCompound,
|
isPipeline,
|
||||||
jobStatus: testJobStatus,
|
jobStatus: testJobStatus,
|
||||||
job,
|
job,
|
||||||
|
pipeline,
|
||||||
} = failingTest;
|
} = failingTest;
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { data: pipelineMappings, isLoading } = usePipelineMappings();
|
||||||
const { state: jobState, jobFactory } = useContext(JobContext);
|
const { jobFactory } = useContext(JobContext);
|
||||||
|
|
||||||
const { state: store, updateStore, removeFailure } = useContext(StoreContext);
|
const { state: store, updateStore, removeFailure } = useContext(StoreContext);
|
||||||
|
|
||||||
|
@ -77,32 +86,54 @@ export default function FailingBox(props) {
|
||||||
return "error";
|
return "error";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const retryPipelineTest = () => {
|
||||||
|
const primaries = pipelineMappings.filter((m) => m.includes(testName));
|
||||||
|
const builderCache = {
|
||||||
|
branches: asBranches(primaries),
|
||||||
|
tree: asTree(primaries),
|
||||||
|
selectedBranches: as1d(primaries),
|
||||||
|
isTriage: true,
|
||||||
|
};
|
||||||
|
const pipeline = jobFactory(builderCache);
|
||||||
|
if (store.focusJob) navigate(`/qualiteer/jobs#p${pipeline.id}`);
|
||||||
|
};
|
||||||
|
|
||||||
const retryTest = () => {
|
const retryTest = () => {
|
||||||
|
if (isPipeline) return retryPipelineTest();
|
||||||
const jobId = jobFactory({ testNames: [testName], isTriage: true });
|
const jobId = jobFactory({ testNames: [testName], isTriage: true });
|
||||||
if (store.focusJob) navigate(`/qualiteer/jobs#${jobId}`);
|
if (store.focusJob) navigate(`/qualiteer/jobs#${jobId}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const navigateToJob = () => {
|
||||||
|
if (pipeline) return navigate(`/qualiteer/jobs#p${pipeline.id}`);
|
||||||
|
navigate(`/qualiteer/jobs#${job.jobId}`);
|
||||||
|
};
|
||||||
|
|
||||||
const jobOnClick = () => {
|
const jobOnClick = () => {
|
||||||
|
if (pipeline) return navigateToJob;
|
||||||
if (!job) return retryTest;
|
if (!job) return retryTest;
|
||||||
switch (job.status) {
|
switch (job.status) {
|
||||||
case jobStatus.OK:
|
case jobStatus.OK:
|
||||||
return null;
|
return navigateToJob;
|
||||||
case jobStatus.ERROR:
|
case jobStatus.ERROR:
|
||||||
return retryTest;
|
return retryTest;
|
||||||
case jobStatus.PENDING:
|
case jobStatus.PENDING:
|
||||||
return null;
|
return navigateToJob;
|
||||||
case jobStatus.ACTIVE:
|
case jobStatus.ACTIVE:
|
||||||
return null;
|
return navigateToJob;
|
||||||
case jobStatus.CANCELED:
|
case jobStatus.CANCELED:
|
||||||
return retryTest;
|
return navigateToJob;
|
||||||
case jobStatus.QUEUED:
|
case jobStatus.QUEUED:
|
||||||
return null;
|
return navigateToJob;
|
||||||
default:
|
default:
|
||||||
return retryTest;
|
return retryTest;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function jobIcon() {
|
function jobIcon() {
|
||||||
|
if (pipeline && pipeline.isCanceled)
|
||||||
|
return <DoNotDisturbIcon color="warning" />;
|
||||||
|
if (pipeline) return <ViewColumnIcon color="secondary" />;
|
||||||
if (!job) return <ReplayIcon />;
|
if (!job) return <ReplayIcon />;
|
||||||
switch (job.status) {
|
switch (job.status) {
|
||||||
case jobStatus.OK:
|
case jobStatus.OK:
|
||||||
|
@ -221,7 +252,7 @@ export default function FailingBox(props) {
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
{isCompound && <ViewColumnIcon />}
|
{isPipeline && <ViewColumnIcon />}
|
||||||
</div>
|
</div>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@ function JobPipelineDisplay(props) {
|
||||||
function jobIcon(name) {
|
function jobIcon(name) {
|
||||||
const job = findJob(name);
|
const job = findJob(name);
|
||||||
const status = job ? job.status : null;
|
const status = job ? job.status : null;
|
||||||
|
if (pipeline.isCanceled) return <DoNotDisturbIcon color="warning" />;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case jobStatus.OK:
|
case jobStatus.OK:
|
||||||
return <CheckIcon color="success" />;
|
return <CheckIcon color="success" />;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue