Commit 0f5bee97 authored by Sarah Groff Hennigh-Palermo's avatar Sarah Groff Hennigh-Palermo Committed by Scott Hampton

Fix tests and support parallel jobs in CI viz

- Update tests to pass with the new supprot for parallel jobs
- Update CI viz to trace lines and highlight needs properly
parent 4e249f7e
#import "~/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql" #import "~/pipelines/graphql/fragments/pipeline_stages_connection.fragment.graphql"
query getCiConfigData($projectPath: ID!, $content: String!) { query getCiConfigData($projectPath: ID!, $content: String!) {
ciConfig(projectPath: $projectPath, content: $content) { ciConfig(projectPath: $projectPath, content: $content) {
......
...@@ -105,9 +105,7 @@ export default { ...@@ -105,9 +105,7 @@ export default {
highlightedJobs() { highlightedJobs() {
// If you are hovering on a job, then the jobs we want to highlight are: // If you are hovering on a job, then the jobs we want to highlight are:
// The job you are currently hovering + all of its needs. // The job you are currently hovering + all of its needs.
return this.hasHighlightedJob return [this.highlightedJob, ...this.needsObject[this.highlightedJob]];
? [this.highlightedJob, ...this.needsObject[this.highlightedJob]]
: [];
}, },
highlightedLinks() { highlightedLinks() {
// If you are hovering on a job, then the links we want to highlight are: // If you are hovering on a job, then the links we want to highlight are:
......
...@@ -4,6 +4,7 @@ fragment PipelineStagesConnection on CiConfigStageConnection { ...@@ -4,6 +4,7 @@ fragment PipelineStagesConnection on CiConfigStageConnection {
groups { groups {
nodes { nodes {
name name
size
jobs { jobs {
nodes { nodes {
name name
......
import { pickBy } from 'lodash'; import { pickBy } from 'lodash';
import { SUPPORTED_FILTER_PARAMETERS } from './constants'; import { SUPPORTED_FILTER_PARAMETERS } from './constants';
import { createNodeDict } from './components/parsing_utils';
export const validateParams = (params) => { export const validateParams = (params) => {
return pickBy(params, (val, key) => SUPPORTED_FILTER_PARAMETERS.includes(key) && val); return pickBy(params, (val, key) => SUPPORTED_FILTER_PARAMETERS.includes(key) && val);
...@@ -15,19 +16,8 @@ export const createUniqueLinkId = (stageName, jobName) => `${stageName}-${jobNam ...@@ -15,19 +16,8 @@ export const createUniqueLinkId = (stageName, jobName) => `${stageName}-${jobNam
* @returns {Object} - Hash of jobs * @returns {Object} - Hash of jobs
*/ */
export const createJobsHash = (stages = []) => { export const createJobsHash = (stages = []) => {
const jobsHash = {}; const nodes = stages.flatMap(({ groups }) => groups);
return createNodeDict(nodes);
stages.forEach((stage) => {
if (stage.groups.length > 0) {
stage.groups.forEach((group) => {
group.jobs.forEach((job) => {
jobsHash[job.name] = job;
});
});
}
});
return jobsHash;
}; };
/** /**
...@@ -56,6 +46,14 @@ export const generateJobNeedsDict = (jobs = {}) => { ...@@ -56,6 +46,14 @@ export const generateJobNeedsDict = (jobs = {}) => {
// to save some performance. // to save some performance.
const newNeeds = acc[job] ?? recursiveNeeds(job); const newNeeds = acc[job] ?? recursiveNeeds(job);
// In case it's a parallel job (size > 1), the name of the group
// and the job will be different. This mean we also need to add the group name
// to the list of `needs` to ensure we can properly reference it.
const group = jobs[job];
if (group.size > 1) {
return [job, group.name, ...newNeeds];
}
return [job, ...newNeeds]; return [job, ...newNeeds];
}) })
.flat(Infinity); .flat(Infinity);
......
...@@ -49,6 +49,7 @@ export const mockCiConfigQueryResponse = { ...@@ -49,6 +49,7 @@ export const mockCiConfigQueryResponse = {
nodes: [ nodes: [
{ {
name: 'job_test_1', name: 'job_test_1',
size: 1,
jobs: { jobs: {
nodes: [ nodes: [
{ {
...@@ -63,10 +64,12 @@ export const mockCiConfigQueryResponse = { ...@@ -63,10 +64,12 @@ export const mockCiConfigQueryResponse = {
}, },
{ {
name: 'job_test_2', name: 'job_test_2',
size: 1,
jobs: { jobs: {
nodes: [ nodes: [
{ {
name: 'job_test_2', name: 'job_test_2',
needs: { nodes: [], __typename: 'CiConfigNeedConnection' }, needs: { nodes: [], __typename: 'CiConfigNeedConnection' },
__typename: 'CiConfigJob', __typename: 'CiConfigJob',
}, },
...@@ -86,6 +89,7 @@ export const mockCiConfigQueryResponse = { ...@@ -86,6 +89,7 @@ export const mockCiConfigQueryResponse = {
nodes: [ nodes: [
{ {
name: 'job_build', name: 'job_build',
size: 1,
jobs: { jobs: {
nodes: [ nodes: [
{ {
......
...@@ -68,10 +68,10 @@ describe('utils functions', () => { ...@@ -68,10 +68,10 @@ describe('utils functions', () => {
it('returns a hash with the jobname as key and all its data as value', () => { it('returns a hash with the jobname as key and all its data as value', () => {
const jobs = { const jobs = {
[jobName1]: job1, [jobName1]: { jobs: [job1], name: jobName1, needs: [] },
[jobName2]: job2, [jobName2]: { jobs: [job2], name: jobName2, needs: [] },
[jobName3]: job3, [jobName3]: { jobs: [job3], name: jobName3, needs: job3.needs },
[jobName4]: job4, [jobName4]: { jobs: [job4], name: jobName4, needs: job4.needs },
}; };
expect(createJobsHash(pipelineGraphData.stages)).toEqual(jobs); expect(createJobsHash(pipelineGraphData.stages)).toEqual(jobs);
...@@ -110,5 +110,41 @@ describe('utils functions', () => { ...@@ -110,5 +110,41 @@ describe('utils functions', () => {
[jobName4]: [jobName3, jobName1, jobName2], [jobName4]: [jobName3, jobName1, jobName2],
}); });
}); });
it('handles parallel jobs by adding the group name as a need', () => {
const size = 3;
const jobOptimize1 = 'optimize_1';
const jobPrepareA = 'prepare_a';
const jobPrepareA1 = `${jobPrepareA} 1/${size}`;
const jobPrepareA2 = `${jobPrepareA} 2/${size}`;
const jobPrepareA3 = `${jobPrepareA} 3/${size}`;
const jobsParallel = {
[jobOptimize1]: {
jobs: [job1],
name: [jobOptimize1],
needs: [jobPrepareA1, jobPrepareA2, jobPrepareA3],
},
[jobPrepareA]: { jobs: [], name: jobPrepareA, needs: [], size },
[jobPrepareA1]: { jobs: [], name: jobPrepareA, needs: [], size },
[jobPrepareA2]: { jobs: [], name: jobPrepareA, needs: [], size },
[jobPrepareA3]: { jobs: [], name: jobPrepareA, needs: [], size },
};
expect(generateJobNeedsDict(jobsParallel)).toEqual({
[jobOptimize1]: [
jobPrepareA1,
// This is the important part, the `jobPrepareA` group name has been
// added to our list of needs.
jobPrepareA,
jobPrepareA2,
jobPrepareA3,
],
[jobPrepareA]: [],
[jobPrepareA1]: [],
[jobPrepareA2]: [],
[jobPrepareA3]: [],
});
});
}); });
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment