create-claude-workspace 2.3.23 → 2.3.24
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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// ─── CI pipeline status polling ───
|
|
2
2
|
// Uses gh/glab CLI to watch pipeline status after push.
|
|
3
3
|
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
4
5
|
const POLL_INTERVAL = 15_000;
|
|
5
6
|
const MAX_POLL_TIME = 30 * 60_000; // 30 minutes
|
|
6
7
|
const CLI_TIMEOUT = 15_000;
|
|
@@ -20,38 +21,80 @@ export function detectCIPlatform(projectDir) {
|
|
|
20
21
|
}
|
|
21
22
|
/**
|
|
22
23
|
* Check if the CLI tool for a given platform is installed and authenticated.
|
|
23
|
-
*
|
|
24
|
+
* Tries the CLI name directly, then known install paths (for freshly installed tools
|
|
25
|
+
* not yet in the current process PATH).
|
|
24
26
|
*/
|
|
25
27
|
export function checkPlatformCLI(platform) {
|
|
26
28
|
if (platform === 'none')
|
|
27
|
-
return
|
|
29
|
+
return { status: 'ok' };
|
|
28
30
|
const cli = platform === 'github' ? 'gh' : 'glab';
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
catch (err) {
|
|
34
|
-
const code = err.code;
|
|
35
|
-
if (code === 'ENOENT') {
|
|
36
|
-
return `${cli} CLI is not installed`;
|
|
37
|
-
}
|
|
38
|
-
return `${cli} CLI error: ${err.message?.split('\n')[0]}`;
|
|
39
|
-
}
|
|
31
|
+
const bin = resolveCLIBinary(cli);
|
|
32
|
+
if (!bin)
|
|
33
|
+
return { status: 'not-installed' };
|
|
40
34
|
// Check if authenticated
|
|
41
35
|
try {
|
|
42
36
|
if (platform === 'github') {
|
|
43
|
-
execFileSync(
|
|
37
|
+
execFileSync(bin, ['auth', 'status'], { stdio: 'pipe', timeout: 10_000 });
|
|
44
38
|
}
|
|
45
39
|
else {
|
|
46
|
-
|
|
47
|
-
execFileSync('glab', ['api', 'version'], { stdio: 'pipe', timeout: 10_000 });
|
|
40
|
+
execFileSync(bin, ['auth', 'status'], { stdio: 'pipe', timeout: 10_000 });
|
|
48
41
|
}
|
|
49
42
|
}
|
|
50
43
|
catch {
|
|
51
|
-
return
|
|
44
|
+
return { status: 'not-authenticated', command: `${cli} auth login` };
|
|
45
|
+
}
|
|
46
|
+
return { status: 'ok' };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve the full path to a CLI binary.
|
|
50
|
+
* First tries the bare name (in PATH), then checks known installation directories
|
|
51
|
+
* for freshly installed tools that aren't in the current process PATH.
|
|
52
|
+
*/
|
|
53
|
+
export function resolveCLIBinary(cli) {
|
|
54
|
+
// Try bare name first (already in PATH)
|
|
55
|
+
try {
|
|
56
|
+
execFileSync(cli, ['--version'], { stdio: 'pipe', timeout: 10_000 });
|
|
57
|
+
return cli;
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
if (err.code !== 'ENOENT')
|
|
61
|
+
return cli; // Found but errored
|
|
62
|
+
}
|
|
63
|
+
// Try known installation paths (winget, scoop, choco, brew, etc.)
|
|
64
|
+
const candidates = getKnownCLIPaths(cli);
|
|
65
|
+
for (const path of candidates) {
|
|
66
|
+
try {
|
|
67
|
+
execFileSync(path, ['--version'], { stdio: 'pipe', timeout: 10_000 });
|
|
68
|
+
return path;
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
if (err.code !== 'ENOENT')
|
|
72
|
+
return path;
|
|
73
|
+
}
|
|
52
74
|
}
|
|
53
75
|
return null;
|
|
54
76
|
}
|
|
77
|
+
function getKnownCLIPaths(cli) {
|
|
78
|
+
const paths = [];
|
|
79
|
+
const isWindows = process.platform === 'win32';
|
|
80
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
81
|
+
if (isWindows) {
|
|
82
|
+
const localApps = process.env.LOCALAPPDATA || resolve(home, 'AppData', 'Local');
|
|
83
|
+
const progFiles = process.env.ProgramFiles || 'C:\\Program Files';
|
|
84
|
+
const progFilesX86 = process.env['ProgramFiles(x86)'] || 'C:\\Program Files (x86)';
|
|
85
|
+
if (cli === 'gh') {
|
|
86
|
+
paths.push(resolve(progFiles, 'GitHub CLI', 'gh.exe'), resolve(progFilesX86, 'GitHub CLI', 'gh.exe'), resolve(localApps, 'Microsoft', 'WinGet', 'Links', 'gh.exe'), resolve(home, 'scoop', 'shims', 'gh.exe'));
|
|
87
|
+
}
|
|
88
|
+
else if (cli === 'glab') {
|
|
89
|
+
paths.push(resolve(progFiles, 'glab', 'bin', 'glab.exe'), resolve(localApps, 'Microsoft', 'WinGet', 'Links', 'glab.exe'), resolve(home, 'scoop', 'shims', 'glab.exe'));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
// macOS / Linux
|
|
94
|
+
paths.push(`/usr/local/bin/${cli}`, `/opt/homebrew/bin/${cli}`, resolve(home, '.local', 'bin', cli));
|
|
95
|
+
}
|
|
96
|
+
return paths;
|
|
97
|
+
}
|
|
55
98
|
/**
|
|
56
99
|
* Attempt to install the CLI tool for a given platform.
|
|
57
100
|
* Returns true if installation succeeded, false otherwise.
|
package/dist/scheduler/index.mjs
CHANGED
|
@@ -259,22 +259,31 @@ export async function runScheduler(opts) {
|
|
|
259
259
|
// Ensure platform CLI is available before task mode detection
|
|
260
260
|
const detectedPlatform = detectCIPlatform(opts.projectDir);
|
|
261
261
|
if (detectedPlatform !== 'none') {
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
logger.warn(`${
|
|
262
|
+
const cli = detectedPlatform === 'github' ? 'gh' : 'glab';
|
|
263
|
+
let cliCheck = checkPlatformCLI(detectedPlatform);
|
|
264
|
+
if (cliCheck.status === 'not-installed') {
|
|
265
|
+
logger.warn(`${cli} CLI is not installed — attempting auto-install`);
|
|
266
266
|
const installResult = installPlatformCLI(detectedPlatform);
|
|
267
267
|
if (installResult.success) {
|
|
268
268
|
logger.info(`Installed ${cli} via ${installResult.method}`);
|
|
269
|
-
|
|
270
|
-
if (authError?.includes('not authenticated')) {
|
|
271
|
-
logger.warn(`${cli} installed but needs authentication. Run: ${cli} auth login`);
|
|
272
|
-
}
|
|
269
|
+
cliCheck = checkPlatformCLI(detectedPlatform);
|
|
273
270
|
}
|
|
274
271
|
else {
|
|
275
272
|
logger.error(`Failed to install ${cli}: ${installResult.error}`);
|
|
273
|
+
logger.error(`Install ${cli} manually and re-run the scheduler.`);
|
|
274
|
+
process.exit(1);
|
|
276
275
|
}
|
|
277
276
|
}
|
|
277
|
+
if (cliCheck.status === 'not-authenticated') {
|
|
278
|
+
logger.error(`${cli} CLI is installed but not authenticated.`);
|
|
279
|
+
logger.error(`Run this command to authenticate, then re-run the scheduler:`);
|
|
280
|
+
logger.error(` ${cliCheck.command}`);
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
if (cliCheck.status === 'error') {
|
|
284
|
+
logger.error(`${cli} CLI error: ${cliCheck.message}`);
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
278
287
|
}
|
|
279
288
|
// Task mode detection
|
|
280
289
|
if (opts.taskMode) {
|