codekingpro/portable-devtools
114k
1const Definition = require('@npmcli/config/lib/definitions/definition.js')
2const globalDefinitions = require('@npmcli/config/lib/definitions/definitions.js')
3const TrustCommand = require('../../trust-cmd.js')
4const path = require('node:path')
5
6class TrustGitLab extends TrustCommand {
7 static description = 'Create a trusted relationship between a package and GitLab CI/CD'
8 static name = 'gitlab'
9 static positionals = 1 // expects at most 1 positional (package name)
10 static providerName = 'GitLab CI/CD'
11 static providerEntity = 'GitLab project'
12 static providerFile = 'GitLab CI/CD Pipeline'
13 static providerHostname = 'https://gitlab.com'
14
15 // entity means project / repository
16 static entityKey = 'project'
17
18 static usage = [
19 '[package] --file [--project|--repo|--repository] [--env|--environment] [-y|--yes]',
20 ]
21
22 static definitions = [
23 new Definition('file', {
24 default: null,
25 type: String,
26 required: true,
27 description: 'Name of pipeline file (e.g., .gitlab-ci.yml)',
28 }),
29 new Definition('project', {
30 default: null,
31 type: String,
32 description: 'Name of the project in the format group/project or group/subgroup/project',
33 }),
34 new Definition('environment', {
35 default: null,
36 type: String,
37 description: 'CI environment name',
38 alias: ['env'],
39 }),
40 // globals are alphabetical
41 globalDefinitions['dry-run'],
42 globalDefinitions.json,
43 globalDefinitions.registry,
44 globalDefinitions.yes,
45 ]
46
47 getEntityUrl ({ providerHostname, file, entity }) {
48 if (file) {
49 return new URL(`${entity}/-/blob/HEAD/${file}`, providerHostname).toString()
50 }
51 return new URL(entity, providerHostname).toString()
52 }
53
54 validateEntity (entity) {
55 if (entity.split('/').length < 2) {
56 throw new Error(`${this.constructor.providerEntity} must be specified in the format group/project or group/subgroup/project`)
57 }
58 }
59
60 validateFile (file) {
61 if (file !== path.basename(file)) {
62 throw new Error('GitLab CI/CD pipeline file must be just a file not a path')
63 }
64 }
65
66 static optionsToBody (options) {
67 const { file, project, environment } = options
68 const trustConfig = {
69 type: 'gitlab',
70 claims: {
71 project_path: project,
72 // this looks off, but this is correct
73 /** The ref path to the top-level pipeline definition, for example, gitlab.example.com/my-group/my-project//.gitlab-ci.yml@refs/heads/main. Introduced in GitLab 16.2. This claim is null unless the pipeline definition is located in the same project. */
74 ci_config_ref_uri: {
75 file,
76 },
77 ...(environment) && { environment },
78 },
79 }
80 return trustConfig
81 }
82
83 // Convert API response body to options
84 static bodyToOptions (body) {
85 const file = body.claims?.ci_config_ref_uri?.file
86 const project = body.claims?.project_path
87 const environment = body.claims?.environment
88 return {
89 ...(body.id) && { id: body.id },
90 ...(body.type) && { type: body.type },
91 ...(file) && { file },
92 ...(project) && { project },
93 ...(environment) && { environment },
94 }
95 }
96
97 async exec (positionalArgs, flags) {
98 await this.createConfigCommand({
99 positionalArgs,
100 flags,
101 })
102 }
103}
104
105module.exports = TrustGitLab
106 