• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

screwdriver-cd / screwdriver / #3412

12 May 2026 12:11AM UTC coverage: 75.519% (-19.9%) from 95.405%
#3412

Pull #3493

screwdriver

web-flow
Merge branch 'master' into fix_event_meta_update
Pull Request #3493: fix: Exclusive control over meta updates

1703 of 2430 branches covered (70.08%)

Branch coverage included in aggregate %.

13 of 13 new or added lines in 1 file covered. (100.0%)

1057 existing lines in 57 files now uncovered.

4374 of 5617 relevant lines covered (77.87%)

106.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

12.77
/plugins/pipelines/remove.js
1
'use strict';
2

3
const boom = require('@hapi/boom');
1✔
4
const joi = require('joi');
1✔
5
const schema = require('screwdriver-data-schema');
1✔
6
const logger = require('screwdriver-logger');
1✔
7
const idSchema = schema.models.pipeline.base.extract('id');
1✔
8

9
module.exports = () => ({
393✔
10
    method: 'DELETE',
11
    path: '/pipelines/{id}',
12
    options: {
13
        description: 'Delete a single pipeline',
14
        notes: 'Returns null if successful',
15
        tags: ['api', 'pipelines'],
16
        auth: {
17
            strategies: ['token'],
18
            scope: ['user', '!guest']
19
        },
20

21
        handler: async (request, h) => {
UNCOV
22
            const { pipelineFactory, bannerFactory } = request.server.app;
×
UNCOV
23
            const { userFactory } = request.server.app;
×
UNCOV
24
            const { username, scmContext, scmUserId } = request.auth.credentials;
×
25

26
            // Fetch the pipeline and user models
UNCOV
27
            return Promise.all([pipelineFactory.get(request.params.id), userFactory.get({ username, scmContext })])
×
28
                .then(([pipeline, user]) => {
UNCOV
29
                    if (!pipeline) {
×
UNCOV
30
                        throw boom.notFound('Pipeline does not exist');
×
31
                    }
UNCOV
32
                    if (pipeline.state === 'DELETING') {
×
UNCOV
33
                        throw boom.conflict('This pipeline is already being deleted.');
×
34
                    }
UNCOV
35
                    if (!user) {
×
UNCOV
36
                        throw boom.notFound(`User ${username} does not exist`);
×
37
                    }
38

UNCOV
39
                    const scmDisplayName = bannerFactory.scm.getDisplayName({ scmContext });
×
40
                    // Lookup whether user is admin
UNCOV
41
                    const adminDetails = request.server.plugins.banners.screwdriverAdminDetails(
×
42
                        username,
43
                        scmDisplayName,
44
                        scmUserId
45
                    );
46

UNCOV
47
                    if (pipeline.configPipelineId && pipeline.state !== 'INACTIVE') {
×
UNCOV
48
                        if (!adminDetails.isAdmin) {
×
UNCOV
49
                            throw boom.forbidden(
×
50
                                'Child pipeline can only be removed' +
51
                                    ` after removing it from scmUrls in config pipeline ${pipeline.configPipelineId}`
52
                            );
53
                        }
54
                    }
55

56
                    // ask the user for permissions on this repo
UNCOV
57
                    return (
×
58
                        user
59
                            .getPermissions(pipeline.scmUri)
60
                            // check if user has admin access
61
                            .then(permissions => {
UNCOV
62
                                if (!permissions.admin) {
×
UNCOV
63
                                    throw boom.forbidden(
×
64
                                        `User ${username} does not have admin permission for this repo`
65
                                    );
66
                                }
67
                            })
68
                            .catch(error => {
69
                                // Allow cluster admins to remove pipeline
UNCOV
70
                                if (adminDetails.isAdmin) {
×
UNCOV
71
                                    return Promise.resolve(null);
×
72
                                }
73

UNCOV
74
                                throw boom.boomify(error, { statusCode: error.statusCode });
×
75
                            })
76
                            // user has good permissions, remove the pipeline
77
                            .then(async () => {
UNCOV
78
                                logger.info(
×
79
                                    `[Audit] user ${user.username}:${scmContext} deletes the pipeline pipelineId:${request.params.id}, scmUri:${pipeline.scmUri}.`
80
                                );
UNCOV
81
                                await pipeline.remove();
×
82
                            })
UNCOV
83
                            .then(() => h.response().code(204))
×
84
                    );
85
                })
86
                .catch(err => {
UNCOV
87
                    throw err;
×
88
                });
89
        },
90
        validate: {
91
            params: joi.object({
92
                id: idSchema
93
            })
94
        }
95
    }
96
});
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc