screwdriver-api 7.0.242 → 7.0.244
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
package/plugins/builds/update.js
CHANGED
|
@@ -37,7 +37,6 @@ async function getBuildToUpdate(id, buildFactory) {
|
|
|
37
37
|
async function validateUserPermission(build, request) {
|
|
38
38
|
const { jobFactory, userFactory, bannerFactory, pipelineFactory } = request.server.app;
|
|
39
39
|
const { username, scmContext, scmUserId } = request.auth.credentials;
|
|
40
|
-
|
|
41
40
|
const { status: desiredStatus } = request.payload;
|
|
42
41
|
|
|
43
42
|
const scmDisplayName = bannerFactory.scm.getDisplayName({ scmContext });
|
|
@@ -66,6 +65,20 @@ async function validateUserPermission(build, request) {
|
|
|
66
65
|
await getUserPermissions({ user, scmUri, level: 'push', isAdmin: adminDetails.isAdmin });
|
|
67
66
|
}
|
|
68
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Prevent duplicate builds with the same build ID
|
|
70
|
+
* @param {Object} build Build object
|
|
71
|
+
* @param {Object} request hapi request object
|
|
72
|
+
* @throws boom.forbidden error
|
|
73
|
+
*/
|
|
74
|
+
async function preventDuplicateBuild(build, request) {
|
|
75
|
+
const { status: desiredStatus } = request.payload;
|
|
76
|
+
|
|
77
|
+
if (build.status === 'RUNNING' && desiredStatus === 'RUNNING') {
|
|
78
|
+
throw boom.forbidden(`Can not update status to RUNNING. Build Id: ${build.id} is still running.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
69
82
|
module.exports = () => ({
|
|
70
83
|
method: 'PUT',
|
|
71
84
|
path: '/builds/{id}',
|
|
@@ -91,7 +104,9 @@ module.exports = () => ({
|
|
|
91
104
|
|
|
92
105
|
const build = await getBuildToUpdate(id, buildFactory);
|
|
93
106
|
|
|
94
|
-
if (
|
|
107
|
+
if (isBuild) {
|
|
108
|
+
await preventDuplicateBuild(build, request);
|
|
109
|
+
} else {
|
|
95
110
|
await validateUserPermission(build, request);
|
|
96
111
|
}
|
|
97
112
|
|
package/plugins/events/create.js
CHANGED
|
@@ -5,8 +5,7 @@ const boom = require('@hapi/boom');
|
|
|
5
5
|
const validationSchema = require('screwdriver-data-schema');
|
|
6
6
|
const ANNOT_RESTRICT_PR = 'screwdriver.cd/restrictPR';
|
|
7
7
|
const { getScmUri, isStageTeardown } = require('../helper');
|
|
8
|
-
const {
|
|
9
|
-
const { Status, BUILD_STATUS_MESSAGES } = require('../builds/triggers/helpers');
|
|
8
|
+
const { createEvent } = require('./helper/createEvent');
|
|
10
9
|
|
|
11
10
|
module.exports = () => ({
|
|
12
11
|
method: 'POST',
|
|
@@ -253,28 +252,12 @@ module.exports = () => ({
|
|
|
253
252
|
}
|
|
254
253
|
}
|
|
255
254
|
|
|
256
|
-
const event = await
|
|
255
|
+
const event = await createEvent(payload, request.server);
|
|
257
256
|
|
|
258
257
|
if (event.builds === null) {
|
|
259
258
|
return boom.notFound('No jobs to start.');
|
|
260
259
|
}
|
|
261
260
|
|
|
262
|
-
const virtualJobBuilds = event.builds.filter(b => b.status === 'CREATED');
|
|
263
|
-
|
|
264
|
-
for (const build of virtualJobBuilds) {
|
|
265
|
-
await updateBuildAndTriggerDownstreamJobs(
|
|
266
|
-
{
|
|
267
|
-
status: Status.SUCCESS,
|
|
268
|
-
statusMessage: BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessage,
|
|
269
|
-
statusMessageType: BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessageType
|
|
270
|
-
},
|
|
271
|
-
build,
|
|
272
|
-
request.server,
|
|
273
|
-
username,
|
|
274
|
-
scmContext
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
261
|
// everything succeeded, inform the user
|
|
279
262
|
const location = urlLib.format({
|
|
280
263
|
host: request.headers.host,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { updateBuildAndTriggerDownstreamJobs } = require('../../builds/helper/updateBuild');
|
|
4
|
+
const { Status, BUILD_STATUS_MESSAGES } = require('../../builds/triggers/helpers');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('screwdriver-models/lib/event')} Event
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a new event.
|
|
12
|
+
* Updates the status of all the virtual builds at the beginning of the event workflow to "SUCCESS"
|
|
13
|
+
* and trigger their downstream jobs.
|
|
14
|
+
*
|
|
15
|
+
* @method createEvent
|
|
16
|
+
* @param {Object} config
|
|
17
|
+
* @param {String} config.username
|
|
18
|
+
* @param {Object} config.scmContext
|
|
19
|
+
* @param {Object} server
|
|
20
|
+
* @returns {Promise<Event>} Newly created event
|
|
21
|
+
*/
|
|
22
|
+
async function createEvent(config, server) {
|
|
23
|
+
const { eventFactory } = server.app;
|
|
24
|
+
const { username, scmContext } = config;
|
|
25
|
+
const event = await eventFactory.create(config);
|
|
26
|
+
|
|
27
|
+
if (event.builds) {
|
|
28
|
+
const virtualJobBuilds = event.builds.filter(b => b.status === 'CREATED');
|
|
29
|
+
|
|
30
|
+
for (const build of virtualJobBuilds) {
|
|
31
|
+
await updateBuildAndTriggerDownstreamJobs(
|
|
32
|
+
{
|
|
33
|
+
status: Status.SUCCESS,
|
|
34
|
+
statusMessage: BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessage,
|
|
35
|
+
statusMessageType: BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessageType
|
|
36
|
+
},
|
|
37
|
+
build,
|
|
38
|
+
server,
|
|
39
|
+
username,
|
|
40
|
+
scmContext
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return event;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
createEvent
|
|
50
|
+
};
|
|
@@ -4,6 +4,7 @@ const boom = require('@hapi/boom');
|
|
|
4
4
|
const joi = require('joi');
|
|
5
5
|
const schema = require('screwdriver-data-schema');
|
|
6
6
|
const { getUserPermissions } = require('../helper');
|
|
7
|
+
const { createEvent } = require('../events/helper/createEvent');
|
|
7
8
|
const idSchema = schema.models.pipeline.base.extract('id');
|
|
8
9
|
|
|
9
10
|
module.exports = () => ({
|
|
@@ -19,7 +20,7 @@ module.exports = () => ({
|
|
|
19
20
|
},
|
|
20
21
|
|
|
21
22
|
handler: async (request, h) => {
|
|
22
|
-
const { pipelineFactory,
|
|
23
|
+
const { pipelineFactory, userFactory } = request.server.app;
|
|
23
24
|
const { username, scmContext } = request.auth.credentials;
|
|
24
25
|
const { id } = request.params;
|
|
25
26
|
const { scm } = pipelineFactory;
|
|
@@ -41,7 +42,7 @@ module.exports = () => ({
|
|
|
41
42
|
}
|
|
42
43
|
});
|
|
43
44
|
|
|
44
|
-
const
|
|
45
|
+
const createdEvents = await Promise.allSettled(
|
|
45
46
|
pipelines.map(async p => {
|
|
46
47
|
const pipelineToken = await p.token;
|
|
47
48
|
const pipelineScmContext = p.scmContext;
|
|
@@ -53,18 +54,21 @@ module.exports = () => ({
|
|
|
53
54
|
|
|
54
55
|
await getUserPermissions({ user, scmUri: p.scmUri, level: 'push' });
|
|
55
56
|
|
|
56
|
-
await
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
await createEvent(
|
|
58
|
+
{
|
|
59
|
+
pipelineId: p.id,
|
|
60
|
+
sha,
|
|
61
|
+
username,
|
|
62
|
+
scmContext: pipelineScmContext,
|
|
63
|
+
startFrom: '~commit',
|
|
64
|
+
causeMessage: `Started by ${username}`
|
|
65
|
+
},
|
|
66
|
+
request.server
|
|
67
|
+
);
|
|
64
68
|
})
|
|
65
69
|
);
|
|
66
70
|
|
|
67
|
-
const rejected =
|
|
71
|
+
const rejected = createdEvents.filter(createdEvent => createdEvent.status === 'rejected');
|
|
68
72
|
|
|
69
73
|
if (rejected.length) {
|
|
70
74
|
throw boom.forbidden('Failed to start some child pipelines due to lack of permissions.');
|
|
@@ -4,6 +4,7 @@ const workflowParser = require('screwdriver-workflow-parser');
|
|
|
4
4
|
const schema = require('screwdriver-data-schema');
|
|
5
5
|
const logger = require('screwdriver-logger');
|
|
6
6
|
const { getReadOnlyInfo } = require('../helper');
|
|
7
|
+
const { createEvent } = require('../events/helper/createEvent');
|
|
7
8
|
|
|
8
9
|
const ANNOT_NS = 'screwdriver.cd';
|
|
9
10
|
const ANNOT_CHAIN_PR = `${ANNOT_NS}/chainPR`;
|
|
@@ -413,10 +414,10 @@ async function triggeredPipelines(
|
|
|
413
414
|
* Start Events
|
|
414
415
|
* @async startEvents
|
|
415
416
|
* @param {Array} eventConfigs Array of event config objects
|
|
416
|
-
* @param {Object}
|
|
417
|
+
* @param {Object} server Server
|
|
417
418
|
* @return {Promise<Array>} Array of created events
|
|
418
419
|
*/
|
|
419
|
-
async function startEvents(eventConfigs,
|
|
420
|
+
async function startEvents(eventConfigs, server) {
|
|
420
421
|
const events = [];
|
|
421
422
|
let errorCount = 0;
|
|
422
423
|
let eventsCount = 0;
|
|
@@ -426,7 +427,7 @@ async function startEvents(eventConfigs, eventFactory) {
|
|
|
426
427
|
if (eventConfig && eventConfig.configPipelineSha) {
|
|
427
428
|
eventsCount += 1;
|
|
428
429
|
|
|
429
|
-
return
|
|
430
|
+
return createEvent(eventConfig, server);
|
|
430
431
|
}
|
|
431
432
|
|
|
432
433
|
return Promise.resolve(null);
|
|
@@ -626,7 +627,7 @@ async function createPREvents(options, request) {
|
|
|
626
627
|
})
|
|
627
628
|
);
|
|
628
629
|
|
|
629
|
-
const events = await startEvents(eventConfigs,
|
|
630
|
+
const events = await startEvents(eventConfigs, request.server);
|
|
630
631
|
|
|
631
632
|
return events;
|
|
632
633
|
}
|
|
@@ -944,23 +945,15 @@ function pullRequestEvent(pluginOptions, request, h, parsed, token) {
|
|
|
944
945
|
/**
|
|
945
946
|
* Create events for each pipeline
|
|
946
947
|
* @async createEvents
|
|
947
|
-
* @param {
|
|
948
|
-
* @param {UserFactory}
|
|
949
|
-
* @param {PipelineFactory}
|
|
950
|
-
* @param {Array}
|
|
951
|
-
* @param {Object}
|
|
948
|
+
* @param {Object} server
|
|
949
|
+
* @param {UserFactory} userFactory To get user permission
|
|
950
|
+
* @param {PipelineFactory} pipelineFactory To use scm module
|
|
951
|
+
* @param {Array} pipelines The pipelines to start events
|
|
952
|
+
* @param {Object} parsed It has information to create event
|
|
952
953
|
* @param {String} [skipMessage] Message to skip starting builds
|
|
953
954
|
* @returns {Promise} Promise that resolves into events
|
|
954
955
|
*/
|
|
955
|
-
async function createEvents(
|
|
956
|
-
eventFactory,
|
|
957
|
-
userFactory,
|
|
958
|
-
pipelineFactory,
|
|
959
|
-
pipelines,
|
|
960
|
-
parsed,
|
|
961
|
-
skipMessage,
|
|
962
|
-
scmConfigFromHook
|
|
963
|
-
) {
|
|
956
|
+
async function createEvents(server, userFactory, pipelineFactory, pipelines, parsed, skipMessage, scmConfigFromHook) {
|
|
964
957
|
const { action, branch, sha, username, scmContext, changedFiles, type, releaseName, ref } = parsed;
|
|
965
958
|
|
|
966
959
|
const pipelineTuples = await Promise.all(
|
|
@@ -1101,7 +1094,7 @@ async function createEvents(
|
|
|
1101
1094
|
})
|
|
1102
1095
|
);
|
|
1103
1096
|
|
|
1104
|
-
const events = await startEvents(eventConfigs,
|
|
1097
|
+
const events = await startEvents(eventConfigs, server);
|
|
1105
1098
|
|
|
1106
1099
|
return events;
|
|
1107
1100
|
}
|
|
@@ -1117,7 +1110,7 @@ async function createEvents(
|
|
|
1117
1110
|
* @param {String} [skipMessage] Message to skip starting builds
|
|
1118
1111
|
*/
|
|
1119
1112
|
async function pushEvent(request, h, parsed, skipMessage, token) {
|
|
1120
|
-
const {
|
|
1113
|
+
const { pipelineFactory, userFactory } = request.server.app;
|
|
1121
1114
|
const { hookId, checkoutUrl, branch, scmContext, type, action, changedFiles, releaseName, ref } = parsed;
|
|
1122
1115
|
|
|
1123
1116
|
const fullCheckoutUrl = `${checkoutUrl}#${branch}`;
|
|
@@ -1154,7 +1147,7 @@ async function pushEvent(request, h, parsed, skipMessage, token) {
|
|
|
1154
1147
|
request.log(['webhook', hookId], `Skipping since Pipeline ${fullCheckoutUrl} does not exist`);
|
|
1155
1148
|
} else {
|
|
1156
1149
|
events = await createEvents(
|
|
1157
|
-
|
|
1150
|
+
request.server,
|
|
1158
1151
|
userFactory,
|
|
1159
1152
|
pipelineFactory,
|
|
1160
1153
|
pipelines,
|