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

screwdriver-cd / screwdriver / #3202

25 Jul 2025 04:52PM UTC coverage: 67.669% (-27.3%) from 94.935%
#3202

push

screwdriver

web-flow
feat(3363): Update the existing endpoint to get admin for a pipeline from the specified SCM context (#3370)

1284 of 2114 branches covered (60.74%)

Branch coverage included in aggregate %.

1 of 11 new or added lines in 1 file covered. (9.09%)

1235 existing lines in 49 files now uncovered.

3417 of 4833 relevant lines covered (70.7%)

50.53 hits per line

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

20.51
/plugins/pipelines/openPr.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 helper = require('./helper');
1✔
7
const pipelineIdSchema = schema.models.pipeline.base.extract('id');
1✔
8
const pipelineCheckoutUrlSchema = schema.models.pipeline.create.extract('checkoutUrl');
1✔
9
const pipelineRootDirSchema = schema.models.pipeline.create.extract('rootDir');
1✔
10

11
module.exports = () => ({
434✔
12
    method: 'POST',
13
    path: '/pipelines/{id}/openPr',
14
    options: {
15
        description: 'Open pull request for repository',
16
        notes: 'Open pull request',
17
        tags: ['api', 'pipelines'],
18
        auth: {
19
            strategies: ['token'],
20
            scope: ['user', '!guest']
21
        },
22

23
        handler: async (request, h) => {
UNCOV
24
            const { userFactory } = request.server.app;
×
UNCOV
25
            const { username, scmContext } = request.auth.credentials;
×
UNCOV
26
            const { files, title, message } = request.payload;
×
UNCOV
27
            const checkoutUrl = helper.formatCheckoutUrl(request.payload.checkoutUrl);
×
UNCOV
28
            const rootDir = helper.sanitizeRootDir(request.payload.rootDir);
×
29

UNCOV
30
            return userFactory
×
31
                .get({ username, scmContext })
32
                .then(user => {
UNCOV
33
                    if (!user) {
×
UNCOV
34
                        throw boom.notFound(`User ${username} does not exist`);
×
35
                    }
36

UNCOV
37
                    return user
×
38
                        .unsealToken()
39
                        .then(token => {
UNCOV
40
                            return userFactory.scm
×
41
                                .parseUrl({
42
                                    scmContext,
43
                                    rootDir,
44
                                    checkoutUrl,
45
                                    token
46
                                })
47
                                .then(scmUri =>
UNCOV
48
                                    user
×
49
                                        .getPermissions(scmUri)
50
                                        .then(permissions => {
UNCOV
51
                                            if (!permissions.push) {
×
UNCOV
52
                                                throw boom.forbidden(
×
53
                                                    `User ${user.getFullDisplayName()} does not have push permission for this repo`
54
                                                );
55
                                            }
56
                                        })
57
                                        .then(() => {
UNCOV
58
                                            let scmUrl = checkoutUrl;
×
59

60
                                            // Set branch if missing
UNCOV
61
                                            if (checkoutUrl.split('#').length === 1) {
×
UNCOV
62
                                                scmUrl = scmUrl.concat(`#${scmUri.split(':')[2]}`);
×
63
                                            }
64

UNCOV
65
                                            return userFactory.scm.openPr({
×
66
                                                checkoutUrl: scmUrl,
67
                                                files,
68
                                                token,
69
                                                scmContext,
70
                                                title,
71
                                                message
72
                                            });
73
                                        })
74
                                        .catch(error => {
75
                                            // 404 error throws, if branch name is incorrect
UNCOV
76
                                            throw boom.boomify(error, { statusCode: error.statusCode });
×
77
                                        })
78
                                );
79
                        })
80
                        .then(async pullRequest => {
UNCOV
81
                            if (!pullRequest) {
×
UNCOV
82
                                throw boom.notImplemented('openPr not implemented for gitlab');
×
83
                            }
UNCOV
84
                            const html = await pullRequest.data.html_url;
×
85

UNCOV
86
                            return h.response({ prUrl: html }).code(201);
×
87
                        });
88
                })
89
                .catch(err => {
UNCOV
90
                    throw err;
×
91
                });
92
        },
93
        validate: {
94
            params: joi.object({
95
                id: pipelineIdSchema
96
            }),
97
            payload: joi.object({
98
                checkoutUrl: pipelineCheckoutUrlSchema,
99
                rootDir: pipelineRootDirSchema,
100
                files: joi
101
                    .array()
102
                    .items(
103
                        joi.object().keys({
104
                            name: joi.string().required(),
105
                            content: joi.string().required()
106
                        })
107
                    )
108
                    .min(1)
109
                    .required(),
110
                title: joi.string().required(),
111
                message: joi.string().required()
112
            })
113
        }
114
    }
115
});
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