gh-setup-git-identity 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # gh-setup-git-identity
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1094f06: feat: fully configurable support of `gh auth login`
8
+
9
+ Added configurable options for GitHub authentication that mirror all `gh auth login` flags:
10
+
11
+ - `--hostname`: GitHub hostname (default: `github.com`) - enables GitHub Enterprise support
12
+ - `--scopes` / `-s`: Authentication scopes (default: `repo,workflow,user,read:org,gist`)
13
+ - `--git-protocol` / `-p`: Git protocol - `ssh` or `https` (default: `https`)
14
+ - `--web` / `-w`: Open browser to authenticate (default: `true`)
15
+ - `--with-token`: Read token from stdin for non-interactive authentication
16
+ - `--skip-ssh-key`: Skip SSH key generation/upload prompt
17
+ - `--insecure-storage`: Store credentials in plain text instead of credential store
18
+ - `--clipboard`: Copy OAuth code to clipboard
19
+
20
+ These options can be configured via:
21
+
22
+ - CLI flags
23
+ - Environment variables (`GH_AUTH_HOSTNAME`, `GH_AUTH_SCOPES`, etc.)
24
+ - `.lenv` configuration file
25
+
26
+ The library also exports `defaultAuthOptions` object with all default values.
27
+
3
28
  ## 0.5.0
4
29
 
5
30
  ### Minor Changes
package/README.md CHANGED
@@ -86,14 +86,51 @@ gh-setup-git-identity --verbose
86
86
  ```
87
87
  Usage: gh-setup-git-identity [options]
88
88
 
89
- Options:
90
- --global, -g Set git config globally (default: true)
91
- --local, -l Set git config locally (in current repository)
92
- --dry-run, --dry Dry run - show what would be done without making changes
93
- --verify Verify current git identity configuration
94
- --verbose, -v Enable verbose output
95
- --help, -h Show help
96
- --version Show version number
89
+ Git Identity Options:
90
+ --global, -g Set git config globally (default: true)
91
+ --local, -l Set git config locally (in current repository)
92
+ --dry-run, --dry Dry run - show what would be done without making changes
93
+ --verify Verify current git identity configuration
94
+ --verbose, -v Enable verbose output
95
+
96
+ GitHub Authentication Options:
97
+ --hostname GitHub hostname to authenticate with (default: github.com)
98
+ --scopes, -s Authentication scopes, comma-separated (default: repo,workflow,user,read:org,gist)
99
+ --git-protocol, -p Protocol for git operations: ssh or https (default: https)
100
+ --web, -w Open a browser to authenticate (default: true)
101
+ --with-token Read token from standard input
102
+ --skip-ssh-key Skip generate/upload SSH key prompt
103
+ --insecure-storage Save credentials in plain text instead of credential store
104
+ --clipboard Copy one-time OAuth device code to clipboard
105
+
106
+ General Options:
107
+ --help, -h Show help
108
+ --version Show version number
109
+ ```
110
+
111
+ ### Advanced Authentication Examples
112
+
113
+ ```bash
114
+ # Authenticate with GitHub Enterprise
115
+ gh-setup-git-identity --hostname enterprise.github.com
116
+
117
+ # Use SSH protocol instead of HTTPS
118
+ gh-setup-git-identity --git-protocol ssh
119
+
120
+ # Authenticate with custom scopes
121
+ gh-setup-git-identity --scopes repo,user,gist
122
+
123
+ # Use token-based authentication (reads from stdin)
124
+ echo "ghp_xxxxx" | gh-setup-git-identity --with-token
125
+
126
+ # Copy OAuth code to clipboard automatically
127
+ gh-setup-git-identity --clipboard
128
+
129
+ # Skip SSH key generation prompt
130
+ gh-setup-git-identity --git-protocol ssh --skip-ssh-key
131
+
132
+ # Store credentials in plain text (not recommended for production)
133
+ gh-setup-git-identity --insecure-storage
97
134
  ```
98
135
 
99
136
  ### First Run (Not Authenticated)
@@ -206,14 +243,39 @@ Check if GitHub CLI is authenticated.
206
243
 
207
244
  #### `runGhAuthLogin(options?)`
208
245
 
