(rootDir: string, repo: string, pm: PackageManager)
| 62 | // ---- PAT flow ---- |
| 63 | |
| 64 | async function setupPat(rootDir: string, repo: string, pm: PackageManager): Promise<void> { |
| 65 | const patUrl = 'https://github.com/settings/personal-access-tokens/new'; |
| 66 | |
| 67 | p.log.info(''); |
| 68 | p.note( |
| 69 | [ |
| 70 | `1. Open: ${pc.cyan(patUrl)}`, |
| 71 | '', |
| 72 | `2. Set a name, e.g. ${pc.dim('"bumpy-ci"')}`, |
| 73 | '', |
| 74 | `3. Under ${pc.bold('Resource owner')}, select the org or account that owns ${pc.cyan(repo)}`, |
| 75 | '', |
| 76 | `4. Set ${pc.bold('Expiration')} — choose a longer duration to avoid frequent rotation`, |
| 77 | ` (you'll need to regenerate and update the secret when it expires)`, |
| 78 | '', |
| 79 | `5. Under ${pc.bold('Repository access')}, select ${pc.bold('"Only select repositories"')}`, |
| 80 | ` and choose ${pc.cyan(repo)}`, |
| 81 | '', |
| 82 | `6. Under ${pc.bold('Permissions → Repository permissions')}, grant:`, |
| 83 | ...PAT_PERMISSIONS.map((perm) => ` • ${pc.bold(perm)}`), |
| 84 | '', |
| 85 | '7. Click "Generate token" and copy the value', |
| 86 | '', |
| 87 | pc.dim('Note: if the resource owner is an org, an admin may need to approve'), |
| 88 | pc.dim('the token request before it can be used.'), |
| 89 | '', |
| 90 | pc.dim('Tip: enable branch protection rules on your main branch to prevent'), |
| 91 | pc.dim('direct pushes — the PAT will only be used to push the version branch.'), |
| 92 | ].join('\n'), |
| 93 | 'Create a fine-grained PAT', |
| 94 | ); |
| 95 | |
| 96 | // Try to open browser |
| 97 | const shouldOpen = unwrap(await p.confirm({ message: 'Open the token creation page in your browser?' })); |
| 98 | if (shouldOpen) { |
| 99 | openBrowser(patUrl); |
| 100 | } |
| 101 | |
| 102 | // Prompt for the token |
| 103 | const token = unwrap( |
| 104 | await p.text({ |
| 105 | message: 'Paste your token:', |
| 106 | placeholder: 'github_pat_...', |
| 107 | validate: (value) => { |
| 108 | if (!value?.trim()) return 'Token is required'; |
| 109 | if (!value?.startsWith('github_pat_')) return 'Expected a fine-grained PAT (starts with github_pat_)'; |
| 110 | }, |
| 111 | }), |
| 112 | ); |
| 113 | |
| 114 | await storeSecret(rootDir, repo, token, pm); |
| 115 | } |
| 116 | |
| 117 | // ---- GitHub App flow ---- |
| 118 |
no test coverage detected
searching dependent graphs…