@remogram/cli 0.1.0-beta.4 → 0.1.0-beta.5

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.
Files changed (2) hide show
  1. package/index.js +118 -2
  2. package/package.json +7 -7
package/index.js CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  FACT_INVENTORY_PACKET_TYPES,
23
23
  forgeFactInventoryPacket,
24
24
  assertWriteCommandConfigured,
25
+ parseSinceObservedAt,
25
26
  } from '@remogram/core';
26
27
  import { provider as giteaApi } from '@remogram/provider-gitea-api';
27
28
  import { provider as githubApi } from '@remogram/provider-github-api';
@@ -229,7 +230,7 @@ async function buildDoctorPacket(cwd, providers) {
229
230
  'write_config',
230
231
  missing.length ? 'warn' : 'pass',
231
232
  missing.length
232
- ? `Provider supports write commands but .remogram.json write_commands omits: ${missing.join(', ')}`
233
+ ? `Provider supports write commands but .remogram.json write_commands omits: ${missing.join(', ')}. Add ids for Remogram CLI/MCP writes, or use forge/CI tooling for those actions outside Remogram.`
233
234
  : 'Consumer write_commands matches provider write surface',
234
235
  { provider_write_commands: providerWrites, configured_write_commands: configuredWrites },
235
236
  ),
@@ -415,6 +416,66 @@ export async function runCli(argv, options = {}) {
415
416
  ctx,
416
417
  inventoryBody,
417
418
  );
