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 TrustGitHub extends TrustCommand {
7 static description = 'Create a trusted relationship between a package and GitHub Actions'
8 static name = 'github'
9 static positionals = 1 // expects at most 1 positional (package name)
10 static providerName = 'GitHub Actions'
11 static providerEntity = 'GitHub repository'
12 static providerFile = 'GitHub Actions Workflow'
13 static providerHostname = 'https://github.com'
14
15 // entity means project / repository
16 static entityKey = 'repository'
17
18 static usage = [
19 '[package] --file [--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 workflow file within a repositories .GitHub folder (must end in yaml, yml)',
28 }),
29 new Definition('repository', {
30 default: null,
31 type: String,
32 description: 'Name of the repository in the format owner/repo',
33 alias: ['repo'],
34 }),
35 new Definition('environment', {
36 default: null,
37 type: String,
38 description: 'CI environment name',
39 alias: ['env'],
40 }),
41 // globals are alphabetical
42 globalDefinitions['dry-run'],
43 globalDefinitions.json,
44 globalDefinitions.registry,
45 globalDefinitions.yes,
46 ]
47
48 getEntityUrl ({ providerHostname, file, entity }) {
49 if (file) {
50 return new URL(`${entity}/blob/HEAD/.github/workflows/${file}`, providerHostname).toString()
51 }
52 return new URL(entity, providerHostname).toString()
53 }
54
55 validateEntity (entity) {
56 if (entity.split('/').length !== 2) {
57 throw new Error(`${this.constructor.providerEntity} must be specified in the format owner/repository`)
58 }
59 }
60
61 validateFile (file) {
62 if (file !== path.basename(file)) {
63 throw new Error('GitHub Actions workflow must be just a file not a path')
64 }
65 }
66
67 static optionsToBody (options) {
68 const { file, repository, environment } = options
69 const trustConfig = {
70 type: 'github',
71 claims: {
72 repository,
73 workflow_ref: {
74 file,
75 },
76 ...(environment) && { environment },
77 },
78 }
79 return trustConfig
80 }
81
82 // Convert API response body to options
83 static bodyToOptions (body) {
84 const file = body.claims?.workflow_ref?.file
85 const repository = body.claims?.repository
86 const environment = body.claims?.environment
87 return {
88 ...(body.id) && { id: body.id },
89 ...(body.type) && { type: body.type },
90 ...(file) && { file },
91 ...(repository) && { repository },
92 ...(environment) && { environment },
93 }
94 }
95
96 async exec (positionalArgs, flags) {
97 await this.createConfigCommand({
98 positionalArgs,
99 flags,
100 })
101 }
102}
103
104module.exports = TrustGitHub
105 