duoops 0.2.0 → 0.2.1
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/dist/commands/init.js +54 -6
- package/oclif.manifest.json +91 -91
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -20,6 +20,29 @@ const hasBinary = (command) => {
|
|
|
20
20
|
return false;
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
+
const detectGlabToken = (host = 'gitlab.com') => {
|
|
24
|
+
const candidates = [
|
|
25
|
+
path.join(os.homedir(), '.config', 'glab-cli', 'config.yml'),
|
|
26
|
+
path.join(os.homedir(), 'Library', 'Application Support', 'glab-cli', 'config.yml'),
|
|
27
|
+
];
|
|
28
|
+
for (const configPath of candidates) {
|
|
29
|
+
try {
|
|
30
|
+
if (!fs.existsSync(configPath))
|
|
31
|
+
continue;
|
|
32
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
33
|
+
const hostSection = content.split(`${host}:`)[1];
|
|
34
|
+
if (!hostSection)
|
|
35
|
+
continue;
|
|
36
|
+
const isOauth = hostSection.match(/is_oauth2:\s*"?true"?/);
|
|
37
|
+
if (isOauth)
|
|
38
|
+
continue;
|
|
39
|
+
const tokenMatch = hostSection.match(/token:\s*(?:!!null\s+)?(\S+)/);
|
|
40
|
+
if (tokenMatch?.[1] && tokenMatch[1].startsWith('glpat-'))
|
|
41
|
+
return tokenMatch[1];
|
|
42
|
+
}
|
|
43
|
+
catch { /* ignore */ }
|
|
44
|
+
}
|
|
45
|
+
};
|
|
23
46
|
const detectGitRemotePath = () => {
|
|
24
47
|
try {
|
|
25
48
|
const remote = execSync('git remote get-url origin', { encoding: 'utf8' }).trim();
|
|
@@ -248,16 +271,41 @@ export default class Init extends Command {
|
|
|
248
271
|
static description = 'Initialize DuoOps, optionally wiring a GitLab project and GCP runner';
|
|
249
272
|
async run() {
|
|
250
273
|
this.log(bold('Welcome to DuoOps!'));
|
|
251
|
-
this.log('You will need a GitLab Personal Access Token with the "api" scope.');
|
|
252
|
-
this.log('Create one at https://gitlab.com/-/user_settings/personal_access_tokens\n');
|
|
253
274
|
const gitlabUrl = await input({
|
|
254
275
|
default: 'https://gitlab.com',
|
|
255
276
|
message: 'GitLab URL',
|
|
256
277
|
});
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
278
|
+
const { host } = new URL(gitlabUrl);
|
|
279
|
+
const glabToken = detectGlabToken(host);
|
|
280
|
+
const envToken = process.env.GITLAB_TOKEN || process.env.GL_TOKEN;
|
|
281
|
+
let gitlabToken;
|
|
282
|
+
if (glabToken || envToken) {
|
|
283
|
+
const source = glabToken ? 'glab CLI' : 'environment';
|
|
284
|
+
const detected = glabToken || envToken;
|
|
285
|
+
const masked = detected.slice(0, 6) + '...' + detected.slice(-4);
|
|
286
|
+
const useDetected = await confirm({
|
|
287
|
+
default: true,
|
|
288
|
+
message: `Found GitLab token from ${source} (${masked}). Use it?`,
|
|
289
|
+
});
|
|
290
|
+
if (useDetected) {
|
|
291
|
+
gitlabToken = detected;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
this.log('Create one at https://gitlab.com/-/user_settings/personal_access_tokens\n');
|
|
295
|
+
gitlabToken = await password({
|
|
296
|
+
mask: '*',
|
|
297
|
+
message: 'GitLab Personal Access Token',
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
this.log('You will need a GitLab Personal Access Token with the "api" scope.');
|
|
303
|
+
this.log('Create one at https://gitlab.com/-/user_settings/personal_access_tokens\n');
|
|
304
|
+
gitlabToken = await password({
|
|
305
|
+
mask: '*',
|
|
306
|
+
message: 'GitLab Personal Access Token',
|
|
307
|
+
});
|
|
308
|
+
}
|
|
261
309
|
const enableMeasure = await confirm({
|
|
262
310
|
message: 'Enable Measure/Sustainability Tracking (BigQuery)?',
|
|
263
311
|
});
|
package/oclif.manifest.json
CHANGED
|
@@ -360,96 +360,6 @@
|
|
|
360
360
|
"deploy.js"
|
|
361
361
|
]
|
|
362
362
|
},
|
|
363
|
-
"pipelines:list": {
|
|
364
|
-
"aliases": [],
|
|
365
|
-
"args": {
|
|
366
|
-
"project": {
|
|
367
|
-
"description": "Project ID or path (e.g. group/project)",
|
|
368
|
-
"name": "project",
|
|
369
|
-
"required": false
|
|
370
|
-
}
|
|
371
|
-
},
|
|
372
|
-
"description": "List GitLab CI pipelines for a project",
|
|
373
|
-
"examples": [
|
|
374
|
-
"<%= config.bin %> <%= command.id %> group/my-project",
|
|
375
|
-
"<%= config.bin %> <%= command.id %> 123 --limit 20 --ref main"
|
|
376
|
-
],
|
|
377
|
-
"flags": {
|
|
378
|
-
"limit": {
|
|
379
|
-
"char": "n",
|
|
380
|
-
"description": "Maximum number of pipelines to return",
|
|
381
|
-
"name": "limit",
|
|
382
|
-
"default": 10,
|
|
383
|
-
"hasDynamicHelp": false,
|
|
384
|
-
"multiple": false,
|
|
385
|
-
"type": "option"
|
|
386
|
-
},
|
|
387
|
-
"ref": {
|
|
388
|
-
"description": "Filter by branch or tag",
|
|
389
|
-
"name": "ref",
|
|
390
|
-
"hasDynamicHelp": false,
|
|
391
|
-
"multiple": false,
|
|
392
|
-
"type": "option"
|
|
393
|
-
},
|
|
394
|
-
"status": {
|
|
395
|
-
"description": "Filter by status (created, pending, running, success, failed, canceled, skipped, manual, scheduled)",
|
|
396
|
-
"name": "status",
|
|
397
|
-
"hasDynamicHelp": false,
|
|
398
|
-
"multiple": false,
|
|
399
|
-
"type": "option"
|
|
400
|
-
}
|
|
401
|
-
},
|
|
402
|
-
"hasDynamicHelp": false,
|
|
403
|
-
"hiddenAliases": [],
|
|
404
|
-
"id": "pipelines:list",
|
|
405
|
-
"pluginAlias": "duoops",
|
|
406
|
-
"pluginName": "duoops",
|
|
407
|
-
"pluginType": "core",
|
|
408
|
-
"strict": true,
|
|
409
|
-
"enableJsonFlag": false,
|
|
410
|
-
"isESM": true,
|
|
411
|
-
"relativePath": [
|
|
412
|
-
"dist",
|
|
413
|
-
"commands",
|
|
414
|
-
"pipelines",
|
|
415
|
-
"list.js"
|
|
416
|
-
]
|
|
417
|
-
},
|
|
418
|
-
"pipelines:show": {
|
|
419
|
-
"aliases": [],
|
|
420
|
-
"args": {
|
|
421
|
-
"project": {
|
|
422
|
-
"description": "Project ID (e.g. 123456)",
|
|
423
|
-
"name": "project",
|
|
424
|
-
"required": true
|
|
425
|
-
},
|
|
426
|
-
"pipeline_id": {
|
|
427
|
-
"description": "Pipeline ID",
|
|
428
|
-
"name": "pipeline_id",
|
|
429
|
-
"required": true
|
|
430
|
-
}
|
|
431
|
-
},
|
|
432
|
-
"description": "Show pipeline details and jobs",
|
|
433
|
-
"examples": [
|
|
434
|
-
"<%= config.bin %> <%= command.id %> 12345 67890"
|
|
435
|
-
],
|
|
436
|
-
"flags": {},
|
|
437
|
-
"hasDynamicHelp": false,
|
|
438
|
-
"hiddenAliases": [],
|
|
439
|
-
"id": "pipelines:show",
|
|
440
|
-
"pluginAlias": "duoops",
|
|
441
|
-
"pluginName": "duoops",
|
|
442
|
-
"pluginType": "core",
|
|
443
|
-
"strict": true,
|
|
444
|
-
"enableJsonFlag": false,
|
|
445
|
-
"isESM": true,
|
|
446
|
-
"relativePath": [
|
|
447
|
-
"dist",
|
|
448
|
-
"commands",
|
|
449
|
-
"pipelines",
|
|
450
|
-
"show.js"
|
|
451
|
-
]
|
|
452
|
-
},
|
|
453
363
|
"measure:calculate": {
|
|
454
364
|
"aliases": [],
|
|
455
365
|
"args": {},
|
|
@@ -599,6 +509,96 @@
|
|
|
599
509
|
"seed.js"
|
|
600
510
|
]
|
|
601
511
|
},
|
|
512
|
+
"pipelines:list": {
|
|
513
|
+
"aliases": [],
|
|
514
|
+
"args": {
|
|
515
|
+
"project": {
|
|
516
|
+
"description": "Project ID or path (e.g. group/project)",
|
|
517
|
+
"name": "project",
|
|
518
|
+
"required": false
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
"description": "List GitLab CI pipelines for a project",
|
|
522
|
+
"examples": [
|
|
523
|
+
"<%= config.bin %> <%= command.id %> group/my-project",
|
|
524
|
+
"<%= config.bin %> <%= command.id %> 123 --limit 20 --ref main"
|
|
525
|
+
],
|
|
526
|
+
"flags": {
|
|
527
|
+
"limit": {
|
|
528
|
+
"char": "n",
|
|
529
|
+
"description": "Maximum number of pipelines to return",
|
|
530
|
+
"name": "limit",
|
|
531
|
+
"default": 10,
|
|
532
|
+
"hasDynamicHelp": false,
|
|
533
|
+
"multiple": false,
|
|
534
|
+
"type": "option"
|
|
535
|
+
},
|
|
536
|
+
"ref": {
|
|
537
|
+
"description": "Filter by branch or tag",
|
|
538
|
+
"name": "ref",
|
|
539
|
+
"hasDynamicHelp": false,
|
|
540
|
+
"multiple": false,
|
|
541
|
+
"type": "option"
|
|
542
|
+
},
|
|
543
|
+
"status": {
|
|
544
|
+
"description": "Filter by status (created, pending, running, success, failed, canceled, skipped, manual, scheduled)",
|
|
545
|
+
"name": "status",
|
|
546
|
+
"hasDynamicHelp": false,
|
|
547
|
+
"multiple": false,
|
|
548
|
+
"type": "option"
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
"hasDynamicHelp": false,
|
|
552
|
+
"hiddenAliases": [],
|
|
553
|
+
"id": "pipelines:list",
|
|
554
|
+
"pluginAlias": "duoops",
|
|
555
|
+
"pluginName": "duoops",
|
|
556
|
+
"pluginType": "core",
|
|
557
|
+
"strict": true,
|
|
558
|
+
"enableJsonFlag": false,
|
|
559
|
+
"isESM": true,
|
|
560
|
+
"relativePath": [
|
|
561
|
+
"dist",
|
|
562
|
+
"commands",
|
|
563
|
+
"pipelines",
|
|
564
|
+
"list.js"
|
|
565
|
+
]
|
|
566
|
+
},
|
|
567
|
+
"pipelines:show": {
|
|
568
|
+
"aliases": [],
|
|
569
|
+
"args": {
|
|
570
|
+
"project": {
|
|
571
|
+
"description": "Project ID (e.g. 123456)",
|
|
572
|
+
"name": "project",
|
|
573
|
+
"required": true
|
|
574
|
+
},
|
|
575
|
+
"pipeline_id": {
|
|
576
|
+
"description": "Pipeline ID",
|
|
577
|
+
"name": "pipeline_id",
|
|
578
|
+
"required": true
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
"description": "Show pipeline details and jobs",
|
|
582
|
+
"examples": [
|
|
583
|
+
"<%= config.bin %> <%= command.id %> 12345 67890"
|
|
584
|
+
],
|
|
585
|
+
"flags": {},
|
|
586
|
+
"hasDynamicHelp": false,
|
|
587
|
+
"hiddenAliases": [],
|
|
588
|
+
"id": "pipelines:show",
|
|
589
|
+
"pluginAlias": "duoops",
|
|
590
|
+
"pluginName": "duoops",
|
|
591
|
+
"pluginType": "core",
|
|
592
|
+
"strict": true,
|
|
593
|
+
"enableJsonFlag": false,
|
|
594
|
+
"isESM": true,
|
|
595
|
+
"relativePath": [
|
|
596
|
+
"dist",
|
|
597
|
+
"commands",
|
|
598
|
+
"pipelines",
|
|
599
|
+
"show.js"
|
|
600
|
+
]
|
|
601
|
+
},
|
|
602
602
|
"runner:logs": {
|
|
603
603
|
"aliases": [],
|
|
604
604
|
"args": {},
|
|
@@ -669,5 +669,5 @@
|
|
|
669
669
|
]
|
|
670
670
|
}
|
|
671
671
|
},
|
|
672
|
-
"version": "0.2.
|
|
672
|
+
"version": "0.2.1"
|
|
673
673
|
}
|