209
- Run `gh auth login` interactively with the required scopes.
246
+ Run `gh auth login` with configurable options.
210
247
 
211
248
  **Parameters:**
249
+ - `options.hostname` - GitHub hostname (default: `'github.com'`)
250
+ - `options.scopes` - OAuth scopes, comma-separated (default: `'repo,workflow,user,read:org,gist'`)
251
+ - `options.gitProtocol` - Git protocol: `'ssh'` or `'https'` (default: `'https'`)
252
+ - `options.web` - Open browser to authenticate (default: `true`)
253
+ - `options.withToken` - Read token from stdin (default: `false`)
254
+ - `options.skipSshKey` - Skip SSH key prompt (default: `false`)
255
+ - `options.insecureStorage` - Store credentials in plain text (default: `false`)
256
+ - `options.clipboard` - Copy OAuth code to clipboard (default: `false`)
212
257
  - `options.verbose` - Enable verbose logging (default: `false`)
213
258
  - `options.logger` - Custom logger (default: `console`)
214
259
 
215
260
  **Returns:** `Promise<boolean>` - `true` if login was successful
216
261
 
262
+ #### `defaultAuthOptions`
263
+
264
+ Default authentication options object that can be imported and used as a reference:
265
+
266
+ ```javascript
267
+ {
268
+ hostname: 'github.com',
269
+ scopes: 'repo,workflow,user,read:org,gist',
270
+ gitProtocol: 'https',
271
+ web: true,
272
+ withToken: false,
273
+ skipSshKey: false,
274
+ insecureStorage: false,
275
+ clipboard: false
276
+ }
277
+ ```
278
+
217
279
  #### `getGitHubUserInfo(options?)`
218
280
 
219
281
  Get GitHub user information (username and primary email).
@@ -242,11 +304,23 @@ Get current git identity configuration.
242
304
 
243
305
  ### Environment Variables
244
306
 
307
+ #### Git Identity Options
308
+
245
309
  - `GH_SETUP_GIT_IDENTITY_GLOBAL` - Set global config (default: `true`)
246
310
  - `GH_SETUP_GIT_IDENTITY_LOCAL` - Set local config (default: `false`)
247
311
  - `GH_SETUP_GIT_IDENTITY_DRY_RUN` - Enable dry run mode (default: `false`)
248
312
  - `GH_SETUP_GIT_IDENTITY_VERBOSE` - Enable verbose output (default: `false`)
249
313
 
314
+ #### GitHub Authentication Options
315
+
316
+ - `GH_AUTH_HOSTNAME` - GitHub hostname (default: `github.com`)
317
+ - `GH_AUTH_SCOPES` - Authentication scopes (default: `repo,workflow,user,read:org,gist`)
318
+ - `GH_AUTH_GIT_PROTOCOL` - Git protocol: `ssh` or `https` (default: `https`)
319
+ - `GH_AUTH_WEB` - Open browser for authentication (default: `true`)
320
+ - `GH_AUTH_SKIP_SSH_KEY` - Skip SSH key prompt (default: `false`)
321
+ - `GH_AUTH_INSECURE_STORAGE` - Store credentials in plain text (default: `false`)
322
+ - `GH_AUTH_CLIPBOARD` - Copy OAuth code to clipboard (default: `false`)
323
+
250
324
  ## Testing
251
325
 
252
326
  Run tests using bun:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gh-setup-git-identity",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "A tool to setup git identity based on current gh user",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/cli.js CHANGED
@@ -7,13 +7,14 @@
7
7
  */
8
8
 
9
9
  import { makeConfig } from 'lino-arguments';
10
- import { setupGitIdentity, isGhAuthenticated, runGhAuthLogin, verifyGitIdentity } from './index.js';
10
+ import { setupGitIdentity, isGhAuthenticated, runGhAuthLogin, verifyGitIdentity, defaultAuthOptions } from './index.js';
11
11
 
12
12
  // Parse command-line arguments with environment variable and .lenv support
