@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.
- package/README.md +13 -0
- package/dist/__tests__/gh.test.d.ts +2 -0
- package/dist/__tests__/gh.test.d.ts.map +1 -0
- package/dist/__tests__/gh.test.js +46 -0
- package/dist/__tests__/gh.test.js.map +1 -0
- package/dist/__tests__/login.test.d.ts +2 -0
- package/dist/__tests__/login.test.d.ts.map +1 -0
- package/dist/__tests__/login.test.js +25 -0
- package/dist/__tests__/login.test.js.map +1 -0
- package/dist/__tests__/project.test.d.ts +2 -0
- package/dist/__tests__/project.test.d.ts.map +1 -0
- package/dist/__tests__/project.test.js +17 -0
- package/dist/__tests__/project.test.js.map +1 -0
- package/dist/client.d.ts +220 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +171 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/activity.d.ts +3 -0
- package/dist/commands/activity.d.ts.map +1 -0
- package/dist/commands/activity.js +38 -0
- package/dist/commands/activity.js.map +1 -0
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +58 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/channels.d.ts +3 -0
- package/dist/commands/channels.d.ts.map +1 -0
- package/dist/commands/channels.js +60 -0
- package/dist/commands/channels.js.map +1 -0
- package/dist/commands/claims.d.ts +3 -0
- package/dist/commands/claims.d.ts.map +1 -0
- package/dist/commands/claims.js +33 -0
- package/dist/commands/claims.js.map +1 -0
- package/dist/commands/helpers.d.ts +9 -0
- package/dist/commands/helpers.d.ts.map +1 -0
- package/dist/commands/helpers.js +36 -0
- package/dist/commands/helpers.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +41 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/issue.d.ts +3 -0
- package/dist/commands/issue.d.ts.map +1 -0
- package/dist/commands/issue.js +151 -0
- package/dist/commands/issue.js.map +1 -0
- package/dist/commands/issues.d.ts +3 -0
- package/dist/commands/issues.d.ts.map +1 -0
- package/dist/commands/issues.js +34 -0
- package/dist/commands/issues.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +50 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/pr.d.ts +3 -0
- package/dist/commands/pr.d.ts.map +1 -0
- package/dist/commands/pr.js +93 -0
- package/dist/commands/pr.js.map +1 -0
- package/dist/commands/regression.d.ts +3 -0
- package/dist/commands/regression.d.ts.map +1 -0
- package/dist/commands/regression.js +29 -0
- package/dist/commands/regression.js.map +1 -0
- package/dist/commands/release.d.ts +3 -0
- package/dist/commands/release.d.ts.map +1 -0
- package/dist/commands/release.js +48 -0
- package/dist/commands/release.js.map +1 -0
- package/dist/commands/repos.d.ts +3 -0
- package/dist/commands/repos.d.ts.map +1 -0
- package/dist/commands/repos.js +88 -0
- package/dist/commands/repos.js.map +1 -0
- package/dist/commands/stats.d.ts +3 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +34 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +35 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/test.d.ts +3 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +44 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/trigger.d.ts +3 -0
- package/dist/commands/trigger.d.ts.map +1 -0
- package/dist/commands/trigger.js +25 -0
- package/dist/commands/trigger.js.map +1 -0
- package/dist/commands/workflows.d.ts +3 -0
- package/dist/commands/workflows.d.ts.map +1 -0
- package/dist/commands/workflows.js +108 -0
- package/dist/commands/workflows.js.map +1 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +67 -0
- package/dist/config.js.map +1 -0
- package/dist/gh.d.ts +45 -0
- package/dist/gh.d.ts.map +1 -0
- package/dist/gh.js +82 -0
- package/dist/gh.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +12 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +71 -0
- package/dist/output.js.map +1 -0
- package/dist/project.d.ts +15 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +64 -0
- package/dist/project.js.map +1 -0
- package/dist/prompts.d.ts +4 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +24 -0
- package/dist/prompts.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { loadConfig, saveConfig, clearConfig, resolveApiKey } from "../config.js";
|
|
2
|
+
export function registerAuthCommands(program) {
|
|
3
|
+
const auth = program
|
|
4
|
+
.command("auth")
|
|
5
|
+
.description("Manage authentication");
|
|
6
|
+
auth
|
|
7
|
+
.command("login")
|
|
8
|
+
.description("Authenticate with an API key")
|
|
9
|
+
.argument("[api-key]", "API key (sfk_...)")
|
|
10
|
+
.action(async (apiKey) => {
|
|
11
|
+
if (!apiKey) {
|
|
12
|
+
// Interactive: read from stdin
|
|
13
|
+
const { createInterface } = await import("node:readline");
|
|
14
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
15
|
+
apiKey = await new Promise((resolve) => {
|
|
16
|
+
rl.question("Enter your RenaissShipFlow API key (sfk_...): ", (answer) => {
|
|
17
|
+
rl.close();
|
|
18
|
+
resolve(answer.trim());
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
if (!apiKey) {
|
|
23
|
+
console.error("Error: API key is required.");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
const config = loadConfig();
|
|
27
|
+
config.apiKey = apiKey;
|
|
28
|
+
saveConfig(config);
|
|
29
|
+
console.log("API key saved. You can now use renaiss-shipflow commands.");
|
|
30
|
+
});
|
|
31
|
+
auth
|
|
32
|
+
.command("logout")
|
|
33
|
+
.description("Clear stored credentials")
|
|
34
|
+
.action(() => {
|
|
35
|
+
clearConfig();
|
|
36
|
+
console.log("Logged out. Stored credentials cleared.");
|
|
37
|
+
});
|
|
38
|
+
auth
|
|
39
|
+
.command("status")
|
|
40
|
+
.description("Show current authentication status")
|
|
41
|
+
.action(() => {
|
|
42
|
+
const key = resolveApiKey();
|
|
43
|
+
if (key) {
|
|
44
|
+
const masked = key.substring(0, 8) + "..." + key.substring(key.length - 4);
|
|
45
|
+
console.log(`Authenticated with key: ${masked}`);
|
|
46
|
+
if (process.env.SHIPFLOW_API_KEY) {
|
|
47
|
+
console.log(" (from SHIPFLOW_API_KEY env var)");
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.log(" (from ~/.config/renaissshipflow/config.json)");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.log("Not authenticated. Run: renaiss-shipflow auth login");
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElF,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,MAAM,IAAI,GAAG,OAAO;SACjB,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAExC,IAAI;SACD,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;SAC1C,MAAM,CAAC,KAAK,EAAE,MAAe,EAAE,EAAE;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,+BAA+B;YAC/B,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;YAC1D,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7E,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;gBAC7C,EAAE,CAAC,QAAQ,CAAC,gDAAgD,EAAE,CAAC,MAAM,EAAE,EAAE;oBACvE,EAAE,CAAC,KAAK,EAAE,CAAC;oBACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACzB,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,UAAU,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEL,IAAI;SACD,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0BAA0B,CAAC;SACvC,MAAM,CAAC,GAAG,EAAE;QACX,WAAW,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEL,IAAI;SACD,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,oCAAoC,CAAC;SACjD,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC3E,OAAO,CAAC,GAAG,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;YACjD,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;YACnD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QACrE,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../src/commands/channels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8D9D"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { getClient, getOrg, getFormat, handleError } from "./helpers.js";
|
|
2
|
+
import { formatOutput, printTable } from "../output.js";
|
|
3
|
+
export function registerChannelCommands(program) {
|
|
4
|
+
const channels = program
|
|
5
|
+
.command("channels")
|
|
6
|
+
.description("Manage notification channels");
|
|
7
|
+
channels
|
|
8
|
+
.command("list")
|
|
9
|
+
.description("List notification channels")
|
|
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.listChannels(org);
|
|
17
|
+
const format = getFormat(this);
|
|
18
|
+
formatOutput(format, data, () => {
|
|
19
|
+
if (data.length === 0) {
|
|
20
|
+
console.log("No notification channels configured.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
printTable(["ID", "Type", "Label", "Identifier", "Created"], data.map((c) => [
|
|
24
|
+
c.id,
|
|
25
|
+
c.channelType,
|
|
26
|
+
c.label,
|
|
27
|
+
c.channelIdentifier,
|
|
28
|
+
c.createdAt,
|
|
29
|
+
]));
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
handleError(err);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
channels
|
|
37
|
+
.command("add")
|
|
38
|
+
.description("Add a notification channel")
|
|
39
|
+
.requiredOption("--type <type>", "Channel type (discord, slack, webhook, email)")
|
|
40
|
+
.requiredOption("--identifier <id>", "Channel identifier (e.g. channel ID, URL)")
|
|
41
|
+
.requiredOption("--label <name>", "Display label")
|
|
42
|
+
.action(async function () {
|
|
43
|
+
try {
|
|
44
|
+
const client = getClient(this);
|
|
45
|
+
const org = getOrg(this);
|
|
46
|
+
const opts = this.opts();
|
|
47
|
+
const channel = await client.addChannel(org, {
|
|
48
|
+
channelType: opts.type,
|
|
49
|
+
channelIdentifier: opts.identifier,
|
|
50
|
+
label: opts.label,
|
|
51
|
+
});
|
|
52
|
+
console.log(`Channel "${channel.label}" (${channel.channelType}) added.`);
|
|
53
|
+
console.log(` ID: ${channel.id}`);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
handleError(err);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=channels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels.js","sourceRoot":"","sources":["../../src/commands/channels.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAExD,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,MAAM,QAAQ,GAAG,OAAO;SACrB,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,8BAA8B,CAAC,CAAC;IAE/C,QAAQ;SACL,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4BAA4B,CAAC;SACzC,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,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAE/B,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE;gBAC9B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;oBACpD,OAAO;gBACT,CAAC;gBACD,UAAU,CACR,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC,EAChD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;oBACd,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,iBAAiB;oBACnB,CAAC,CAAC,SAAS;iBACZ,CAAC,CACH,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,QAAQ;SACL,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,4BAA4B,CAAC;SACzC,cAAc,CAAC,eAAe,EAAE,+CAA+C,CAAC;SAChF,cAAc,CAAC,mBAAmB,EAAE,2CAA2C,CAAC;SAChF,cAAc,CAAC,gBAAgB,EAAE,eAAe,CAAC;SACjD,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,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAEzB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;gBAC3C,WAAW,EAAE,IAAI,CAAC,IAAI;gBACtB,iBAAiB,EAAE,IAAI,CAAC,UAAU;gBAClC,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC,CAAC;YAEH,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,KAAK,MAAM,OAAO,CAAC,WAAW,UAAU,CAAC,CAAC;YAC1E,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claims.d.ts","sourceRoot":"","sources":["../../src/commands/claims.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoB5D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ShipFlowClient } from "../client.js";
|
|
2
|
+
import { resolveApiUrl, resolveAuthToken, loadCredentials } from "../config.js";
|
|
3
|
+
import { resolveProject } from "../project.js";
|
|
4
|
+
export function registerClaimsCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command("claims")
|
|
7
|
+
.description("List active agent claims (who is working on what)")
|
|
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 claims = await client.listClaims(creds.org, project.projectId);
|
|
19
|
+
if (opts.json) {
|
|
20
|
+
console.log(JSON.stringify({ claims }, null, 2));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (claims.length === 0) {
|
|
24
|
+
console.log("No active claims — every open issue is up for grabs.");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (const c of claims) {
|
|
28
|
+
const agent = c.agent ? ` (${c.agent})` : "";
|
|
29
|
+
console.log(`#${c.issueNumber} ${c.repo} — ${c.actor}${agent}, expires ${c.expiresAt}`);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=claims.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claims.js","sourceRoot":"","sources":["../../src/commands/claims.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,mDAAmD,CAAC;SAChE,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;QAEpD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QACzG,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK,GAAG,KAAK,aAAa,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { ShipFlowClient } from "../client.js";
|
|
3
|
+
import type { OutputFormat } from "../output.js";
|
|
4
|
+
/** Extract common options from any command that has inherited parent opts. */
|
|
5
|
+
export declare function getClient(cmd: Command): ShipFlowClient;
|
|
6
|
+
export declare function getOrg(cmd: Command): string;
|
|
7
|
+
export declare function getFormat(cmd: Command): OutputFormat;
|
|
8
|
+
export declare function handleError(err: unknown): never;
|
|
9
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/commands/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAWtD;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE3C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAKpD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAO/C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ShipFlowClient } from "../client.js";
|
|
2
|
+
import { resolveApiUrl, resolveApiKey } from "../config.js";
|
|
3
|
+
/** Extract common options from any command that has inherited parent opts. */
|
|
4
|
+
export function getClient(cmd) {
|
|
5
|
+
const opts = cmd.optsWithGlobals();
|
|
6
|
+
const apiKey = resolveApiKey();
|
|
7
|
+
if (!apiKey) {
|
|
8
|
+
console.error("Error: No API key found. Set SHIPFLOW_API_KEY env var or run: renaiss-shipflow auth login");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
return new ShipFlowClient({
|
|
12
|
+
baseUrl: resolveApiUrl(opts.apiUrl),
|
|
13
|
+
apiKey,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function getOrg(cmd) {
|
|
17
|
+
return cmd.optsWithGlobals().org || "default";
|
|
18
|
+
}
|
|
19
|
+
export function getFormat(cmd) {
|
|
20
|
+
const opts = cmd.opts();
|
|
21
|
+
if (opts.json)
|
|
22
|
+
return "json";
|
|
23
|
+
if (opts.yaml)
|
|
24
|
+
return "yaml";
|
|
25
|
+
return "table";
|
|
26
|
+
}
|
|
27
|
+
export function handleError(err) {
|
|
28
|
+
if (err instanceof Error) {
|
|
29
|
+
console.error(`Error: ${err.message}`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.error("An unknown error occurred.");
|
|
33
|
+
}
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/commands/helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG5D,8EAA8E;AAC9E,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,2FAA2F,CAAC,CAAC;QAC3G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,cAAc,CAAC;QACxB,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QACnC,MAAM;KACP,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAY;IACjC,OAAO,GAAG,CAAC,eAAe,EAAE,CAAC,GAAG,IAAI,SAAS,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC7B,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC7B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8B1D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { ShipFlowClient } from "../client.js";
|
|
3
|
+
import { resolveApiUrl, resolveAuthToken, loadCredentials, loadProjectCache, saveProjectCache, projectCacheKeyForRepoPath, } from "../config.js";
|
|
4
|
+
import { getCwdRepoRoot, getCwdRemote } from "../project.js";
|
|
5
|
+
import { promptSelect } from "../prompts.js";
|
|
6
|
+
export function registerInitCommand(program) {
|
|
7
|
+
program
|
|
8
|
+
.command("init")
|
|
9
|
+
.description("Link the current repo to a ShipFlow project")
|
|
10
|
+
.action(async () => {
|
|
11
|
+
const auth = resolveAuthToken();
|
|
12
|
+
const creds = loadCredentials();
|
|
13
|
+
if (!auth || !creds) {
|
|
14
|
+
console.error("Not signed in. Run: renaiss-shipflow login");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const root = getCwdRepoRoot();
|
|
18
|
+
const remote = getCwdRemote();
|
|
19
|
+
if (!root || !remote) {
|
|
20
|
+
console.error("Not in a git repo with a github.com origin remote.");
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const client = new ShipFlowClient({ baseUrl: resolveApiUrl(program.opts().apiUrl), jwt: auth.token });
|
|
24
|
+
const lookup = await client.getRepoByFullName(creds.org, remote.owner, remote.repo);
|
|
25
|
+
if (!lookup.projects?.length) {
|
|
26
|
+
console.error(`Repo ${remote.owner}/${remote.repo} is not in any project on this org.`);
|
|
27
|
+
console.error("Add it via the dashboard first, then re-run init.");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
const chosen = lookup.projects.length === 1
|
|
31
|
+
? lookup.projects[0]
|
|
32
|
+
: lookup.projects[await promptSelect("Pick a project to link:", lookup.projects.map(p => p.name))];
|
|
33
|
+
const cache = loadProjectCache();
|
|
34
|
+
cache[projectCacheKeyForRepoPath(resolve(root))] = {
|
|
35
|
+
projectId: chosen.id, projectName: chosen.name, org: creds.org, tenantId: creds.tenantId,
|
|
36
|
+
};
|
|
37
|
+
saveProjectCache(cache);
|
|
38
|
+
console.log(`Linked ${remote.owner}/${remote.repo} → ${chosen.name}.`);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EACL,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAChD,gBAAgB,EAAE,gBAAgB,EAAE,0BAA0B,GAC/D,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,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,IAAI,GAAG,cAAc,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAE/G,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,MAAM,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACpF,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,QAAQ,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,qCAAqC,CAAC,CAAC;YACxF,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;YACzC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YACpB,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,YAAY,CAAC,yBAAyB,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAErG,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;QACjC,KAAK,CAAC,0BAA0B,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG;YACjD,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzF,CAAC;QACF,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../../src/commands/issue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoH3D"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { hostname } from "node:os";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
import { ShipFlowClient, ClaimConflictError } from "../client.js";
|
|
5
|
+
import { resolveApiUrl, resolveAuthToken, loadCredentials } from "../config.js";
|
|
6
|
+
import { resolveProject } from "../project.js";
|
|
7
|
+
import { ghIssueView, ghIssueCreate } from "../gh.js";
|
|
8
|
+
import { promptText } from "../prompts.js";
|
|
9
|
+
export function registerIssueCommand(program) {
|
|
10
|
+
const issue = program.command("issue").description("Issue actions");
|
|
11
|
+
issue
|
|
12
|
+
.command("create")
|
|
13
|
+
.description("Open a new issue (and signal ShipFlow)")
|
|
14
|
+
.option("--repo <fullname>", "Override target repo")
|
|
15
|
+
.option("--title <title>", "Issue title")
|
|
16
|
+
.option("--body <body>", "Issue body (- for stdin)")
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
const ctx = await loadCtx(program);
|
|
19
|
+
const repo = opts.repo ?? ctx.project.repoFullName;
|
|
20
|
+
const title = opts.title ?? await promptText("Title: ");
|
|
21
|
+
const body = opts.body === "-" ? await readStdin() : (opts.body ?? "");
|
|
22
|
+
const created = ghIssueCreate(repo, title, body);
|
|
23
|
+
// Note: creating an issue does NOT claim it — claims are exclusive
|
|
24
|
+
// work locks now; run `issue work <n>` to pick it up.
|
|
25
|
+
console.log(created.url);
|
|
26
|
+
});
|
|
27
|
+
issue
|
|
28
|
+
.command("work <number>")
|
|
29
|
+
.description("Exclusively claim an issue (lock + dump context); exits 3 when another agent holds it")
|
|
30
|
+
.option("--repo <fullname>", "Override target repo")
|
|
31
|
+
.option("--agent <name>", "Agent label recorded on the claim (default: $SHIPFLOW_AGENT or hostname)")
|
|
32
|
+
.option("--ttl <minutes>", "Claim lifetime in minutes (default 120)")
|
|
33
|
+
.option("--json", "Output JSON")
|
|
34
|
+
.action(async (numberStr, opts) => {
|
|
35
|
+
const ctx = await loadCtx(program);
|
|
36
|
+
const number = parseInt(numberStr, 10);
|
|
37
|
+
const repo = opts.repo ?? ctx.project.repoFullName;
|
|
38
|
+
const agent = opts.agent ?? process.env.SHIPFLOW_AGENT ?? hostname();
|
|
39
|
+
// Take the exclusive claim FIRST — if another agent holds the issue,
|
|
40
|
+
// skip it without doing any work.
|
|
41
|
+
try {
|
|
42
|
+
await ctx.client.claimIssue(ctx.creds.org, ctx.project.projectId, number, {
|
|
43
|
+
repo, agent, ttlMinutes: opts.ttl ? parseInt(opts.ttl, 10) : undefined,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
if (e instanceof ClaimConflictError) {
|
|
48
|
+
console.error(`⛔ #${number} is taken: ${e.message}`);
|
|
49
|
+
process.exit(3);
|
|
50
|
+
}
|
|
51
|
+
console.warn(`Claim failed (continuing unlocked): ${e.message}`);
|
|
52
|
+
}
|
|
53
|
+
const issueData = ghIssueView(repo, number);
|
|
54
|
+
const triage = await ctx.client.getTriage(ctx.creds.org, ctx.project.projectId, repo, number).catch(() => null);
|
|
55
|
+
if (opts.json) {
|
|
56
|
+
console.log(JSON.stringify({ issue: issueData, triage, project: ctx.project }, null, 2));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
console.log(`Issue #${issueData.number} — "${issueData.title}"`);
|
|
60
|
+
console.log(`Repo: ${repo}`);
|
|
61
|
+
console.log(`State: ${issueData.state} • Labels: ${issueData.labels.map((l) => l.name).join(", ") || "(none)"}`);
|
|
62
|
+
console.log("");
|
|
63
|
+
console.log(issueData.body || "(no body)");
|
|
64
|
+
if (triage) {
|
|
65
|
+
console.log("\n── ShipFlow context ──");
|
|
66
|
+
if (triage.priority)
|
|
67
|
+
console.log(`Priority: ${triage.priority}`);
|
|
68
|
+
if (triage.relatedFeatures?.length)
|
|
69
|
+
console.log(`Features touched: ${triage.relatedFeatures.join(", ")}`);
|
|
70
|
+
if (triage.relatedFiles?.length) {
|
|
71
|
+
console.log("Files likely involved:");
|
|
72
|
+
triage.relatedFiles.slice(0, 10).forEach((f) => console.log(` ${f}`));
|
|
73
|
+
}
|
|
74
|
+
if (triage.relatedCommits?.length) {
|
|
75
|
+
console.log("Recent commits in same area:");
|
|
76
|
+
triage.relatedCommits.slice(0, 5).forEach((c) => console.log(` ${c}`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
issue
|
|
81
|
+
.command("done <number>")
|
|
82
|
+
.description("Release an issue (signal only)")
|
|
83
|
+
.option("--reason <reason>", "Why you're releasing it (e.g. blocked, finished)")
|
|
84
|
+
.option("--repo <fullname>", "Override target repo")
|
|
85
|
+
.action(async (numberStr, opts) => {
|
|
86
|
+
const ctx = await loadCtx(program);
|
|
87
|
+
const number = parseInt(numberStr, 10);
|
|
88
|
+
const repo = opts.repo ?? ctx.project.repoFullName;
|
|
89
|
+
await ctx.client.signal(ctx.creds.org, ctx.project.projectId, "issues", number, "release-claim", { repo, reason: opts.reason ?? "" });
|
|
90
|
+
console.log(`Released #${number}.`);
|
|
91
|
+
});
|
|
92
|
+
issue
|
|
93
|
+
.command("evidence <number>")
|
|
94
|
+
.description("Attach testing screenshots to an issue (reporter thread + GitHub comment)")
|
|
95
|
+
.option("--image <path...>", "Screenshot file(s), up to 4")
|
|
96
|
+
.option("--pr <n>", "Related PR number")
|
|
97
|
+
.option("--preview-url <url>", "Testing site URL")
|
|
98
|
+
.option("--caption <text>", "Short note shown with the screenshots")
|
|
99
|
+
.option("--repo <fullname>", "Override target repo")
|
|
100
|
+
.option("--json", "Output JSON")
|
|
101
|
+
.action(async (numberStr, opts) => {
|
|
102
|
+
if (!opts.image?.length) {
|
|
103
|
+
console.error("At least one --image is required.");
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
const ctx = await loadCtx(program);
|
|
107
|
+
const number = parseInt(numberStr, 10);
|
|
108
|
+
const repo = opts.repo ?? ctx.project.repoFullName;
|
|
109
|
+
const images = opts.image.slice(0, 4).map((p) => ({
|
|
110
|
+
filename: basename(p),
|
|
111
|
+
data: new Uint8Array(readFileSync(p)),
|
|
112
|
+
}));
|
|
113
|
+
const res = await ctx.client.attachEvidence(ctx.creds.org, ctx.project.projectId, number, {
|
|
114
|
+
repo,
|
|
115
|
+
pr: opts.pr ? parseInt(opts.pr, 10) : undefined,
|
|
116
|
+
previewUrl: opts.previewUrl,
|
|
117
|
+
caption: opts.caption,
|
|
118
|
+
images,
|
|
119
|
+
});
|
|
120
|
+
if (opts.json) {
|
|
121
|
+
console.log(JSON.stringify(res, null, 2));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const where = [];
|
|
125
|
+
if (res.threadNotified)
|
|
126
|
+
where.push("reporter thread");
|
|
127
|
+
if (res.githubCommented)
|
|
128
|
+
where.push("GitHub issue comment");
|
|
129
|
+
console.log(`🧪 Evidence delivered to: ${where.join(" + ") || "nowhere (check server logs)"}`);
|
|
130
|
+
for (const u of res.threadImageUrls ?? [])
|
|
131
|
+
console.log(` ${u}`);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
async function loadCtx(program) {
|
|
135
|
+
const auth = resolveAuthToken();
|
|
136
|
+
const creds = loadCredentials();
|
|
137
|
+
if (!auth || !creds) {
|
|
138
|
+
console.error("Not signed in. Run: renaiss-shipflow login");
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
const client = new ShipFlowClient({ baseUrl: resolveApiUrl(program.opts().apiUrl), jwt: auth.token });
|
|
142
|
+
const project = await resolveProject(client, creds);
|
|
143
|
+
return { auth, creds, client, project };
|
|
144
|
+
}
|
|
145
|
+
async function readStdin() {
|
|
146
|
+
const chunks = [];
|
|
147
|
+
for await (const c of process.stdin)
|
|
148
|
+
chunks.push(c);
|
|
149
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=issue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue.js","sourceRoot":"","sources":["../../src/commands/issue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../../src/commands/issues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqB5D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ShipFlowClient } from "../client.js";
|
|
2
|
+
import { resolveApiUrl, resolveAuthToken, loadCredentials } from "../config.js";
|
|
3
|
+
import { resolveProject } from "../project.js";
|
|
4
|
+
import { ghIssueList } from "../gh.js";
|
|
5
|
+
export function registerIssuesCommand(program) {
|
|
6
|
+
const issues = program.command("issues").description("Issue listing");
|
|
7
|
+
issues
|
|
8
|
+
.command("list")
|
|
9
|
+
.description("List open issues for the current repo, with ShipFlow triage overlay")
|
|
10
|
+
.option("--state <state>", "Issue state", "open")
|
|
11
|
+
.option("--limit <n>", "Max results", "30")
|
|
12
|
+
.option("--json", "Output JSON")
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
const auth = resolveAuthToken();
|
|
15
|
+
const creds = loadCredentials();
|
|
16
|
+
if (!auth || !creds) {
|
|
17
|
+
console.error("Not signed in. Run: renaiss-shipflow login");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const client = new ShipFlowClient({ baseUrl: resolveApiUrl(program.opts().apiUrl), jwt: auth.token });
|
|
21
|
+
const project = await resolveProject(client, creds);
|
|
22
|
+
const list = ghIssueList(project.repoFullName, opts.state, parseInt(opts.limit, 10));
|
|
23
|
+
if (opts.json) {
|
|
24
|
+
console.log(JSON.stringify({ project, issues: list }, null, 2));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (const i of list) {
|
|
28
|
+
console.log(`#${i.number} ${i.title}`);
|
|
29
|
+
if (i.labels.length)
|
|
30
|
+
console.log(` ${i.labels.map((l) => l.name).join(", ")}`);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=issues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issues.js","sourceRoot":"","sources":["../../src/commands/issues.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;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;IACtE,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,qEAAqE,CAAC;SAClF,MAAM,CAAC,iBAAiB,EAAE,aAAa,EAAE,MAAM,CAAC;SAChD,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,CAAC;SAC1C,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC;SAC/B,MAAM,CAAC,KAAK,EAAE,IAAsD,EAAE,EAAE;QACvE,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,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QACrF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC3F,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACxC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM;gBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmD3D"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ghInstalled, ghAuthStatus, ghAuthLogin, ghAuthToken } from "../gh.js";
|
|
2
|
+
import { ShipFlowClient } from "../client.js";
|
|
3
|
+
import { resolveApiUrl, saveCredentials, loadConfig, saveConfig } from "../config.js";
|
|
4
|
+
import { promptSelect } from "../prompts.js";
|
|
5
|
+
export function registerLoginCommand(program) {
|
|
6
|
+
program
|
|
7
|
+
.command("login")
|
|
8
|
+
.description("Sign in to ShipFlow (uses gh auth)")
|
|
9
|
+
.option("--no-gh-bootstrap", "Don't auto-run `gh auth login` if gh isn't logged in")
|
|
10
|
+
.action(async (opts) => {
|
|
11
|
+
if (!ghInstalled()) {
|
|
12
|
+
console.error("gh (GitHub CLI) is not installed. See https://cli.github.com/");
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
if (ghAuthStatus() === "logged-out") {
|
|
16
|
+
if (!opts.ghBootstrap) {
|
|
17
|
+
console.error("gh is not logged in. Run `gh auth login` first or omit --no-gh-bootstrap.");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
if (!ghAuthLogin()) {
|
|
21
|
+
console.error("gh auth login was cancelled or failed.");
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const ghToken = ghAuthToken();
|
|
26
|
+
if (!ghToken) {
|
|
27
|
+
console.error("Could not read gh auth token.");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
const client = new ShipFlowClient({ baseUrl: resolveApiUrl(program.opts().apiUrl) });
|
|
31
|
+
const result = await client.exchangeGhToken(ghToken);
|
|
32
|
+
let chosen = result.tenants[0];
|
|
33
|
+
if (result.tenants.length > 1) {
|
|
34
|
+
const idx = await promptSelect("You belong to multiple ShipFlow tenants. Pick one:", result.tenants.map((t) => `${t.tenant.displayName} (${t.tenant.githubOrg})`));
|
|
35
|
+
chosen = result.tenants[idx];
|
|
36
|
+
}
|
|
37
|
+
saveCredentials({
|
|
38
|
+
jwt: chosen.token,
|
|
39
|
+
refreshToken: chosen.refreshToken,
|
|
40
|
+
tenantId: chosen.tenant.id,
|
|
41
|
+
org: chosen.tenant.githubOrg,
|
|
42
|
+
expiresAt: Math.floor(Date.now() / 1000) + 24 * 60 * 60, // matches server tokenTTL
|
|
43
|
+
});
|
|
44
|
+
const cfg = loadConfig();
|
|
45
|
+
cfg.defaultOrg = chosen.tenant.githubOrg;
|
|
46
|
+
saveConfig(cfg);
|
|
47
|
+
console.log(`Signed in as @${process.env.USER ?? "you"} for ${chosen.tenant.displayName}.`);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr.d.ts","sourceRoot":"","sources":["../../src/commands/pr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuDxD"}
|