@renaiss-shipflow/cli 0.2.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.
Files changed (114) hide show
  1. package/README.md +13 -0
  2. package/dist/__tests__/gh.test.d.ts +2 -0
  3. package/dist/__tests__/gh.test.d.ts.map +1 -0
  4. package/dist/__tests__/gh.test.js +46 -0
  5. package/dist/__tests__/gh.test.js.map +1 -0
  6. package/dist/__tests__/login.test.d.ts +2 -0
  7. package/dist/__tests__/login.test.d.ts.map +1 -0
  8. package/dist/__tests__/login.test.js +25 -0
  9. package/dist/__tests__/login.test.js.map +1 -0
  10. package/dist/__tests__/project.test.d.ts +2 -0
  11. package/dist/__tests__/project.test.d.ts.map +1 -0
  12. package/dist/__tests__/project.test.js +17 -0
  13. package/dist/__tests__/project.test.js.map +1 -0
  14. package/dist/client.d.ts +220 -0
  15. package/dist/client.d.ts.map +1 -0
  16. package/dist/client.js +171 -0
  17. package/dist/client.js.map +1 -0
  18. package/dist/commands/activity.d.ts +3 -0
  19. package/dist/commands/activity.d.ts.map +1 -0
  20. package/dist/commands/activity.js +38 -0
  21. package/dist/commands/activity.js.map +1 -0
  22. package/dist/commands/auth.d.ts +3 -0
  23. package/dist/commands/auth.d.ts.map +1 -0
  24. package/dist/commands/auth.js +58 -0
  25. package/dist/commands/auth.js.map +1 -0
  26. package/dist/commands/channels.d.ts +3 -0
  27. package/dist/commands/channels.d.ts.map +1 -0
  28. package/dist/commands/channels.js +60 -0
  29. package/dist/commands/channels.js.map +1 -0
  30. package/dist/commands/claims.d.ts +3 -0
  31. package/dist/commands/claims.d.ts.map +1 -0
  32. package/dist/commands/claims.js +33 -0
  33. package/dist/commands/claims.js.map +1 -0
  34. package/dist/commands/helpers.d.ts +9 -0
  35. package/dist/commands/helpers.d.ts.map +1 -0
  36. package/dist/commands/helpers.js +36 -0
  37. package/dist/commands/helpers.js.map +1 -0
  38. package/dist/commands/init.d.ts +3 -0
  39. package/dist/commands/init.d.ts.map +1 -0
  40. package/dist/commands/init.js +41 -0
  41. package/dist/commands/init.js.map +1 -0
  42. package/dist/commands/issue.d.ts +3 -0
  43. package/dist/commands/issue.d.ts.map +1 -0
  44. package/dist/commands/issue.js +151 -0
  45. package/dist/commands/issue.js.map +1 -0
  46. package/dist/commands/issues.d.ts +3 -0
  47. package/dist/commands/issues.d.ts.map +1 -0
  48. package/dist/commands/issues.js +34 -0
  49. package/dist/commands/issues.js.map +1 -0
  50. package/dist/commands/login.d.ts +3 -0
  51. package/dist/commands/login.d.ts.map +1 -0
  52. package/dist/commands/login.js +50 -0
  53. package/dist/commands/login.js.map +1 -0
  54. package/dist/commands/pr.d.ts +3 -0
  55. package/dist/commands/pr.d.ts.map +1 -0
  56. package/dist/commands/pr.js +93 -0
  57. package/dist/commands/pr.js.map +1 -0
  58. package/dist/commands/regression.d.ts +3 -0
  59. package/dist/commands/regression.d.ts.map +1 -0
  60. package/dist/commands/regression.js +29 -0
  61. package/dist/commands/regression.js.map +1 -0
  62. package/dist/commands/release.d.ts +3 -0
  63. package/dist/commands/release.d.ts.map +1 -0
  64. package/dist/commands/release.js +48 -0
  65. package/dist/commands/release.js.map +1 -0
  66. package/dist/commands/repos.d.ts +3 -0
  67. package/dist/commands/repos.d.ts.map +1 -0
  68. package/dist/commands/repos.js +88 -0
  69. package/dist/commands/repos.js.map +1 -0
  70. package/dist/commands/stats.d.ts +3 -0
  71. package/dist/commands/stats.d.ts.map +1 -0
  72. package/dist/commands/stats.js +34 -0
  73. package/dist/commands/stats.js.map +1 -0
  74. package/dist/commands/status.d.ts +3 -0
  75. package/dist/commands/status.d.ts.map +1 -0
  76. package/dist/commands/status.js +35 -0
  77. package/dist/commands/status.js.map +1 -0
  78. package/dist/commands/test.d.ts +3 -0
  79. package/dist/commands/test.d.ts.map +1 -0
  80. package/dist/commands/test.js +44 -0
  81. package/dist/commands/test.js.map +1 -0
  82. package/dist/commands/trigger.d.ts +3 -0
  83. package/dist/commands/trigger.d.ts.map +1 -0
  84. package/dist/commands/trigger.js +25 -0
  85. package/dist/commands/trigger.js.map +1 -0
  86. package/dist/commands/workflows.d.ts +3 -0
  87. package/dist/commands/workflows.d.ts.map +1 -0
  88. package/dist/commands/workflows.js +108 -0
  89. package/dist/commands/workflows.js.map +1 -0
  90. package/dist/config.d.ts +39 -0
  91. package/dist/config.d.ts.map +1 -0
  92. package/dist/config.js +67 -0
  93. package/dist/config.js.map +1 -0
  94. package/dist/gh.d.ts +45 -0
  95. package/dist/gh.d.ts.map +1 -0
  96. package/dist/gh.js +82 -0
  97. package/dist/gh.js.map +1 -0
  98. package/dist/index.d.ts +3 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +45 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/output.d.ts +12 -0
  103. package/dist/output.d.ts.map +1 -0
  104. package/dist/output.js +71 -0
  105. package/dist/output.js.map +1 -0
  106. package/dist/project.d.ts +15 -0
  107. package/dist/project.d.ts.map +1 -0
  108. package/dist/project.js +64 -0
  109. package/dist/project.js.map +1 -0
  110. package/dist/prompts.d.ts +4 -0
  111. package/dist/prompts.d.ts.map +1 -0
  112. package/dist/prompts.js +24 -0
  113. package/dist/prompts.js.map +1 -0
  114. package/package.json +46 -0
