screwdriver-api 7.0.170 → 7.0.172

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.
@@ -0,0 +1,1180 @@
1
+ # Overview
2
+ Pipeline template abstracts entire pipeline configuration into reusable modules which can be imported (screwdriver.yaml) and extended to build individual pipelines.
3
+
4
+ Github: https://github.com/screwdriver-cd/screwdriver/issues/2135
5
+
6
+ ## Table of Contents
7
+
8
+ - [Requirements](#requirements)
9
+ - [Design](#design)
10
+ - [Template Management](#template-management)
11
+ - [Template Configuration Schema](#template-configuration-schema)
12
+ - [API](#api)
13
+ - [DB Model](#db-model)
14
+ - [Domain Model](#domain-model)
15
+ - [Config Parser](#config-parser)
16
+ - [Template Validator](#template-validator)
17
+ - [Data Access Object/Layer (DAO)](#data-access-objectlayer-dao)
18
+ - [Endpoints](#endpoints)
19
+ - [SD CLI](#sd-cli)
20
+ - [UI](#ui)
21
+ - [Template Usage](#template-usage-1)
22
+ - [Pipeline configuration](#pipeline-configuration)
23
+ - [API](#api-1)
24
+ - [DB Model](#db-model-1)
25
+ - [Domain Model](#domain-model-1)
26
+ - [Config Parser](#config-parser-1)
27
+ - [UI](#ui-1)
28
+
29
+ # Requirements
30
+ ## Template Management
31
+ 1. Ability to validate a pipeline template configuration
32
+ 1. Ability to create/store versioned pipeline template configuration from the screwdriver pipeline which owns the template
33
+ 1. Ability to create/update tags referring to a version of the template from a screwdriver pipeline which owns the template
34
+ 1. A Screwdriver admin should be able to mark a pipeline template as trusted or not
35
+ a. Capture the version since it was marked as trusted
36
+ b. Clear the version, when a template is no longer marked as trusted which was previously trusted
37
+ 1. All users should be able to view all the pipeline templates available in the system
38
+ 1. All users should be able to view all the versions of a pipeline template
39
+ 1. All Users should be able to view the configuration a specific version of a pipeline template
40
+ 1. Below users should be allowed to delete a specific version and all of its associated tags
41
+ a. Screwdriver admin
42
+ b. Screwdriver pipeline owning the template
43
+ c. Admins of the SCM repo hosting the template configuration
44
+ 1. Below users should be allowed to delete a template and all of its associated versions and tags
45
+ a. Screwdriver admin
46
+ b. Screwdriver pipeline owning the template
47
+ c. Admins of the SCM repo hosting the template configuration
48
+
49
+ ## Template Usage
50
+ To be updated
51
+
52
+
53
+ # Design
54
+ ## Template Management
55
+
56
+ ![Screenshot 2023-08-14 at 9 58 41 PM](https://github.com/screwdriver-cd/screwdriver/assets/67897071/8bff2e37-8b2b-415e-866a-24f12894de72)
57
+
58
+ ### Template Configuration Schema
59
+
60
+ ![Screenshot 2023-08-14 at 9 59 33 PM](https://github.com/screwdriver-cd/screwdriver/assets/67897071/9e9fdb9d-7acc-4031-aec2-3fc6a9782ebf)
61
+
62
+
63
+
64
+ __Basic Configuration:__
65
+
66
+ ```yaml
67
+ namespace: myNamespace
68
+ name: template_name
69
+ version: '1.3.2'
70
+ description: template for testing
71
+ maintainer: foo@bar.com
72
+
73
+ config:
74
+ jobs:
75
+ main:
76
+ image:
77
+ steps:
78
+ ```
79
+
80
+
81
+ __Advanced Configuration:__
82
+
83
+ ```yaml
84
+ namespace: myNamespace
85
+ name: template_name
86
+ version: '1.3.2'
87
+ description: template for testing
88
+ maintainer: foo@bar.com
89
+ config:
90
+ shared:
91
+ image:
92
+ environment:
93
+ SD_SONAR_OPTS:
94
+ steps:
95
+ annotations:
96
+
97
+ parameters:
98
+ FOO: bar
99
+
100
+ jobs:
101
+ main:
102
+ requires:
103
+ image:
104
+ template:
105
+ steps:
106
+ parameters:
107
+ secrets:
108
+ settings:
109
+ email:
110
+ slack:
111
+ annotations:
112
+ sourcePaths:
113
+ test:
114
+ ....
115
+
116
+ ```
117
+
118
+ | Field | Sub Field | Schema | Description |
119
+ | ---------- | ------------- |------------- |------------- |
120
+ | namespace | | Same as Job template `namespace` [schema][schema-namespace] | Required |
121
+ | name | | Same as Job template `name` [schema][schema-name] | Required |
122
+ | maintainer | | Same as Job template `maintainer` [schema][schema-maintainer] | Required |
123
+ | version | | Same as Job template `version` [schema][schema-version] | Required |
124
+ | description | | Same as Job template `description` [schema][schema-description] | Required |
125
+ | config | shared | Same as Pipeline `shared` [schema][schema-shared] | Optional |
126
+ | | jobs | Same as Pipeline `jobs` [schema][schema-jobs] | Required |
127
+ | | parameters | Same as Pipeline `parameters` [schema][schema-params] | Optional |
128
+
129
+
130
+ ## API
131
+
132
+ ### DB Model
133
+
134
+ **Pipeline Template**
135
+
136
+ Approach 1 - Add Pipeline template data to existing template table:
137
+
138
+ - Add new column `templateType` that takes 2 values -> `PIPELINE` and `JOB`
139
+ - `images` column should have NULL when `templateType` = `PIPELINE`
140
+
141
+
142
+ Approach 2 - Create new tables
143
+
144
+ Add two new tables to persist pipeline template
145
+ - templateMeta
146
+ - metadata about pipeline template: `name`, `namespace`, `maintainer`, etc.
147
+ - pipelineTemplateVersions
148
+ - configuration associated with individual versions
149
+
150
+
151
+
152
+ ***templateMeta***
153
+
154
+ | Column | Type | Nullable | Description |
155
+ | ---------- | ------------- |------------- |------------- |
156
+ | id | Sequelize.INTEGER.UNSIGNED | No | |
157
+ | pipelineId | Sequelize.DOUBLE | No | Identifier of the Screwdriver pipeline which owns the template |
158
+ | namespace | Sequelize.STRING(64) | No | |
159
+ | name | Sequelize.STRING(64) | No | |
160
+ | maintainer | Sequelize.STRING(64) | No | |
161
+ | trustedSinceVersion | Sequelize.STRING(32) | Yes | |
162
+ | latestVersion | Sequelize.STRING(16) | Yes | |
163
+ | createTime | Sequelize.STRING(32) | No | |
164
+ | updateTime | Sequelize.STRING(32) | No | |
165
+ | templateType | Sequelize.STRING(16) | No | Allowed values: ‘JOB’, ‘PIPELINE’ |
166
+
167
+ _Constraints_
168
+
169
+ - Add composite unique constraint on name, namespace, and templateType
170
+
171
+ _Indexes_
172
+
173
+ - Add index on name
174
+ - Add index on namespace
175
+
176
+ ***pipelineTemplateVersions***
177
+
178
+ | Column | Type | Nullable | Description |
179
+ | ---------- | ------------- |------------- |------------- |
180
+ | id | Sequelize.INTEGER.UNSIGNED | No | |
181
+ | templateId | Sequelize.DOUBLE | No | Identifier of the Screwdriver pipeline which owns the template |
182
+ | description | Sequelize.STRING(64) | No | |
183
+ | version | Sequelize.STRING(64) | No | |
184
+ | config | Sequelize.STRING(64) | No | |
185
+ | createTime | Sequelize.STRING(32) | Yes | |
186
+
187
+ _Constraints_
188
+
189
+ - Composite unique constraint on templateId and version
190
+
191
+ _Indexes_
192
+
193
+ - Add index on templateId
194
+ - Add index on version
195
+
196
+
197
+ **Conclusion**
198
+
199
+ Proceeding with approach #2
200
+ - Normalizes the data to reduce redundancy
201
+
202
+
203
+
204
+
205
+ **Pipeline Template Tags**
206
+
207
+ We can reuse the existing `templateTags` table to store the tags associated with pipeline templates by adding a new column `templateType`
208
+
209
+ ***Existing Columns***
210
+ | Column | Type | Nullable | Description |
211
+ | ---------- | ------------- |------------- |------------- |
212
+ | id | Sequelize.INTEGER.UNSIGNED | No | |
213
+ | createTime | Sequelize.STRING(32) | No | Created during API call |
214
+ | namespace | Sequelize.STRING(64) | No | |
215
+ | name | Sequelize.STRING(64)| No | |
216
+ | tag | Sequelize.STRING(30) | No | |
217
+ | version | Sequelize.STRING(16) | No | |
218
+
219
+ ***New Columns***
220
+ | Column | Type | Nullable | Description |
221
+ | ---------- | ------------- |------------- |------------- |
222
+ | templateType | Sequelize.STRING(16) | No | Allowed values: ‘JOB’, ‘PIPELINE’ & Default value: ‘JOB’ |
223
+
224
+
225
+ _Constraints_
226
+ - Drop unique constraint on `name`, `namespace` and `tag` columns
227
+ - Add unique constraint on `name`, `namespace`, ‘type’ and `tag` columns
228
+
229
+
230
+
231
+
232
+ ### Domain Model
233
+
234
+ **PipelineTemplate**
235
+
236
+ | Field | Sub Field | Schema | Description |
237
+ | ---------- | ------------- |------------- |------------- |
238
+ | id | | Same as Job template `id` [schema][schema-domain-id] | |
239
+ | name | | Same as this [schema][schema-domain-name] | |
240
+ | namespace | | Same as this [schema][schema-domain-namespace] | |
241
+ | maintainer | | Same as this [schema][schema-domain-maintainer] | |
242
+ | trustedSinceVersion | | Same as this [schema][schema-domain-trustedSinceVersion] | |
243
+ | latestVersion | | Same as this [schema][schema-domain-latestVersion] | |
244
+ | pipelineId | | Same as this [schema][schema-domain-pipelineId] | |
245
+
246
+ **PipelineTemplateVersion**
247
+
248
+ | Field | Sub Field | Schema | Description |
249
+ | ---------- | ------------- |------------- |------------- |
250
+ | id | | Same as Job template `id` [schema][schema-domain-id] | |
251
+ | description | | Same as this [schema][schema-domain-description] | |
252
+ | version | | Same as this [schema][schema-domain-version] | |
253
+ | config | shared | Same as this [schema][schema-domain-shared] | |
254
+ | | jobs | Same as this [schema][schema-domain-jobs] | Required |
255
+ | | parameters | Same as this [schema][schema-domain-params] | |
256
+ | createTime | | Same as this [schema][schema-domain-createTime] | |
257
+ | templateId | | Same as this [schema][schema-domain-id] | |
258
+
259
+
260
+ ### Config Parser
261
+
262
+ No change needed
263
+
264
+ ### Template Validator
265
+
266
+ Add a new function that takes the parsed template (Javascript) object as input and validates it against the [schema][schema-template-validator].
267
+
268
+ ### Data Access Object/Layer (DAO)
269
+
270
+ Provides an interface to integrate with the database.
271
+
272
+ ***TemplateMeta***
273
+
274
+ The `TemplateMeta` module will extend the `BaseModel` class to expose methods to update or delete pipeline/job templates. For pipeline templates:
275
+
276
+ _remove(templateVersionFactory, templateTagFactory)_
277
+ - Deletes template metadata by removing the entry from `templateMeta` table
278
+ - Get the configurations associated with all the versions of this template using templateVersionFactory
279
+ - Call remove(templateTagFactory) on each version from step #2
280
+
281
+ _update()_
282
+ Default implementation
283
+
284
+
285
+ ***TemplateMetaFactory***
286
+
287
+ The `TemplateMetaFactory` module will extend the `BaseFactory` class to expose methods to create or fetch pipeline templates.
288
+
289
+ _list(config)_
290
+
291
+ Fetch and return entries from `templateMeta` table for the criteria specified in the config.
292
+
293
+ Arguments:
294
+ | Argument | Description |
295
+ | ---------- | ------------- |
296
+ | config.params.id | Identifier of the template |
297
+ | config.params.name | |
298
+ | config.params.namespace | |
299
+
300
+
301
+ _get(config)_
302
+
303
+ Fetch and return the template configuration from `PipelineTemplate` matching the criteria specified in the config
304
+
305
+ Arguments:
306
+ | Argument | Description |
307
+ | ---------- | ------------- |
308
+ | config.params.id | |
309
+ | config.params.name | |
310
+ | config.params.namespace | |
311
+
312
+
313
+
314
+ _create(config)_
315
+
316
+ Calls getTemplateType() method to update `templateType` field in templateMeta table
317
+
318
+ Arguments:
319
+ | Argument | Description |
320
+ | ---------- | ------------- |
321
+ | config.<?> |`?` refers to the fields mentioned in template configuration schema |
322
+ | config.pipelineId | Identifier of the Screwdriver pipeline that is publishing the template |
323
+
324
+
325
+
326
+ ***PipelineTemplate***
327
+
328
+ The `PipelineTemplate` module will extend the `TemplateMeta` class.
329
+
330
+ ***PipelineTemplateFactory***
331
+
332
+ The `PipelineTemplateFactory` module will extend the `TemplateMetaFactory` class to expose methods to create or fetch pipeline templates.
333
+
334
+ _getTemplateType()_
335
+ Return the type of template as ‘PIPELINE’
336
+
337
+
338
+ ***PipelineTemplateVersion***
339
+
340
+ The `PipelineTemplateVersion` module will extend the `BaseModel` class to expose methods to update or delete pipeline template versions.
341
+
342
+ _remove(templateTagFactory)_
343
+ - Removes the entry from `pipelineTemplateVersions` table
344
+ - Get all the associated tags using templateTagFactory.list(config)
345
+ - Call remove() on each tag from step #2
346
+
347
+ _update()_
348
+ Default implementation
349
+
350
+
351
+ ***PipelineTemplateVersionFactory***
352
+
353
+ The `PipelineTemplateVersionFactory` module will extend the `BaseFactory` class to expose methods to create or fetch template versions.
354
+
355
+ _create(config)_
356
+ 1. If template does not exist in `templateMeta`,
357
+ - adds a new entry in `templateMeta` table to persist metadata associated with the template
358
+ - Adds an entry in `pipelineTemplateVersions` table to persist version and configuration for the new template by calling templateVersionFactory.create()
359
+
360
+ 1. If template exists in `templateMeta`,
361
+ - adds entry in `pipelineTemplateVersions` table with latest details to persist version and configuration for the new template by calling templateVersionFactory.create()
362
+
363
+ Arguments:
364
+ | Argument | Description |
365
+ | ---------- | ------------- |
366
+ | config.<?> |`?` refers to the fields of PipelineTemplateVersion |
367
+
368
+
369
+ _list(config)_
370
+
371
+ Fetch and return entries from `pipelineTemplateVersions` table for the criteria specified in the config.
372
+
373
+ Arguments:
374
+ | Argument | Description |
375
+ | ---------- | ------------- |
376
+ | config.params.templateId| |
377
+ | config.params.name | |
378
+ | config.params.namespace | |
379
+
380
+
381
+ _get(config)_
382
+
383
+ Fetch and return the template configuration from `pipelineTemplateVersions` matching the criteria specified in the config
384
+
385
+ Arguments:
386
+ | Argument | Description |
387
+ | ---------- | ------------- |
388
+ | config.params.templateId | Filter result by templateId. Template name and templateId are mutually exclusive |
389
+ | config.params.name | |
390
+ | config.params.namespace | |
391
+ | config.params.version | |
392
+
393
+
394
+ _getWithMetadata(config)_
395
+
396
+ Fetch and return the template configuration from `pipelineTemplateVersions` matching the criteria specified in the config and also include the corresponding metadata from the `templateMeta` table
397
+
398
+ Arguments:
399
+ | Argument | Description |
400
+ | ---------- | ------------- |
401
+ | config.params.templateId | Filter result by templateId |
402
+ | config.params.name | |
403
+ | config.params.namespace | |
404
+ | config.params.version | |
405
+
406
+
407
+ ***TemplateTagFactory***
408
+
409
+ As we are utilizing the current templateTags table and introducing a new column called `templateType`, we will modify the existing templateTagsFactory module to incorporate the `templateType` field.
410
+
411
+ _listPipelineTemplateTags(config)_
412
+
413
+ This will add `templateType`: ‘PIPELINE’ to `config.params`
414
+
415
+
416
+ Arguments:
417
+ | Argument | Description |
418
+ | ---------- | ------------- |
419
+ | config.templateName | |
420
+ | config.templateNamespace | |
421
+ | config.params.version | |
422
+
423
+ Will set `config.params.templateType` = 'PIPELINE’
424
+
425
+ _createPipelineTag(config)_
426
+
427
+ This will add `templateType: ‘PIPELINE’` to `config` and then call `create(config)`
428
+
429
+
430
+ Arguments:
431
+ | Argument | Description |
432
+ | ---------- | ------------- |
433
+ | config.templateName | |
434
+ | config.templateNamespace | |
435
+ | config.params.version | |
436
+
437
+ Will set `config.params.templateType` = 'PIPELINE’
438
+
439
+
440
+ ***PipelineTemplateTagFactory***
441
+ The PipelineTemplateTagFactory module will extend the TemplateTagFactory class to expose methods to get template types.
442
+
443
+ _getTemplateType()_
444
+ Return `templateType` as ‘PIPELINE’
445
+
446
+ ***JobTemplateTagFactory***
447
+ The JobTemplateTagFactory module will extend the TemplateTagFactory class to expose methods to get template types.
448
+
449
+ _getTemplateType()_
450
+ Return `templateType` as ‘JOB’
451
+
452
+
453
+
454
+ ### Endpoints
455
+
456
+ ***1. Validate a template***
457
+
458
+ This endpoint parses the template yaml file and confirms its validity so that it can be used for publishing with no errors.
459
+
460
+ **Request:**
461
+
462
+ - **Method**: POST
463
+ - **Path** : ‘/pipeline/template/validate’
464
+ - **Payload:**
465
+
466
+ ```
467
+ {
468
+ "namespace": "myNamespace",
469
+ "name": "template_name",
470
+ "version": "1.3",
471
+ "description": "template for testing",
472
+ "maintainer": "foo@bar.com",
473
+ "config": {
474
+ "jobs": {
475
+ "main": {
476
+ "image": "node:18",
477
+ "steps": "abc",
478
+ "requires": "xyz"
479
+ }
480
+ }
481
+ }}
482
+ ```
483
+
484
+ **Response:**
485
+
486
+ JSON containing the property ‘valid’ indicating if the template is valid or not.
487
+
488
+ ```
489
+ {
490
+ "valid": "true"
491
+ }
492
+ ```
493
+
494
+
495
+ ***2. Validate and Publish a template***
496
+
497
+ This endpoint accepts template configuration as input, validates it and publishes it so that it can be used to create pipelines.
498
+
499
+ **Request:**
500
+
501
+ - **Method**: POST
502
+ - **Path** : ‘validator/pipelineTemplate’
503
+ - **Payload:**
504
+
505
+ ```
506
+ {
507
+ "namespace": "myNamespace",
508
+ "name": "template_name",
509
+ "version": "1.3",
510
+ "description": "template for testing",
511
+ "maintainer": "foo@bar.com",
512
+ "config": {
513
+ "jobs": {
514
+ "main": {
515
+ "image": "node:18",
516
+ "steps": "abc",
517
+ "requires": "xyz"
518
+ }
519
+ }
520
+ }}
521
+ ```
522
+
523
+ **Response:**
524
+
525
+ JSON object representing the template version along with the metadata which was created by the API.
526
+
527
+ ```
528
+ {
529
+ "id": 3,
530
+ "templateId": 123,
531
+ "pipelineId": 3,
532
+ "namespace": "myNamespace",
533
+ "name": "template_name",
534
+ "version": "1.3.2",
535
+ "description": "template for testing",
536
+ "maintainer": "foo@bar.com",
537
+ "config": {
538
+ "jobs": {
539
+ "main": {
540
+ "image": "node:18",
541
+ "steps": "abc",
542
+ "requires": "xyz"
543
+ }
544
+ }
545
+ },
546
+ "createTime": "2023-06-12T21:52:22.706Z"
547
+ }
548
+ ```
549
+
550
+
551
+ ***3. Create/Update template tag***
552
+
553
+ This endpoint accepts the version as input and creates/updates a tag for the template name and namespace specified in the endpoint path.
554
+
555
+ **Request:**
556
+
557
+ - **Method**: PUT
558
+ - **Path** : ‘/pipeline/template/{templateNamespace}/{templateName}/tags/{tagName}’
559
+ - **Payload:**
560
+
561
+ ```
562
+ {
563
+
564
+ "version": "1.3.2"
565
+ }
566
+ ```
567
+
568
+ **Response:**
569
+
570
+ JSON object representing the template tag details and status code.
571
+
572
+ ```
573
+ {
574
+ "id": 2,
575
+ "createTime": "2023-06-12T21:52:22.706Z"
576
+ "namespace": "tempNameSpace"
577
+ "name": "templateName",
578
+ "tag": "tagName",
579
+ "version": "1.3.2",
580
+ }
581
+ ```
582
+
583
+
584
+ ***4. List all the templates***
585
+
586
+ Returns an array template meta for all the pipeline templates
587
+
588
+ **Request:**
589
+
590
+ - **Method**: GET
591
+ - **Path** : ‘/pipeline/templates’
592
+
593
+ **Response:**
594
+
595
+ JSON object consisting of a list of objects having template metadata for each template.
596
+
597
+ ```
598
+ Status Code: 200 (OK)
599
+ Response Body:
600
+ [
601
+ {
602
+ "id": 123,
603
+ "pipelineId": 3,
604
+ "name": "example-template",
605
+ "namespace": "my-namespace",
606
+ "description": "An example template",
607
+ "maintainer": "example123@gmail.com",
608
+ “trustedSinceVersion”: “true”,
609
+ “latestVersion”: “1.3.2”,
610
+ "createTime": "2023-06-12T21:52:22.706Z",
611
+ "updateTime": "2023-06-29T11:23:45.706Z"
612
+ },
613
+ {
614
+
615
+ },
616
+
617
+ ]
618
+ ```
619
+
620
+ ***5. Get a specific template by id***
621
+
622
+ Returns an array of details for a specific template when its id is provided in the endpoint.
623
+
624
+ **Request:**
625
+
626
+ - **Method**: GET
627
+ - **Path** : ‘/pipeline/template/{templateId}`
628
+
629
+ **Response:**
630
+
631
+ JSON object consisting template details for the given Id.
632
+
633
+ ```
634
+ Status Code: 200 (OK)
635
+ Response Body:
636
+ {
637
+ "id": 123,
638
+ "pipelineId": 3,
639
+ "namespace": "my-namespace",
640
+ "name": "example-template",
641
+ "description": "An example template",
642
+ "maintainer": "example@gmail.com",
643
+ “trustedSinceVersion”: “1.2.3”,
644
+ "latestVersion": "1.3.2",
645
+ "createTime": "2023-06-12T21:52:22.706Z",
646
+ "updateTime": "2023-06-29T11:23:45.706Z"
647
+
648
+ }
649
+ ```
650
+
651
+ ***6. Get a specific template by namespace and name***
652
+
653
+ Returns template meta for the specified namespace and name
654
+
655
+ **Request:**
656
+
657
+ - **Method**: GET
658
+ - **Path** : ‘/pipeline/templates/{templateNamespace}/{templateName}`
659
+
660
+ **Response:**
661
+
662
+ JSON object consisting template details for the given template namespace and name combination.
663
+
664
+ ```
665
+ Status Code: 200 (OK)
666
+ Response Body:
667
+ {
668
+ "id": 123,
669
+ "pipelineId": 3,
670
+ "namespace": "my-namespace",
671
+ "name": "example-template",
672
+ "description": "An example template",
673
+ "maintainer": "example@gmail.com",
674
+ “trustedSinceVersion”: “1.2.3”,
675
+ "latestVersion": "1.3.2",
676
+ "createTime": "2023-06-12T21:52:22.706Z",
677
+ "updateTime": "2023-06-29T11:23:45.706Z"
678
+
679
+ }
680
+ ```
681
+
682
+ ***7. List all the versions for a template namespace and name***
683
+
684
+ Returns fields from the pipelineTemplateVersions table for the specified namespace and name.
685
+
686
+ **Request:**
687
+
688
+ - **Method**: GET
689
+ - **Path** : ‘/pipeline/templates/{templateNamespace}/{templateName}/versions`
690
+
691
+ **Response:**
692
+
693
+ JSON object consisting list of template records, representing all versions of the specified template name.
694
+
695
+ ```
696
+ Status Code: 200 (OK)
697
+ Response Body:
698
+ [
699
+ {
700
+ "id": 1,
701
+ "templateId": 123,
702
+ "description": "An example template",
703
+ "version": "1.0.0",
704
+ "config": {
705
+ "jobs": {
706
+ "main": {
707
+ "image": "node:18",
708
+ "steps": {
709
+ "printLine": "echo 'Testing template creation V1'"
710
+ },
711
+ "requires": "[~pr, ~commit]"
712
+ }
713
+ }
714
+ },
715
+ "createTime": "2023-06-12T21:52:22.706Z"
716
+ },
717
+ {
718
+ "id": 2,
719
+ "templateId": 123,
720
+ "description": "An example template",
721
+ "version": "1.1.0",
722
+ "config": {
723
+ "jobs": {
724
+ "main": {
725
+ "image": "node:18",
726
+ "steps": {
727
+ "printLine": "echo 'Testing template creation V1.1'"
728
+ },
729
+ "requires": "[~pr, ~commit]"
730
+ }
731
+ }
732
+ },
733
+ "createTime": "2023-06-12T21:52:22.706Z" }
734
+ ]
735
+ ```
736
+
737
+ ***8. List all the tags for a template namespace and name***
738
+
739
+ Returns fields from pipeline template tag table for specified namespace and name.
740
+
741
+
742
+ **Request:**
743
+
744
+ - **Method**: GET
745
+ - **Path** : ‘/pipeline/templates/{templateNamespace}/{templateName}/tags`
746
+
747
+ **Response:**
748
+
749
+ JSON object consisting list of template tags, representing all the tags associated with the specified template name and namespace.
750
+
751
+ ```
752
+ Status Code: 200 (OK)
753
+ Response Body:
754
+ [
755
+ {
756
+ "id": 1,
757
+ "createTime": "2023-06-12T22:52:22.706Z",
758
+ "namespace": "namespace123",
759
+ "name": "testTemplate",
760
+ "tag": "stable",
761
+ "version": "1.0.0"
762
+ },
763
+ {
764
+ "id": 2,
765
+ "createTime": "2023-06-12T24:45:22.706Z",
766
+ "namespace": "namespace123",
767
+ "name": "testTemplate",
768
+ "tag": "latest"
769
+ "version": "1.1.0"
770
+ }
771
+ ]
772
+ ```
773
+
774
+ ***9. Get a specific template version details by version number or tag***
775
+
776
+ Returns fields from both template meta and version table associated with the specified pipeline template namespace, name and version/tag
777
+
778
+
779
+ **Request:**
780
+
781
+ - **Method**: GET
782
+ - **Path** : ‘/pipeline/templates/{templateNamespace}/{templateName}/{versionOrTag}’
783
+
784
+ **Response:**
785
+
786
+ JSON object consisting of the template details for the given version number or tag.
787
+
788
+ ```
789
+ Status Code: 200 (OK)
790
+ Response Body:
791
+ [
792
+ {
793
+ "id":1",
794
+ "templateId": 123,
795
+ "pipelineId": 3,
796
+ "namespace": "myNamespace",
797
+ "name": "template_name",
798
+ "version": "1.3.2",
799
+ "description": "template for testing",
800
+ "maintainer": "example@gmail.com",
801
+ "config": {
802
+ "jobs": {
803
+ "main": {
804
+ "image": "node:18",
805
+ "steps": {
806
+ "printLine": "echo 'Testing template creation V1'"
807
+ },
808
+ "requires": "[~pr, ~commit]"
809
+ }
810
+ }
811
+ },
812
+ "createTime": "2023-06-12T21:52:22.706Z"
813
+ }
814
+ ]
815
+ ```
816
+
817
+ ***10. Remove template and associated versions and tags***
818
+
819
+ Deletes the template and its corresponding versions and tags
820
+
821
+
822
+ **Request:**
823
+
824
+ - **Method**: DELETE
825
+ - **Path** : ‘/pipeline/templates/{templateNamespace}/{templateName}`
826
+
827
+ **Response:**
828
+
829
+ HTTP status code 204 (No Content)
830
+
831
+
832
+ ***11. Remove template tag***
833
+
834
+ Deletes the template tag for a specific template from the `templateTags` table where `templateType` is ‘PIPELINE’
835
+
836
+
837
+ **Request:**
838
+
839
+ - **Method**: DELETE
840
+ - **Path** : ‘/pipeline/templates/{templateNamespace}/{templateName}/tags/{tagName}’
841
+
842
+ **Response:**
843
+
844
+ HTTP status code 204 (No Content)
845
+
846
+ ***12. Remove template version and associated tags***
847
+
848
+ Deletes the specific template tag and then removes the associated versions
849
+
850
+ **Request:**
851
+
852
+ - **Method**: DELETE
853
+ - **Path** : ‘/pipeline/templates/{templateNamespace}/{templateName}/versions/{version}`
854
+
855
+ **Response:**
856
+
857
+ HTTP status code 204 (No Content)
858
+
859
+
860
+ ### SD CLI
861
+
862
+ We will introduce new commands to validate, publish and tag pipeline templates because using the existing commands will not allow us to easily differentiate between the two types of templates (job template and pipeline template)
863
+
864
+ CLI can be installed using below command:
865
+
866
+ ``` $ npm install sd-template-main ```
867
+
868
+
869
+ ***1. Validate***
870
+
871
+ We will add a new command `pipeline-template-validate`.
872
+
873
+
874
+ The default path to the template.yaml file is `./sd-template.yaml` unless specified in the environment variable `SD_TEMPLATE_PATH`
875
+
876
+ This command will
877
+ - read the content of ‘template.yaml’ and parse it into Javascript object
878
+ - make a POST request ‘/pipeline/template/validate’ endpoint
879
+
880
+ Note: This command does accept any arguments
881
+
882
+ Usage:
883
+
884
+ ```$ ./node_modules/.bin/pipeline-template-validate --json```
885
+
886
+
887
+ ***2. Publish***
888
+
889
+ We will add a new command `pipeline-template-publish`.
890
+
891
+ This command will
892
+ - Read the content of `template.yaml` and parse it into Javascript object
893
+ - Make a POST request to `/pipelineTemplates` endpoint to create a new template
894
+ - Make a PUT request to `/pipeline/template/{templateName}/tags/{tagName}` endpoint to create/update the tag for the newly created template
895
+
896
+ The default path to the template.yaml file is `./sd-template.yaml` unless specified in the environment variable `SD_TEMPLATE_PATH`
897
+
898
+
899
+ Arguments:
900
+ | Argument | Optional | Description |
901
+ | ---------- | ------------- | ------------- |
902
+ | tag| Yes | Specifies the name of the tag to be created/updated after the template is created. Uses `latest` as the tag name if not specified.
903
+
904
+
905
+ Usage:
906
+
907
+ ```
908
+ $ ./node_modules/.bin/pipeline-template-publish --json
909
+
910
+ #takes custom tag name "stable"
911
+ $ ./node_modules/.bin/pipeline-template-publish --json --tag stable
912
+ ```
913
+
914
+
915
+ ***3. Create/Update Tag***
916
+
917
+ We will add a new command `pipeline-template-tag`.
918
+
919
+ This command will
920
+ - Take template details (`name`, `namespace` and `version`) and name of the tag as input
921
+ - Make a PUT request to ‘/pipeline/template/{templateName}/tags/{tagName}’ endpoint to create or update the tag to the specified template
922
+
923
+
924
+
925
+ Arguments:
926
+ | Argument | Description |
927
+ | ---------- | ------------- |
928
+ | namespace| Specifies template namespace |
929
+ | name| Specifies template name |
930
+ | version| Specifies version of the template |
931
+ | tag| Specifies tag name |
932
+
933
+
934
+ Usage:
935
+
936
+ ```
937
+ $ ./node_modules/.bin/pipeline-template-tag --json --namespace template123 –name 123 --version 4.0.0 --tag stable
938
+ ```
939
+
940
+ ***4. Remove a Template***
941
+
942
+ We will add a new command `pipeline-template-remove`.
943
+
944
+ This command will
945
+ - Remove a template and associated versions and tags by making a DELETE request to the ‘/pipeline/templates/{templateName}’ API endpoint
946
+
947
+
948
+
949
+ Arguments:
950
+ | Argument | Description |
951
+ | ---------- | ------------- |
952
+ | namespace| Specifies template namespace |
953
+ | name| Specifies template name |
954
+
955
+
956
+ Usage:
957
+
958
+ ```
959
+ $ ./node_modules/.bin/pipeline-template-remove --json --namespace template123 –name 123
960
+ ```
961
+
962
+
963
+
964
+ ***5. Remove a Template Tag***
965
+
966
+ We will add a new command `pipeline-template-remove-tag`.
967
+
968
+ This command will
969
+ - Take template details (`name` and `namespace`) and name of the tag as input
970
+ - Make a DELETE request ‘/pipeline/templates/{templateName}/tags/{tagName}’ endpoint to remove the tag for the specified template
971
+
972
+
973
+
974
+
975
+ Arguments:
976
+ | Argument | Description |
977
+ | ---------- | ------------- |
978
+ | namespace| Specifies template namespace |
979
+ | name| Specifies template name |
980
+ | tag| Specifies tag name |
981
+
982
+
983
+ Usage:
984
+
985
+ ```
986
+ $ ./node_modules/.bin/pipeline-template-remove-tag --json --namespace template123 –name 123 --tag stable
987
+ ```
988
+
989
+ ***6. Remove a Template Version***
990
+
991
+ We will add a new command `pipeline-template-remove-version`.
992
+
993
+ This command will
994
+ - Take template name, namespace and version as input
995
+ - Make a DELETE request ‘/pipeline/templates/{templateName}versions/{version}’ endpoint to delete the config and tags associated with the specified version
996
+
997
+
998
+ Arguments:
999
+ | Argument | Description |
1000
+ | ---------- | ------------- |
1001
+ | namespace| Specifies template namespace |
1002
+ | name| Specifies template name |
1003
+ | version| Specifies the template version to be removed |
1004
+
1005
+
1006
+ Usage:
1007
+
1008
+ ```
1009
+ $ ./node_modules/.bin/pipeline-template-remove-version --namespace template123 –name 123 --version 1.0.0
1010
+ ```
1011
+
1012
+
1013
+ ***7. Get a Template Config with metadata by Tag***
1014
+
1015
+ We will add a new command `pipeline-template-get`.
1016
+
1017
+ This command will
1018
+ - Take template details (`name` and `namespace`) and tag name as input
1019
+ - Make a GET request to ‘/pipeline/templates/{templateName}/{versionOrTag}’ endpoint to get template configuration along with its metadata associated with the specified tag
1020
+
1021
+
1022
+
1023
+ Arguments:
1024
+ | Argument | Description |
1025
+ | ---------- | ------------- |
1026
+ | namespace| Specifies template namespace |
1027
+ | name| Specifies template name |
1028
+ | tag| Specifies the template tag name |
1029
+
1030
+
1031
+ Usage:
1032
+
1033
+ ```
1034
+ $ ./node_modules/.bin/pipeline-template-get --namespace template123 –name 123 --tag latest
1035
+ ```
1036
+
1037
+ ## UI
1038
+
1039
+ TODO: Will be updated after the meeting with the UX designer.
1040
+
1041
+
1042
+
1043
+
1044
+ ## Template Usage
1045
+
1046
+ ### Pipeline configuration
1047
+
1048
+ __Basic Configuration (without customization):__
1049
+
1050
+ ```yaml
1051
+ template: foo/bar@latest
1052
+ ```
1053
+
1054
+ __Advanced Configuration (with customization):__
1055
+
1056
+ ```yaml
1057
+ template: foo/bar@latest
1058
+ shared:
1059
+ environment:
1060
+ SD_SONAR_OPTS:
1061
+ settings:
1062
+ email: [foo@bar.com]
1063
+ ```
1064
+ New fields:
1065
+
1066
+ | Field | Sub Field | Schema |Description |
1067
+ | ---------- | ------------- | ------------- | ------------- |
1068
+ | template| |Same as job `template` [schema][schema-uasage-template]| Optional. Mutually exclusive with existing fields `jobs` and `parameters` |
1069
+
1070
+
1071
+ Existing fields:
1072
+
1073
+ | Field | Sub Field | Schema |Description |
1074
+ | ---------- | ------------- | ------------- | ------------- |
1075
+ | shared| settings, environment |Refer to job [schema][schema-uasage-shared]| Optional. Allowed even when pipeline is using a template |
1076
+ | | annotations, blockedBy, cache, description, freezeWindows, image, matrix, order, parameters, provider, requires, secrets, sourcePaths, steps, template, templateId| | Not allowed when pipeline is using a template. Note: Customization of these fields would be supported in future phases|
1077
+
1078
+
1079
+ ## API
1080
+
1081
+ ### DB Model
1082
+
1083
+ **Pipeline**
1084
+ - Add a new column `templateVersionId` in ‘pipeline’ table
1085
+
1086
+
1087
+ | Column | Type | Nullable |Description |
1088
+ | ---------- | ------------- | ------------- | ------------- |
1089
+ | templateVersionId | Sequelize.DOUBLE |Yes| Identifier of ‘pipelineTemplateVersions’ table |
1090
+
1091
+
1092
+ ### Domain Model
1093
+
1094
+ **Pipeline**
1095
+ - Add a new field `templateVersionId`
1096
+
1097
+
1098
+ | Column | Type | Nullable |Description |
1099
+ | ---------- | ------------- | ------------- | ------------- |
1100
+ | templateVersionId | Joi.number().integer().positive() |Yes| Identifier of ‘pipelineTemplateVersions’ table |
1101
+
1102
+
1103
+ ### Config Parser
1104
+
1105
+ ![Screenshot 2023-08-15 at 11 13 51 AM](https://github.com/screwdriver-cd/screwdriver/assets/67897071/20a29ce7-b19b-4cf0-8a84-7ddfeb71b81d)
1106
+
1107
+ When pipeline configuration contains `template` we need to perform below steps before flattening the configuration to build domain objects (pipeline, jobs, etc)
1108
+ 1. Validate the configuration
1109
+
1110
+ a. `jobs` and `parameters` should not be allowed
1111
+
1112
+ b. `shared` can contain only `settings` and `environment`
1113
+
1114
+ 1. Get template configuration (`shared`, `jobs`, `parameters`) from DB
1115
+ 1. Merge `shared` from pipeline configuration into template configuration
1116
+
1117
+ This merged configuration will then be flattened (merging `shared` into job configuration, etc) as it is done currently.
1118
+
1119
+ Also, reference to the template will be set in the `pipeline` domain object.
1120
+
1121
+
1122
+ ## UI
1123
+
1124
+ TODO: Will be updated after the meeting with the UX designer.
1125
+
1126
+
1127
+
1128
+
1129
+
1130
+
1131
+
1132
+
1133
+
1134
+
1135
+
1136
+
1137
+
1138
+
1139
+
1140
+
1141
+
1142
+
1143
+
1144
+
1145
+
1146
+
1147
+
1148
+
1149
+
1150
+
1151
+
1152
+
1153
+
1154
+
1155
+
1156
+ [schema-namespace]: https://github.com/screwdriver-cd/data-schema/blob/master/config/template.js#L7
1157
+ [schema-name]: https://github.com/screwdriver-cd/data-schema/blob/master/config/template.js#LL15C1-L15C41
1158
+ [schema-maintainer]: https://github.com/screwdriver-cd/data-schema/blob/master/config/template.js#LL47C1-L47C41
1159
+ [schema-version]: hhttps://github.com/screwdriver-cd/data-schema/blob/master/config/template.js#L30
1160
+ [schema-description]: https://github.com/screwdriver-cd/data-schema/blob/master/config/template.js#L42
1161
+ [schema-shared]: https://github.com/screwdriver-cd/data-schema/blob/master/config/base.js#LL31C1-L31C1
1162
+ [schema-jobs]: https://github.com/screwdriver-cd/data-schema/blob/master/config/base.js#L26
1163
+ [schema-params]: https://github.com/screwdriver-cd/data-schema/blob/master/config/parameters.js#L13
1164
+ [schema-domain-id]: https://github.com/screwdriver-cd/data-schema/blob/master/models/template.js#L9
1165
+ [schema-domain-name]: https://github.com/screwdriver-cd/data-schema/blob/master/models/template.js#L12
1166
+ [schema-domain-namespace]: https://github.com/screwdriver-cd/data-schema/blob/master/models/template.js#L17
1167
+ [schema-domain-maintainer]: https://github.com/screwdriver-cd/data-schema/blob/master/models/template.js#L15
1168
+ [schema-domain-trustedSinceVersion]: https://github.com/screwdriver-cd/data-schema/blob/master/config/template.js#L36
1169
+ [schema-domain-latestVersion]: https://github.com/screwdriver-cd/data-schema/blob/master/config/template.js#L36
1170
+ [schema-domain-pipelineId]: https://github.com/screwdriver-cd/data-schema/blob/master/models/pipeline.js#L30C7-L30C7
1171
+ [schema-domain-description]: https://github.com/screwdriver-cd/data-schema/blob/master/models/template.js#L14
1172
+ [schema-domain-version]: https://github.com/screwdriver-cd/data-schema/blob/master/models/template.js#L13
1173
+ [schema-domain-shared]: https://github.com/screwdriver-cd/data-schema/blob/master/config/base.js#LL31C1-L31C1
1174
+ [schema-domain-jobs]: https://github.com/screwdriver-cd/data-schema/blob/master/config/base.js#L67
1175
+ [schema-domain-params]: https://github.com/screwdriver-cd/data-schema/blob/master/config/parameters.js#L6
1176
+ [schema-domain-createTime]: https://github.com/screwdriver-cd/data-schema/blob/master/models/template.js#L19
1177
+ [schema-template-validator]: https://docs.google.com/document/d/12MAT6XxHQ28vqkPw6xlcxtVR3M5tOgnYGHEfUPyAWPI/edit#heading=h.47lbrhrjbdr6
1178
+ [schema-uasage-template]: https://github.com/screwdriver-cd/data-schema/blob/master/config/job.js#L129
1179
+ [schema-uasage-shared]: https://github.com/screwdriver-cd/data-schema/blob/master/config/job.js#L161
1180
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screwdriver-api",
3
- "version": "7.0.170",
3
+ "version": "7.0.172",
4
4
  "description": "API server for the Screwdriver.cd service",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -106,7 +106,7 @@
106
106
  "screwdriver-coverage-bookend": "^2.0.0",
107
107
  "screwdriver-coverage-sonar": "^4.1.1",
108
108
  "screwdriver-data-schema": "^23.2.0",
109
- "screwdriver-datastore-sequelize": "^8.1.1",
109
+ "screwdriver-datastore-sequelize": "^8.2.0",
110
110
  "screwdriver-executor-base": "^9.0.1",
111
111
  "screwdriver-executor-docker": "^6.0.0",
112
112
  "screwdriver-executor-k8s": "^15.0.1",
@@ -36,6 +36,7 @@ const {
36
36
  buildsToRestartFilter,
37
37
  trimJobName,
38
38
  getParallelBuilds,
39
+ isStartFromMiddleOfStage,
39
40
  Status
40
41
  } = require('./triggers/helpers');
41
42
 
@@ -77,7 +78,8 @@ async function triggerNextJobs(config, app) {
77
78
  /** @type Array<string> */
78
79
  const nextJobsTrigger = workflowParser.getNextJobs(currentEvent.workflowGraph, {
79
80
  trigger: currentJob.name,
80
- chainPR: currentPipeline.chainPR
81
+ chainPR: currentPipeline.chainPR,
82
+ startFrom: currentEvent.startFrom
81
83
  });
82
84
  const pipelineJoinData = await createJoinObject(nextJobsTrigger, current, eventFactory);
83
85
  const originalCurrentJobName = trimJobName(currentJob.name);
@@ -114,7 +116,10 @@ async function triggerNextJobs(config, app) {
114
116
  * 2. ([~D,B,C]->A) currentJob=D, nextJob=A, joinList(A)=[B,C]
115
117
  * joinList doesn't include D, so start A
116
118
  */
117
- if (isOrTrigger(currentEvent.workflowGraph, originalCurrentJobName, trimJobName(nextJobName))) {
119
+ if (
120
+ isOrTrigger(currentEvent.workflowGraph, originalCurrentJobName, trimJobName(nextJobName)) ||
121
+ isStartFromMiddleOfStage(currentJob.name, currentEvent.startFrom, currentEvent.workflowGraph)
122
+ ) {
118
123
  nextBuild = await orTrigger.execute(
119
124
  currentEvent,
120
125
  currentPipeline.id,
@@ -6,6 +6,7 @@ const merge = require('lodash.mergewith');
6
6
  const schema = require('screwdriver-data-schema');
7
7
  const { EXTERNAL_TRIGGER_ALL } = schema.config.regex;
8
8
  const { getFullStageJobName } = require('../../helper');
9
+ const STAGE_SETUP_PATTERN = /^stage@([\w-]+)(?::setup)$/;
9
10
 
10
11
  /**
11
12
  * @typedef {import('screwdriver-models').JobFactory} JobFactory
@@ -1063,6 +1064,38 @@ function buildsToRestartFilter(joinPipeline, groupEventBuilds, currentEvent, cur
1063
1064
  .filter(build => build !== null);
1064
1065
  }
1065
1066
 
1067
+ /**
1068
+ * Check if the job is setup job with setup suffix
1069
+ * @param {String} jobName Job name
1070
+ * @return {Boolean}
1071
+ */
1072
+ function isStageSetup(jobName) {
1073
+ return STAGE_SETUP_PATTERN.test(jobName);
1074
+ }
1075
+
1076
+ /**
1077
+ * Check if the job is a stage job
1078
+ * @param {String} jobName Job name
1079
+ * @param {Object} workflowGraph Workflow Graph
1080
+ * @return {Boolean}
1081
+ */
1082
+ function isStageJob(workflowGraph, jobName) {
1083
+ const jobNode = workflowGraph.nodes.find(n => n.name === jobName);
1084
+
1085
+ return jobNode.stageName !== undefined;
1086
+ }
1087
+
1088
+ /**
1089
+ * Check if the current job is a stage setup and the next job is a non-setup stage job
1090
+ * @param {String} triggerJob Current job
1091
+ * @param {String} startFrom Next job
1092
+ * @param {Object} workflowGraph Workflow Graph
1093
+ * @return {Boolean}
1094
+ */
1095
+ function isStartFromMiddleOfStage(triggerJob, startFrom, workflowGraph) {
1096
+ return isStageSetup(triggerJob) && !isStageSetup(startFrom) && isStageJob(workflowGraph, startFrom);
1097
+ }
1098
+
1066
1099
  module.exports = {
1067
1100
  Status,
1068
1101
  parseJobInfo,
@@ -1085,5 +1118,6 @@ module.exports = {
1085
1118
  extractCurrentPipelineJoinData,
1086
1119
  extractExternalJoinData,
1087
1120
  buildsToRestartFilter,
1088
- trimJobName
1121
+ trimJobName,
1122
+ isStartFromMiddleOfStage
1089
1123
  };
@@ -110,9 +110,13 @@ Query Params:
110
110
  * `type` - *Optional* Get pipeline or pr events (default `pipeline`)
111
111
  * `prNum` - *Optional* Return only PR events of specified PR number
112
112
  * `sha` - *Optional* Search `sha` and `configPipelineSha` for events
113
+ * `id` - *Optional* Fetch specific event ID; alternatively can use greater than(`gt:`) or less than(`lt:`) prefix
113
114
 
114
115
  `GET /pipelines/{id}/events?page={pageNumber}&count={countNumber}&sort={sort}&type={type}&prNum={prNumber}&sha={sha}`
115
116
 
117
+ `GET /pipelines/{id}/events?id=gt:{eventId}&count={countNumber}` (greater than eventId)
118
+ `GET /pipelines/{id}/events?id=lt:{eventId}&count={countNumber}` (less than eventId)
119
+
116
120
  #### Get all pipeline builds
117
121
  `page`, `count`, `sort`, `latest`, `sortBy`, `fetchSteps`, `readOnly`, and `groupEventId` are optional
118
122
  When `latest=true` and `groupEventId` is set, only latest builds in a pipeline based on groupEventId will be returned. The `latest` parameter must be used in conjunction with the `groupEventId`.
@@ -13,6 +13,12 @@ const shaSchema = joi
13
13
  .example('ccc49349d3cffbd12ea9e3d41521480b4aa5de5f');
14
14
  const typeSchema = schema.models.event.base.extract('type');
15
15
  const pipelineIdSchema = schema.models.pipeline.base.extract('id');
16
+ const INEQUALITY_SIGNS = /^(gt|lt):([\d]+)$/;
17
+ const queryIdSchema = joi
18
+ .alternatives()
19
+ .try(pipelineIdSchema, joi.string().regex(INEQUALITY_SIGNS))
20
+ .label('Query ID schema')
21
+ .example('gt:12345');
16
22
 
17
23
  module.exports = () => ({
18
24
  method: 'GET',
@@ -28,7 +34,7 @@ module.exports = () => ({
28
34
 
29
35
  handler: async (request, h) => {
30
36
  const factory = request.server.app.pipelineFactory;
31
- const { page, count, sha, prNum } = request.query;
37
+ const { page, count, sha, prNum, id } = request.query;
32
38
 
33
39
  return factory
34
40
  .get(request.params.id)
@@ -61,6 +67,11 @@ module.exports = () => ({
61
67
  };
62
68
  }
63
69
 
70
+ // Event id filter
71
+ if (id) {
72
+ config.params.id = id;
73
+ }
74
+
64
75
  return pipeline.getEvents(config);
65
76
  })
66
77
  .then(events => h.response(events.map(e => e.toJson())))
@@ -80,6 +91,7 @@ module.exports = () => ({
80
91
  type: typeSchema,
81
92
  prNum: prNumSchema,
82
93
  sha: shaSchema,
94
+ id: queryIdSchema,
83
95
  search: joi.forbidden(), // we don't support search for Pipeline list events
84
96
  getCount: joi.forbidden() // we don't support getCount for Pipeline list events
85
97
  })