@jonit-dev/night-watch-cli 1.5.1 → 1.5.2
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/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/cancel.d.ts +46 -0
- package/dist/commands/cancel.d.ts.map +1 -0
- package/dist/commands/cancel.js +239 -0
- package/dist/commands/cancel.js.map +1 -0
- package/dist/commands/prds.d.ts +13 -0
- package/dist/commands/prds.d.ts.map +1 -0
- package/dist/commands/prds.js +192 -0
- package/dist/commands/prds.js.map +1 -0
- package/dist/commands/prs.d.ts +13 -0
- package/dist/commands/prs.d.ts.map +1 -0
- package/dist/commands/prs.js +101 -0
- package/dist/commands/prs.js.map +1 -0
- package/dist/commands/retry.d.ts +9 -0
- package/dist/commands/retry.d.ts.map +1 -0
- package/dist/commands/retry.js +72 -0
- package/dist/commands/retry.js.map +1 -0
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +4 -0
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/update.d.ts +21 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +87 -0
- package/dist/commands/update.js.map +1 -0
- package/package.json +1 -1
- package/scripts/night-watch-cron.sh +86 -37
- package/scripts/night-watch-helpers.sh +135 -1
- package/scripts/night-watch-pr-reviewer-cron.sh +64 -15
- package/templates/night-watch-pr-reviewer.md +7 -11
- package/templates/night-watch.md +9 -20
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,7 @@ import { dashboardCommand } from './commands/dashboard.js';
|
|
|
15
15
|
import { doctorCommand } from './commands/doctor.js';
|
|
16
16
|
import { serveCommand } from './commands/serve.js';
|
|
17
17
|
import { historyCommand } from './commands/history.js';
|
|
18
|
+
import { updateCommand } from './commands/update.js';
|
|
18
19
|
// Get package.json version
|
|
19
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
20
21
|
const __dirname = dirname(__filename);
|
|
@@ -46,5 +47,7 @@ dashboardCommand(program);
|
|
|
46
47
|
serveCommand(program);
|
|
47
48
|
// Register history command (used by bash scripts for cooldown tracking)
|
|
48
49
|
historyCommand(program);
|
|
50
|
+
// Register update command
|
|
51
|
+
updateCommand(program);
|
|
49
52
|
program.parse();
|
|
50
53
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,2BAA2B;AAC3B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,kDAAkD,CAAC;KAC/D,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,wBAAwB;AACxB,WAAW,CAAC,OAAO,CAAC,CAAC;AAErB,uBAAuB;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AAEpB,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,4BAA4B;AAC5B,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,WAAW,CAAC,OAAO,CAAC,CAAC;AAErB,uBAAuB;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AAEpB,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,6BAA6B;AAC7B,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAE1B,yBAAyB;AACzB,YAAY,CAAC,OAAO,CAAC,CAAC;AAEtB,wEAAwE;AACxE,cAAc,CAAC,OAAO,CAAC,CAAC;AAExB,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancel command for Night Watch CLI
|
|
3
|
+
* Gracefully stops a running executor or reviewer process
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
export interface ICancelOptions {
|
|
7
|
+
type: "run" | "review" | "all";
|
|
8
|
+
force?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get lock file paths for a project
|
|
12
|
+
*/
|
|
13
|
+
export declare function getLockFilePaths(projectName: string): {
|
|
14
|
+
executor: string;
|
|
15
|
+
reviewer: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Prompt user for confirmation
|
|
19
|
+
*/
|
|
20
|
+
export declare function promptConfirmation(prompt: string): Promise<boolean>;
|
|
21
|
+
/**
|
|
22
|
+
* Wait for specified milliseconds
|
|
23
|
+
*/
|
|
24
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Check if a process is still running
|
|
27
|
+
*/
|
|
28
|
+
export declare function isProcessRunning(pid: number): boolean;
|
|
29
|
+
export interface ICancelResult {
|
|
30
|
+
success: boolean;
|
|
31
|
+
message: string;
|
|
32
|
+
cleanedUp?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Attempt to cancel a single process
|
|
36
|
+
*/
|
|
37
|
+
export declare function cancelProcess(processType: "executor" | "reviewer", lockPath: string, force?: boolean): Promise<ICancelResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Cancel running execution
|
|
40
|
+
*/
|
|
41
|
+
export declare function performCancel(projectDir: string, options: ICancelOptions): Promise<ICancelResult[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Cancel command implementation
|
|
44
|
+
*/
|
|
45
|
+
export declare function cancelCommand(program: Command): void;
|
|
46
|
+
//# sourceMappingURL=cancel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancel.d.ts","sourceRoot":"","sources":["../../src/commands/cancel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAKA;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAazE;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,UAAU,GAAG,UAAU,EACpC,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,aAAa,CAAC,CA+HxB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,EAAE,CAAC,CAiB1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkDpD"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancel command for Night Watch CLI
|
|
3
|
+
* Gracefully stops a running executor or reviewer process
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import * as readline from "readline";
|
|
8
|
+
import { LOCK_FILE_PREFIX } from "../constants.js";
|
|
9
|
+
import { checkLockFile } from "../utils/status-data.js";
|
|
10
|
+
import { dim, info, success, error as uiError, warn, } from "../utils/ui.js";
|
|
11
|
+
/**
|
|
12
|
+
* Get lock file paths for a project
|
|
13
|
+
*/
|
|
14
|
+
export function getLockFilePaths(projectName) {
|
|
15
|
+
return {
|
|
16
|
+
executor: `${LOCK_FILE_PREFIX}${projectName}.lock`,
|
|
17
|
+
reviewer: `${LOCK_FILE_PREFIX}pr-reviewer-${projectName}.lock`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Prompt user for confirmation
|
|
22
|
+
*/
|
|
23
|
+
export async function promptConfirmation(prompt) {
|
|
24
|
+
const rl = readline.createInterface({
|
|
25
|
+
input: process.stdin,
|
|
26
|
+
output: process.stdout,
|
|
27
|
+
});
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
rl.question(`${prompt} `, (answer) => {
|
|
30
|
+
rl.close();
|
|
31
|
+
const normalized = answer.toLowerCase().trim();
|
|
32
|
+
resolve(normalized === "y" || normalized === "yes");
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Wait for specified milliseconds
|
|
38
|
+
*/
|
|
39
|
+
export function sleep(ms) {
|
|
40
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if a process is still running
|
|
44
|
+
*/
|
|
45
|
+
export function isProcessRunning(pid) {
|
|
46
|
+
try {
|
|
47
|
+
process.kill(pid, 0);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Attempt to cancel a single process
|
|
56
|
+
*/
|
|
57
|
+
export async function cancelProcess(processType, lockPath, force = false) {
|
|
58
|
+
const lockStatus = checkLockFile(lockPath);
|
|
59
|
+
// No lock file exists
|
|
60
|
+
if (!lockStatus.pid) {
|
|
61
|
+
return {
|
|
62
|
+
success: true,
|
|
63
|
+
message: `${processType} is not running (no lock file)`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const pid = lockStatus.pid;
|
|
67
|
+
// Lock file exists but process is not running (stale)
|
|
68
|
+
if (!lockStatus.running) {
|
|
69
|
+
// Clean up stale lock file
|
|
70
|
+
try {
|
|
71
|
+
fs.unlinkSync(lockPath);
|
|
72
|
+
return {
|
|
73
|
+
success: true,
|
|
74
|
+
message: `${processType} is not running (cleaned up stale lock file for PID ${pid})`,
|
|
75
|
+
cleanedUp: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return {
|
|
80
|
+
success: true,
|
|
81
|
+
message: `${processType} is not running (stale lock file exists but could not be removed)`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Process is running - prompt for confirmation
|
|
86
|
+
const confirmPrompt = `Kill ${processType} (PID ${pid})? [y/N]`;
|
|
87
|
+
if (!force) {
|
|
88
|
+
const confirmed = await promptConfirmation(confirmPrompt);
|
|
89
|
+
if (!confirmed) {
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
message: `Cancelled - ${processType} (PID ${pid}) left running`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
dim(confirmPrompt + " y (forced)");
|
|
98
|
+
}
|
|
99
|
+
// Send SIGTERM
|
|
100
|
+
try {
|
|
101
|
+
process.kill(pid, "SIGTERM");
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
message: `Failed to send SIGTERM to ${processType} (PID ${pid}): ${errorMessage}`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
info(`Sent SIGTERM to ${processType} (PID ${pid}), waiting 3 seconds...`);
|
|
111
|
+
// Wait 3 seconds
|
|
112
|
+
await sleep(3000);
|
|
113
|
+
// Check if process is still running
|
|
114
|
+
if (!isProcessRunning(pid)) {
|
|
115
|
+
// Clean up lock file
|
|
116
|
+
try {
|
|
117
|
+
fs.unlinkSync(lockPath);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Ignore cleanup errors
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
success: true,
|
|
124
|
+
message: `${processType} (PID ${pid}) terminated successfully`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
// Process still running after SIGTERM
|
|
128
|
+
warn(`${processType} (PID ${pid}) is still running after SIGTERM`);
|
|
129
|
+
// Offer to send SIGKILL
|
|
130
|
+
const killPrompt = `Send SIGKILL to ${processType} (PID ${pid})? [y/N]`;
|
|
131
|
+
let shouldKill;
|
|
132
|
+
if (!force) {
|
|
133
|
+
shouldKill = await promptConfirmation(killPrompt);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
dim(killPrompt + " y (forced)");
|
|
137
|
+
shouldKill = true;
|
|
138
|
+
}
|
|
139
|
+
if (!shouldKill) {
|
|
140
|
+
return {
|
|
141
|
+
success: false,
|
|
142
|
+
message: `${processType} (PID ${pid}) still running - SIGTERM sent but process did not terminate`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// Send SIGKILL
|
|
146
|
+
try {
|
|
147
|
+
process.kill(pid, "SIGKILL");
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
151
|
+
return {
|
|
152
|
+
success: false,
|
|
153
|
+
message: `Failed to send SIGKILL to ${processType} (PID ${pid}): ${errorMessage}`,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// Wait briefly for SIGKILL to take effect
|
|
157
|
+
await sleep(500);
|
|
158
|
+
// Final check
|
|
159
|
+
if (!isProcessRunning(pid)) {
|
|
160
|
+
// Clean up lock file
|
|
161
|
+
try {
|
|
162
|
+
fs.unlinkSync(lockPath);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// Ignore cleanup errors
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
success: true,
|
|
169
|
+
message: `${processType} (PID ${pid}) killed successfully`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
message: `${processType} (PID ${pid}) could not be terminated even with SIGKILL`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Cancel running execution
|
|
179
|
+
*/
|
|
180
|
+
export async function performCancel(projectDir, options) {
|
|
181
|
+
const projectName = path.basename(projectDir);
|
|
182
|
+
const lockPaths = getLockFilePaths(projectName);
|
|
183
|
+
const results = [];
|
|
184
|
+
const force = options.force ?? false;
|
|
185
|
+
if (options.type === "run" || options.type === "all") {
|
|
186
|
+
const result = await cancelProcess("executor", lockPaths.executor, force);
|
|
187
|
+
results.push(result);
|
|
188
|
+
}
|
|
189
|
+
if (options.type === "review" || options.type === "all") {
|
|
190
|
+
const result = await cancelProcess("reviewer", lockPaths.reviewer, force);
|
|
191
|
+
results.push(result);
|
|
192
|
+
}
|
|
193
|
+
return results;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Cancel command implementation
|
|
197
|
+
*/
|
|
198
|
+
export function cancelCommand(program) {
|
|
199
|
+
program
|
|
200
|
+
.command("cancel")
|
|
201
|
+
.description("Cancel running executor or reviewer processes")
|
|
202
|
+
.option("-t, --type <type>", "Process type to cancel: 'run', 'review', or 'all'", "all")
|
|
203
|
+
.option("-f, --force", "Skip confirmation prompts")
|
|
204
|
+
.action(async (options) => {
|
|
205
|
+
try {
|
|
206
|
+
// Validate type option
|
|
207
|
+
const validTypes = ["run", "review", "all"];
|
|
208
|
+
if (!validTypes.includes(options.type)) {
|
|
209
|
+
uiError(`Invalid type '${options.type}'. Must be one of: ${validTypes.join(", ")}`);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
const cancelOptions = {
|
|
213
|
+
type: options.type,
|
|
214
|
+
force: options.force,
|
|
215
|
+
};
|
|
216
|
+
const projectDir = process.cwd();
|
|
217
|
+
const results = await performCancel(projectDir, cancelOptions);
|
|
218
|
+
// Output results
|
|
219
|
+
for (const result of results) {
|
|
220
|
+
if (result.success) {
|
|
221
|
+
success(result.message);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
uiError(result.message);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Exit with error code if any cancel failed
|
|
228
|
+
const hasFailure = results.some((r) => !r.success);
|
|
229
|
+
if (hasFailure) {
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
uiError(`Error cancelling processes: ${err instanceof Error ? err.message : String(err)}`);
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=cancel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancel.js","sourceRoot":"","sources":["../../src/commands/cancel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRDs command for Night Watch CLI
|
|
3
|
+
* Lists all PRDs with their status (ready/blocked/in-progress/done) and dependencies
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
export interface IPrdsOptions {
|
|
7
|
+
json?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* PRDs command implementation
|
|
11
|
+
*/
|
|
12
|
+
export declare function prdsCommand(program: Command): void;
|
|
13
|
+
//# sourceMappingURL=prds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prds.d.ts","sourceRoot":"","sources":["../../src/commands/prds.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAqHD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiGlD"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRDs command for Night Watch CLI
|
|
3
|
+
* Lists all PRDs with their status (ready/blocked/in-progress/done) and dependencies
|
|
4
|
+
*/
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { loadConfig } from "../config.js";
|
|
7
|
+
import { collectPrdInfo, } from "../utils/status-data.js";
|
|
8
|
+
import { createTable, dim, header, } from "../utils/ui.js";
|
|
9
|
+
import { execSync } from "child_process";
|
|
10
|
+
/**
|
|
11
|
+
* Get open PR branch names using gh CLI
|
|
12
|
+
*/
|
|
13
|
+
function getOpenPrBranches(projectDir) {
|
|
14
|
+
try {
|
|
15
|
+
execSync("git rev-parse --git-dir", {
|
|
16
|
+
cwd: projectDir,
|
|
17
|
+
encoding: "utf-8",
|
|
18
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return new Set();
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
execSync("which gh", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return new Set();
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const output = execSync("gh pr list --state open --json headRefName", {
|
|
32
|
+
cwd: projectDir,
|
|
33
|
+
encoding: "utf-8",
|
|
34
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
35
|
+
});
|
|
36
|
+
const prs = JSON.parse(output);
|
|
37
|
+
return new Set(prs.map((pr) => pr.headRefName));
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return new Set();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Derive a branch name from a PRD name
|
|
45
|
+
* Converts "01-feature-name.md" or "01-feature-name" to potential branch patterns
|
|
46
|
+
*/
|
|
47
|
+
function deriveBranchPatterns(prdName, branchPrefix) {
|
|
48
|
+
// Remove .md extension if present
|
|
49
|
+
const baseName = prdName.replace(/\.md$/, "");
|
|
50
|
+
// Common patterns:
|
|
51
|
+
// 1. night-watch/01-feature-name
|
|
52
|
+
// 2. feat/01-feature-name
|
|
53
|
+
// 3. feature/01-feature-name
|
|
54
|
+
return [
|
|
55
|
+
`${branchPrefix}${baseName}`,
|
|
56
|
+
`feat/${baseName}`,
|
|
57
|
+
`feature/${baseName}`,
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Find matching PR for a PRD
|
|
62
|
+
*/
|
|
63
|
+
function findMatchingPr(prdName, openPrBranches, branchPrefix) {
|
|
64
|
+
const patterns = deriveBranchPatterns(prdName, branchPrefix);
|
|
65
|
+
for (const pattern of patterns) {
|
|
66
|
+
// Check for exact match
|
|
67
|
+
if (openPrBranches.has(pattern)) {
|
|
68
|
+
return pattern;
|
|
69
|
+
}
|
|
70
|
+
// Check for partial match (branch might have additional suffix)
|
|
71
|
+
for (const branch of openPrBranches) {
|
|
72
|
+
if (branch === pattern || branch.startsWith(`${pattern}-`) || branch.startsWith(`${pattern}/`)) {
|
|
73
|
+
return branch;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Format status with color
|
|
81
|
+
*/
|
|
82
|
+
function formatStatus(status) {
|
|
83
|
+
switch (status) {
|
|
84
|
+
case "ready":
|
|
85
|
+
return chalk.green("ready");
|
|
86
|
+
case "blocked":
|
|
87
|
+
return chalk.yellow("blocked");
|
|
88
|
+
case "in-progress":
|
|
89
|
+
return chalk.cyan("in-progress");
|
|
90
|
+
case "done":
|
|
91
|
+
return chalk.dim("done");
|
|
92
|
+
default:
|
|
93
|
+
return status;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Format dependencies list
|
|
98
|
+
*/
|
|
99
|
+
function formatDependencies(dependencies, unmetDependencies) {
|
|
100
|
+
if (dependencies.length === 0) {
|
|
101
|
+
return chalk.dim("-");
|
|
102
|
+
}
|
|
103
|
+
return dependencies.map((dep) => {
|
|
104
|
+
const isUnmet = unmetDependencies.includes(dep);
|
|
105
|
+
return isUnmet ? chalk.red(dep) : chalk.green(dep);
|
|
106
|
+
}).join(", ");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* PRDs command implementation
|
|
110
|
+
*/
|
|
111
|
+
export function prdsCommand(program) {
|
|
112
|
+
program
|
|
113
|
+
.command("prds")
|
|
114
|
+
.description("List all PRDs with their status and dependencies")
|
|
115
|
+
.option("--json", "Output as JSON")
|
|
116
|
+
.action(async (options) => {
|
|
117
|
+
try {
|
|
118
|
+
const projectDir = process.cwd();
|
|
119
|
+
const config = loadConfig(projectDir);
|
|
120
|
+
// Collect PRD info using existing utility
|
|
121
|
+
const prds = collectPrdInfo(projectDir, config.prdDir, config.maxRuntime);
|
|
122
|
+
// Get open PR branches for in-progress detection
|
|
123
|
+
const openPrBranches = getOpenPrBranches(projectDir);
|
|
124
|
+
// Filter out summary file and update in-progress status based on open PRs
|
|
125
|
+
const filteredPrds = prds.filter((prd) => !prd.name.toLowerCase().includes("night-watch-summary"));
|
|
126
|
+
// Update status based on open PRs
|
|
127
|
+
for (const prd of filteredPrds) {
|
|
128
|
+
if (prd.status !== "done") {
|
|
129
|
+
const matchingPr = findMatchingPr(prd.name, openPrBranches, config.branchPrefix);
|
|
130
|
+
if (matchingPr) {
|
|
131
|
+
prd.status = "in-progress";
|
|
132
|
+
prd.prBranch = matchingPr;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Sort: ready first, then blocked, then in-progress, then done
|
|
137
|
+
const statusOrder = {
|
|
138
|
+
"ready": 0,
|
|
139
|
+
"blocked": 1,
|
|
140
|
+
"in-progress": 2,
|
|
141
|
+
"done": 3,
|
|
142
|
+
};
|
|
143
|
+
filteredPrds.sort((a, b) => statusOrder[a.status] - statusOrder[b.status]);
|
|
144
|
+
// Output as JSON if requested
|
|
145
|
+
if (options.json) {
|
|
146
|
+
const jsonOutput = filteredPrds.map((prd) => ({
|
|
147
|
+
name: prd.name,
|
|
148
|
+
status: prd.status,
|
|
149
|
+
dependencies: prd.dependencies,
|
|
150
|
+
unmetDependencies: prd.unmetDependencies,
|
|
151
|
+
pr: prd.prBranch || null,
|
|
152
|
+
}));
|
|
153
|
+
console.log(JSON.stringify(jsonOutput, null, 2));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// Display header
|
|
157
|
+
header("PRD Status");
|
|
158
|
+
if (filteredPrds.length === 0) {
|
|
159
|
+
dim("No PRDs found.");
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// Create and populate table
|
|
163
|
+
const table = createTable({
|
|
164
|
+
head: ["Name", "Status", "Dependencies", "PR"],
|
|
165
|
+
colWidths: [35, 12, 40, 30],
|
|
166
|
+
});
|
|
167
|
+
for (const prd of filteredPrds) {
|
|
168
|
+
const prBranch = prd.prBranch;
|
|
169
|
+
table.push([
|
|
170
|
+
prd.status === "done" ? chalk.dim(prd.name) : prd.name,
|
|
171
|
+
formatStatus(prd.status),
|
|
172
|
+
formatDependencies(prd.dependencies, prd.unmetDependencies),
|
|
173
|
+
prBranch ? chalk.cyan(prBranch) : chalk.dim("-"),
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
176
|
+
console.log(table.toString());
|
|
177
|
+
// Summary counts
|
|
178
|
+
const ready = filteredPrds.filter((p) => p.status === "ready").length;
|
|
179
|
+
const blocked = filteredPrds.filter((p) => p.status === "blocked").length;
|
|
180
|
+
const inProgress = filteredPrds.filter((p) => p.status === "in-progress").length;
|
|
181
|
+
const done = filteredPrds.filter((p) => p.status === "done").length;
|
|
182
|
+
console.log();
|
|
183
|
+
dim(` Ready: ${ready} | Blocked: ${blocked} | In Progress: ${inProgress} | Done: ${done}`);
|
|
184
|
+
console.log();
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
console.error(`Error listing PRDs: ${error instanceof Error ? error.message : String(error)}`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=prds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prds.js","sourceRoot":"","sources":["../../src/commands/prds.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRs command for Night Watch CLI
|
|
3
|
+
* Lists matching PRs with their CI status and review scores
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
export interface IPrsOptions {
|
|
7
|
+
json?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* PRs command implementation
|
|
11
|
+
*/
|
|
12
|
+
export declare function prsCommand(program: Command): void;
|
|
13
|
+
//# sourceMappingURL=prs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prs.d.ts","sourceRoot":"","sources":["../../src/commands/prs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA0CD;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmEjD"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRs command for Night Watch CLI
|
|
3
|
+
* Lists matching PRs with their CI status and review scores
|
|
4
|
+
*/
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { loadConfig } from "../config.js";
|
|
7
|
+
import { collectPrInfo } from "../utils/status-data.js";
|
|
8
|
+
import { createTable, dim, header, info } from "../utils/ui.js";
|
|
9
|
+
/**
|
|
10
|
+
* Format CI status with color coding
|
|
11
|
+
*/
|
|
12
|
+
function formatCiStatus(status) {
|
|
13
|
+
switch (status) {
|
|
14
|
+
case "pass":
|
|
15
|
+
return chalk.green("pass");
|
|
16
|
+
case "fail":
|
|
17
|
+
return chalk.red("fail");
|
|
18
|
+
case "pending":
|
|
19
|
+
return chalk.yellow("pending");
|
|
20
|
+
default:
|
|
21
|
+
return chalk.dim("unknown");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Format review score with color coding
|
|
26
|
+
*/
|
|
27
|
+
function formatReviewScore(score) {
|
|
28
|
+
if (score === null) {
|
|
29
|
+
return chalk.dim("-");
|
|
30
|
+
}
|
|
31
|
+
if (score >= 80) {
|
|
32
|
+
return chalk.green(String(score));
|
|
33
|
+
}
|
|
34
|
+
if (score >= 60) {
|
|
35
|
+
return chalk.yellow(String(score));
|
|
36
|
+
}
|
|
37
|
+
return chalk.red(String(score));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* PRs command implementation
|
|
41
|
+
*/
|
|
42
|
+
export function prsCommand(program) {
|
|
43
|
+
program
|
|
44
|
+
.command("prs")
|
|
45
|
+
.description("List matching PRs with CI status and review scores")
|
|
46
|
+
.option("--json", "Output PRs as JSON")
|
|
47
|
+
.action(async (options) => {
|
|
48
|
+
try {
|
|
49
|
+
const projectDir = process.cwd();
|
|
50
|
+
const config = loadConfig(projectDir);
|
|
51
|
+
const prs = collectPrInfo(projectDir, config.branchPatterns);
|
|
52
|
+
// Output as JSON if requested
|
|
53
|
+
if (options.json) {
|
|
54
|
+
const output = {
|
|
55
|
+
prs,
|
|
56
|
+
count: prs.length,
|
|
57
|
+
};
|
|
58
|
+
console.log(JSON.stringify(output, null, 2));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Print header
|
|
62
|
+
console.log();
|
|
63
|
+
console.log(chalk.bold.cyan("Night Watch PRs"));
|
|
64
|
+
console.log(chalk.dim("-".repeat(40)));
|
|
65
|
+
console.log();
|
|
66
|
+
if (prs.length === 0) {
|
|
67
|
+
info("No open PRs matching configured branch patterns found.");
|
|
68
|
+
dim(`Branch patterns: ${config.branchPatterns.join(", ")}`);
|
|
69
|
+
console.log();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
header(`Open PRs (${prs.length})`);
|
|
73
|
+
// Create and populate table
|
|
74
|
+
const table = createTable({
|
|
75
|
+
head: ["#", "Title", "Branch", "CI", "Score", "URL"],
|
|
76
|
+
colWidths: [6, 30, 25, 10, 8, 50],
|
|
77
|
+
});
|
|
78
|
+
for (const pr of prs) {
|
|
79
|
+
// Truncate title if too long
|
|
80
|
+
const title = pr.title.length > 27 ? pr.title.substring(0, 24) + "..." : pr.title;
|
|
81
|
+
// Truncate branch if too long
|
|
82
|
+
const branch = pr.branch.length > 22 ? pr.branch.substring(0, 19) + "..." : pr.branch;
|
|
83
|
+
table.push([
|
|
84
|
+
String(pr.number),
|
|
85
|
+
title,
|
|
86
|
+
branch,
|
|
87
|
+
formatCiStatus(pr.ciStatus),
|
|
88
|
+
formatReviewScore(pr.reviewScore),
|
|
89
|
+
pr.url,
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
console.log(table.toString());
|
|
93
|
+
console.log();
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error(`Error listing PRs: ${error instanceof Error ? error.message : String(error)}`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=prs.js.map
|