From e7b9b29b812889c4ec8b7caad8cdcaac819b79ae Mon Sep 17 00:00:00 2001 From: Dayanand Sagar Date: Thu, 7 Mar 2024 14:59:10 -0800 Subject: [PATCH] feat(3014): Process and include stage info in the workflow graph nodes when triggerFactory is not available (#50) --- lib/getWorkflow.js | 54 ++++++++++---------- test/lib/getWorkflow.test.js | 95 ++++++++++++++++++++---------------- 2 files changed, 81 insertions(+), 68 deletions(-) diff --git a/lib/getWorkflow.js b/lib/getWorkflow.js index 9a58336..c3dd934 100644 --- a/lib/getWorkflow.js +++ b/lib/getWorkflow.js @@ -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 }; diff --git a/test/lib/getWorkflow.test.js b/test/lib/getWorkflow.test.js index ec5bec5..1251f06 100644 --- a/test/lib/getWorkflow.test.js +++ b/test/lib/getWorkflow.test.js @@ -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' }, @@ -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); }); }); });