13
13
  const config = makeConfig({
14
14
  yargs: ({ yargs, getenv }) =>
15
15
  yargs
16
16
  .usage('Usage: $0 [options]')
17
+ // Git identity options
17
18
  .option('global', {
18
19
  alias: 'g',
19
20
  type: 'boolean',
@@ -43,17 +44,70 @@ const config = makeConfig({
43
44
  description: 'Verify current git identity configuration',
44
45
  default: false
45
46
  })
47
+ // gh auth login options
48
+ .option('hostname', {
49
+ type: 'string',
50
+ description: 'GitHub hostname to authenticate with',
51
+ default: getenv('GH_AUTH_HOSTNAME', defaultAuthOptions.hostname)
52
+ })
53
+ .option('scopes', {
54
+ alias: 's',
55
+ type: 'string',
56
+ description: 'Additional authentication scopes to request (comma-separated)',
57
+ default: getenv('GH_AUTH_SCOPES', defaultAuthOptions.scopes)
58
+ })
59
+ .option('git-protocol', {
60
+ alias: 'p',
61
+ type: 'string',
62
+ description: 'Protocol for git operations: ssh or https',
63
+ choices: ['ssh', 'https'],
64
+ default: getenv('GH_AUTH_GIT_PROTOCOL', defaultAuthOptions.gitProtocol)
65
+ })
66
+ .option('web', {
67
+ alias: 'w',
68
+ type: 'boolean',
69
+ description: 'Open a browser to authenticate',
70
+ default: getenv('GH_AUTH_WEB', defaultAuthOptions.web)
71
+ })
72
+ .option('with-token', {
73
+ type: 'boolean',
74
+ description: 'Read token from standard input',
75
+ default: false
76
+ })
77
+ .option('skip-ssh-key', {
78
+ type: 'boolean',
79
+ description: 'Skip generate/upload SSH key prompt',
80
+ default: getenv('GH_AUTH_SKIP_SSH_KEY', defaultAuthOptions.skipSshKey)
81
+ })
82
+ .option('insecure-storage', {
83
+ type: 'boolean',
84
+ description: 'Save authentication credentials in plain text instead of credential store',
85
+ default: getenv('GH_AUTH_INSECURE_STORAGE', defaultAuthOptions.insecureStorage)
86
+ })
87
+ .option('clipboard', {
88
+ type: 'boolean',
89
+ description: 'Copy one-time OAuth device code to clipboard',
90
+ default: getenv('GH_AUTH_CLIPBOARD', defaultAuthOptions.clipboard)
91
+ })
46
92
  .check((argv) => {
47
93
  // --global and --local are mutually exclusive
48
94
  if (argv.global && argv.local) {
49
95
  throw new Error('Arguments global and local are mutually exclusive');
50
96
  }
97
+ // --web and --with-token are mutually exclusive
98
+ if (argv.web && argv.withToken) {
99
+ throw new Error('Arguments web and with-token are mutually exclusive');
100
+ }
51
101
  return true;
52
102
  })
53
103
  .example('$0', 'Setup git identity globally using GitHub user')
54
104
  .example('$0 --local', 'Setup git identity for current repository only')
55
105
  .example('$0 --dry-run', 'Show what would be configured without making changes')
56
106
  .example('$0 --verify', 'Verify current git identity configuration')
107
+ .example('$0 --hostname enterprise.github.com', 'Authenticate with GitHub Enterprise')
108
+ .example('$0 --scopes repo,user,gist', 'Authenticate with custom scopes')
109
+ .example('$0 --git-protocol ssh', 'Use SSH protocol for git operations')
110
+ .example('$0 --with-token < token.txt', 'Authenticate using a token file')
57
111
  .help('h')
58
112
  .alias('h', 'help')
59
113
  .version('0.1.0')
@@ -135,13 +189,26 @@ async function main() {
135
189
  if (!authenticated) {
136
190
  console.log('GitHub CLI is not authenticated. Starting authentication...');
137
191
 
138
- // Automatically run gh auth login
139
- const loginSuccess = await runGhAuthLogin({ verbose: config.verbose });
192
+ // Prepare auth options from CLI arguments
193
+ const authOptions = {
194
+ hostname: config.hostname,
195
+ scopes: config.scopes,
196
+ gitProtocol: config.gitProtocol,
197
+ web: config.web,
198
+ withToken: config.withToken,
199
+ skipSshKey: config.skipSshKey,
200
+ insecureStorage: config.insecureStorage,
201
+ clipboard: config.clipboard,
202
+ verbose: config.verbose
203
+ };
204
+
205
+ // Automatically run gh auth login with configured options
206
+ const loginSuccess = await runGhAuthLogin(authOptions);
140
207
 
141
208
  if (!loginSuccess) {
142
209
  console.log('');
143
210
  console.log('Authentication failed. Please try running manually:');
144
- console.log(' printf "y" | gh auth login -h github.com -s repo,workflow,user,read:org,gist --git-protocol https --web');
211
+ console.log(` printf "y" | gh auth login -h ${config.hostname} -s ${config.scopes} --git-protocol ${config.gitProtocol} --web`);
145
212
  process.exit(1);
146
213
  }
147
214
  }
package/src/index.js CHANGED
@@ -114,27 +114,97 @@ function execInteractiveCommand(command, args = [], options = {}) {
114
114
  });
115
115
  }
116
116
 
117
+ /**
118
+ * Default options for gh auth login
119
+ */
120
+ export const defaultAuthOptions = {
121
+ hostname: 'github.com',
122
+ scopes: 'repo,workflow,user,read:org,gist',
123
+ gitProtocol: 'https',
124
+ web: true,
125
+ withToken: false,
126
+ skipSshKey: false,
127
+ insecureStorage: false,
128
+ clipboard: false
129
+ };
130
+
117
131
  /**
118
132
  * Run gh auth login interactively
119
133
  *
120
134
  * @param {Object} options - Options
135
+ * @param {string} options.hostname - GitHub hostname (default: 'github.com')
136
+ * @param {string} options.scopes - OAuth scopes, comma-separated (default: 'repo,workflow,user,read:org,gist')
137
+ * @param {string} options.gitProtocol - Git protocol: 'ssh' or 'https' (default: 'https')
138
+ * @param {boolean} options.web - Open browser to authenticate (default: true)
139
+ * @param {boolean} options.withToken - Read token from stdin (default: false)
140
+ * @param {boolean} options.skipSshKey - Skip SSH key generation/upload prompt (default: false)
141
+ * @param {boolean} options.insecureStorage - Store credentials in plain text (default: false)
142
+ * @param {boolean} options.clipboard - Copy OAuth code to clipboard (default: false)
121
143
  * @param {boolean} options.verbose - Enable verbose logging
122
144
  * @param {Object} options.logger - Custom logger
123
145
  * @returns {Promise<boolean>} True if login was successful
124
146
  */
125
147
  export async function runGhAuthLogin(options = {}) {
126
- const { verbose = false, logger = console } = options;
148
+ const {
149
+ hostname = defaultAuthOptions.hostname,
150
+ scopes = defaultAuthOptions.scopes,
151
+ gitProtocol = defaultAuthOptions.gitProtocol,
152
+ web = defaultAuthOptions.web,
153
+ withToken = defaultAuthOptions.withToken,
154
+ skipSshKey = defaultAuthOptions.skipSshKey,
155
+ insecureStorage = defaultAuthOptions.insecureStorage,
156
+ clipboard = defaultAuthOptions.clipboard,
157
+ verbose = false,
158
+ logger = console
159
+ } = options;
160
+
127
161
  const log = createDefaultLogger({ verbose, logger });
128
162
 
129
- // Run gh auth login with the required scopes
130
- // Use 'y' as input to confirm default account selection
131
- const result = await execInteractiveCommand('gh', [
132
- 'auth', 'login',
133
- '-h', 'github.com',
134
- '-s', 'repo,workflow,user,read:org,gist',
135
- '--git-protocol', 'https',
136
- '--web'
137
- ], { input: 'y\n' });
163
+ // Build the arguments for gh auth login
164
+ const args = ['auth', 'login'];
165
+
166
+ // Add hostname
167
+ if (hostname) {
168
+ args.push('-h', hostname);
169
+ }
170
+
171
+ // Add scopes
172
+ if (scopes) {
173
+ args.push('-s', scopes);
174
+ }
175
+
176
+ // Add git protocol
177
+ if (gitProtocol) {
178
+ args.push('--git-protocol', gitProtocol);
179
+ }
180
+
181
+ // Add boolean flags
182
+ if (web && !withToken) {
183
+ args.push('--web');
184
+ }
185
+
186
+ if (withToken) {
187
+ args.push('--with-token');
188
+ }
189
+
190
+ if (skipSshKey) {
191
+ args.push('--skip-ssh-key');
192
+ }
193
+
194
+ if (insecureStorage) {
195
+ args.push('--insecure-storage');
196
+ }
197
+
198
+ if (clipboard && web && !withToken) {
199
+ args.push('--clipboard');
200
+ }
201
+
202
+ log.debug(() => `Running: gh ${args.join(' ')}`);
203
+
204
+ // Run gh auth login
205
+ // Use 'y' as input to confirm default account selection (only needed for interactive mode)
206
+ const inputValue = withToken ? undefined : 'y\n';
207
+ const result = await execInteractiveCommand('gh', args, { input: inputValue });
138
208
 
139
209
  if (result.exitCode !== 0) {
140
210
  log.error(() => 'GitHub CLI authentication failed');
@@ -368,6 +438,7 @@ export async function verifyGitIdentity(options = {}) {
368
438
  }
369
439
 
370
440
  export default {
441
+ defaultAuthOptions,
371
442
  isGhAuthenticated,
372
443
  runGhAuthLogin,
373
444
  getGitHubUsername,
@@ -10,7 +10,8 @@ import {
10
10
  getGitHubEmail,
11
11
  getGitHubUserInfo,
12
12
  getGitConfig,
13
- verifyGitIdentity
13
+ verifyGitIdentity,
14
+ defaultAuthOptions
14
15
  } from '../src/index.js';
15
16
 
16
17
  // Note: These tests require gh to be authenticated
@@ -89,10 +90,42 @@ test('runGhAuthLogin - is exported as a function', async () => {
89
90
  assert.equal(typeof runGhAuthLogin, 'function');
90
91
  });
91
92
 
93
+ // Test: defaultAuthOptions is exported and has correct structure
94
+ test('defaultAuthOptions - is exported with correct default values', async () => {
95
+ assert.ok(typeof defaultAuthOptions === 'object');
96
+ assert.equal(defaultAuthOptions.hostname, 'github.com');
97
+ assert.equal(defaultAuthOptions.scopes, 'repo,workflow,user,read:org,gist');
98
+ assert.equal(defaultAuthOptions.gitProtocol, 'https');
99
+ assert.equal(defaultAuthOptions.web, true);
100
+ assert.equal(defaultAuthOptions.withToken, false);
101
+ assert.equal(defaultAuthOptions.skipSshKey, false);
102
+ assert.equal(defaultAuthOptions.insecureStorage, false);
103
+ assert.equal(defaultAuthOptions.clipboard, false);
104
+ });
105
+
106
+ // Test: defaultAuthOptions contains all expected keys
107
+ test('defaultAuthOptions - contains all expected keys', async () => {
108
+ const expectedKeys = [
109
+ 'hostname',
110
+ 'scopes',
111
+ 'gitProtocol',
112
+ 'web',
113
+ 'withToken',
114
+ 'skipSshKey',
115
+ 'insecureStorage',
116
+ 'clipboard'
117
+ ];
118
+
119
+ for (const key of expectedKeys) {
120
+ assert.ok(key in defaultAuthOptions, `Missing key: ${key}`);
121
+ }
122
+ });
123
+
92
124
  // Test: module exports
93
125
  test('module exports all expected functions', async () => {
94
126
  const module = await import('../src/index.js');
95
127
 
128
+ assert.ok(typeof module.defaultAuthOptions === 'object');
96
129
  assert.ok(typeof module.isGhAuthenticated === 'function');
97
130
  assert.ok(typeof module.runGhAuthLogin === 'function');
98
131
  assert.ok(typeof module.getGitHubUsername === 'function');
@@ -110,6 +143,7 @@ test('default export contains all functions', async () => {
110
143
  const defaultExport = module.default;
111
144
 
112
145
  assert.ok(typeof defaultExport === 'object');
146
+ assert.ok(typeof defaultExport.defaultAuthOptions === 'object');
113
147
  assert.ok(typeof defaultExport.isGhAuthenticated === 'function');
114
148
  assert.ok(typeof defaultExport.runGhAuthLogin === 'function');
115
149
  assert.ok(typeof defaultExport.getGitHubUsername === 'function');