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.
@@ -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 gitlabToken = await password({
258
- mask: '*',
259
- message: 'GitLab Personal Access Token',
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
  });
@@ -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.0"
672
+ "version": "0.2.1"
673
673
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duoops",
3
3
  "description": "Toolset for Explainable and Sustainable CI on Gitlab.",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "author": "Younes Laaroussi",
6
6
  "bin": {
7
7
  "duoops": "./bin/run.js"