@@ -0,0 +1,93 @@
1
+ import { execSync } from "node:child_process";
2
+ import { ShipFlowClient } from "../client.js";
3
+ import { resolveApiUrl, resolveAuthToken, loadCredentials } from "../config.js";
4
+ import { resolveProject } from "../project.js";
5
+ import { ghPRCreate, ghPRMerge } from "../gh.js";
6
+ export function registerPRCommand(program) {
7
+ const pr = program.command("pr").description("Pull request actions");
8
+ pr
9
+ .command("create")
10
+ .description("Open a PR; prepends ShipFlow context to the body and signals ShipFlow")
11
+ .option("--issue <n>", "Issue number this PR closes (auto-detected from branch if omitted)")
12
+ .option("--title <title>", "PR title")
13
+ .option("--body <body>", "PR body (added under ShipFlow header)")
14
+ .option("--base <ref>", "Base branch")
15
+ .option("--draft", "Create as draft")
16
+ .option("--preview-url <url>", "Testing/preview site for this PR (relayed to the issue reporter)")
17
+ .option("--json", "Output JSON")
18
+ .action(async (opts) => {
19
+ const ctx = await loadCtx(program);
20
+ const branch = currentBranch();
21
+ const issueNumber = opts.issue ? parseInt(opts.issue, 10) : detectIssueFromBranch(branch);
22
+ const triage = issueNumber ? await ctx.client.getTriage(ctx.creds.org, ctx.project.projectId, ctx.project.repoFullName, issueNumber).catch(() => null) : null;
23
+ const header = buildShipFlowHeader(ctx.project.projectName, issueNumber, triage);
24
+ const body = `${header}\n\n${opts.body ?? ""}`;
25
+ const created = ghPRCreate({ repo: ctx.project.repoFullName, body, title: opts.title, base: opts.base, head: branch, draft: opts.draft });
26
+ try {
27
+ await ctx.client.signal(ctx.creds.org, ctx.project.projectId, "prs", created.number, "opened", {
28
+ repo: ctx.project.repoFullName,
29
+ branch,
30
+ headSha: execSync("git rev-parse HEAD").toString().trim(),
31
+ issueRefs: issueNumber ? [issueNumber] : [],
32
+ previewUrl: opts.previewUrl ?? "",
33
+ });
34
+ }
35
+ catch (e) {
36
+ console.warn(`PR opened but ShipFlow signal failed: ${e.message}`);
37
+ }
38
+ if (opts.json) {
39
+ console.log(JSON.stringify(created));
40
+ return;
41
+ }
42
+ console.log(created.url);
43
+ });
44
+ pr
45
+ .command("merge <number>")
46
+ .description("Merge a PR; signals ShipFlow (no downstream cascade)")
47
+ .option("--mode <mode>", "squash | merge | rebase", "squash")
48
+ .option("--keep-branch", "Don't delete the head branch")
49
+ .action(async (numberStr, opts) => {
50
+ const ctx = await loadCtx(program);
51
+ const number = parseInt(numberStr, 10);
52
+ const result = ghPRMerge(ctx.project.repoFullName, number, opts.mode, !opts.keepBranch);
53
+ try {
54
+ await ctx.client.signal(ctx.creds.org, ctx.project.projectId, "prs", number, "merged", {
55
+ repo: ctx.project.repoFullName,
56
+ mergedSha: result.mergedSha,
57
+ });
58
+ }
59
+ catch (e) {
60
+ console.warn(`Merged but ShipFlow signal failed: ${e.message}`);
61
+ }
62
+ console.log(`merged: ${result.mergedSha}`);
63
+ });
64
+ }
65
+ async function loadCtx(program) {
66
+ const auth = resolveAuthToken();
67
+ const creds = loadCredentials();
68
+ if (!auth || !creds) {
69
+ console.error("Not signed in. Run: renaiss-shipflow login");
70
+ process.exit(1);
71
+ }
72
+ const client = new ShipFlowClient({ baseUrl: resolveApiUrl(program.opts().apiUrl), jwt: auth.token });
73
+ const project = await resolveProject(client, creds);
74
+ return { auth, creds, client, project };
75
+ }
76
+ function currentBranch() {
77
+ return execSync("git rev-parse --abbrev-ref HEAD").toString().trim();
78
+ }
79
+ function detectIssueFromBranch(branch) {
80
+ const m = branch.match(/^(?:issue|fix|feat)\/(\d+)/);
81
+ return m ? parseInt(m[1], 10) : undefined;
82
+ }
83
+ function buildShipFlowHeader(project, issue, triage) {
84
+ const lines = ["## ShipFlow context", `- Project: ${project}`];
85
+ if (issue)
86
+ lines.push(`- Closes #${issue}`);
87
+ if (triage?.priority)
88
+ lines.push(`- Triage priority: ${triage.priority}`);
89
+ if (triage?.relatedFeatures?.length)
90
+ lines.push(`- Features: ${triage.relatedFeatures.join(", ")}`);
91
+ return lines.join("\n");
92
+ }
93
+ //# sourceMappingURL=pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/commands/pr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerRegressionCommand(program: Command): void;
3
+ //# sourceMappingURL=regression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regression.d.ts","sourceRoot":"","sources":["../../src/commands/regression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiBhE"}
@@ -0,0 +1,29 @@
1
+ import { execSync } from "node:child_process";
2
+ import { ShipFlowClient } from "../client.js";
3
+ import { resolveApiUrl, resolveAuthToken, loadCredentials } from "../config.js";
4
+ import { resolveProject } from "../project.js";
5
+ export function registerRegressionCommand(program) {
6
+ program
7
+ .command("regression")
8
+ .description("Trigger ShipFlow's server-side regression test_runner")
9
+ .option("--ref <sha>", "Ref to test (defaults to current HEAD)")
10
+ .option("--json", "Output JSON")
11
+ .action(async (opts) => {
12
+ const auth = resolveAuthToken();
13
+ const creds = loadCredentials();
14
+ if (!auth || !creds) {
15
+ console.error("Not signed in. Run: renaiss-shipflow login");
16
+ process.exit(1);
17
+ }
18
+ const ref = opts.ref ?? execSync("git rev-parse HEAD").toString().trim();
19
+ const client = new ShipFlowClient({ baseUrl: resolveApiUrl(program.opts().apiUrl), jwt: auth.token });
20
+ const project = await resolveProject(client, creds);
21
+ const result = await client.triggerWorkflow(creds.org, project.projectId, "test_runner", { repo: project.repoFullName, ref });
22
+ if (opts.json) {
23
+ console.log(JSON.stringify(result));
24
+ return;
25
+ }
26
+ console.log(`Regression run queued: ${result.runId}`);
27
+ });
28
+ }
29
+ //# sourceMappingURL=regression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regression.js","sourceRoot":"","sources":["../../src/commands/regression.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,uDAAuD,CAAC;SACpE,MAAM,CAAC,aAAa,EAAE,wCAAwC,CAAC;SAC/D,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC;SAC/B,MAAM,CAAC,KAAK,EAAE,IAAsC,EAAE,EAAE;QACvD,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QACtG,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,QAAQ,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QACzE,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACtG,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9H,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerReleaseCommand(program: Command): void;
3
+ //# sourceMappingURL=release.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../src/commands/release.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4B7D"}
@@ -0,0 +1,48 @@
1
+ import { execSync } from "node:child_process";
2
+ import { ShipFlowClient } from "../client.js";
3
+ import { resolveApiUrl, resolveAuthToken, loadCredentials } from "../config.js";
4
+ import { resolveProject } from "../project.js";
5
+ import { promptText } from "../prompts.js";
6
+ export function registerReleaseCommand(program) {
7
+ program
8
+ .command("release")
9
+ .description("Trigger a ShipFlow release (patch_notes + regression + downstream workflows)")
10
+ .option("--tag <tag>", "Release tag (e.g. v0.7.3)")
11
+ .option("--base-tag <tag>", "Previous tag (auto-detect if omitted)")
12
+ .option("--env <env>", "Target environment (staging|prod)")
13
+ .option("--wait", "Block and stream status until terminal")
14
+ .option("--json", "Output JSON")
15
+ .action(async (opts) => {
16
+ const auth = resolveAuthToken();
17
+ const creds = loadCredentials();
18
+ if (!auth || !creds) {
19
+ console.error("Not signed in. Run: renaiss-shipflow login");
20
+ process.exit(1);
21
+ }
22
+ const client = new ShipFlowClient({ baseUrl: resolveApiUrl(program.opts().apiUrl), jwt: auth.token });
23
+ const project = await resolveProject(client, creds);
24
+ const tag = opts.tag ?? await promptText("Tag (e.g. v0.7.3): ");
25
+ const baseTag = opts.baseTag ?? safeLatestTag();
26
+ const result = await client.triggerRelease(creds.org, project.projectId, {
27
+ repo: project.repoFullName, tag, baseTag, env: opts.env,
28
+ });
29
+ if (opts.json) {
30
+ console.log(JSON.stringify(result));
31
+ return;
32
+ }
33
+ console.log(`Release queued: ${result.releaseRunId}`);
34
+ console.log(`Workflows: ${result.workflowRunIds.join(", ")}`);
35
+ if (opts.wait) {
36
+ console.log("(--wait not yet implemented; check the dashboard for status.)");
37
+ }
38
+ });
39
+ }
40
+ function safeLatestTag() {
41
+ try {
42
+ return execSync("git describe --tags --abbrev=0", { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
48
+ //# sourceMappingURL=release.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release.js","sourceRoot":"","sources":["../../src/commands/release.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,8EAA8E,CAAC;SAC3F,MAAM,CAAC,aAAa,EAAE,2BAA2B,CAAC;SAClD,MAAM,CAAC,kBAAkB,EAAE,uCAAuC,CAAC;SACnE,MAAM,CAAC,aAAa,EAAE,mCAAmC,CAAC;SAC1D,MAAM,CAAC,QAAQ,EAAE,wCAAwC,CAAC;SAC1D,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC;SAC/B,MAAM,CAAC,KAAK,EAAE,IAAsF,EAAE,EAAE;QACvG,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QACtG,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACtG,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAEpD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,MAAM,UAAU,CAAC,qBAAqB,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,aAAa,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE;YACvE,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG;SACxD,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,aAAa;IACpB,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;IAC/G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerRepoCommands(program: Command): void;
3
+ //# sourceMappingURL=repos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repos.d.ts","sourceRoot":"","sources":["../../src/commands/repos.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwF3D"}
@@ -0,0 +1,88 @@
1
+ import { getClient, getOrg, getFormat, handleError } from "./helpers.js";
2
+ import { formatOutput, printTable } from "../output.js";
3
+ export function registerRepoCommands(program) {
4
+ const repos = program
5
+ .command("repos")
6
+ .description("Manage tracked repositories");
7
+ repos
8
+ .command("list")
9
+ .description("List tracked repositories")
10
+ .option("--json", "Output as JSON")
11
+ .option("--yaml", "Output as YAML")
12
+ .action(async function () {
13
+ try {
14
+ const client = getClient(this);
15
+ const org = getOrg(this);
16
+ const data = await client.listRepos(org);
17
+ const format = getFormat(this);
18
+ formatOutput(format, data, () => {
19
+ if (data.length === 0) {
20
+ console.log("No repositories tracked. Use: renaiss-shipflow repos add <owner/repo>");
21
+ return;
22
+ }
23
+ printTable(["Name", "Full Name", "Active", "Workflows", "Last Activity"], data.map((r) => [
24
+ r.name,
25
+ r.fullName,
26
+ r.isActive ? "yes" : "no",
27
+ `${r.enabledWorkflowCount}/${r.workflowCount}`,
28
+ r.lastActivityAt ?? "never",
29
+ ]));
30
+ });
31
+ }
32
+ catch (err) {
33
+ handleError(err);
34
+ }
35
+ });
36
+ repos
37
+ .command("add")
38
+ .description("Start tracking a new repository")
39
+ .argument("<repo>", "Full repository name (owner/repo)")
40
+ .action(async function (repo) {
41
+ try {
42
+ const client = getClient(this);
43
+ const org = getOrg(this);
44
+ // Adding a repo is done by updating a workflow on it;
45
+ // the backend auto-creates the repo entry if it doesn't exist.
46
+ await client.updateWorkflow(org, repo, "issue_triage", { enabled: false });
47
+ console.log(`Repository "${repo}" is now tracked by RenaissShipFlow.`);
48
+ }
49
+ catch (err) {
50
+ handleError(err);
51
+ }
52
+ });
53
+ repos
54
+ .command("show")
55
+ .description("Show details for a specific repository")
56
+ .argument("<repo>", "Repository name")
57
+ .option("--json", "Output as JSON")
58
+ .option("--yaml", "Output as YAML")
59
+ .action(async function (repo) {
60
+ try {
61
+ const client = getClient(this);
62
+ const org = getOrg(this);
63
+ const data = await client.getRepo(org, repo);
64
+ const format = getFormat(this);
65
+ formatOutput(format, data, () => {
66
+ console.log(`Repository: ${data.fullName}`);
67
+ console.log(` Active: ${data.isActive ? "yes" : "no"}`);
68
+ console.log(` URL: ${data.htmlUrl}`);
69
+ console.log(` Created: ${data.createdAt}`);
70
+ console.log(` Workflows:`);
71
+ if (data.workflowConfigs.length === 0) {
72
+ console.log(" (none configured)");
73
+ }
74
+ else {
75
+ for (const wf of data.workflowConfigs) {
76
+ const status = wf.enabled ? "enabled" : "disabled";
77
+ const lastRun = wf.lastRunAt ?? "never";
78
+ console.log(` - ${wf.workflowType}: ${status} (last run: ${lastRun})`);
79
+ }
80
+ }
81
+ });
82
+ }
83
+ catch (err) {
84
+ handleError(err);
85
+ }
86
+ });
87
+ }
88
+ //# sourceMappingURL=repos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repos.js","sourceRoot":"","sources":["../../src/commands/repos.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerStatsCommand(program: Command): void;
3
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8B3D"}
@@ -0,0 +1,34 @@
1
+ import { getClient, getOrg, getFormat, handleError } from "./helpers.js";
2
+ import { formatOutput } from "../output.js";
3
+ export function registerStatsCommand(program) {
4
+ program
5
+ .command("stats")
6
+ .description("Show usage statistics for the current billing period")
7
+ .option("--json", "Output as JSON")
8
+ .option("--yaml", "Output as YAML")
9
+ .action(async function () {
10
+ try {
11
+ const client = getClient(this);
12
+ const org = getOrg(this);
13
+ const format = getFormat(this);
14
+ const stats = await client.getStats(org);
15
+ formatOutput(format, stats, () => {
16
+ console.log(`Usage Statistics`);
17
+ console.log(` Total Executions: ${stats.totalExecutions}`);
18
+ console.log(` Succeeded: ${stats.successCount}`);
19
+ console.log(` Failed: ${stats.failureCount}`);
20
+ console.log(` Active Repos: ${stats.activeRepos}`);
21
+ if (stats.workflowBreakdown && Object.keys(stats.workflowBreakdown).length > 0) {
22
+ console.log(` By Workflow:`);
23
+ for (const [type, count] of Object.entries(stats.workflowBreakdown)) {
24
+ console.log(` ${type}: ${count}`);
25
+ }
26
+ }
27
+ });
28
+ }
29
+ catch (err) {
30
+ handleError(err);
31
+ }
32
+ });
33
+ }
34
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,sDAAsD,CAAC;SACnE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK;QACX,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAEzC,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC/B,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;gBAChC,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC;gBAC5D,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;gBACzD,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;gBACzD,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;gBACxD,IAAI,KAAK,CAAC,iBAAiB,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC/E,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;oBAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;wBACpE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerStatusCommand(program: Command): void;
3
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwB5D"}
@@ -0,0 +1,35 @@
1
+ import { ShipFlowClient } from "../client.js";
2
+ import { resolveApiUrl, resolveAuthToken, loadCredentials } from "../config.js";
3
+ import { resolveProject } from "../project.js";
4
+ export function registerStatusCommand(program) {
5
+ program
6
+ .command("status")
7
+ .description("Show ShipFlow status for the current project")
8
+ .option("--json", "Output JSON")
9
+ .action(async (opts) => {
10
+ const auth = resolveAuthToken();
11
+ const creds = loadCredentials();
12
+ if (!auth || !creds) {
13
+ console.error("Not signed in. Run: renaiss-shipflow login");
14
+ process.exit(1);
15
+ }
16
+ const client = new ShipFlowClient({ baseUrl: resolveApiUrl(program.opts().apiUrl), jwt: auth.token });
17
+ const project = await resolveProject(client, creds);
18
+ const status = await client.getProjectStatus(creds.org, project.projectId);
19
+ if (opts.json) {
20
+ console.log(JSON.stringify({ project, status }, null, 2));
21
+ return;
22
+ }
23
+ console.log(`Project: ${project.projectName}`);
24
+ console.log(`Repo: ${project.repoFullName}`);
25
+ console.log(`Org: ${project.org}`);
26
+ const recent = status.recentWorkflows ?? [];
27
+ console.log(`Recent workflows: ${recent.length}`);
28
+ const summaries = status.latestSummaries ?? {};
29
+ for (const [k, v] of Object.entries(summaries)) {
30
+ const summary = v?.data?.exec_summary || v?.summary || "(no summary)";
31
+ console.log(` ${k}: ${String(summary).split("\n")[0]}`);
32
+ }
33
+ });
34
+ }
35
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC;SAC/B,MAAM,CAAC,KAAK,EAAE,IAAwB,EAAE,EAAE;QACzC,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QACtG,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACtG,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAC3E,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QACrF,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACvC,MAAM,MAAM,GAAI,MAAM,CAAC,eAAyB,IAAI,EAAE,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAClD,MAAM,SAAS,GAAI,MAAM,CAAC,eAA2C,IAAI,EAAE,CAAC;QAC5E,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/C,MAAM,OAAO,GAAI,CAAS,EAAE,IAAI,EAAE,YAAY,IAAK,CAAS,EAAE,OAAO,IAAI,cAAc,CAAC;YACxF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerTestCommand(program: Command): void;
3
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAc1D"}
@@ -0,0 +1,44 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { getCwdRepoRoot } from "../project.js";
5
+ export function registerTestCommand(program) {
6
+ program
7
+ .command("test")
8
+ .description("Run the project's local test command (auto-detected)")
9
+ .allowUnknownOption()
10
+ .action(() => {
11
+ const root = getCwdRepoRoot();
12
+ if (!root) {
13
+ console.error("Not in a git repo.");
14
+ process.exit(1);
15
+ }
16
+ const runner = detectRunner(root);
17
+ if (!runner) {
18
+ console.error("Could not detect a test runner. Run your test command manually.");
19
+ process.exit(2);
20
+ }
21
+ console.log(`> ${runner.cmd} ${runner.args.join(" ")}`);
22
+ const r = spawnSync(runner.cmd, runner.args, { stdio: "inherit", cwd: root });
23
+ process.exit(r.status ?? 1);
24
+ });
25
+ }
26
+ function detectRunner(root) {
27
+ if (existsSync(join(root, "package.json"))) {
28
+ if (existsSync(join(root, "bun.lockb")) || existsSync(join(root, "bun.lock")))
29
+ return { cmd: "bun", args: ["test"] };
30
+ if (existsSync(join(root, "pnpm-lock.yaml")))
31
+ return { cmd: "pnpm", args: ["test"] };
32
+ if (existsSync(join(root, "yarn.lock")))
33
+ return { cmd: "yarn", args: ["test"] };
34
+ return { cmd: "npm", args: ["test"] };
35
+ }
36
+ if (existsSync(join(root, "go.mod")))
37
+ return { cmd: "go", args: ["test", "./..."] };
38
+ if (existsSync(join(root, "Cargo.toml")))
39
+ return { cmd: "cargo", args: ["test"] };
40
+ if (existsSync(join(root, "pyproject.toml")) || existsSync(join(root, "pytest.ini")))
41
+ return { cmd: "pytest", args: [] };
42
+ return null;
43
+ }
44
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerTriggerCommand(program: Command): void;
3
+ //# sourceMappingURL=trigger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsB7D"}
@@ -0,0 +1,25 @@
1
+ import { getClient, getOrg, handleError } from "./helpers.js";
2
+ export function registerTriggerCommand(program) {
3
+ program
4
+ .command("trigger")
5
+ .description("Manually trigger a workflow")
6
+ .argument("<workflow-type>", "Workflow type to trigger (e.g. regression_tests)")
7
+ .requiredOption("--repo <repo>", "Repository name")
8
+ .action(async function (workflowType) {
9
+ try {
10
+ const client = getClient(this);
11
+ const org = getOrg(this);
12
+ const opts = this.opts();
13
+ // Trigger is implemented as an update with a trigger signal.
14
+ // The backend dispatches the workflow when it receives this.
15
+ await client.updateWorkflow(org, opts.repo, workflowType, {
16
+ settings: { _trigger: true },
17
+ });
18
+ console.log(`Workflow "${workflowType}" triggered on ${opts.repo}.`);
19
+ }
20
+ catch (err) {
21
+ handleError(err);
22
+ }
23
+ });
24
+ }
25
+ //# sourceMappingURL=trigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger.js","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE9D,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,6BAA6B,CAAC;SAC1C,QAAQ,CAAC,iBAAiB,EAAE,kDAAkD,CAAC;SAC/E,cAAc,CAAC,eAAe,EAAE,iBAAiB,CAAC;SAClD,MAAM,CAAC,KAAK,WAA0B,YAAoB;QACzD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAEzB,6DAA6D;YAC7D,6DAA6D;YAC7D,MAAM,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE;gBACxD,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;aAC7B,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,aAAa,YAAY,kBAAkB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACvE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerWorkflowCommands(program: Command): void;
3
+ //# sourceMappingURL=workflows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/commands/workflows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoG/D"}
@@ -0,0 +1,108 @@
1
+ import { getClient, getOrg, getFormat, handleError } from "./helpers.js";
2
+ import { formatOutput, printTable } from "../output.js";
3
+ export function registerWorkflowCommands(program) {
4
+ const workflows = program
5
+ .command("workflows")
6
+ .description("Manage repository workflows");
7
+ workflows
8
+ .command("list")
9
+ .description("List workflows for a repository")
10
+ .requiredOption("--repo <repo>", "Repository name")
11
+ .option("--json", "Output as JSON")
12
+ .option("--yaml", "Output as YAML")
13
+ .action(async function () {
14
+ try {
15
+ const client = getClient(this);
16
+ const org = getOrg(this);
17
+ const opts = this.opts();
18
+ const repo = await client.getRepo(org, opts.repo);
19
+ const format = getFormat(this);
20
+ formatOutput(format, repo.workflowConfigs, () => {
21
+ if (repo.workflowConfigs.length === 0) {
22
+ console.log("No workflows configured for this repository.");
23
+ return;
24
+ }
25
+ printTable(["Type", "Enabled", "Last Run", "Status"], repo.workflowConfigs.map((wf) => [
26
+ wf.workflowType,
27
+ wf.enabled ? "yes" : "no",
28
+ wf.lastRunAt ?? "never",
29
+ wf.lastRunStatus ?? "-",
30
+ ]));
31
+ });
32
+ }
33
+ catch (err) {
34
+ handleError(err);
35
+ }
36
+ });
37
+ workflows
38
+ .command("enable")
39
+ .description("Enable a workflow for a repository")
40
+ .argument("<type>", "Workflow type (e.g. issue_triage, patch_notes)")
41
+ .requiredOption("--repo <repo>", "Repository name")
42
+ .action(async function (type) {
43
+ try {
44
+ const client = getClient(this);
45
+ const org = getOrg(this);
46
+ const opts = this.opts();
47
+ await client.updateWorkflow(org, opts.repo, type, { enabled: true });
48
+ console.log(`Workflow "${type}" enabled on ${opts.repo}.`);
49
+ }
50
+ catch (err) {
51
+ handleError(err);
52
+ }
53
+ });
54
+ workflows
55
+ .command("disable")
56
+ .description("Disable a workflow for a repository")
57
+ .argument("<type>", "Workflow type (e.g. issue_triage, patch_notes)")
58
+ .requiredOption("--repo <repo>", "Repository name")
59
+ .action(async function (type) {
60
+ try {
61
+ const client = getClient(this);
62
+ const org = getOrg(this);
63
+ const opts = this.opts();
64
+ await client.updateWorkflow(org, opts.repo, type, { enabled: false });
65
+ console.log(`Workflow "${type}" disabled on ${opts.repo}.`);
66
+ }
67
+ catch (err) {
68
+ handleError(err);
69
+ }
70
+ });
71
+ workflows
72
+ .command("configure")
73
+ .description("Configure workflow settings")
74
+ .argument("<type>", "Workflow type")
75
+ .requiredOption("--repo <repo>", "Repository name")
76
+ .option("--set <key=value...>", "Set configuration values", collectKeyValue, {})
77
+ .action(async function (type) {
78
+ try {
79
+ const client = getClient(this);
80
+ const org = getOrg(this);
81
+ const opts = this.opts();
82
+ const settings = opts.set;
83
+ if (Object.keys(settings).length === 0) {
84
+ console.error("Error: At least one --set key=value is required.");
85
+ process.exit(1);
86
+ }
87
+ await client.updateWorkflow(org, opts.repo, type, { settings });
88
+ console.log(`Workflow "${type}" configured on ${opts.repo}.`);
89
+ for (const [k, v] of Object.entries(settings)) {
90
+ console.log(` ${k} = ${v}`);
91
+ }
92
+ }
93
+ catch (err) {
94
+ handleError(err);
95
+ }
96
+ });
97
+ }
98
+ /** Commander custom option parser for repeatable key=value pairs. */
99
+ function collectKeyValue(value, prev) {
100
+ const idx = value.indexOf("=");
101
+ if (idx === -1) {
102
+ console.error(`Error: Invalid --set format "${value}". Expected key=value.`);
103
+ process.exit(1);
104
+ }
105
+ prev[value.substring(0, idx)] = value.substring(idx + 1);
106
+ return prev;
107
+ }
108
+ //# sourceMappingURL=workflows.js.map