screwdriver-api 8.0.74 → 8.0.75

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screwdriver-api",
3
- "version": "8.0.74",
3
+ "version": "8.0.75",
4
4
  "description": "API server for the Screwdriver.cd service",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -8,6 +8,7 @@ const { getFullStageJobName } = require('../../helper');
8
8
  const { updateVirtualBuildSuccess } = require('../triggers/helpers');
9
9
  const TERMINAL_STATUSES = ['FAILURE', 'ABORTED', 'UNSTABLE', 'COLLAPSED'];
10
10
  const FINISHED_STATUSES = ['SUCCESS', ...TERMINAL_STATUSES];
11
+ const NON_TERMINATED_STATUSES = ['CREATED', 'RUNNING', 'QUEUED', 'BLOCKED', 'FROZEN'];
11
12
 
12
13
  /**
13
14
  * @typedef {import('screwdriver-models/lib/build')} Build
@@ -15,6 +16,50 @@ const FINISHED_STATUSES = ['SUCCESS', ...TERMINAL_STATUSES];
15
16
  * @typedef {import('screwdriver-models/lib/step')} Step
16
17
  */
17
18
 
19
+ /**
20
+ * Get the message when the build is stopped from the event.
21
+ *
22
+ * @method getEventAbortedStatusMessage
23
+ * @param {Build[]} builds Build Array
24
+ */
25
+ function getEventAbortedStatusMessage(builds) {
26
+ for (const b of builds) {
27
+ if (b.status === 'ABORTED' && b.statusMessage && b.statusMessage.startsWith('Aborted event')) {
28
+ return b.statusMessage;
29
+ }
30
+ }
31
+
32
+ return undefined;
33
+ }
34
+
35
+ /**
36
+ * Stop builds and set status message
37
+ *
38
+ * @method stopBuilds
39
+ * @param {String} statusMessage Build status message
40
+ * @param {Build[]} builds Build Array
41
+ */
42
+ function stopBuilds(builds, statusMessage) {
43
+ const unchangedBuilds = [];
44
+ const changedBuilds = [];
45
+
46
+ for (const build of builds) {
47
+ if (NON_TERMINATED_STATUSES.includes(build.status)) {
48
+ if (build.status === 'RUNNING') {
49
+ build.endTime = new Date().toISOString();
50
+ }
51
+ build.status = 'ABORTED';
52
+ build.statusMessage = statusMessage;
53
+
54
+ changedBuilds.push(build);
55
+ } else {
56
+ unchangedBuilds.push(build);
57
+ }
58
+ }
59
+
60
+ return { unchangedBuilds, changedBuilds };
61
+ }
62
+
18
63
  /**
19
64
  * Identify whether this build resulted in a previously failed job to become successful.
20
65
  *
@@ -363,7 +408,21 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
363
408
  let isFixed = Promise.resolve(false);
364
409
  let stopFrozen = null;
365
410
 
366
- updateBuildStatus(build, desiredStatus, statusMessage, statusMessageType, username);
411
+ // If the event is Aborted, check if there are any builds within the same event
412
+ // that have been stopped by the event, and if so, force this build to be Aborted.
413
+ if (build.status !== 'ABORTED' && event.status === 'ABORTED') {
414
+ const builds = await event.getBuilds();
415
+ const eventAbortedStatusMessage = getEventAbortedStatusMessage(builds);
416
+
417
+ if (eventAbortedStatusMessage) {
418
+ build.status = 'ABORTED';
419
+ build.statusMessage = eventAbortedStatusMessage;
420
+ }
421
+ }
422
+
423
+ if (build.status !== 'ABORTED') {
424
+ updateBuildStatus(build, desiredStatus, statusMessage, statusMessageType, username);
425
+ }
367
426
 
368
427
  // If status got updated to RUNNING or COLLAPSED, update init endTime and code
369
428
  if (['RUNNING', 'COLLAPSED', 'FROZEN'].includes(desiredStatus)) {
@@ -475,7 +534,17 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
475
534
 
476
535
  // update event status
477
536
  const latestBuilds = await newEvent.getBuilds();
478
- const newEventStatus = deriveEventStatusFromBuildStatuses(latestBuilds);
537
+ let updatedBuilds = latestBuilds;
538
+
539
+ const eventAbortedStatusMessage = getEventAbortedStatusMessage(latestBuilds);
540
+
541
+ if (eventAbortedStatusMessage) {
542
+ const { unchangedBuilds, changedBuilds } = stopBuilds(latestBuilds, eventAbortedStatusMessage);
543
+
544
+ updatedBuilds = [...unchangedBuilds, ...(await Promise.all(changedBuilds.map(b => b.update())))];
545
+ }
546
+
547
+ const newEventStatus = deriveEventStatusFromBuildStatuses(updatedBuilds);
479
548
 
480
549
  if (newEventStatus && newEvent.status !== newEventStatus) {
481
550
  newEvent.status = newEventStatus;
@@ -486,6 +555,7 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
486
555
  }
487
556
 
488
557
  module.exports = {
558
+ stopBuilds,
489
559
  updateBuildAndTriggerDownstreamJobs,
490
560
  deriveEventStatusFromBuildStatuses,
491
561
  getStageBuild,
@@ -7,7 +7,7 @@ const joi = require('joi');
7
7
  const schema = require('screwdriver-data-schema');
8
8
  const getSchema = schema.models.event.get;
9
9
  const idSchema = schema.models.event.base.extract('id');
10
- const { deriveEventStatusFromBuildStatuses } = require('../builds/helper/updateBuild');
10
+ const { deriveEventStatusFromBuildStatuses, stopBuilds } = require('../builds/helper/updateBuild');
11
11
  const nonTerminatedStatus = ['CREATED', 'RUNNING', 'QUEUED', 'BLOCKED', 'FROZEN'];
12
12
 
13
13
  module.exports = () => ({
@@ -79,25 +79,13 @@ module.exports = () => ({
79
79
 
80
80
  // User has good permissions, get event builds
81
81
  const builds = await event.getBuilds();
82
- const toUpdateBuilds = [];
83
- const updatedBuilds = [];
84
82
 
85
83
  // Update endtime and stop running builds
86
84
  // Note: COLLAPSED builds will never run
87
- builds.forEach(b => {
88
- if (nonTerminatedStatus.includes(b.status)) {
89
- if (b.status === 'RUNNING') {
90
- b.endTime = new Date().toISOString();
91
- }
92
- b.status = 'ABORTED';
93
- b.statusMessage = `Aborted by ${username}`;
94
-
95
- toUpdateBuilds.push(b.update());
96
- } else {
97
- updatedBuilds.push(b);
98
- }
99
- });
100
- updatedBuilds.push(...(await Promise.all(toUpdateBuilds)));
85
+ const statusMessage = `Aborted event by ${username}`;
86
+
87
+ const { unchangedBuilds, changedBuilds } = stopBuilds(builds, statusMessage);
88
+ const updatedBuilds = [...unchangedBuilds, ...(await Promise.all(changedBuilds.map(b => b.update())))];
101
89
 
102
90
  const newEventStatus = deriveEventStatusFromBuildStatuses(updatedBuilds);
103
91