screwdriver-api 7.0.141 → 7.0.142
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugins/builds/index.js +60 -7
- package/plugins/builds/triggers/and.js +6 -2
- package/plugins/builds/triggers/helpers.js +17 -6
- package/plugins/builds/triggers/joinBase.js +8 -6
- package/plugins/builds/triggers/or.js +3 -2
- package/plugins/builds/triggers/orBase.js +21 -4
- package/plugins/builds/triggers/remoteJoin.js +15 -2
- package/plugins/builds/triggers/remoteTrigger.js +3 -2
- package/plugins/builds/update.js +1 -1
package/package.json
CHANGED
package/plugins/builds/index.js
CHANGED
|
@@ -35,7 +35,8 @@ const {
|
|
|
35
35
|
getBuildsForGroupEvent,
|
|
36
36
|
buildsToRestartFilter,
|
|
37
37
|
trimJobName,
|
|
38
|
-
getParallelBuilds
|
|
38
|
+
getParallelBuilds,
|
|
39
|
+
Status
|
|
39
40
|
} = require('./triggers/helpers');
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -87,10 +88,14 @@ async function triggerNextJobs(config, app) {
|
|
|
87
88
|
const andTrigger = new AndTrigger(app, config, currentEvent);
|
|
88
89
|
const currentPipelineNextJobs = extractCurrentPipelineJoinData(pipelineJoinData, currentPipeline.id);
|
|
89
90
|
|
|
91
|
+
const downstreamOfNextJobsToBeProcessed = [];
|
|
92
|
+
|
|
90
93
|
for (const [nextJobName, nextJob] of Object.entries(currentPipelineNextJobs)) {
|
|
91
94
|
const nextJobId = nextJob.id || (await getJobId(nextJobName, currentPipeline.id, jobFactory));
|
|
95
|
+
const { isVirtual: isNextJobVirtual, stageName: nextJobStageName } = nextJob;
|
|
92
96
|
const resource = `pipeline:${currentPipeline.id}:event:${currentEvent.id}`;
|
|
93
97
|
let lock;
|
|
98
|
+
let nextBuild;
|
|
94
99
|
|
|
95
100
|
try {
|
|
96
101
|
lock = await locker.lock(resource);
|
|
@@ -110,9 +115,34 @@ async function triggerNextJobs(config, app) {
|
|
|
110
115
|
* joinList doesn't include D, so start A
|
|
111
116
|
*/
|
|
112
117
|
if (isOrTrigger(currentEvent.workflowGraph, originalCurrentJobName, trimJobName(nextJobName))) {
|
|
113
|
-
await orTrigger.execute(
|
|
118
|
+
nextBuild = await orTrigger.execute(
|
|
119
|
+
currentEvent,
|
|
120
|
+
currentPipeline.id,
|
|
121
|
+
nextJobName,
|
|
122
|
+
nextJobId,
|
|
123
|
+
parentBuilds,
|
|
124
|
+
isNextJobVirtual
|
|
125
|
+
);
|
|
114
126
|
} else {
|
|
115
|
-
await andTrigger.execute(
|
|
127
|
+
nextBuild = await andTrigger.execute(
|
|
128
|
+
nextJobName,
|
|
129
|
+
nextJobId,
|
|
130
|
+
parentBuilds,
|
|
131
|
+
joinListNames,
|
|
132
|
+
isNextJobVirtual,
|
|
133
|
+
nextJobStageName
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (isNextJobVirtual && nextBuild.status === Status.SUCCESS) {
|
|
138
|
+
downstreamOfNextJobsToBeProcessed.push({
|
|
139
|
+
build: nextBuild,
|
|
140
|
+
event: currentEvent,
|
|
141
|
+
job: await nextBuild.job,
|
|
142
|
+
pipeline: currentPipeline,
|
|
143
|
+
scmContext: config.scmContext,
|
|
144
|
+
username: config.username
|
|
145
|
+
});
|
|
116
146
|
}
|
|
117
147
|
} catch (err) {
|
|
118
148
|
logger.error(
|
|
@@ -199,6 +229,7 @@ async function triggerNextJobs(config, app) {
|
|
|
199
229
|
|
|
200
230
|
for (const [nextJobName, nextJob] of Object.entries(joinedPipeline.jobs)) {
|
|
201
231
|
const nextJobId = nextJob.id || (await getJobId(nextJobName, currentPipeline.id, jobFactory));
|
|
232
|
+
const { isVirtual: isNextJobVirtual, stageName: nextJobStageName } = nextJob;
|
|
202
233
|
|
|
203
234
|
const { parentBuilds } = parseJobInfo({
|
|
204
235
|
joinObj: joinedPipeline.jobs,
|
|
@@ -209,16 +240,19 @@ async function triggerNextJobs(config, app) {
|
|
|
209
240
|
nextPipelineId: joinedPipelineId
|
|
210
241
|
});
|
|
211
242
|
|
|
243
|
+
let nextBuild;
|
|
244
|
+
|
|
212
245
|
try {
|
|
213
246
|
if (resource) lock = await locker.lock(resource);
|
|
214
247
|
|
|
215
248
|
if (isOrTrigger(externalEvent.workflowGraph, remoteTriggerName, nextJobName)) {
|
|
216
|
-
await remoteTrigger.execute(
|
|
249
|
+
nextBuild = await remoteTrigger.execute(
|
|
217
250
|
externalEvent,
|
|
218
251
|
externalEvent.pipelineId,
|
|
219
252
|
nextJobName,
|
|
220
253
|
nextJobId,
|
|
221
|
-
parentBuilds
|
|
254
|
+
parentBuilds,
|
|
255
|
+
isNextJobVirtual
|
|
222
256
|
);
|
|
223
257
|
} else {
|
|
224
258
|
// Re get join list when first time remote trigger since external event was empty and cannot get workflow graph then
|
|
@@ -228,15 +262,30 @@ async function triggerNextJobs(config, app) {
|
|
|
228
262
|
: workflowParser.getSrcForJoin(externalEvent.workflowGraph, { jobName: nextJobName });
|
|
229
263
|
const joinListNames = joinList.map(j => j.name);
|
|
230
264
|
|
|
231
|
-
await remoteJoin.execute(
|
|
265
|
+
nextBuild = await remoteJoin.execute(
|
|
232
266
|
externalEvent,
|
|
233
267
|
nextJobName,
|
|
234
268
|
nextJobId,
|
|
235
269
|
parentBuilds,
|
|
236
270
|
groupEventBuilds,
|
|
237
|
-
joinListNames
|
|
271
|
+
joinListNames,
|
|
272
|
+
isNextJobVirtual,
|
|
273
|
+
nextJobStageName
|
|
238
274
|
);
|
|
239
275
|
}
|
|
276
|
+
|
|
277
|
+
if (isNextJobVirtual && nextBuild.status === Status.SUCCESS) {
|
|
278
|
+
const nextJobModel = await nextBuild.job;
|
|
279
|
+
|
|
280
|
+
downstreamOfNextJobsToBeProcessed.push({
|
|
281
|
+
build: nextBuild,
|
|
282
|
+
event: currentEvent,
|
|
283
|
+
job: nextJobModel,
|
|
284
|
+
pipeline: await nextJobModel.pipeline,
|
|
285
|
+
scmContext: config.scmContext,
|
|
286
|
+
username: config.username
|
|
287
|
+
});
|
|
288
|
+
}
|
|
240
289
|
} catch (err) {
|
|
241
290
|
logger.error(
|
|
242
291
|
`Error in triggerJobsInExternalPipeline:${joinedPipelineId} from pipeline:${currentPipeline.id}-${currentJob.name}-event:${currentEvent.id} `,
|
|
@@ -248,6 +297,10 @@ async function triggerNextJobs(config, app) {
|
|
|
248
297
|
}
|
|
249
298
|
}
|
|
250
299
|
|
|
300
|
+
for (const nextConfig of downstreamOfNextJobsToBeProcessed) {
|
|
301
|
+
await triggerNextJobs(nextConfig, app);
|
|
302
|
+
}
|
|
303
|
+
|
|
251
304
|
return null;
|
|
252
305
|
}
|
|
253
306
|
|
|
@@ -56,9 +56,11 @@ class AndTrigger extends JoinBase {
|
|
|
56
56
|
* @param {String} nextJobId
|
|
57
57
|
* @param {Record<String, Object>} parentBuilds
|
|
58
58
|
* @param {String[]} joinListNames
|
|
59
|
+
* @param {Boolean} isNextJobVirtual
|
|
60
|
+
* @param {String} nextJobStageName
|
|
59
61
|
* @returns {Promise<Build>}
|
|
60
62
|
*/
|
|
61
|
-
async execute(nextJobName, nextJobId, parentBuilds, joinListNames) {
|
|
63
|
+
async execute(nextJobName, nextJobId, parentBuilds, joinListNames, isNextJobVirtual, nextJobStageName) {
|
|
62
64
|
logger.info(`Fetching finished builds for event ${this.currentEvent.id}`);
|
|
63
65
|
|
|
64
66
|
const relatedBuilds = await this.fetchRelatedBuilds();
|
|
@@ -90,7 +92,9 @@ class AndTrigger extends JoinBase {
|
|
|
90
92
|
nextJobId,
|
|
91
93
|
parentBuilds: newParentBuilds,
|
|
92
94
|
parentBuildId: this.currentBuild.id,
|
|
93
|
-
joinListNames
|
|
95
|
+
joinListNames,
|
|
96
|
+
isNextJobVirtual,
|
|
97
|
+
nextJobStageName
|
|
94
98
|
});
|
|
95
99
|
}
|
|
96
100
|
}
|
|
@@ -601,17 +601,18 @@ async function getParentBuildStatus({ newBuild, joinListNames, pipelineId, build
|
|
|
601
601
|
* @param {Build} arg.newBuild Next build
|
|
602
602
|
* @param {String|undefined} arg.jobName Job name
|
|
603
603
|
* @param {String|undefined} arg.pipelineId Pipeline ID
|
|
604
|
-
* @param {
|
|
604
|
+
* @param {String|undefined} arg.stageName Stage name
|
|
605
|
+
* @param {Boolean} arg.isVirtualJob If the job is virtual or not
|
|
605
606
|
* @returns {Promise<Build|null>} The newly updated/created build
|
|
606
607
|
*/
|
|
607
|
-
async function handleNewBuild({ done, hasFailure, newBuild, jobName, pipelineId,
|
|
608
|
+
async function handleNewBuild({ done, hasFailure, newBuild, jobName, pipelineId, stageName, isVirtualJob }) {
|
|
608
609
|
if (!done || Status.isStarted(newBuild.status)) {
|
|
609
610
|
return null;
|
|
610
611
|
}
|
|
611
612
|
|
|
612
613
|
// Delete new build since previous build failed
|
|
613
614
|
if (hasFailure) {
|
|
614
|
-
const stageTeardownName =
|
|
615
|
+
const stageTeardownName = stageName ? getFullStageJobName({ stageName, jobName: 'teardown' }) : '';
|
|
615
616
|
|
|
616
617
|
// New build is not stage teardown job
|
|
617
618
|
if (jobName !== stageTeardownName) {
|
|
@@ -624,7 +625,14 @@ async function handleNewBuild({ done, hasFailure, newBuild, jobName, pipelineId,
|
|
|
624
625
|
return null;
|
|
625
626
|
}
|
|
626
627
|
|
|
627
|
-
//
|
|
628
|
+
// Bypass execution of the build if the job is virtual
|
|
629
|
+
if (isVirtualJob) {
|
|
630
|
+
newBuild.status = Status.SUCCESS;
|
|
631
|
+
|
|
632
|
+
return newBuild.update();
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// All join builds finished successfully, and it's clear that a new build has not been started before.
|
|
628
636
|
// Start new build.
|
|
629
637
|
newBuild.status = Status.QUEUED;
|
|
630
638
|
await newBuild.update();
|
|
@@ -790,7 +798,10 @@ async function createJoinObject(nextJobNames, current, eventFactory) {
|
|
|
790
798
|
isExternal = true;
|
|
791
799
|
}
|
|
792
800
|
|
|
793
|
-
const
|
|
801
|
+
const node = event.workflowGraph.nodes.find(n => n.name === trimJobName(jobName));
|
|
802
|
+
const jId = node.id;
|
|
803
|
+
const isVirtual = node.virtual || false;
|
|
804
|
+
const stageName = node.stageName || null;
|
|
794
805
|
|
|
795
806
|
if (!joinObj[nextJobPipelineId]) joinObj[nextJobPipelineId] = {};
|
|
796
807
|
const pipelineObj = joinObj[nextJobPipelineId];
|
|
@@ -810,7 +821,7 @@ async function createJoinObject(nextJobNames, current, eventFactory) {
|
|
|
810
821
|
}
|
|
811
822
|
|
|
812
823
|
if (!pipelineObj.jobs) pipelineObj.jobs = {};
|
|
813
|
-
pipelineObj.jobs[nextJobName] = { id: jId, join: jobs, isExternal };
|
|
824
|
+
pipelineObj.jobs[nextJobName] = { id: jId, join: jobs, isExternal, isVirtual, stageName };
|
|
814
825
|
}
|
|
815
826
|
|
|
816
827
|
return joinObj;
|
|
@@ -9,7 +9,6 @@ const { createInternalBuild, updateParentBuilds, getParentBuildStatus, handleNew
|
|
|
9
9
|
* @typedef {import('screwdriver-models').JobFactory} JobFactory
|
|
10
10
|
* @typedef {import('screwdriver-models/lib/event')} Event
|
|
11
11
|
* @typedef {import('screwdriver-models/lib/build')} Build
|
|
12
|
-
* @typedef {import('screwdriver-models/lib/stage')} Stage
|
|
13
12
|
*/
|
|
14
13
|
|
|
15
14
|
class JoinBase {
|
|
@@ -21,7 +20,6 @@ class JoinBase {
|
|
|
21
20
|
* @param {JobFactory} app.jobFactory Server app object
|
|
22
21
|
* @param {Object} config Configuration object
|
|
23
22
|
* @param {Build} config.build
|
|
24
|
-
* @param {Stage} config.stage
|
|
25
23
|
* @param {String} config.username
|
|
26
24
|
* @param {String} config.scmContext
|
|
27
25
|
*/
|
|
@@ -31,7 +29,6 @@ class JoinBase {
|
|
|
31
29
|
this.jobFactory = app.jobFactory;
|
|
32
30
|
|
|
33
31
|
this.currentBuild = config.build;
|
|
34
|
-
this.stage = config.stage;
|
|
35
32
|
this.username = config.username;
|
|
36
33
|
this.scmContext = config.scmContext;
|
|
37
34
|
}
|
|
@@ -47,6 +44,8 @@ class JoinBase {
|
|
|
47
44
|
* @param {import('./helpers').ParentBuilds} parentBuilds
|
|
48
45
|
* @param {String} parentBuildId
|
|
49
46
|
* @param {String[]} joinListNames
|
|
47
|
+
* @param {Boolean} isNextJobVirtual
|
|
48
|
+
* @param {String} nextJobStageName
|
|
50
49
|
* @returns {Promise<Build[]|null>}
|
|
51
50
|
*/
|
|
52
51
|
async processNextBuild({
|
|
@@ -57,7 +56,9 @@ class JoinBase {
|
|
|
57
56
|
nextJobId,
|
|
58
57
|
parentBuilds,
|
|
59
58
|
parentBuildId,
|
|
60
|
-
joinListNames
|
|
59
|
+
joinListNames,
|
|
60
|
+
isNextJobVirtual,
|
|
61
|
+
nextJobStageName
|
|
61
62
|
}) {
|
|
62
63
|
let newBuild;
|
|
63
64
|
|
|
@@ -103,9 +104,10 @@ class JoinBase {
|
|
|
103
104
|
done,
|
|
104
105
|
hasFailure,
|
|
105
106
|
newBuild,
|
|
106
|
-
nextJobName,
|
|
107
|
+
jobName: nextJobName,
|
|
107
108
|
pipelineId,
|
|
108
|
-
|
|
109
|
+
isVirtualJob: isNextJobVirtual,
|
|
110
|
+
stageName: nextJobStageName
|
|
109
111
|
});
|
|
110
112
|
}
|
|
111
113
|
}
|
|
@@ -15,10 +15,11 @@ class OrTrigger extends OrBase {
|
|
|
15
15
|
* @param {String} nextJobName
|
|
16
16
|
* @param {Number} nextJobId
|
|
17
17
|
* @param {import('./helpers').ParentBuilds} parentBuilds
|
|
18
|
+
* @param {Boolean} isNextJobVirtual
|
|
18
19
|
* @return {Promise<Build|null>}
|
|
19
20
|
*/
|
|
20
|
-
async execute(event, pipelineId, nextJobName, nextJobId, parentBuilds) {
|
|
21
|
-
return this.trigger(event, pipelineId, nextJobName, nextJobId, parentBuilds);
|
|
21
|
+
async execute(event, pipelineId, nextJobName, nextJobId, parentBuilds, isNextJobVirtual) {
|
|
22
|
+
return this.trigger(event, pipelineId, nextJobName, nextJobId, parentBuilds, isNextJobVirtual);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -39,10 +39,11 @@ class OrBase {
|
|
|
39
39
|
* @param {String} nextJobName
|
|
40
40
|
* @param {Number} nextJobId
|
|
41
41
|
* @param {import('./helpers').ParentBuilds} parentBuilds
|
|
42
|
+
* @param {Boolean} isNextJobVirtual
|
|
42
43
|
* @return {Promise<Build|null>}
|
|
43
44
|
*/
|
|
44
|
-
async trigger(event, pipelineId, nextJobName, nextJobId, parentBuilds) {
|
|
45
|
-
|
|
45
|
+
async trigger(event, pipelineId, nextJobName, nextJobId, parentBuilds, isNextJobVirtual) {
|
|
46
|
+
let nextBuild = await this.buildFactory.get({
|
|
46
47
|
eventId: event.id,
|
|
47
48
|
jobId: nextJobId
|
|
48
49
|
});
|
|
@@ -52,13 +53,20 @@ class OrBase {
|
|
|
52
53
|
return nextBuild;
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
// Bypass execution of the build if the job is virtual
|
|
57
|
+
if (isNextJobVirtual) {
|
|
58
|
+
nextBuild.status = Status.SUCCESS;
|
|
59
|
+
|
|
60
|
+
return nextBuild.update();
|
|
61
|
+
}
|
|
62
|
+
|
|
55
63
|
nextBuild.status = Status.QUEUED;
|
|
56
64
|
await nextBuild.update();
|
|
57
65
|
|
|
58
66
|
return nextBuild.start();
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
|
|
69
|
+
nextBuild = await createInternalBuild({
|
|
62
70
|
jobFactory: this.jobFactory,
|
|
63
71
|
buildFactory: this.buildFactory,
|
|
64
72
|
pipelineId,
|
|
@@ -70,8 +78,17 @@ class OrBase {
|
|
|
70
78
|
baseBranch: event.baseBranch || null,
|
|
71
79
|
parentBuilds,
|
|
72
80
|
parentBuildId: this.currentBuild.id,
|
|
73
|
-
start:
|
|
81
|
+
start: !isNextJobVirtual
|
|
74
82
|
});
|
|
83
|
+
|
|
84
|
+
// Bypass execution of the build if the job is virtual
|
|
85
|
+
if (isNextJobVirtual) {
|
|
86
|
+
nextBuild.status = Status.SUCCESS;
|
|
87
|
+
|
|
88
|
+
nextBuild = nextBuild.update();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return nextBuild;
|
|
75
92
|
}
|
|
76
93
|
}
|
|
77
94
|
|
|
@@ -28,9 +28,20 @@ class RemoteJoin extends JoinBase {
|
|
|
28
28
|
* @param {import('./helpers').ParentBuilds} parentBuilds
|
|
29
29
|
* @param {Build[]} groupEventBuilds Builds of the downstream pipeline, where only the latest ones for each job are included that have the same groupEventId as the externalEvent
|
|
30
30
|
* @param {String[]} joinListNames
|
|
31
|
+
* @param {Boolean} isNextJobVirtual
|
|
32
|
+
* @param {String} nextJobStageName
|
|
31
33
|
* @returns {Promise<Build|null>}
|
|
32
34
|
*/
|
|
33
|
-
async execute(
|
|
35
|
+
async execute(
|
|
36
|
+
externalEvent,
|
|
37
|
+
nextJobName,
|
|
38
|
+
nextJobId,
|
|
39
|
+
parentBuilds,
|
|
40
|
+
groupEventBuilds,
|
|
41
|
+
joinListNames,
|
|
42
|
+
isNextJobVirtual,
|
|
43
|
+
nextJobStageName
|
|
44
|
+
) {
|
|
34
45
|
// When restart case, should we create a new build ?
|
|
35
46
|
const nextBuild = groupEventBuilds.find(b => b.jobId === nextJobId && b.eventId === externalEvent.id);
|
|
36
47
|
|
|
@@ -51,7 +62,9 @@ class RemoteJoin extends JoinBase {
|
|
|
51
62
|
nextJobId,
|
|
52
63
|
parentBuilds: newParentBuilds,
|
|
53
64
|
parentBuildId,
|
|
54
|
-
joinListNames
|
|
65
|
+
joinListNames,
|
|
66
|
+
isNextJobVirtual,
|
|
67
|
+
nextJobStageName
|
|
55
68
|
});
|
|
56
69
|
}
|
|
57
70
|
}
|
|
@@ -15,10 +15,11 @@ class RemoteTrigger extends OrBase {
|
|
|
15
15
|
* @param {String} nextJobName
|
|
16
16
|
* @param {String} nextJobId
|
|
17
17
|
* @param {import('./helpers').ParentBuilds} parentBuilds
|
|
18
|
+
* @param {Boolean} isNextJobVirtual
|
|
18
19
|
* @returns {Promise<Build|null>}
|
|
19
20
|
*/
|
|
20
|
-
async execute(event, pipelineId, nextJobName, nextJobId, parentBuilds) {
|
|
21
|
-
return this.trigger(event, pipelineId, nextJobName, nextJobId, parentBuilds);
|
|
21
|
+
async execute(event, pipelineId, nextJobName, nextJobId, parentBuilds, isNextJobVirtual) {
|
|
22
|
+
return this.trigger(event, pipelineId, nextJobName, nextJobId, parentBuilds, isNextJobVirtual);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
package/plugins/builds/update.js
CHANGED
|
@@ -338,7 +338,7 @@ module.exports = () => ({
|
|
|
338
338
|
);
|
|
339
339
|
} else {
|
|
340
340
|
await triggerNextJobs(
|
|
341
|
-
{ pipeline, job, build: newBuild, username, scmContext, event: newEvent
|
|
341
|
+
{ pipeline, job, build: newBuild, username, scmContext, event: newEvent },
|
|
342
342
|
request.server.app
|
|
343
343
|
);
|
|
344
344
|
}
|