diff --git a/plugins/builds/index.js b/plugins/builds/index.js index adf726837..a2e2d7bba 100644 --- a/plugins/builds/index.js +++ b/plugins/builds/index.js @@ -34,7 +34,8 @@ const { createExternalEvent, getBuildsForGroupEvent, buildsToRestartFilter, - trimJobName + trimJobName, + getParallelBuilds } = require('./triggers/helpers'); /** @@ -140,6 +141,18 @@ async function triggerNextJobs(config, app) { // This includes CREATED builds too const groupEventBuilds = externalEvent !== undefined ? await getBuildsForGroupEvent(externalEvent.groupEventId, buildFactory) : []; + + // fetch builds created due to trigger + if (externalEvent) { + const parallelBuilds = await getParallelBuilds({ + eventFactory, + parentEventId: externalEvent.id, + pipelineId: externalEvent.pipelineId + }); + + groupEventBuilds.push(...parallelBuilds); + } + const buildsToRestart = buildsToRestartFilter(joinedPipeline, groupEventBuilds, currentEvent, currentBuild); const isRestart = buildsToRestart.length > 0; diff --git a/plugins/builds/triggers/remoteJoin.js b/plugins/builds/triggers/remoteJoin.js index 9f314c419..38b9d3128 100644 --- a/plugins/builds/triggers/remoteJoin.js +++ b/plugins/builds/triggers/remoteJoin.js @@ -1,6 +1,6 @@ 'use strict'; -const { getParallelBuilds, mergeParentBuilds, getParentBuildIds } = require('./helpers'); +const { mergeParentBuilds, getParentBuildIds } = require('./helpers'); const { JoinBase } = require('./joinBase'); /** @@ -31,15 +31,6 @@ class RemoteJoin extends JoinBase { * @returns {Promise} */ async execute(externalEvent, nextJobName, nextJobId, parentBuilds, groupEventBuilds, joinListNames) { - // fetch builds created due to trigger - const parallelBuilds = await getParallelBuilds({ - eventFactory: this.eventFactory, - parentEventId: externalEvent.id, - pipelineId: externalEvent.pipelineId - }); - - groupEventBuilds.push(...parallelBuilds); - // When restart case, should we create a new build ? const nextBuild = groupEventBuilds.find(b => b.jobId === nextJobId && b.eventId === externalEvent.id); diff --git a/test/plugins/trigger.test.js b/test/plugins/trigger.test.js index 6ffd330a7..5bbdf5da6 100644 --- a/test/plugins/trigger.test.js +++ b/test/plugins/trigger.test.js @@ -1634,6 +1634,34 @@ describe('trigger tests', () => { assert.equal(upstreamPipeline.getBuildsOf('target').length, 1); }); + it('[ sd@2:a, sd@2:b ] is triggered in restart event when only sd@2:b restarts', async () => { + const upstreamPipeline = await pipelineFactoryMock.createFromFile('sd@2:a_sd@2:b-upstream.yaml'); + const downstreamPipeline = await pipelineFactoryMock.createFromFile('sd@2:a_sd@2:b-downstream.yaml'); + + const upstreamEvent = await eventFactoryMock.create({ + pipelineId: upstreamPipeline.id, + startFrom: 'hub' + }); + + await upstreamEvent.run(); + + const downstreamEvent = downstreamPipeline.getLatestEvent(); + + await downstreamEvent.getBuildOf('a').complete('SUCCESS'); + await downstreamEvent.getBuildOf('b').complete('SUCCESS'); + + const downstreamRestartEvent = await downstreamEvent.restartFrom('b'); + + assert.isNull(downstreamRestartEvent.getBuildOf('a')); + await downstreamRestartEvent.getBuildOf('b').complete('SUCCESS'); + + const upstreamRestartEvent = upstreamPipeline.getLatestEvent(); + + assert.equal(upstreamEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamRestartEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamPipeline.getBuildsOf('target').length, 2); + }); + it('Multiple [ sd@2:a, sd@2:b ] is triggered', async () => { const upstreamPipeline = await pipelineFactoryMock.createFromFile('sd@2:a_sd@2:b-multiple-upstream.yaml'); const downstreamPipeline = await pipelineFactoryMock.createFromFile('sd@2:a_sd@2:b-downstream.yaml'); @@ -1850,6 +1878,30 @@ describe('trigger tests', () => { assert.equal(upstreamPipeline.getBuildsOf('target').length, 1); }); + it('[ sd@2:a, b ] is triggered in restart event when only b restarts', async () => { + const upstreamPipeline = await pipelineFactoryMock.createFromFile('sd@2:a_b-upstream.yaml'); + const downstreamPipeline = await pipelineFactoryMock.createFromFile('sd@2:a_b-downstream.yaml'); + + const upstreamEvent = await eventFactoryMock.create({ + pipelineId: upstreamPipeline.id, + startFrom: 'hub' + }); + + await upstreamEvent.run(); + + const downstreamEvent = downstreamPipeline.getLatestEvent(); + + await downstreamEvent.getBuildOf('a').complete('SUCCESS'); + + const upstreamRestartEvent = await upstreamEvent.restartFrom('b'); + + await upstreamRestartEvent.getBuildOf('b').complete('SUCCESS'); + + assert.equal(upstreamEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamRestartEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamPipeline.getBuildsOf('target').length, 2); + }); + it('[ sd@2:a, sd@3:a ] is triggered', async () => { const upstreamPipeline = await pipelineFactoryMock.createFromFile('sd@2:a_sd@3:a-upstream.yaml'); const downstreamPipeline1 = await pipelineFactoryMock.createFromFile('sd@2:a_sd@3:a-downstream.yaml'); @@ -1953,6 +2005,35 @@ describe('trigger tests', () => { assert.equal(upstreamPipeline.getBuildsOf('target').length, 1); }); + it('[ sd@2:a, sd@3:a ] is triggered in restart event when only sd@3:a restarts', async () => { + const upstreamPipeline = await pipelineFactoryMock.createFromFile('sd@2:a_sd@3:a-upstream.yaml'); + const downstreamPipeline1 = await pipelineFactoryMock.createFromFile('sd@2:a_sd@3:a-downstream.yaml'); + const downstreamPipeline2 = await pipelineFactoryMock.createFromFile('sd@2:a_sd@3:a-downstream.yaml'); + + const upstreamEvent = await eventFactoryMock.create({ + pipelineId: upstreamPipeline.id, + startFrom: 'hub' + }); + + await upstreamEvent.run(); + + const downstreamEvent1 = downstreamPipeline1.getLatestEvent(); + const downstreamEvent2 = downstreamPipeline2.getLatestEvent(); + + await downstreamEvent1.getBuildOf('a').complete('SUCCESS'); + await downstreamEvent2.getBuildOf('a').complete('SUCCESS'); + + const downstreamRestartEvent2 = await downstreamEvent2.restartFrom('a'); + + await downstreamRestartEvent2.getBuildOf('a').complete('SUCCESS'); + + const upstreamRestartEvent = upstreamPipeline.getLatestEvent(); + + assert.equal(upstreamEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamRestartEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamPipeline.getBuildsOf('target').length, 2); + }); + it('[ ~sd@2:a, sd@2:b, sd@2:c ] is triggered when sd@2:a succeeds', async () => { const upstreamPipeline = await pipelineFactoryMock.createFromFile('~sd@2:a_sd@2:b_sd@2:c-upstream.yaml'); const downstreamPipeline = await pipelineFactoryMock.createFromFile('~sd@2:a_sd@2:b_sd@2:c-downstream.yaml'); @@ -2061,6 +2142,35 @@ describe('trigger tests', () => { assert.equal(upstreamPipeline.getBuildsOf('target').length, 1); }); + it('[ ~sd@2:a, sd@2:b, sd@2:c ] is triggered in restart event when only sd@2:c restarts', async () => { + const upstreamPipeline = await pipelineFactoryMock.createFromFile('~sd@2:a_sd@2:b_sd@2:c-upstream.yaml'); + const downstreamPipeline = await pipelineFactoryMock.createFromFile('~sd@2:a_sd@2:b_sd@2:c-downstream.yaml'); + + const upstreamEvent = await eventFactoryMock.create({ + pipelineId: upstreamPipeline.id, + startFrom: 'hub' + }); + + await upstreamEvent.run(); + + const downstreamEvent = downstreamPipeline.getLatestEvent(); + + await downstreamEvent.getBuildOf('a').complete('SUCCESS'); + await downstreamEvent.getBuildOf('b').complete('SUCCESS'); + await downstreamEvent.getBuildOf('c').complete('SUCCESS'); + + const downstreamRestartEvent = await downstreamEvent.restartFrom('c'); + + assert.isNull(downstreamRestartEvent.getBuildOf('b')); + await downstreamRestartEvent.getBuildOf('c').complete('SUCCESS'); + + const upstreamRestartEvent = upstreamPipeline.getLatestEvent(); + + assert.equal(upstreamEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamRestartEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamPipeline.getBuildsOf('target').length, 2); + }); + it('[ ~sd@2:a, b, c ] is triggered', async () => { const upstreamPipeline = await pipelineFactoryMock.createFromFile('~sd@2:a_b_c-upstream.yaml'); const downstreamPipeline = await pipelineFactoryMock.createFromFile('~sd@2:a_b_c-downstream.yaml'); @@ -2486,6 +2596,33 @@ describe('trigger tests', () => { assert.equal(upstreamPipeline.getBuildsOf('target').length, 1); }); + it('[ ~sd@2:a, sd@2:a, sd@2:b ] is triggered in restart event when only sd@1:a restarts', async () => { + const upstreamPipeline = await pipelineFactoryMock.createFromFile('~sd@2:a_sd@2:a_sd@2:b-upstream.yaml'); + const downstreamPipeline = await pipelineFactoryMock.createFromFile('~sd@2:a_sd@2:a_sd@2:b-downstream.yaml'); + + const upstreamEvent = await eventFactoryMock.create({ + pipelineId: upstreamPipeline.id, + startFrom: 'hub' + }); + + await upstreamEvent.run(); + + const downstreamEvent = downstreamPipeline.getLatestEvent(); + + await downstreamEvent.getBuildOf('a').complete('SUCCESS'); + await downstreamEvent.getBuildOf('b').complete('SUCCESS'); + + const downstreamRestartEvent = await downstreamEvent.restartFrom('a'); + + await downstreamRestartEvent.getBuildOf('a').complete('SUCCESS'); + + const upstreamRestartEvent = upstreamPipeline.getLatestEvent(); + + assert.equal(upstreamEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamRestartEvent.getBuildOf('target').status, 'RUNNING'); + assert.equal(upstreamPipeline.getBuildsOf('target').length, 2); + }); + it('[ sd@3:a, sd@3:b ] is triggered in second stream pipeline', async () => { const firstPipeline = await pipelineFactoryMock.createFromFile('sd@3:a_sd@3:b-first.yaml'); const secondPipeline = await pipelineFactoryMock.createFromFile('sd@3:a_sd@3:b-second.yaml');