419
+ } else if (group === 'cr' && sub === 'files') {
420
+ const number = parsePositiveInt(flags.number, '--number');
421
+ if (number == null) {
422
+ throw Object.assign(new Error('--number required'), {
423
+ forgeError: forgeError(ERROR_CODES.INVALID_ARGS, '--number required for cr files'),
424
+ });
425
+ }
426
+ if (typeof provider.crFiles !== 'function') {
427
+ throw Object.assign(new Error('cr files not implemented for provider'), {
428
+ forgeError: forgeError(
429
+ ERROR_CODES.PROVIDER_UNSUPPORTED,
430
+ 'cr files not implemented for provider',
431
+ ),
432
+ });
433
+ }
434
+ packet = forgePacket(
435
+ PACKET_TYPES.CR_FILES,
436
+ ctx,
437
+ await provider.crFiles(ctx, { number }),
438
+ );
439
+ } else if (group === 'cr' && sub === 'comments') {
440
+ const number = parsePositiveInt(flags.number, '--number');
441
+ if (number == null) {
442
+ throw Object.assign(new Error('--number required'), {
443
+ forgeError: forgeError(ERROR_CODES.INVALID_ARGS, '--number required for cr comments'),
444
+ });
445
+ }
446
+ if (typeof provider.crComments !== 'function') {
447
+ throw Object.assign(new Error('cr comments not implemented for provider'), {
448
+ forgeError: forgeError(
449
+ ERROR_CODES.PROVIDER_UNSUPPORTED,
450
+ 'cr comments not implemented for provider',
451
+ ),
452
+ });
453
+ }
454
+ packet = forgePacket(
455
+ PACKET_TYPES.CR_COMMENTS,
456
+ ctx,
457
+ await provider.crComments(ctx, { number }),
458
+ );
459
+ } else if (group === 'forge' && sub === 'changes') {
460
+ let sinceIso;
461
+ try {
462
+ sinceIso = parseSinceObservedAt(flags.since);
463
+ } catch (err) {
464
+ throw err;
465
+ }
466
+ if (typeof provider.forgeChanges !== 'function') {
467
+ throw Object.assign(new Error('forge changes not implemented for provider'), {
468
+ forgeError: forgeError(
469
+ ERROR_CODES.PROVIDER_UNSUPPORTED,
470
+ 'forge changes not implemented for provider',
471
+ ),
472
+ });
473
+ }
474
+ packet = forgePacket(
475
+ PACKET_TYPES.FORGE_CHANGES,
476
+ ctx,
477
+ await provider.forgeChanges(ctx, { since: sinceIso }),
478
+ );
418
479
  } else if (group === 'cr' && sub === 'open') {
419
480
  if (typeof provider.crOpen !== 'function') {
420
481
  throw Object.assign(new Error('cr open not implemented for provider'), {
@@ -445,6 +506,27 @@ export async function runCli(argv, options = {}) {
445
506
  body: flags.body,
446
507
  }),
447
508
  );
509
+ } else if (group === 'status' && sub === 'set') {
510
+ if (typeof provider.statusSet !== 'function') {
511
+ throw Object.assign(new Error('status set not implemented for provider'), {
512
+ forgeError: forgeError(
513
+ ERROR_CODES.PROVIDER_UNSUPPORTED,
514
+ 'status set not implemented for provider',
515
+ ),
516
+ });
517
+ }
518
+ assertWriteCommandConfigured(ctx.config, 'status_set');
519
+ packet = forgePacket(
520
+ PACKET_TYPES.COMMIT_STATUS_SET,
521
+ ctx,
522
+ await provider.statusSet(ctx, {
523
+ sha: flags.sha,
524
+ context: flags.context,
525
+ state: flags.state,
526
+ target_url: flags.target_url,
527
+ description: flags.description,
528
+ }),
529
+ );
448
530
  } else if (group === 'pr' && sub === 'view') {
449
531
  const number = parsePositiveInt(flags.number, '--number');
450
532
  if (number == null) {
@@ -500,6 +582,40 @@ export async function runCli(argv, options = {}) {
500
582
  ...(allowedPaths ? { allowed_paths: allowedPaths } : {}),
501
583
  }),
502
584
  );
585
+ } else if (group === 'branch' && sub === 'protection') {
586
+ const branchRef = flags.branch_ref;
587
+ if (!branchRef) {
588
+ throw Object.assign(new Error('--branch-ref required'), {
589
+ forgeError: forgeError(
590
+ ERROR_CODES.INVALID_ARGS,
591
+ '--branch-ref required for branch protection',
592
+ ),
593
+ });
594
+ }
595
+ assertGitRef(branchRef, '--branch-ref');
596
+ if (typeof provider.branchProtection !== 'function') {
597
+ throw Object.assign(new Error('branch protection not implemented for provider'), {
598
+ forgeError: forgeError(
599
+ ERROR_CODES.PROVIDER_UNSUPPORTED,
600
+ 'branch protection not implemented for provider',
601
+ ),
602
+ });
603
+ }
604
+ packet = forgePacket(
605
+ PACKET_TYPES.BRANCH_PROTECTION,
606
+ ctx,
607
+ await provider.branchProtection(ctx, { branchRef }),
608
+ );
609
+ } else if (group === 'whoami' && sub == null) {
610
+ if (typeof provider.whoami !== 'function') {
611
+ throw Object.assign(new Error('whoami not implemented for provider'), {
612
+ forgeError: forgeError(
613
+ ERROR_CODES.PROVIDER_UNSUPPORTED,
614
+ 'whoami not implemented for provider',
615
+ ),
616
+ });
617
+ }
618
+ packet = forgePacket(PACKET_TYPES.PROVIDER_IDENTITY, ctx, await provider.whoami(ctx));
503
619
  } else if (group === 'sync' && sub === 'plan') {
504
620
  const remote = flags.remote || ctx.config.remote;
505
621
  assertGitRemote(remote, '--remote');
@@ -512,7 +628,7 @@ export async function runCli(argv, options = {}) {
512
628
  throw Object.assign(new Error(`Unknown command: ${positional.join(' ')}`), {
513
629
  forgeError: forgeError(
514
630
  ERROR_CODES.INVALID_ARGS,
515
- 'Unknown command. Try: provider capabilities, repo status, refs compare, refs inventory, cr inventory, cr open, pr view, pr checks, merge plan, sync plan',
631
+ 'Unknown command. Try: provider capabilities, repo status, refs compare, refs inventory, cr inventory, cr files, cr comments, cr open, status set, forge changes, pr view, pr checks, merge plan, sync plan, whoami, branch protection',
516
632
  ),
517
633
  });
518
634
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remogram/cli",
3
- "version": "0.1.0-beta.4",
3
+ "version": "0.1.0-beta.5",
4
4
  "description": "Remogram forge boundary CLI",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,11 +27,11 @@
27
27
  "node": ">=20"
28
28
  },
29
29
  "dependencies": {
30
- "@remogram/core": "0.1.0-beta.4",
31
- "@remogram/provider-gitea-api": "0.1.0-beta.4",
32
- "@remogram/provider-github-api": "0.1.0-beta.4",
33
- "@remogram/provider-gitlab-api": "0.1.0-beta.4",
34
- "@remogram/provider-gitea-tea": "0.1.0-beta.4",
35
- "@remogram/provider-github-gh": "0.1.0-beta.4"
30
+ "@remogram/core": "0.1.0-beta.5",
31
+ "@remogram/provider-gitea-api": "0.1.0-beta.5",
32
+ "@remogram/provider-github-api": "0.1.0-beta.5",
33
+ "@remogram/provider-gitlab-api": "0.1.0-beta.5",
34
+ "@remogram/provider-gitea-tea": "0.1.0-beta.5",
35
+ "@remogram/provider-github-gh": "0.1.0-beta.5"
36
36
  }
37
37
  }