screwdriver-api 8.0.83 → 8.0.84
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
CHANGED
|
@@ -5,7 +5,7 @@ const hoek = require('@hapi/hoek');
|
|
|
5
5
|
const merge = require('lodash.mergewith');
|
|
6
6
|
const { PR_JOB_NAME, PR_STAGE_NAME, STAGE_TEARDOWN_PATTERN } = require('screwdriver-data-schema').config.regex;
|
|
7
7
|
const { getFullStageJobName } = require('../../helper');
|
|
8
|
-
const { updateVirtualBuildSuccess } = require('../triggers/helpers');
|
|
8
|
+
const { updateVirtualBuildSuccess, emitBuildStatusEvent } = require('../triggers/helpers');
|
|
9
9
|
const TERMINAL_STATUSES = ['FAILURE', 'ABORTED', 'UNSTABLE', 'COLLAPSED'];
|
|
10
10
|
const FINISHED_STATUSES = ['SUCCESS', ...TERMINAL_STATUSES];
|
|
11
11
|
const NON_TERMINATED_STATUSES = ['CREATED', 'RUNNING', 'QUEUED', 'BLOCKED', 'FROZEN'];
|
|
@@ -60,25 +60,6 @@ function stopBuilds(builds, statusMessage) {
|
|
|
60
60
|
return { unchangedBuilds, changedBuilds };
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
/**
|
|
64
|
-
* Identify whether this build resulted in a previously failed job to become successful.
|
|
65
|
-
*
|
|
66
|
-
* @method isFixedBuild
|
|
67
|
-
* @param {Build} build Build Object
|
|
68
|
-
* @param {JobFactory} jobFactory Job Factory instance
|
|
69
|
-
*/
|
|
70
|
-
async function isFixedBuild(build, jobFactory) {
|
|
71
|
-
if (build.status !== 'SUCCESS') {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const job = await jobFactory.get(build.jobId);
|
|
76
|
-
const failureBuild = await job.getLatestBuild({ status: 'FAILURE' });
|
|
77
|
-
const successBuild = await job.getLatestBuild({ status: 'SUCCESS' });
|
|
78
|
-
|
|
79
|
-
return !!((failureBuild && !successBuild) || failureBuild.id > successBuild.id);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
63
|
/**
|
|
83
64
|
* Stops a frozen build from executing
|
|
84
65
|
*
|
|
@@ -405,7 +386,6 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
|
|
|
405
386
|
throw boom.badRequest(`Cannot update builds to ${desiredStatus}`);
|
|
406
387
|
}
|
|
407
388
|
|
|
408
|
-
let isFixed = Promise.resolve(false);
|
|
409
389
|
let stopFrozen = null;
|
|
410
390
|
|
|
411
391
|
// If the event is Aborted, check if there are any builds within the same event
|
|
@@ -429,7 +409,6 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
|
|
|
429
409
|
await updateInitStep(build, server.app);
|
|
430
410
|
} else {
|
|
431
411
|
stopFrozen = stopFrozenBuild(build, currentStatus);
|
|
432
|
-
isFixed = isFixedBuild(build, jobFactory);
|
|
433
412
|
}
|
|
434
413
|
|
|
435
414
|
const [newBuild, newEvent] = await Promise.all([build.update(), event.update(), stopFrozen]);
|
|
@@ -437,16 +416,7 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
|
|
|
437
416
|
const pipeline = await job.pipeline;
|
|
438
417
|
|
|
439
418
|
if (desiredStatus) {
|
|
440
|
-
await server
|
|
441
|
-
settings: job.permutations[0].settings,
|
|
442
|
-
status: newBuild.status,
|
|
443
|
-
event: newEvent.toJson(),
|
|
444
|
-
pipeline: pipeline.toJson(),
|
|
445
|
-
jobName: job.name,
|
|
446
|
-
build: newBuild.toJson(),
|
|
447
|
-
buildLink: `${buildFactory.uiUri}/pipelines/${pipeline.id}/builds/${build.id}`,
|
|
448
|
-
isFixed: await isFixed
|
|
449
|
-
});
|
|
419
|
+
await emitBuildStatusEvent({ server, build: newBuild, pipeline, event: newEvent, job });
|
|
450
420
|
}
|
|
451
421
|
|
|
452
422
|
const skipFurther = /\[(skip further)\]/.test(newEvent.causeMessage);
|
|
@@ -485,7 +455,7 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
|
|
|
485
455
|
} else if (newBuild.status === 'SUCCESS' && isStageTeardown && stageBuildHasFailure) {
|
|
486
456
|
await removeJoinBuilds({ pipeline, job, build: newBuild, event: newEvent, stage }, server.app);
|
|
487
457
|
} else {
|
|
488
|
-
await triggerNextJobs({ pipeline, job, build: newBuild, username, scmContext, event: newEvent }, server
|
|
458
|
+
await triggerNextJobs({ pipeline, job, build: newBuild, username, scmContext, event: newEvent }, server);
|
|
489
459
|
}
|
|
490
460
|
|
|
491
461
|
// Determine if stage teardown build should start
|
|
@@ -520,7 +490,13 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
|
|
|
520
490
|
stageTeardownBuild.parentBuildId = stageJobBuilds.map(b => b.id);
|
|
521
491
|
|
|
522
492
|
if (teardownNode && teardownNode.virtual) {
|
|
523
|
-
await updateVirtualBuildSuccess(
|
|
493
|
+
await updateVirtualBuildSuccess({
|
|
494
|
+
server,
|
|
495
|
+
build: stageTeardownBuild,
|
|
496
|
+
pipeline,
|
|
497
|
+
event: newEvent,
|
|
498
|
+
job: stageTeardownJob
|
|
499
|
+
});
|
|
524
500
|
await updateStageBuildStatus({ stageBuild, newStatus: 'SUCCESS', job: stageTeardownJob });
|
|
525
501
|
} else {
|
|
526
502
|
stageTeardownBuild.status = 'QUEUED';
|
package/plugins/builds/index.js
CHANGED
|
@@ -65,14 +65,15 @@ async function deleteBuild(buildConfig, buildFactory) {
|
|
|
65
65
|
/**
|
|
66
66
|
* Trigger the next jobs of the current job
|
|
67
67
|
* @param { import('./types/index').ServerConfig } config Configuration object
|
|
68
|
-
* @param {
|
|
68
|
+
* @param { Object } server Server object
|
|
69
|
+
* @param { import('./types/index').ServerApp } server.app Server app object
|
|
69
70
|
* @return {Promise<null>} Resolves to the newly created build or null
|
|
70
71
|
*/
|
|
71
|
-
async function triggerNextJobs(config,
|
|
72
|
+
async function triggerNextJobs(config, server) {
|
|
72
73
|
const currentPipeline = config.pipeline;
|
|
73
74
|
const currentJob = config.job;
|
|
74
75
|
const currentBuild = config.build;
|
|
75
|
-
const { jobFactory, buildFactory, eventFactory, pipelineFactory, stageFactory, stageBuildFactory } = app;
|
|
76
|
+
const { jobFactory, buildFactory, eventFactory, pipelineFactory, stageFactory, stageBuildFactory } = server.app;
|
|
76
77
|
|
|
77
78
|
/** @type {EventModel} */
|
|
78
79
|
const currentEvent = await eventFactory.get({ id: currentBuild.eventId });
|
|
@@ -92,8 +93,8 @@ async function triggerNextJobs(config, app) {
|
|
|
92
93
|
|
|
93
94
|
// Trigger OrTrigger and AndTrigger for current pipeline jobs.
|
|
94
95
|
// Helper function to handle triggering jobs in same pipeline
|
|
95
|
-
const orTrigger = new OrTrigger(
|
|
96
|
-
const andTrigger = new AndTrigger(
|
|
96
|
+
const orTrigger = new OrTrigger(server, config);
|
|
97
|
+
const andTrigger = new AndTrigger(server, config, currentEvent);
|
|
97
98
|
const currentPipelineNextJobs = extractCurrentPipelineJoinData(pipelineJoinData, currentPipeline.id);
|
|
98
99
|
|
|
99
100
|
const downstreamOfNextJobsToBeProcessed = [];
|
|
@@ -155,7 +156,8 @@ async function triggerNextJobs(config, app) {
|
|
|
155
156
|
eventId: currentEvent.id
|
|
156
157
|
});
|
|
157
158
|
|
|
158
|
-
|
|
159
|
+
// The next build is only created (not started) when nextBuild is null
|
|
160
|
+
if (stageBuild && nextBuild) {
|
|
159
161
|
await updateStageBuildStatus({ stageBuild, newStatus: nextBuild.status, job: nextJob });
|
|
160
162
|
}
|
|
161
163
|
|
|
@@ -182,8 +184,8 @@ async function triggerNextJobs(config, app) {
|
|
|
182
184
|
|
|
183
185
|
// Trigger RemoteJoin and RemoteTrigger for current and external pipeline jobs.
|
|
184
186
|
// Helper function to handle triggering jobs in external pipeline
|
|
185
|
-
const remoteTrigger = new RemoteTrigger(
|
|
186
|
-
const remoteJoin = new RemoteJoin(
|
|
187
|
+
const remoteTrigger = new RemoteTrigger(server, config);
|
|
188
|
+
const remoteJoin = new RemoteJoin(server, config, currentEvent);
|
|
187
189
|
const externalPipelineJoinData = extractExternalJoinData(pipelineJoinData, currentPipeline.id);
|
|
188
190
|
|
|
189
191
|
for (const [joinedPipelineId, joinedPipeline] of Object.entries(externalPipelineJoinData)) {
|
|
@@ -389,7 +391,7 @@ async function triggerNextJobs(config, app) {
|
|
|
389
391
|
}
|
|
390
392
|
|
|
391
393
|
for (const nextConfig of downstreamOfNextJobsToBeProcessed) {
|
|
392
|
-
await triggerNextJobs(nextConfig,
|
|
394
|
+
await triggerNextJobs(nextConfig, server);
|
|
393
395
|
}
|
|
394
396
|
|
|
395
397
|
return null;
|
|
@@ -606,19 +606,67 @@ async function getParentBuildStatus({ joinListNames, joinBuilds }) {
|
|
|
606
606
|
return { hasFailure, done };
|
|
607
607
|
}
|
|
608
608
|
|
|
609
|
+
/**
|
|
610
|
+
* Emit 'build_status' event to notify
|
|
611
|
+
* @param {Object} arg
|
|
612
|
+
* @param {Object} arg.server Server object
|
|
613
|
+
* @param {Build} arg.build Build
|
|
614
|
+
* @param {Pipeline} [arg.pipeline] Pipeline
|
|
615
|
+
* @param {Event} [arg.event] Event
|
|
616
|
+
* @param {Job} [arg.job] Job
|
|
617
|
+
* @returns {Promise}
|
|
618
|
+
*/
|
|
619
|
+
async function emitBuildStatusEvent({ server, build, pipeline, event, job }) {
|
|
620
|
+
const { buildFactory } = server.app;
|
|
621
|
+
|
|
622
|
+
event = event || (await build.event); // eslint-disable-line no-param-reassign
|
|
623
|
+
job = job || (await build.job); // eslint-disable-line no-param-reassign
|
|
624
|
+
pipeline = pipeline || (await job.pipeline); // eslint-disable-line no-param-reassign
|
|
625
|
+
|
|
626
|
+
let isFixed = false;
|
|
627
|
+
|
|
628
|
+
if (build.status === Status.SUCCESS) {
|
|
629
|
+
const failureBuild = await job.getLatestBuild({ status: Status.FAILURE });
|
|
630
|
+
const successBuild = await job.getLatestBuild({ status: Status.SUCCESS });
|
|
631
|
+
|
|
632
|
+
// Identify whether this build resulted in a previously failed job to become successful.
|
|
633
|
+
isFixed = !!((failureBuild && !successBuild) || failureBuild.id > successBuild.id);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return server.events.emit('build_status', {
|
|
637
|
+
settings: job.permutations[0].settings,
|
|
638
|
+
status: build.status,
|
|
639
|
+
event: event.toJson(),
|
|
640
|
+
pipeline: pipeline.toJson(),
|
|
641
|
+
jobName: job.name,
|
|
642
|
+
build: build.toJson(),
|
|
643
|
+
buildLink: `${buildFactory.uiUri}/pipelines/${pipeline.id}/builds/${build.id}`,
|
|
644
|
+
isFixed
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
|
|
609
648
|
/**
|
|
610
649
|
* Update virtual build status to SUCCESS and init metadata
|
|
611
|
-
* @param {
|
|
650
|
+
* @param {Object} arg
|
|
651
|
+
* @param {Object} arg.server Server object
|
|
652
|
+
* @param {Build} arg.build Build
|
|
653
|
+
* @param {Pipeline} [arg.pipeline] Pipeline
|
|
654
|
+
* @param {Event} [arg.event] Event
|
|
655
|
+
* @param {Job} [arg.job] Job
|
|
612
656
|
* @returns {Promise<Build>}
|
|
613
657
|
*/
|
|
614
|
-
async function updateVirtualBuildSuccess(build) {
|
|
658
|
+
async function updateVirtualBuildSuccess({ server, build, pipeline, event, job }) {
|
|
615
659
|
build.status = Status.SUCCESS;
|
|
616
660
|
build.statusMessage = BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessage;
|
|
617
661
|
build.statusMessageType = BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessageType;
|
|
618
662
|
|
|
619
663
|
await build.initMeta();
|
|
620
664
|
|
|
621
|
-
|
|
665
|
+
const newBuild = await build.update();
|
|
666
|
+
|
|
667
|
+
await emitBuildStatusEvent({ server, build: newBuild, pipeline, event, job });
|
|
668
|
+
|
|
669
|
+
return newBuild;
|
|
622
670
|
}
|
|
623
671
|
|
|
624
672
|
/**
|
|
@@ -628,6 +676,7 @@ async function updateVirtualBuildSuccess(build) {
|
|
|
628
676
|
* if no failure, start new build
|
|
629
677
|
* Otherwise, do nothing
|
|
630
678
|
* @param {Object} arg If the build is done or not
|
|
679
|
+
* @param {Object} arg.server Server object
|
|
631
680
|
* @param {String[]} arg.joinListNames Join list names
|
|
632
681
|
* @param {Build} arg.newBuild Next build
|
|
633
682
|
* @param {Job} arg.job Next job
|
|
@@ -639,6 +688,7 @@ async function updateVirtualBuildSuccess(build) {
|
|
|
639
688
|
* @returns {Promise<Build|null>} The newly updated/created build
|
|
640
689
|
*/
|
|
641
690
|
async function handleNewBuild({
|
|
691
|
+
server,
|
|
642
692
|
joinListNames,
|
|
643
693
|
newBuild,
|
|
644
694
|
job,
|
|
@@ -687,7 +737,7 @@ async function handleNewBuild({
|
|
|
687
737
|
|
|
688
738
|
// Bypass execution of the build if the job is virtual
|
|
689
739
|
if (isVirtualJob && !hasFreezeWindows(job)) {
|
|
690
|
-
return updateVirtualBuildSuccess(newBuild);
|
|
740
|
+
return updateVirtualBuildSuccess({ server, build: newBuild, event, job });
|
|
691
741
|
}
|
|
692
742
|
|
|
693
743
|
// All join builds finished successfully, and it's clear that a new build has not been started before.
|
|
@@ -1203,6 +1253,7 @@ module.exports = {
|
|
|
1203
1253
|
getJoinBuilds,
|
|
1204
1254
|
getParentBuildStatus,
|
|
1205
1255
|
handleNewBuild,
|
|
1256
|
+
emitBuildStatusEvent,
|
|
1206
1257
|
ensureStageTeardownBuildExists,
|
|
1207
1258
|
getBuildsForGroupEvent,
|
|
1208
1259
|
createJoinObject,
|
|
@@ -14,19 +14,20 @@ const { createInternalBuild, updateParentBuilds, handleNewBuild } = require('./h
|
|
|
14
14
|
class JoinBase {
|
|
15
15
|
/**
|
|
16
16
|
* Base class for AND trigger and RemoteJoin
|
|
17
|
-
* @param {Object}
|
|
18
|
-
* @param {EventFactory} app.eventFactory Server app object
|
|
19
|
-
* @param {BuildFactory} app.buildFactory Server app object
|
|
20
|
-
* @param {JobFactory} app.jobFactory Server app object
|
|
17
|
+
* @param {Object} server Server object
|
|
18
|
+
* @param {EventFactory} server.app.eventFactory Server app object
|
|
19
|
+
* @param {BuildFactory} server.app.buildFactory Server app object
|
|
20
|
+
* @param {JobFactory} server.app.jobFactory Server app object
|
|
21
21
|
* @param {Object} config Configuration object
|
|
22
22
|
* @param {Build} config.build
|
|
23
23
|
* @param {String} config.username
|
|
24
24
|
* @param {String} config.scmContext
|
|
25
25
|
*/
|
|
26
|
-
constructor(
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
26
|
+
constructor(server, config) {
|
|
27
|
+
this.server = server;
|
|
28
|
+
this.eventFactory = server.app.eventFactory;
|
|
29
|
+
this.buildFactory = server.app.buildFactory;
|
|
30
|
+
this.jobFactory = server.app.jobFactory;
|
|
30
31
|
|
|
31
32
|
this.currentBuild = config.build;
|
|
32
33
|
this.username = config.username;
|
|
@@ -89,6 +90,7 @@ class JoinBase {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
return handleNewBuild({
|
|
93
|
+
server: this.server,
|
|
92
94
|
joinListNames,
|
|
93
95
|
newBuild,
|
|
94
96
|
job: nextJob,
|
|
@@ -13,19 +13,20 @@ const { createInternalBuild, Status, updateVirtualBuildSuccess, hasFreezeWindows
|
|
|
13
13
|
class OrBase {
|
|
14
14
|
/**
|
|
15
15
|
* Trigger the next jobs of the current job
|
|
16
|
-
* @param {Object}
|
|
17
|
-
* @param {BuildFactory} app.buildFactory
|
|
18
|
-
* @param {JobFactory} app.jobFactory
|
|
19
|
-
* @param {PipelineFactory} app.pipelineFactory
|
|
16
|
+
* @param {Object} server Server object
|
|
17
|
+
* @param {BuildFactory} server.app.buildFactory
|
|
18
|
+
* @param {JobFactory} server.app.jobFactory
|
|
19
|
+
* @param {PipelineFactory} server.app.pipelineFactory
|
|
20
20
|
* @param {Object} config Configuration object
|
|
21
21
|
* @param {Build} config.currentBuild
|
|
22
22
|
* @param {String} config.username
|
|
23
23
|
* @param {String} config.scmContext
|
|
24
24
|
*/
|
|
25
|
-
constructor(
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
25
|
+
constructor(server, config) {
|
|
26
|
+
this.server = server;
|
|
27
|
+
this.buildFactory = server.app.buildFactory;
|
|
28
|
+
this.jobFactory = server.app.jobFactory;
|
|
29
|
+
this.pipelineFactory = server.app.pipelineFactory;
|
|
29
30
|
|
|
30
31
|
this.currentBuild = config.build;
|
|
31
32
|
this.username = config.username;
|
|
@@ -59,7 +60,7 @@ class OrBase {
|
|
|
59
60
|
|
|
60
61
|
// Bypass execution of the build if the job is virtual
|
|
61
62
|
if (isNextJobVirtual && !hasWindows) {
|
|
62
|
-
return updateVirtualBuildSuccess(nextBuild);
|
|
63
|
+
return updateVirtualBuildSuccess({ server: this.server, build: nextBuild, event, job: nextJob });
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
nextBuild.status = Status.QUEUED;
|
|
@@ -86,7 +87,7 @@ class OrBase {
|
|
|
86
87
|
|
|
87
88
|
// Bypass execution of the build if the job is virtual
|
|
88
89
|
if (isNextJobVirtual && !hasWindows) {
|
|
89
|
-
await updateVirtualBuildSuccess(nextBuild);
|
|
90
|
+
await updateVirtualBuildSuccess({ server: this.server, build: nextBuild, event, job: nextJob });
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
return nextBuild;
|