screwdriver-api 7.0.254 → 7.0.256
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/index.js
CHANGED
|
@@ -39,7 +39,8 @@ const {
|
|
|
39
39
|
getParallelBuilds,
|
|
40
40
|
isStartFromMiddleOfCurrentStage,
|
|
41
41
|
Status,
|
|
42
|
-
getSameParentEvents
|
|
42
|
+
getSameParentEvents,
|
|
43
|
+
isVirtualJob
|
|
43
44
|
} = require('./triggers/helpers');
|
|
44
45
|
const { getFullStageJobName } = require('../helper');
|
|
45
46
|
|
|
@@ -97,7 +98,7 @@ async function triggerNextJobs(config, app) {
|
|
|
97
98
|
|
|
98
99
|
for (const [nextJobName, nextJobInfo] of Object.entries(currentPipelineNextJobs)) {
|
|
99
100
|
const nextJob = await getJob(nextJobName, currentPipeline.id, jobFactory);
|
|
100
|
-
const {
|
|
101
|
+
const { stageName: nextJobStageName } = nextJobInfo;
|
|
101
102
|
const resource = `pipeline:${currentPipeline.id}:groupEvent:${currentEvent.groupEventId}`;
|
|
102
103
|
let lock;
|
|
103
104
|
let nextBuild;
|
|
@@ -123,24 +124,12 @@ async function triggerNextJobs(config, app) {
|
|
|
123
124
|
isOrTrigger(currentEvent.workflowGraph, originalCurrentJobName, trimJobName(nextJobName)) ||
|
|
124
125
|
isStartFromMiddleOfCurrentStage(currentJob.name, currentEvent.startFrom, currentEvent.workflowGraph)
|
|
125
126
|
) {
|
|
126
|
-
nextBuild = await orTrigger.execute(
|
|
127
|
-
currentEvent,
|
|
128
|
-
currentPipeline.id,
|
|
129
|
-
nextJob,
|
|
130
|
-
parentBuilds,
|
|
131
|
-
isNextJobVirtual
|
|
132
|
-
);
|
|
127
|
+
nextBuild = await orTrigger.execute(currentEvent, currentPipeline.id, nextJob, parentBuilds);
|
|
133
128
|
} else {
|
|
134
|
-
nextBuild = await andTrigger.execute(
|
|
135
|
-
nextJob,
|
|
136
|
-
parentBuilds,
|
|
137
|
-
joinListNames,
|
|
138
|
-
isNextJobVirtual,
|
|
139
|
-
nextJobStageName
|
|
140
|
-
);
|
|
129
|
+
nextBuild = await andTrigger.execute(nextJob, parentBuilds, joinListNames, nextJobStageName);
|
|
141
130
|
}
|
|
142
131
|
|
|
143
|
-
if (
|
|
132
|
+
if (isVirtualJob(nextJob) && nextBuild && nextBuild.status === Status.SUCCESS) {
|
|
144
133
|
downstreamOfNextJobsToBeProcessed.push({
|
|
145
134
|
build: nextBuild,
|
|
146
135
|
event: currentEvent,
|
|
@@ -285,7 +274,7 @@ async function triggerNextJobs(config, app) {
|
|
|
285
274
|
if (externalEvent) {
|
|
286
275
|
for (const [nextJobName, nextJobInfo] of Object.entries(joinedPipeline.jobs)) {
|
|
287
276
|
const nextJob = await getJob(nextJobName, joinedPipelineId, jobFactory);
|
|
288
|
-
const {
|
|
277
|
+
const { stageName: nextJobStageName } = nextJobInfo;
|
|
289
278
|
|
|
290
279
|
const { parentBuilds } = parseJobInfo({
|
|
291
280
|
joinObj: joinedPipeline.jobs,
|
|
@@ -306,8 +295,7 @@ async function triggerNextJobs(config, app) {
|
|
|
306
295
|
externalEvent,
|
|
307
296
|
externalEvent.pipelineId,
|
|
308
297
|
nextJob,
|
|
309
|
-
parentBuilds
|
|
310
|
-
isNextJobVirtual
|
|
298
|
+
parentBuilds
|
|
311
299
|
);
|
|
312
300
|
} else {
|
|
313
301
|
// Re get join list when first time remote trigger since external event was empty and cannot get workflow graph then
|
|
@@ -323,12 +311,11 @@ async function triggerNextJobs(config, app) {
|
|
|
323
311
|
parentBuilds,
|
|
324
312
|
groupEventBuilds,
|
|
325
313
|
joinListNames,
|
|
326
|
-
isNextJobVirtual,
|
|
327
314
|
nextJobStageName
|
|
328
315
|
);
|
|
329
316
|
}
|
|
330
317
|
|
|
331
|
-
if (
|
|
318
|
+
if (isVirtualJob(nextJob) && nextBuild && nextBuild.status === Status.SUCCESS) {
|
|
332
319
|
downstreamOfNextJobsToBeProcessed.push({
|
|
333
320
|
build: nextBuild,
|
|
334
321
|
event: currentEvent,
|
|
@@ -128,6 +128,28 @@ function isExternalTrigger(jobName) {
|
|
|
128
128
|
return EXTERNAL_TRIGGER_ALL.test(jobName);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Checks if job is virtual
|
|
133
|
+
* @param {Job} job Job object
|
|
134
|
+
* @returns {Boolean}
|
|
135
|
+
*/
|
|
136
|
+
function isVirtualJob(job) {
|
|
137
|
+
const { annotations } = job.permutations[0];
|
|
138
|
+
|
|
139
|
+
return annotations ? annotations['screwdriver.cd/virtualJob'] === true : false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Checks if job has freezeWindows
|
|
144
|
+
* @param {Job} job Job object
|
|
145
|
+
* @returns {Boolean}
|
|
146
|
+
*/
|
|
147
|
+
function hasFreezeWindows(job) {
|
|
148
|
+
const { freezeWindows } = job.permutations[0];
|
|
149
|
+
|
|
150
|
+
return freezeWindows ? freezeWindows.length > 0 : false;
|
|
151
|
+
}
|
|
152
|
+
|
|
131
153
|
/**
|
|
132
154
|
* Get external pipelineId and job name from the `name`
|
|
133
155
|
* @param {String} name Job name
|
|
@@ -611,11 +633,10 @@ async function getParentBuildStatus({ newBuild, joinListNames, pipelineId, build
|
|
|
611
633
|
* @param {Job} arg.job Next job
|
|
612
634
|
* @param {String|undefined} arg.pipelineId Pipeline ID
|
|
613
635
|
* @param {String|undefined} arg.stageName Stage name
|
|
614
|
-
* @param {Boolean} arg.isVirtualJob If the job is virtual or not
|
|
615
636
|
* @param {Event} arg.event Event
|
|
616
637
|
* @returns {Promise<Build|null>} The newly updated/created build
|
|
617
638
|
*/
|
|
618
|
-
async function handleNewBuild({ done, hasFailure, newBuild, job, pipelineId, stageName,
|
|
639
|
+
async function handleNewBuild({ done, hasFailure, newBuild, job, pipelineId, stageName, event }) {
|
|
619
640
|
if (!done || Status.isStarted(newBuild.status)) {
|
|
620
641
|
return null;
|
|
621
642
|
}
|
|
@@ -636,9 +657,7 @@ async function handleNewBuild({ done, hasFailure, newBuild, job, pipelineId, sta
|
|
|
636
657
|
}
|
|
637
658
|
|
|
638
659
|
// Bypass execution of the build if the job is virtual
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
if (isVirtualJob && !hasFreezeWindows) {
|
|
660
|
+
if (isVirtualJob(job) && !hasFreezeWindows(job)) {
|
|
642
661
|
newBuild.status = Status.SUCCESS;
|
|
643
662
|
newBuild.statusMessage = BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessage;
|
|
644
663
|
newBuild.statusMessageType = BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessageType;
|
|
@@ -902,7 +921,6 @@ async function createJoinObject(nextJobNames, current, eventFactory) {
|
|
|
902
921
|
|
|
903
922
|
const node = event.workflowGraph.nodes.find(n => n.name === trimJobName(jobName));
|
|
904
923
|
const jId = node.id;
|
|
905
|
-
const isVirtual = node.virtual || false;
|
|
906
924
|
const stageName = node.stageName || null;
|
|
907
925
|
|
|
908
926
|
if (!joinObj[nextJobPipelineId]) joinObj[nextJobPipelineId] = {};
|
|
@@ -923,7 +941,7 @@ async function createJoinObject(nextJobNames, current, eventFactory) {
|
|
|
923
941
|
}
|
|
924
942
|
|
|
925
943
|
if (!pipelineObj.jobs) pipelineObj.jobs = {};
|
|
926
|
-
pipelineObj.jobs[nextJobName] = { id: jId, join: jobs, isExternal,
|
|
944
|
+
pipelineObj.jobs[nextJobName] = { id: jId, join: jobs, isExternal, stageName };
|
|
927
945
|
}
|
|
928
946
|
|
|
929
947
|
return joinObj;
|
|
@@ -1192,5 +1210,7 @@ module.exports = {
|
|
|
1192
1210
|
buildsToRestartFilter,
|
|
1193
1211
|
trimJobName,
|
|
1194
1212
|
isStartFromMiddleOfCurrentStage,
|
|
1213
|
+
isVirtualJob,
|
|
1214
|
+
hasFreezeWindows,
|
|
1195
1215
|
BUILD_STATUS_MESSAGES
|
|
1196
1216
|
};
|
|
@@ -43,7 +43,6 @@ class JoinBase {
|
|
|
43
43
|
* @param {import('./helpers').ParentBuilds} parentBuilds
|
|
44
44
|
* @param {String} parentBuildId
|
|
45
45
|
* @param {String[]} joinListNames
|
|
46
|
-
* @param {Boolean} isNextJobVirtual
|
|
47
46
|
* @param {String} nextJobStageName
|
|
48
47
|
* @returns {Promise<Build[]|null>}
|
|
49
48
|
*/
|
|
@@ -55,7 +54,6 @@ class JoinBase {
|
|
|
55
54
|
parentBuilds,
|
|
56
55
|
parentBuildId,
|
|
57
56
|
joinListNames,
|
|
58
|
-
isNextJobVirtual,
|
|
59
57
|
nextJobStageName
|
|
60
58
|
}) {
|
|
61
59
|
let newBuild;
|
|
@@ -104,7 +102,6 @@ class JoinBase {
|
|
|
104
102
|
newBuild,
|
|
105
103
|
job: nextJob,
|
|
106
104
|
pipelineId,
|
|
107
|
-
isVirtualJob: isNextJobVirtual,
|
|
108
105
|
stageName: nextJobStageName,
|
|
109
106
|
event
|
|
110
107
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { createInternalBuild, Status, BUILD_STATUS_MESSAGES } = require('./helpers');
|
|
3
|
+
const { createInternalBuild, Status, BUILD_STATUS_MESSAGES, isVirtualJob, hasFreezeWindows } = require('./helpers');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @typedef {import('screwdriver-models').BuildFactory} BuildFactory
|
|
@@ -38,18 +38,16 @@ class OrBase {
|
|
|
38
38
|
* @param {Number} pipelineId
|
|
39
39
|
* @param {Job} nextJob
|
|
40
40
|
* @param {import('./helpers').ParentBuilds} parentBuilds
|
|
41
|
-
* @param {Boolean} isNextJobVirtual
|
|
42
41
|
* @return {Promise<Build|null>}
|
|
43
42
|
*/
|
|
44
|
-
async trigger(event, pipelineId, nextJob, parentBuilds
|
|
43
|
+
async trigger(event, pipelineId, nextJob, parentBuilds) {
|
|
45
44
|
let nextBuild = await this.buildFactory.get({
|
|
46
45
|
eventId: event.id,
|
|
47
46
|
jobId: nextJob.id
|
|
48
47
|
});
|
|
49
48
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
const isNextJobVirtual = isVirtualJob(nextJob);
|
|
50
|
+
const hasWindows = hasFreezeWindows(nextJob);
|
|
53
51
|
const causeMessage = nextJob.name === event.startFrom ? event.causeMessage : '';
|
|
54
52
|
|
|
55
53
|
if (nextBuild !== null) {
|
|
@@ -58,7 +56,7 @@ class OrBase {
|
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
// Bypass execution of the build if the job is virtual
|
|
61
|
-
if (isNextJobVirtual && !
|
|
59
|
+
if (isNextJobVirtual && !hasWindows) {
|
|
62
60
|
nextBuild.status = Status.SUCCESS;
|
|
63
61
|
nextBuild.statusMessage = BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessage;
|
|
64
62
|
nextBuild.statusMessageType = BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessageType;
|
|
@@ -84,17 +82,17 @@ class OrBase {
|
|
|
84
82
|
baseBranch: event.baseBranch || null,
|
|
85
83
|
parentBuilds,
|
|
86
84
|
parentBuildId: this.currentBuild.id,
|
|
87
|
-
start:
|
|
85
|
+
start: hasWindows || !isNextJobVirtual,
|
|
88
86
|
causeMessage
|
|
89
87
|
});
|
|
90
88
|
|
|
91
89
|
// Bypass execution of the build if the job is virtual
|
|
92
|
-
if (isNextJobVirtual && !
|
|
90
|
+
if (isNextJobVirtual && !hasWindows) {
|
|
93
91
|
nextBuild.status = Status.SUCCESS;
|
|
94
92
|
nextBuild.statusMessage = BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessage;
|
|
95
93
|
nextBuild.statusMessageType = BUILD_STATUS_MESSAGES.SKIP_VIRTUAL_JOB.statusMessageType;
|
|
96
94
|
|
|
97
|
-
|
|
95
|
+
await nextBuild.update();
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
return nextBuild;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const joi = require('joi');
|
|
4
4
|
const schema = require('screwdriver-data-schema');
|
|
5
5
|
const idSchema = schema.models.pipeline.base.extract('id');
|
|
6
|
+
const scmUriSchema = schema.models.pipeline.base.extract('scmUri');
|
|
6
7
|
const listSchema = joi.array().items(schema.models.pipeline.get).label('List of Pipelines');
|
|
7
8
|
const pipelineIdsSchema = joi.alternatives().try(joi.array().items(idSchema), idSchema).required();
|
|
8
9
|
const IDS_KEY = 'ids[]';
|
|
@@ -21,7 +22,7 @@ module.exports = () => ({
|
|
|
21
22
|
|
|
22
23
|
handler: async (request, h) => {
|
|
23
24
|
const { pipelineFactory } = request.server.app;
|
|
24
|
-
const { sort, configPipelineId, sortBy, search, page, count } = request.query;
|
|
25
|
+
const { sort, configPipelineId, sortBy, search, scmUri, page, count } = request.query;
|
|
25
26
|
const scmContexts = pipelineFactory.scm.getScmContexts();
|
|
26
27
|
let pipelineArray = [];
|
|
27
28
|
|
|
@@ -55,6 +56,15 @@ module.exports = () => ({
|
|
|
55
56
|
// See https://www.w3schools.com/sql/sql_like.asp for syntax
|
|
56
57
|
keyword: `%${search}%`
|
|
57
58
|
};
|
|
59
|
+
} else if (scmUri) {
|
|
60
|
+
// The format of scmUri is 'github.com:123:main:source-dir'
|
|
61
|
+
// Search pipelines based on the same repository (include other branch)
|
|
62
|
+
const [scm, id] = scmUri.split(':');
|
|
63
|
+
|
|
64
|
+
config.search = {
|
|
65
|
+
field: 'scmUri',
|
|
66
|
+
keyword: `${scm}:${id}:%`
|
|
67
|
+
};
|
|
58
68
|
} else {
|
|
59
69
|
// default list all to 50 max count, according to schema.api.pagination
|
|
60
70
|
config.paginate = {
|
|
@@ -118,7 +128,8 @@ module.exports = () => ({
|
|
|
118
128
|
query: schema.api.pagination.concat(
|
|
119
129
|
joi.object({
|
|
120
130
|
configPipelineId: idSchema,
|
|
121
|
-
'ids[]': pipelineIdsSchema.optional()
|
|
131
|
+
'ids[]': pipelineIdsSchema.optional(),
|
|
132
|
+
scmUri: scmUriSchema
|
|
122
133
|
})
|
|
123
134
|
)
|
|
124
135
|
}
|