Skip to content

Commit

Permalink
feat(3014): Process and include stage info in the workflow graph node…
Browse files Browse the repository at this point in the history
…s when triggerFactory is not available (#50)
  • Loading branch information
sagar1312 committed Mar 7, 2024
1 parent d06fbea commit e7b9b29
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 68 deletions.
54 changes: 29 additions & 25 deletions lib/getWorkflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,40 +47,44 @@ const calculateNodes = async (jobs, triggerFactory, externalDownstreamOrs, exter
if (!triggerFactory) {
Object.keys(jobs).forEach(name => {
nodes.add(name);
const stageObj = jobs[name].stage;

if (stageObj) {
jobNameToStageNameMap[name] = stageObj.name;
}

if (Array.isArray(jobs[name].requires)) {
jobs[name].requires.forEach(n => nodes.add(filterNodeName(n)));
}
});
} else {
// new implementation. allow external join
await Promise.all(
Object.keys(jobs).map(async jobName => {
nodes.add(jobName);
const stageObj = jobs[jobName].stage;

return [...nodes].map(name => ({ name }));
}

// new implementation. allow external join
await Promise.all(
Object.keys(jobs).map(async jobName => {
nodes.add(jobName);
const stageObj = jobs[jobName].stage;

if (stageObj) {
jobNameToStageNameMap[jobName] = stageObj.name;
}
if (stageObj) {
jobNameToStageNameMap[jobName] = stageObj.name;
}

// upstream nodes
if (Array.isArray(jobs[jobName].requires)) {
jobs[jobName].requires.forEach(n => nodes.add(filterNodeName(n)));
}
// upstream nodes
if (Array.isArray(jobs[jobName].requires)) {
jobs[jobName].requires.forEach(n => nodes.add(filterNodeName(n)));
}

// downstream nodes
const externalDownstreamOr = jobName in externalDownstreamOrs ? externalDownstreamOrs[jobName] : [];
const externalDownstreamAnd = jobName in externalDownstreamAnds ? externalDownstreamAnds[jobName] : [];
// downstream nodes
const externalDownstreamOr = jobName in externalDownstreamOrs ? externalDownstreamOrs[jobName] : [];
const externalDownstreamAnd = jobName in externalDownstreamAnds ? externalDownstreamAnds[jobName] : [];

externalDownstreamOr.forEach(dest => {
nodes.add(dest.replace('~sd@', 'sd@'));
});
externalDownstreamOr.forEach(dest => {
nodes.add(dest.replace('~sd@', 'sd@'));
});

await buildExternalNodes(externalDownstreamAnd, nodes, triggerFactory);
})
);
await buildExternalNodes(externalDownstreamAnd, nodes, triggerFactory);
})
);
}

return [...nodes].map(name => {
const m = { name };
Expand Down
95 changes: 52 additions & 43 deletions test/lib/getWorkflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,52 +253,49 @@ describe('getWorkflow', () => {
assert.deepEqual(result, EXPECTED_EXTERNAL_COMPLEX);
});

it('should handle stages', async () => {
const result = await getWorkflow(
{
jobs: {
'stage@alpha:setup': { requires: ['~commit'], stage: { name: 'alpha' } },
'alpha-deploy': { requires: ['stage@alpha:setup'], stage: { name: 'alpha' } },
'alpha-test': { requires: ['alpha-deploy'], stage: { name: 'alpha' } },
'alpha-certify': { requires: ['alpha-test'], stage: { name: 'alpha' } },
'stage@alpha:teardown': { requires: ['alpha-certify'], stage: { name: 'alpha' } },
'stage@beta:setup': { requires: ['~stage@alpha:teardown'], stage: { name: 'beta' } },
'beta-deploy': { requires: ['~stage@beta:setup'], stage: { name: 'beta' } },
'beta-test': { requires: ['~beta-deploy'], stage: { name: 'beta' } },
'beta-certify': { requires: ['~beta-test'], stage: { name: 'beta' } },
'stage@beta:teardown': { requires: ['~beta-certify'], stage: { name: 'beta' } },
'stage@gamma:setup': { requires: ['triggering-a-stage'], stage: { name: 'gamma' } },
'gamma-deploy': { requires: ['stage@gamma:setup'], stage: { name: 'gamma' } },
'gamma-test-integration': { requires: ['gamma-deploy'], stage: { name: 'gamma' } },
'gamma-test-functional': { requires: ['gamma-deploy'], stage: { name: 'gamma' } },
'gamma-certify': {
requires: ['gamma-test-integration', 'gamma-test-functional'],
stage: { name: 'gamma' }
},
'stage@gamma:teardown': { requires: ['gamma-certify'], stage: { name: 'gamma' } },
'triggering-a-stage': { requires: ['~commit'] },
'triggered-by-a-stage-job': { requires: ['gamma-test-integration'] },
'triggered-after-a-stage': { requires: ['stage@gamma:teardown'] }
describe('should handle stages', async () => {
const PIPELINE_CONFIG = {
jobs: {
'stage@alpha:setup': { requires: ['~commit'], stage: { name: 'alpha' } },
'alpha-deploy': { requires: ['stage@alpha:setup'], stage: { name: 'alpha' } },
'alpha-test': { requires: ['alpha-deploy'], stage: { name: 'alpha' } },
'alpha-certify': { requires: ['alpha-test'], stage: { name: 'alpha' } },
'stage@alpha:teardown': { requires: ['alpha-certify'], stage: { name: 'alpha' } },
'stage@beta:setup': { requires: ['~stage@alpha:teardown'], stage: { name: 'beta' } },
'beta-deploy': { requires: ['~stage@beta:setup'], stage: { name: 'beta' } },
'beta-test': { requires: ['~beta-deploy'], stage: { name: 'beta' } },
'beta-certify': { requires: ['~beta-test'], stage: { name: 'beta' } },
'stage@beta:teardown': { requires: ['~beta-certify'], stage: { name: 'beta' } },
'stage@gamma:setup': { requires: ['triggering-a-stage'], stage: { name: 'gamma' } },
'gamma-deploy': { requires: ['stage@gamma:setup'], stage: { name: 'gamma' } },
'gamma-test-integration': { requires: ['gamma-deploy'], stage: { name: 'gamma' } },
'gamma-test-functional': { requires: ['gamma-deploy'], stage: { name: 'gamma' } },
'gamma-certify': {
requires: ['gamma-test-integration', 'gamma-test-functional'],
stage: { name: 'gamma' }
},
stages: {
alpha: {
description: 'stage for alpha environment',
jobs: ['alpha-deploy', 'alpha-test', 'alpha-certify']
},
beta: {
description: 'stage for beta environment',
jobs: ['beta-deploy', 'beta-test', 'beta-certify']
},
gamma: {
description: 'stage for gamma environment',
jobs: ['gamma-deploy', 'gamma-test-integration', 'gamma-test-functional', 'gamma-certify']
}
}
'stage@gamma:teardown': { requires: ['gamma-certify'], stage: { name: 'gamma' } },
'triggering-a-stage': { requires: ['~commit'] },
'triggered-by-a-stage-job': { requires: ['gamma-test-integration'] },
'triggered-after-a-stage': { requires: ['stage@gamma:teardown'] }
},
triggerFactoryMock
);
stages: {
alpha: {
description: 'stage for alpha environment',
jobs: ['alpha-deploy', 'alpha-test', 'alpha-certify']
},
beta: {
description: 'stage for beta environment',
jobs: ['beta-deploy', 'beta-test', 'beta-certify']
},
gamma: {
description: 'stage for gamma environment',
jobs: ['gamma-deploy', 'gamma-test-integration', 'gamma-test-functional', 'gamma-certify']
}
}
};

assert.deepEqual(result, {
const EXPECTED_WORKFLOW_GRAPH = {
nodes: [
{ name: '~pr' },
{ name: '~commit' },
Expand Down Expand Up @@ -344,6 +341,18 @@ describe('getWorkflow', () => {
{ src: 'gamma-test-integration', dest: 'triggered-by-a-stage-job', join: true },
{ src: 'stage@gamma:teardown', dest: 'triggered-after-a-stage', join: true }
]
};

it('generate workflow graph when triggerFactory is available', async () => {
const result = await getWorkflow(PIPELINE_CONFIG, triggerFactoryMock);

assert.deepEqual(result, EXPECTED_WORKFLOW_GRAPH);
});

it('generate workflow graph when triggerFactory is unavailable', async () => {
const result = await getWorkflow(PIPELINE_CONFIG, null);

assert.deepEqual(result, EXPECTED_WORKFLOW_GRAPH);
});
});
});

0 comments on commit e7b9b29

Please sign in to comment.