screwdriver-api 8.0.66 → 8.0.68
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/config/custom-environment-variables.yaml +26 -26
- package/config/default.yaml +34 -36
- package/package.json +1 -1
- package/plugins/builds/helper/updateBuild.js +79 -9
- package/plugins/builds/index.js +53 -21
- package/plugins/events/stopBuilds.js +18 -4
- package/plugins/pipelines/admins/get.js +1 -1
- package/plugins/webhooks/index.js +3 -11
|
@@ -361,32 +361,32 @@ scms:
|
|
|
361
361
|
# # SCM clone type (https or ssh)
|
|
362
362
|
# cloneType: SCM_GITLAB_RO_CLONE_TYPE
|
|
363
363
|
webhooks:
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
364
|
+
scms:
|
|
365
|
+
# Object keyed by scm name with value webhook settings.
|
|
366
|
+
# Value of webhook settings is an object with the following properties:
|
|
367
|
+
# Example:
|
|
368
|
+
# {
|
|
369
|
+
# "github": {
|
|
370
|
+
# # Obtains the SCM token for a given user. If a user does not have a valid SCM token registered with Screwdriver, it will use this user's token instead.
|
|
371
|
+
# "username": "sd-buildbot",
|
|
372
|
+
# # Ignore commits made by these users
|
|
373
|
+
# "ignoreCommitsBy": [],
|
|
374
|
+
# # Restrict PR: all, none, branch, or fork
|
|
375
|
+
# "restrictPR": "none",
|
|
376
|
+
# # Chain PR: true or false
|
|
377
|
+
# "chainPR": false
|
|
378
|
+
# },
|
|
379
|
+
# "github.example.com": {
|
|
380
|
+
# "username": "someuser",
|
|
381
|
+
# "ignoreCommitsBy": ["someuser", "anotheruser"],
|
|
382
|
+
# "restrictPR": "branch",
|
|
383
|
+
# "chainPR": true
|
|
384
|
+
# }
|
|
385
|
+
# }
|
|
386
|
+
__name: WEBHOOK_SETTINGS
|
|
387
|
+
__format: json
|
|
388
|
+
maxBytes: WEBHOOK_MAX_BYTES
|
|
389
|
+
|
|
390
390
|
|
|
391
391
|
bookends:
|
|
392
392
|
# Object keyed by cluster name with value setup/teardown bookend.
|
package/config/default.yaml
CHANGED
|
@@ -277,42 +277,40 @@ scms: {}
|
|
|
277
277
|
# accessToken: headlesstoken
|
|
278
278
|
# # SCM clone type (https or ssh)
|
|
279
279
|
# cloneType: https
|
|
280
|
-
webhooks:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
#
|
|
313
|
-
|
|
314
|
-
# }
|
|
315
|
-
# }
|
|
280
|
+
webhooks:
|
|
281
|
+
scms:
|
|
282
|
+
github:
|
|
283
|
+
# Obtains the SCM token for a given user. If a user does not have a valid SCM token registered with Screwdriver, it will use this user's token instead.
|
|
284
|
+
username: sd-buildbot
|
|
285
|
+
# Ignore commits made by these users
|
|
286
|
+
ignoreCommitsBy: []
|
|
287
|
+
# Restrict PR: all, none, branch, or fork
|
|
288
|
+
restrictPR: none
|
|
289
|
+
# Chain PR: true or false
|
|
290
|
+
chainPR: false
|
|
291
|
+
# Object keyed by scm name with value webhook settings.
|
|
292
|
+
# Value of webhook settings is an object with the following properties:
|
|
293
|
+
# Example:
|
|
294
|
+
# {
|
|
295
|
+
# "github:github.com": {
|
|
296
|
+
# # Obtains the SCM token for a given user. If a user does not have a valid SCM token registered with Screwdriver, it will use this user's token instead.
|
|
297
|
+
# "username": "sd-buildbot",
|
|
298
|
+
# # Ignore commits made by these users
|
|
299
|
+
# "ignoreCommitsBy": [],
|
|
300
|
+
# # Restrict PR: all, none, branch, or fork
|
|
301
|
+
# "restrictPR": "none",
|
|
302
|
+
# # Chain PR: true or false
|
|
303
|
+
# "chainPR": false
|
|
304
|
+
# },
|
|
305
|
+
# "github.example.com": {
|
|
306
|
+
# "username": "someuser",
|
|
307
|
+
# "ignoreCommitsBy": ["someuser", "anotheruser"],
|
|
308
|
+
# "restrictPR": "branch",
|
|
309
|
+
# "chainPR": true
|
|
310
|
+
# }
|
|
311
|
+
# }
|
|
312
|
+
# Upper limit on incoming uploads to builds
|
|
313
|
+
maxBytes: 1048576 # 1MB
|
|
316
314
|
coverage:
|
|
317
315
|
default: "false"
|
|
318
316
|
plugin: sonar
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@ const { PR_JOB_NAME, PR_STAGE_NAME, STAGE_TEARDOWN_PATTERN } = require('screwdri
|
|
|
7
7
|
const { getFullStageJobName } = require('../../helper');
|
|
8
8
|
const { updateVirtualBuildSuccess } = require('../triggers/helpers');
|
|
9
9
|
const TERMINAL_STATUSES = ['FAILURE', 'ABORTED', 'UNSTABLE', 'COLLAPSED'];
|
|
10
|
-
const FINISHED_STATUSES = ['
|
|
10
|
+
const FINISHED_STATUSES = ['SUCCESS', ...TERMINAL_STATUSES];
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @typedef {import('screwdriver-models/lib/build')} Build
|
|
@@ -140,6 +140,35 @@ async function getStage({ stageFactory, workflowGraph, jobName, pipelineId }) {
|
|
|
140
140
|
return Promise.resolve(stage);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Get stage build for current event
|
|
145
|
+
* @param {StageFactory} stageFactory Stage factory
|
|
146
|
+
* @param {StageBuildFactory} stageBuildFactory stage build factory
|
|
147
|
+
* @param {Object} workflowGraph workflow graph
|
|
148
|
+
* @param {String} jobName job name
|
|
149
|
+
* @param {Number} pipelineId pipeline id
|
|
150
|
+
* @param {Number} eventId event id
|
|
151
|
+
*
|
|
152
|
+
* @returns {StageBuild} stage build for current event
|
|
153
|
+
*/
|
|
154
|
+
async function getStageBuild({ stageFactory, stageBuildFactory, workflowGraph, jobName, pipelineId, eventId }) {
|
|
155
|
+
const stage = await getStage({
|
|
156
|
+
stageFactory,
|
|
157
|
+
workflowGraph,
|
|
158
|
+
jobName,
|
|
159
|
+
pipelineId
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (stage) {
|
|
163
|
+
return stageBuildFactory.get({
|
|
164
|
+
stageId: stage.id,
|
|
165
|
+
eventId
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
143
172
|
/**
|
|
144
173
|
* Get all builds in stage
|
|
145
174
|
*
|
|
@@ -241,6 +270,50 @@ function deriveEventStatusFromBuildStatuses(builds) {
|
|
|
241
270
|
return newEventStatus;
|
|
242
271
|
}
|
|
243
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Update stage build's status
|
|
275
|
+
* Stage build's status can transition as below
|
|
276
|
+
* CREATED -> RUNNING -when all builds are succeeded-> SUCCESS
|
|
277
|
+
* -when some builds are terminated-> FAILURE, ABORTED, UNSTABLE, COLLAPSED
|
|
278
|
+
*
|
|
279
|
+
* @param {Object} param
|
|
280
|
+
* @param {StageBuild} param.stageBuild
|
|
281
|
+
* @param {String} param.newStatus
|
|
282
|
+
* @param {Job} param.job
|
|
283
|
+
* @returns {StageBuild} new stage build's status
|
|
284
|
+
*/
|
|
285
|
+
async function updateStageBuildStatus({ stageBuild, newStatus, job }) {
|
|
286
|
+
if (stageBuild.status === newStatus) {
|
|
287
|
+
return stageBuild;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Not update when the stage build status is terminal
|
|
291
|
+
if (TERMINAL_STATUSES.includes(stageBuild.status)) {
|
|
292
|
+
return stageBuild;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const isStageTeardown = STAGE_TEARDOWN_PATTERN.test(job.name);
|
|
296
|
+
const intermediateStatuses = ['RUNNING', ...TERMINAL_STATUSES];
|
|
297
|
+
const teardownStatuses = ['RUNNING', ...FINISHED_STATUSES];
|
|
298
|
+
|
|
299
|
+
// It means all builds are succeeded if stage build status is not terminal when teardown build is done.
|
|
300
|
+
if (isStageTeardown && teardownStatuses.includes(newStatus)) {
|
|
301
|
+
stageBuild.status = newStatus;
|
|
302
|
+
|
|
303
|
+
return stageBuild.update();
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Stage build status can transition to terminated status in the intermediate builds.
|
|
307
|
+
// But not update to SUCCESS
|
|
308
|
+
if (!isStageTeardown && intermediateStatuses.includes(newStatus)) {
|
|
309
|
+
stageBuild.status = newStatus;
|
|
310
|
+
|
|
311
|
+
return stageBuild.update();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return stageBuild;
|
|
315
|
+
}
|
|
316
|
+
|
|
244
317
|
/**
|
|
245
318
|
* Updates the build and trigger its downstream jobs in the workflow
|
|
246
319
|
*
|
|
@@ -336,14 +409,9 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
|
|
|
336
409
|
eventId: newEvent.id
|
|
337
410
|
});
|
|
338
411
|
|
|
339
|
-
|
|
340
|
-
if (!TERMINAL_STATUSES.includes(stageBuild.status)) {
|
|
341
|
-
stageBuild.status = newBuild.status;
|
|
342
|
-
await stageBuild.update();
|
|
343
|
-
}
|
|
344
|
-
}
|
|
412
|
+
const newStageBuild = await updateStageBuildStatus({ stageBuild, newStatus: newBuild.status, job });
|
|
345
413
|
|
|
346
|
-
stageBuildHasFailure = TERMINAL_STATUSES.includes(
|
|
414
|
+
stageBuildHasFailure = TERMINAL_STATUSES.includes(newStageBuild.status);
|
|
347
415
|
}
|
|
348
416
|
|
|
349
417
|
// Guard against triggering non-successful or unstable builds
|
|
@@ -417,5 +485,7 @@ async function updateBuildAndTriggerDownstreamJobs(config, build, server, userna
|
|
|
417
485
|
|
|
418
486
|
module.exports = {
|
|
419
487
|
updateBuildAndTriggerDownstreamJobs,
|
|
420
|
-
deriveEventStatusFromBuildStatuses
|
|
488
|
+
deriveEventStatusFromBuildStatuses,
|
|
489
|
+
getStageBuild,
|
|
490
|
+
updateStageBuildStatus
|
|
421
491
|
};
|
package/plugins/builds/index.js
CHANGED
|
@@ -44,6 +44,7 @@ const {
|
|
|
44
44
|
getNextJobStageName
|
|
45
45
|
} = require('./triggers/helpers');
|
|
46
46
|
const { getFullStageJobName } = require('../helper');
|
|
47
|
+
const { updateStageBuildStatus, getStageBuild } = require('./helper/updateBuild');
|
|
47
48
|
|
|
48
49
|
/**
|
|
49
50
|
* Delete a build
|
|
@@ -71,7 +72,7 @@ async function triggerNextJobs(config, app) {
|
|
|
71
72
|
const currentPipeline = config.pipeline;
|
|
72
73
|
const currentJob = config.job;
|
|
73
74
|
const currentBuild = config.build;
|
|
74
|
-
const { jobFactory, buildFactory, eventFactory, pipelineFactory } = app;
|
|
75
|
+
const { jobFactory, buildFactory, eventFactory, pipelineFactory, stageFactory, stageBuildFactory } = app;
|
|
75
76
|
|
|
76
77
|
/** @type {EventModel} */
|
|
77
78
|
const currentEvent = await eventFactory.get({ id: currentBuild.eventId });
|
|
@@ -100,8 +101,8 @@ async function triggerNextJobs(config, app) {
|
|
|
100
101
|
for (const [nextJobName] of Object.entries(currentPipelineNextJobs)) {
|
|
101
102
|
const nextJob = await getJob(nextJobName, currentPipeline.id, jobFactory);
|
|
102
103
|
const node = currentEvent.workflowGraph.nodes.find(n => n.name === trimJobName(nextJobName));
|
|
103
|
-
const isNextJobVirtual = node.virtual
|
|
104
|
-
const nextJobStageName = getNextJobStageName({ stageName: node.stageName, nextJobName });
|
|
104
|
+
const isNextJobVirtual = node && node.virtual === true;
|
|
105
|
+
const nextJobStageName = node ? getNextJobStageName({ stageName: node.stageName, nextJobName }) : null;
|
|
105
106
|
const resource = `pipeline:${currentPipeline.id}:groupEvent:${currentEvent.groupEventId}`;
|
|
106
107
|
let lock;
|
|
107
108
|
let nextBuild;
|
|
@@ -144,15 +145,31 @@ async function triggerNextJobs(config, app) {
|
|
|
144
145
|
);
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
if (isNextJobVirtual
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
148
|
+
if (isNextJobVirtual) {
|
|
149
|
+
const stageBuild = await getStageBuild({
|
|
150
|
+
stageFactory,
|
|
151
|
+
stageBuildFactory,
|
|
152
|
+
workflowGraph: currentEvent.workflowGraph,
|
|
153
|
+
jobName: nextJobName,
|
|
154
|
+
pipelineId: currentPipeline.id,
|
|
155
|
+
eventId: currentEvent.id
|
|
155
156
|
});
|
|
157
|
+
|
|
158
|
+
if (stageBuild) {
|
|
159
|
+
await updateStageBuildStatus({ stageBuild, newStatus: nextBuild.status, job: nextJob });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Trigger downstream jobs
|
|
163
|
+
if (nextBuild && nextBuild.status === Status.SUCCESS) {
|
|
164
|
+
downstreamOfNextJobsToBeProcessed.push({
|
|
165
|
+
build: nextBuild,
|
|
166
|
+
event: currentEvent,
|
|
167
|
+
job: nextJob,
|
|
168
|
+
pipeline: currentPipeline,
|
|
169
|
+
scmContext: config.scmContext,
|
|
170
|
+
username: config.username
|
|
171
|
+
});
|
|
172
|
+
}
|
|
156
173
|
}
|
|
157
174
|
} catch (err) {
|
|
158
175
|
logger.error(
|
|
@@ -290,8 +307,8 @@ async function triggerNextJobs(config, app) {
|
|
|
290
307
|
for (const [nextJobName, nextJobInfo] of Object.entries(joinedPipeline.jobs)) {
|
|
291
308
|
const nextJob = await getJob(nextJobName, joinedPipelineId, jobFactory);
|
|
292
309
|
const node = externalEvent.workflowGraph.nodes.find(n => n.name === trimJobName(nextJobName));
|
|
293
|
-
const isNextJobVirtual = node.virtual
|
|
294
|
-
const nextJobStageName = getNextJobStageName({ stageName: node.stageName, nextJobName });
|
|
310
|
+
const isNextJobVirtual = node && node.virtual === true;
|
|
311
|
+
const nextJobStageName = node ? getNextJobStageName({ stageName: node.stageName, nextJobName }) : null;
|
|
295
312
|
|
|
296
313
|
const { parentBuilds } = parseJobInfo({
|
|
297
314
|
joinObj: joinedPipeline.jobs,
|
|
@@ -334,15 +351,30 @@ async function triggerNextJobs(config, app) {
|
|
|
334
351
|
);
|
|
335
352
|
}
|
|
336
353
|
|
|
337
|
-
if (isNextJobVirtual
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
354
|
+
if (isNextJobVirtual) {
|
|
355
|
+
const stageBuild = await getStageBuild({
|
|
356
|
+
stageFactory,
|
|
357
|
+
stageBuildFactory,
|
|
358
|
+
workflowGraph: currentEvent.workflowGraph,
|
|
359
|
+
jobName: nextJob.name,
|
|
360
|
+
pipelineId: currentPipeline.id,
|
|
361
|
+
eventId: currentEvent.id
|
|
345
362
|
});
|
|
363
|
+
|
|
364
|
+
if (stageBuild) {
|
|
365
|
+
await updateStageBuildStatus({ stageBuild, newStatus: nextBuild.status, job: nextJob });
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (nextBuild && nextBuild.status === Status.SUCCESS) {
|
|
369
|
+
downstreamOfNextJobsToBeProcessed.push({
|
|
370
|
+
build: nextBuild,
|
|
371
|
+
event: currentEvent,
|
|
372
|
+
job: nextJob,
|
|
373
|
+
pipeline: await nextJob.pipeline,
|
|
374
|
+
scmContext: config.scmContext,
|
|
375
|
+
username: config.username
|
|
376
|
+
});
|
|
377
|
+
}
|
|
346
378
|
}
|
|
347
379
|
} catch (err) {
|
|
348
380
|
logger.error(
|
|
@@ -8,6 +8,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
10
|
const { deriveEventStatusFromBuildStatuses } = require('../builds/helper/updateBuild');
|
|
11
|
+
const nonTerminatedStatus = ['CREATED', 'RUNNING', 'QUEUED', 'BLOCKED', 'FROZEN'];
|
|
11
12
|
|
|
12
13
|
module.exports = () => ({
|
|
13
14
|
method: 'PUT',
|
|
@@ -78,25 +79,25 @@ module.exports = () => ({
|
|
|
78
79
|
|
|
79
80
|
// User has good permissions, get event builds
|
|
80
81
|
const builds = await event.getBuilds();
|
|
81
|
-
const
|
|
82
|
+
const toUpdateBuilds = [];
|
|
82
83
|
const updatedBuilds = [];
|
|
83
84
|
|
|
84
85
|
// Update endtime and stop running builds
|
|
85
86
|
// Note: COLLAPSED builds will never run
|
|
86
87
|
builds.forEach(b => {
|
|
87
|
-
if (
|
|
88
|
+
if (nonTerminatedStatus.includes(b.status)) {
|
|
88
89
|
if (b.status === 'RUNNING') {
|
|
89
90
|
b.endTime = new Date().toISOString();
|
|
90
91
|
}
|
|
91
92
|
b.status = 'ABORTED';
|
|
92
93
|
b.statusMessage = `Aborted by ${username}`;
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
toUpdateBuilds.push(b.update());
|
|
95
96
|
} else {
|
|
96
97
|
updatedBuilds.push(b);
|
|
97
98
|
}
|
|
98
99
|
});
|
|
99
|
-
updatedBuilds.push(...(await Promise.all(
|
|
100
|
+
updatedBuilds.push(...(await Promise.all(toUpdateBuilds)));
|
|
100
101
|
|
|
101
102
|
const newEventStatus = deriveEventStatusFromBuildStatuses(updatedBuilds);
|
|
102
103
|
|
|
@@ -105,6 +106,19 @@ module.exports = () => ({
|
|
|
105
106
|
await event.update();
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
// Update stageBuild status to ABORTED
|
|
110
|
+
const stageBuilds = await event.getStageBuilds();
|
|
111
|
+
const toUpdateStageBuilds = [];
|
|
112
|
+
|
|
113
|
+
stageBuilds.forEach(sb => {
|
|
114
|
+
if (nonTerminatedStatus.includes(sb.status)) {
|
|
115
|
+
sb.status = 'ABORTED';
|
|
116
|
+
toUpdateStageBuilds.push(sb.update());
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
await Promise.all(toUpdateStageBuilds);
|
|
121
|
+
|
|
108
122
|
// everything succeeded, inform the user
|
|
109
123
|
const location = urlLib.format({
|
|
110
124
|
host: request.headers.host,
|
|
@@ -20,7 +20,7 @@ module.exports = () => ({
|
|
|
20
20
|
},
|
|
21
21
|
|
|
22
22
|
handler: async (request, h) => {
|
|
23
|
-
const pipelineFactory = request.server.app
|
|
23
|
+
const { pipelineFactory } = request.server.app;
|
|
24
24
|
const { scope } = request.auth.credentials;
|
|
25
25
|
const { scmContext, includeUserToken } = request.query;
|
|
26
26
|
|
|
@@ -6,8 +6,7 @@ const boom = require('@hapi/boom');
|
|
|
6
6
|
const { ValidationError } = require('joi');
|
|
7
7
|
const { startHookEvent } = require('./helper');
|
|
8
8
|
|
|
9
|
-
const DEFAULT_MAX_BYTES = 1048576;
|
|
10
|
-
const MAX_BYTES_UPPER_BOUND = 5242880; // 5MB
|
|
9
|
+
const DEFAULT_MAX_BYTES = 1048576; // 1MB
|
|
11
10
|
const providerSchema = joi
|
|
12
11
|
.object({
|
|
13
12
|
username: joi.string().required(),
|
|
@@ -41,7 +40,7 @@ const webhooksPlugin = {
|
|
|
41
40
|
name: 'webhooks',
|
|
42
41
|
async register(server, options) {
|
|
43
42
|
const pluginOptions = joi.attempt(
|
|
44
|
-
options,
|
|
43
|
+
options.scms,
|
|
45
44
|
joi.object().pattern(joi.string(), providerSchema).min(1).required(),
|
|
46
45
|
'Invalid config for plugin-webhooks'
|
|
47
46
|
);
|
|
@@ -59,7 +58,7 @@ const webhooksPlugin = {
|
|
|
59
58
|
}
|
|
60
59
|
},
|
|
61
60
|
payload: {
|
|
62
|
-
maxBytes:
|
|
61
|
+
maxBytes: parseInt(pluginOptions.maxBytes, 10) || DEFAULT_MAX_BYTES,
|
|
63
62
|
parse: false,
|
|
64
63
|
output: 'stream'
|
|
65
64
|
},
|
|
@@ -71,17 +70,10 @@ const webhooksPlugin = {
|
|
|
71
70
|
let hookId;
|
|
72
71
|
|
|
73
72
|
try {
|
|
74
|
-
let size = 0;
|
|
75
73
|
const chunks = [];
|
|
76
74
|
|
|
77
75
|
for await (const chunk of request.payload) {
|
|
78
|
-
size += chunk.length;
|
|
79
76
|
chunks.push(chunk);
|
|
80
|
-
if (size > DEFAULT_MAX_BYTES) {
|
|
81
|
-
throw boom.entityTooLarge(
|
|
82
|
-
`Payload size exceeds the maximum limit of ${DEFAULT_MAX_BYTES} bytes`
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
77
|
}
|
|
86
78
|
|
|
87
79
|
const data = Buffer.concat(chunks).toString();
|