Fused Frontend and Bakcend
This commit is contained in:
parent
55e0a21f79
commit
b7f953e93d
11 changed files with 245 additions and 135 deletions
BIN
bin/executor
BIN
bin/executor
Binary file not shown.
|
@ -11,18 +11,18 @@ const buildCommon = (jobRequest) => {
|
||||||
const { isTriage, ignore, region, testNames } = jobRequest;
|
const { isTriage, ignore, region, testNames } = jobRequest;
|
||||||
const command = [baseCommand, suiteEntry];
|
const command = [baseCommand, suiteEntry];
|
||||||
// Apply Common Flags
|
// Apply Common Flags
|
||||||
command.push(`isTriage=${isTriage}`);
|
if (isTriage) command.push(`isTriage=${isTriage}`);
|
||||||
if(ignore && ignore.length > 0) console.log("Would ignore", ignore);
|
if (ignore && ignore.length > 0) console.log("Would ignore", ignore);
|
||||||
if(region)
|
if (region) command.push(`region=${region}`);
|
||||||
command.push(`region=${region}`);
|
|
||||||
|
|
||||||
// Return new request
|
// Return new request
|
||||||
return { ...jobRequest, command };
|
return { ...jobRequest, command };
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildManual = (jobReq) => {
|
const buildManual = (jobReq) => {
|
||||||
const {testNames} = jobReq;
|
const { command, testNames } = jobReq;
|
||||||
if(testNames.length > 1) throw Error("Currently only 1 test can be selected!");
|
if (testNames.length > 1)
|
||||||
|
throw Error("Currently only 1 test can be selected!");
|
||||||
|
|
||||||
command.push(`test=${testNames[0]}`);
|
command.push(`test=${testNames[0]}`);
|
||||||
|
|
||||||
|
@ -30,38 +30,32 @@ const buildManual = (jobReq) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildTags = (jobReq) => {
|
const buildTags = (jobReq) => {
|
||||||
const {command, tags, testNames} = jobReq;
|
const { command, tags, testNames } = jobReq;
|
||||||
if(testNames && testNames.length > 0){
|
if (testNames && testNames.length > 0) {
|
||||||
return console.log("Would run tags as manual");
|
return console.log("Would run tags as manual");
|
||||||
}
|
}
|
||||||
const arg = Buffer.from(JSON.stringify(tags), "utf8").toString(
|
const arg = Buffer.from(JSON.stringify(tags), "utf8").toString("base64");
|
||||||
"base64"
|
|
||||||
);
|
|
||||||
command.push(`tags=${arg}`);
|
command.push(`tags=${arg}`);
|
||||||
return {...jobReq, command};
|
return { ...jobReq, command };
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildPipeline = (jobReq, socketId) => {
|
const buildPipeline = (jobReq, socketId) => {
|
||||||
const { command, pipeline } = jobReq;
|
const { command, pipeline } = jobReq;
|
||||||
const {__test: test} = pipeline;
|
const { __test: test } = pipeline;
|
||||||
if(!test) throw Error("__test is required for pipeline jobs!");
|
if (!test) throw Error("__test is required for pipeline jobs!");
|
||||||
pipeline.dashboardSocketId = socketId;
|
pipeline.dashboardSocketId = socketId;
|
||||||
const arg = Buffer.from(JSON.stringify(pipeline), "utf8").toString(
|
const arg = Buffer.from(JSON.stringify(pipeline), "utf8").toString("base64");
|
||||||
"base64"
|
command.push(`pipeline=${arg}`);
|
||||||
);
|
command.push(`test=${test}`);
|
||||||
command.push(`pipeline=${arg}`);
|
|
||||||
command.push(`test=${test}`);
|
|
||||||
return { ...jobReq, command };
|
return { ...jobReq, command };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function jobBuilder(jobRequest, id) {
|
export default function jobBuilder(jobRequest, id) {
|
||||||
|
console.log(jobRequest);
|
||||||
const jobReq = buildCommon(jobRequest, id);
|
const jobReq = buildCommon(jobRequest, id);
|
||||||
const {pipeline, testNames, tags } = jobReq;
|
const { pipeline, testNames, tags } = jobReq;
|
||||||
if(pipeline)
|
if (pipeline) return buildPipeline(jobReq, id);
|
||||||
return buildPipeline(jobReq, id);
|
else if (tags) return buildTags(jobReq);
|
||||||
else if(tags)
|
else if (testNames) return buildManual(jobReq); //TODO currently does nothing
|
||||||
return buildTags(jobReq);
|
|
||||||
else if(testNames)
|
|
||||||
return buildManual(jobReq); //TODO currently does nothing
|
|
||||||
else throw Error("At least 1 'pipeline or tags or testNames' is required! ");
|
else throw Error("At least 1 'pipeline or tags or testNames' is required! ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,11 @@ export default class Initiator {
|
||||||
delete triggers[testName].__testDelay;
|
delete triggers[testName].__testDelay;
|
||||||
const jobReq = {
|
const jobReq = {
|
||||||
...jobRequest,
|
...jobRequest,
|
||||||
pipeline: {...pipeline, triggers: triggers[testName],__test:testName },
|
pipeline: {
|
||||||
|
...pipeline,
|
||||||
|
triggers: triggers[testName],
|
||||||
|
__test: testName,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
setTimeout(
|
setTimeout(
|
||||||
() =>
|
() =>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"build:react": "vite build",
|
"build:react": "vite build",
|
||||||
"start": "node dist/app.js",
|
"start": "node dist/app.js",
|
||||||
"start:dev": "nodemon dist/app.js",
|
"start:dev": "nodemon dist/app.js",
|
||||||
"start:dev:replit": "npm run start:react:replit & (sleep 10 && npm run start:dev)",
|
"start:dev:replit": "npm run start:react:replit & (sleep 30 && npm run start:dev)",
|
||||||
"start:react": "vite preview",
|
"start:react": "vite preview",
|
||||||
"start:react:replit": "vite --host",
|
"start:react:replit": "vite --host",
|
||||||
"test": "node tests/index.js",
|
"test": "node tests/index.js",
|
||||||
|
|
|
@ -82,17 +82,18 @@ export const JobProvider = ({ children }) => {
|
||||||
isPipeline: true,
|
isPipeline: true,
|
||||||
initiator: i,
|
initiator: i,
|
||||||
pipelineId: jobPipeline.id,
|
pipelineId: jobPipeline.id,
|
||||||
branchId: pipelineReq.pipeline.__test
|
branchId: pipelineReq.pipeline.__test,
|
||||||
};
|
};
|
||||||
const request = {
|
const request = {
|
||||||
image: "node",
|
image: "node",
|
||||||
name: jobId,
|
name: jobId,
|
||||||
pipeline: pipelineReq,
|
...pipelineReq,
|
||||||
};
|
};
|
||||||
|
|
||||||
jobCreate(job);
|
jobCreate(job);
|
||||||
const onLog = (d) => {
|
const onLog = (d) => {
|
||||||
const job = state.jobs.find((j) => j.jobId === jobId);
|
const job = state.jobs.find((j) => j.jobId === jobId);
|
||||||
|
|
||||||
job.log.push(d);
|
job.log.push(d);
|
||||||
job.status = jobStatus.ACTIVE;
|
job.status = jobStatus.ACTIVE;
|
||||||
jobUpdate({ ...job }, jobId);
|
jobUpdate({ ...job }, jobId);
|
||||||
|
@ -104,48 +105,86 @@ export const JobProvider = ({ children }) => {
|
||||||
job.status = c === 0 ? jobStatus.OK : jobStatus.ERROR;
|
job.status = c === 0 ? jobStatus.OK : jobStatus.ERROR;
|
||||||
jobUpdate({ ...job }, jobId);
|
jobUpdate({ ...job }, jobId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPipelineTrigger = (p) => {
|
const onPipelineTrigger = (p) => {
|
||||||
const { triggers } = p;
|
const { triggers } = p;
|
||||||
for (var t in triggers) {
|
for (var t in triggers) {
|
||||||
const delay = triggers[t].__testDelay ?? 0;
|
const delay = triggers[t].__testDelay ?? 0;
|
||||||
delete triggers[t].__testDelay;
|
delete triggers[t].__testDelay;
|
||||||
const jobReq = {
|
const jobReq = {
|
||||||
...request,
|
...request,
|
||||||
pipeline: {
|
pipeline: {
|
||||||
...pipeline,
|
triggers: triggers[t],
|
||||||
triggers: triggers[t],__test:t
|
__test: t,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
jobPipeline.pendingTriggers[t].push(
|
jobPipeline.pendingTriggers.push({
|
||||||
{
|
testName: t,
|
||||||
|
timer: setTimeout(
|
||||||
testName: t,
|
() => pipelineComponentJob(jobPipeline, jobReq),
|
||||||
timer: setTimeout(() => pipelineComponentJob(jobPipeline, jobReq),delay),
|
delay
|
||||||
triggerAt: Date.now() + delay
|
),
|
||||||
});
|
triggerAt: Date.now() + delay,
|
||||||
}
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const started = i.newPipelineJob(
|
const started = i.newPipelineJob(
|
||||||
request,
|
request,
|
||||||
onLog,
|
onLog,
|
||||||
onClose,
|
onClose,
|
||||||
|
null,
|
||||||
onPipelineTrigger
|
onPipelineTrigger
|
||||||
);
|
);
|
||||||
started.then(() => jobUpdate({ status: jobStatus.ACTIVE }, jobId));
|
started.then(() => jobUpdate({ status: jobStatus.ACTIVE }, jobId));
|
||||||
}
|
}
|
||||||
|
|
||||||
function pipelineFactory(builderCache) {
|
function pipelineFactory(builderCache) {
|
||||||
console.log("Would create pipeline with cache");
|
const { tree, branches, selectedBranches } = builderCache;
|
||||||
const { tree, branches } = builderCache;
|
|
||||||
const __test = Object.keys(tree)[0];
|
const __test = Object.keys(tree)[0];
|
||||||
const pipelineReq = {image: "node", pipeline:{__test, triggers: { ...tree[__test] }}}
|
const pipelineReq = {
|
||||||
|
image: "node",
|
||||||
|
pipeline: { __test, triggers: { ...tree[__test] } },
|
||||||
|
};
|
||||||
const id = `pij${Date.now()}`;
|
const id = `pij${Date.now()}`;
|
||||||
const pipeline = {id, branches, pendingTriggers: {} };
|
const pipeline = { id, branches, pendingTriggers: [], selectedBranches };
|
||||||
const {pipelines} = state;
|
const { pipelines } = state;
|
||||||
pipelines.push(pipeline);
|
pipelines.push(pipeline);
|
||||||
updatePipelines([...pipelines]);
|
updatePipelines([...pipelines]);
|
||||||
return pipelineComponentJob(pipeline, pipelineReq);
|
return pipelineComponentJob(pipeline, pipelineReq);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pipelineCancel(pipelineId) {
|
||||||
|
const pipeline = state.pipelines.find((p) => p.id === pipelineId);
|
||||||
|
pipeline.pendingTriggers.forEach((t) => clearTimeout(t));
|
||||||
|
const jobs = state.jobs.filter(
|
||||||
|
(j) => j.isPipeline && j.pipelineId === pipelineId
|
||||||
|
);
|
||||||
|
for (var j of jobs) {
|
||||||
|
if (j.initiator.sk) j.initiator.sk.close();
|
||||||
|
j.status = jobStatus.CANCELED;
|
||||||
|
jobUpdate({ ...j }, j.jobId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pipelineDestroy(pipelineId) {
|
||||||
|
const pipelineIndex = state.pipelines.findIndex((p) => p.id === pipelineId);
|
||||||
|
const pipeline = state.pipelines[pipelineIndex];
|
||||||
|
pipeline.pendingTriggers.forEach((t) => clearTimeout(t));
|
||||||
|
const jobs = state.jobs.filter(
|
||||||
|
(j) => j.isPipeline && j.pipelineId === pipelineId
|
||||||
|
);
|
||||||
|
for (var j of jobs) {
|
||||||
|
if (
|
||||||
|
j.initiator.sk &&
|
||||||
|
j.status !== jobStatus.OK &&
|
||||||
|
j.status !== jobStatus.ERROR &&
|
||||||
|
j.status !== jobStatus.CANCELED
|
||||||
|
) {
|
||||||
|
j.initiator.sk.close();
|
||||||
|
}
|
||||||
|
jobDelete(j.jobId);
|
||||||
|
}
|
||||||
|
state.pipelines.splice(pipelineIndex, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function jobCancel(jobId) {
|
function jobCancel(jobId) {
|
||||||
|
@ -185,11 +224,12 @@ export const JobProvider = ({ children }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const request = {
|
const request = {
|
||||||
testName: builderCache.testNames[0],
|
testNames: builderCache.testNames,
|
||||||
image: "node",
|
image: "node",
|
||||||
type: "single",
|
type: "single",
|
||||||
name: jobId,
|
name: jobId,
|
||||||
};
|
};
|
||||||
|
console.log(request);
|
||||||
|
|
||||||
jobCreate(job);
|
jobCreate(job);
|
||||||
|
|
||||||
|
@ -223,6 +263,8 @@ export const JobProvider = ({ children }) => {
|
||||||
jobFactory,
|
jobFactory,
|
||||||
jobCancel,
|
jobCancel,
|
||||||
jobDestroy,
|
jobDestroy,
|
||||||
|
pipelineCancel,
|
||||||
|
pipelineDestroy,
|
||||||
};
|
};
|
||||||
const contextValue = useMemo(() => context, [state, dispatch]);
|
const contextValue = useMemo(() => context, [state, dispatch]);
|
||||||
|
|
||||||
|
|
|
@ -1,62 +1,114 @@
|
||||||
import React, { useContext } from "react";
|
import React, { useContext } from "react";
|
||||||
import {useNavigate} from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import JobContext from "../../ctx/JobContext.jsx";
|
import JobContext from "../../ctx/JobContext.jsx";
|
||||||
import Button from "@mui/material/Button";
|
|
||||||
import DialogActions from "@mui/material/DialogActions";
|
import Box from "@mui/material/Box";
|
||||||
import DialogContent from "@mui/material/DialogContent";
|
import AppBar from "@mui/material/AppBar";
|
||||||
|
import Toolbar from "@mui/material/Toolbar";
|
||||||
|
import IconButton from "@mui/material/IconButton";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
import Accordion from "@mui/material/Accordion";
|
import Accordion from "@mui/material/Accordion";
|
||||||
import AccordionSummary from "@mui/material/AccordionSummary";
|
import AccordionSummary from "@mui/material/AccordionSummary";
|
||||||
import Box from "@mui/material/Box";
|
|
||||||
import Typography from "@mui/material/Typography";
|
|
||||||
import Stack from "@mui/material/Stack";
|
import Stack from "@mui/material/Stack";
|
||||||
|
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||||
|
|
||||||
function JobPipelineDisplay(props) {
|
function JobPipelineDisplay(props) {
|
||||||
const { back, pipeline } = props;
|
const { back, pipeline } = props;
|
||||||
const {state: jobState} = useContext(JobContext);
|
const {
|
||||||
|
state: jobState,
|
||||||
|
pipelineCancel,
|
||||||
|
pipelineDestroy,
|
||||||
|
} = useContext(JobContext);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const pipelineJobs = jobState.jobs.filter((j)=>j.isPipeline && j.pipelineId === pipeline.id);
|
const pipelineJobs = jobState.jobs.filter(
|
||||||
|
(j) => j.isPipeline && j.pipelineId === pipeline.id
|
||||||
|
);
|
||||||
|
const selectedBranches = () => {
|
||||||
|
return pipeline.branches.map((b) => {
|
||||||
|
return b.filter((t) => pipeline.selectedBranches.includes(t));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const selectJob = (testName) => () =>{
|
const selectJob = (testName) => () => {
|
||||||
const job = pipelineJobs.find((j)=>j.branchId === testName);
|
const job = pipelineJobs.find((j) => j.branchId === testName);
|
||||||
if(!job) return; navigate(`/qualiteer/jobs#${job.jobId}`);
|
if (!job) return;
|
||||||
|
navigate(`/qualiteer/jobs#${job.jobId}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
function navigateToJobs() {
|
||||||
|
navigate(`/qualiteer/jobs`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelPipeline() {
|
||||||
|
pipelineCancel(pipeline.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deletePipeline() {
|
||||||
|
pipelineDestroy(pipeline.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<Box>
|
||||||
<h3>{}</h3>
|
<AppBar
|
||||||
{pipeline.branches.map((track, i) => (
|
position="fixed"
|
||||||
<React.Fragment key={i}>
|
sx={{
|
||||||
<Typography variant="h6">{i + 1}</Typography>
|
backgroundColor: "white",
|
||||||
<Box>
|
boxShadow: "none",
|
||||||
{track.map((test, j) => (
|
color: "black",
|
||||||
<Accordion
|
}}
|
||||||
expanded={false}
|
>
|
||||||
disableGutters={true}
|
<Toolbar disableGutters />
|
||||||
square
|
<Box sx={{ flexGrow: 1, margin: "0 10px" }}>
|
||||||
key={j}
|
<Toolbar disableGutters>
|
||||||
onClick={selectJob(test)}
|
<IconButton onClick={navigateToJobs}>
|
||||||
|
<ArrowBackIcon />
|
||||||
|
</IconButton>
|
||||||
|
<Typography variant="h6" sx={{ ml: "auto", mr: "auto" }}>
|
||||||
|
{pipeline.id}
|
||||||
|
</Typography>
|
||||||
|
<IconButton onClick={cancelPipeline}>
|
||||||
|
<ArrowBackIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton onClick={deletePipeline}>
|
||||||
|
<ArrowBackIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Toolbar>
|
||||||
|
</Box>
|
||||||
|
</AppBar>
|
||||||
|
<Toolbar disableGutters />
|
||||||
|
{selectedBranches().map((track, i) => (
|
||||||
|
<React.Fragment key={i}>
|
||||||
|
<Typography variant="h6">{i + 1}</Typography>
|
||||||
|
<Box>
|
||||||
|
{track.map((test, j) => (
|
||||||
|
<Accordion
|
||||||
|
expanded={false}
|
||||||
|
disableGutters={true}
|
||||||
|
square
|
||||||
|
key={j}
|
||||||
|
onClick={selectJob(test)}
|
||||||
|
>
|
||||||
|
<AccordionSummary
|
||||||
|
style={{
|
||||||
|
backgroundColor: "rgba(0, 0, 0, .03)",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<AccordionSummary
|
<Typography
|
||||||
style={{
|
component={"span"}
|
||||||
backgroundColor: "rgba(0, 0, 0, .03)",
|
style={{ wordBreak: "break-word", margin: "auto 0" }}
|
||||||
flexWrap: "wrap",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Typography
|
{test}
|
||||||
component={"span"}
|
</Typography>
|
||||||
style={{ wordBreak: "break-word", margin: "auto 0" }}
|
<Stack sx={{ ml: "auto" }}>I</Stack>
|
||||||
>
|
</AccordionSummary>
|
||||||
{test}
|
</Accordion>
|
||||||
</Typography>
|
))}
|
||||||
<Stack sx={{ ml: "auto" }}>I</Stack>
|
</Box>
|
||||||
</AccordionSummary>
|
</React.Fragment>
|
||||||
</Accordion>
|
))}
|
||||||
))}
|
</Box>
|
||||||
</Box>
|
|
||||||
</React.Fragment>
|
|
||||||
))}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,10 +72,8 @@ export default function JobView(props) {
|
||||||
cb();
|
cb();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function navigateToJobs() {
|
function navigateToJobs() {
|
||||||
if(job.isPipeline) return navigate(`/qualiteer/jobs#p${job.pipelineId}`)
|
if (job.isPipeline) return navigate(`/qualiteer/jobs#p${job.pipelineId}`);
|
||||||
navigate("/qualiteer/jobs");
|
navigate("/qualiteer/jobs");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,11 @@ export default function Jobs() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const jobName = location.hash.slice(1);
|
const jobName = location.hash.slice(1);
|
||||||
const pipelineId = jobName.slice(1);
|
const pipelineId = jobName.slice(1);
|
||||||
if(!jobName || !pipelineId) return;
|
if (!jobName || !pipelineId) return;
|
||||||
const hasJob = jobState.pipelines.find((p)=>p.id ===pipelineId);
|
const hasJob = jobState.pipelines.find((p) => p.id === pipelineId);
|
||||||
const hasPipeline = jobState.jobs.find((job) => job.name === jobName);
|
const hasPipeline = jobState.jobs.find((job) => job.name === jobName);
|
||||||
if(hasPipeline || hasJob) return;
|
if (hasPipeline || hasJob) return;
|
||||||
if(jobName || pipelineId) navigate("/qualiteer/jobs");
|
if (jobName || pipelineId) navigate("/qualiteer/jobs");
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -51,29 +51,46 @@ export default function Jobs() {
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
) : null}
|
) : null}
|
||||||
<JobBuilder />
|
<JobBuilder />
|
||||||
{location.hash === "" &&(
|
{location.hash === "" && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{jobState.jobs
|
{jobState.jobs
|
||||||
.filter((j) => !j.isPipeline)
|
.filter((j) => !j.isPipeline)
|
||||||
.map((v, i) => (
|
.map((v, i) => (
|
||||||
|
<a
|
||||||
|
key={i}
|
||||||
|
href={`/qualiteer/jobs#${v.name}`}
|
||||||
|
style={{ textDecoration: "none" }}
|
||||||
|
>
|
||||||
|
<JobBox job={v} />
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
{jobState.pipelines.map((p, i) => (
|
||||||
<a
|
<a
|
||||||
key={i}
|
key={i}
|
||||||
href={`/qualiteer/jobs#${v.name}`}
|
|
||||||
style={{ textDecoration: "none" }}
|
style={{ textDecoration: "none" }}
|
||||||
|
href={`/qualiteer/jobs#p${p.id}`}
|
||||||
>
|
>
|
||||||
<JobBox job={v} />
|
<JobPipelineBox pipeline={p} />
|
||||||
</a>))}
|
</a>
|
||||||
{jobState.pipelines.map((p,i)=><a key={i} style={{textDecoration: "none"}} href={`/qualiteer/jobs#p${p.id}`}>
|
))}
|
||||||
<JobPipelineBox pipeline={p}/>
|
</React.Fragment>
|
||||||
</a>)}
|
|
||||||
</React.Fragment>)
|
|
||||||
}
|
|
||||||
|
|
||||||
{ location.hash[1] === "p"? jobState.pipelines.find((p)=>p.id===location.hash.slice(2)) && (<JobPipelineDisplay pipeline={jobState.pipelines.find((p)=>p.id===location.hash.slice(2))}/>) :
|
|
||||||
jobState.jobs.find((job) => job.name === location.hash.slice(1)) && (<JobView
|
|
||||||
job={jobState.jobs.find((job) => job.name === location.hash.slice(1))}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{location.hash[1] === "p"
|
||||||
|
? jobState.pipelines.find((p) => p.id === location.hash.slice(2)) && (
|
||||||
|
<JobPipelineDisplay
|
||||||
|
pipeline={jobState.pipelines.find(
|
||||||
|
(p) => p.id === location.hash.slice(2)
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: jobState.jobs.find((job) => job.name === location.hash.slice(1)) && (
|
||||||
|
<JobView
|
||||||
|
job={jobState.jobs.find(
|
||||||
|
(job) => job.name === location.hash.slice(1)
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ function PipelineTrackSelector(props) {
|
||||||
...cache,
|
...cache,
|
||||||
branches: asBranches(primaries),
|
branches: asBranches(primaries),
|
||||||
tree: asTree(cache.tracks),
|
tree: asTree(cache.tracks),
|
||||||
|
selectedBranches: as1d(cache.tracks),
|
||||||
});
|
});
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,7 +57,7 @@ const runTests = () => {
|
||||||
liveIndicator();
|
liveIndicator();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const status = runTests();
|
const status = runTests();
|
||||||
pipeline.testData = status.pipelineData;
|
if (pipeline) pipeline.testData = status.pipelineData;
|
||||||
const testResult = {
|
const testResult = {
|
||||||
...status,
|
...status,
|
||||||
name: test,
|
name: test,
|
||||||
|
|
|
@ -19,12 +19,14 @@ const job = {
|
||||||
__testDelay: 1000,
|
__testDelay: 1000,
|
||||||
tertiary1: {},
|
tertiary1: {},
|
||||||
tertiary2: {
|
tertiary2: {
|
||||||
__testDelay: 8000 },
|
__testDelay: 8000,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
secondary2: {
|
secondary2: {
|
||||||
__testDelay: 20000,
|
__testDelay: 20000,
|
||||||
tertiary3: {
|
tertiary3: {
|
||||||
__testDelay: 3000 },
|
__testDelay: 3000,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue