baton-issue-tracker 1.8.0 → 1.9.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/package.json +1 -1
- package/source/cli.js +3 -0
- package/source/commands/reject.js +99 -0
package/package.json
CHANGED
package/source/cli.js
CHANGED
|
@@ -18,6 +18,7 @@ import { run as runNext } from './commands/next.js';
|
|
|
18
18
|
import { run as runLoop } from './commands/loop.js';
|
|
19
19
|
import { run as runStatus } from './commands/status.js';
|
|
20
20
|
import { run as runApprove } from './commands/approve.js';
|
|
21
|
+
import { run as runReject } from './commands/reject.js';
|
|
21
22
|
import { wantsHelp } from './util.js';
|
|
22
23
|
import { run as runView} from './commands/view.js';
|
|
23
24
|
import { run as runSearch } from './commands/search.js';
|
|
@@ -78,6 +79,7 @@ Options:
|
|
|
78
79
|
create --token-limit <n> Optional token budget for this issue
|
|
79
80
|
create --json Output as JSON (for AI agents)
|
|
80
81
|
approve <id> [--json]
|
|
82
|
+
reject <id> --reason <text> Reject an issue with a given reason
|
|
81
83
|
priority <id> <level> [--json] low | medium | high
|
|
82
84
|
update --title <text> New title
|
|
83
85
|
update --description <text> New description
|
|
@@ -138,6 +140,7 @@ async function main() {
|
|
|
138
140
|
search: () => runSearch(args),
|
|
139
141
|
list: () => runList(args),
|
|
140
142
|
approve: () => runApprove(args),
|
|
143
|
+
reject: () => runReject(args),
|
|
141
144
|
priority: () => runPriority(args),
|
|
142
145
|
create: () => runCreate(args),
|
|
143
146
|
update: () => runUpdate(args),
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// reject.js
|
|
2
|
+
// supports rejecting an issue.
|
|
3
|
+
//
|
|
4
|
+
// AI Was used in generating this file.
|
|
5
|
+
// Usage:
|
|
6
|
+
// baton reject <id> [options]
|
|
7
|
+
//
|
|
8
|
+
// Options:
|
|
9
|
+
// --reason <text> Reason for rejection (required)
|
|
10
|
+
// --json Output in JSON format
|
|
11
|
+
// -h, --help Show this help
|
|
12
|
+
//
|
|
13
|
+
// Examples:
|
|
14
|
+
// baton reject 5 --reason "Needs more detail"
|
|
15
|
+
|
|
16
|
+
import { rejectIssue, getIssue } from '../services/issuesService.js';
|
|
17
|
+
import { Status } from '../models/issue.js';
|
|
18
|
+
import { hasFlag, getFlagValue, wantsHelp, renderOutput, renderError, serializeIssue } from '../util.js';
|
|
19
|
+
|
|
20
|
+
const USAGE = "Usage:\n baton reject <id> [options]\n\nOptions:\n --reason <text> Reason for rejection (required)\n --json Output in JSON format\n -h, --help Show this help";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Rejects an issue for a specified ID.
|
|
24
|
+
*
|
|
25
|
+
* @param {string[]} args - The command line arguments
|
|
26
|
+
* @returns {Promise<number>} The exit code: 0 is success, 1 is error.
|
|
27
|
+
*/
|
|
28
|
+
export async function run(args) {
|
|
29
|
+
const isJson = hasFlag(args, '--json');
|
|
30
|
+
|
|
31
|
+
// (0) Help check
|
|
32
|
+
if (wantsHelp(args)) {
|
|
33
|
+
console.log(USAGE);
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// (1) Parse arguments
|
|
38
|
+
const idArgs = args.filter(arg => !arg.startsWith('-'));
|
|
39
|
+
if (idArgs.length === 0) {
|
|
40
|
+
renderError(isJson, `No ID provided.\n${USAGE}`, 'MISSING_ID');
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const id = Number(idArgs[0]);
|
|
45
|
+
if (!Number.isInteger(id)) {
|
|
46
|
+
renderError(isJson, `Invalid ID "${idArgs[0]}". ID must be an integer.`, 'INVALID_ID');
|
|
47
|
+
return 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!hasFlag(args, "--reason")) {
|
|
51
|
+
renderError(isJson, `Missing reason for reject.\n${USAGE}`, 'MISSING_REASON');
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let reasonText;
|
|
56
|
+
try {
|
|
57
|
+
reasonText = getFlagValue(args, "--reason");
|
|
58
|
+
} catch (error) {
|
|
59
|
+
renderError(isJson, error.message, 'INVALID_REASON');
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!reasonText || reasonText.trim() === "") {
|
|
64
|
+
renderError(isJson, "Reason for rejection cannot be empty.", 'EMPTY_REASON');
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let issue;
|
|
69
|
+
try {
|
|
70
|
+
issue = await getIssue(id);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (error.message.includes("not found")) {
|
|
73
|
+
renderError(isJson, error.message, 'NOT_FOUND');
|
|
74
|
+
} else {
|
|
75
|
+
renderError(isJson, error.message);
|
|
76
|
+
}
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (issue.status !== Status.IN_REVIEW) {
|
|
81
|
+
renderError(isJson, `Issue #${id} is currently "${issue.status}". Only issues in "${Status.IN_REVIEW}" status can be rejected.`, 'INVALID_STATE');
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
// (3) Perform rejection
|
|
87
|
+
const updatedIssue = await rejectIssue(id, reasonText);
|
|
88
|
+
const envelope = { status: 'success', issue: serializeIssue(updatedIssue) };
|
|
89
|
+
|
|
90
|
+
renderOutput(isJson, envelope, () => {
|
|
91
|
+
console.log(`Issue #${id} rejected successfully and moved back to "${updatedIssue.status}".`);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return 0;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
renderError(isJson, error.message);
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
}
|