@wipcomputer/wip-ldm-os 0.4.10 → 0.4.12
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/SKILL.md +1 -1
- package/bin/ldm.js +4 -0
- package/bin/wip-install.js +17 -1
- package/lib/deploy.mjs +12 -2
- package/package.json +1 -1
package/SKILL.md
CHANGED
package/bin/ldm.js
CHANGED
|
@@ -64,6 +64,9 @@ const LOCK_PATH = join(LDM_ROOT, 'state', '.ldm-install.lock');
|
|
|
64
64
|
|
|
65
65
|
function acquireInstallLock() {
|
|
66
66
|
try {
|
|
67
|
+
// Child processes spawned by `ldm install` inherit this env var
|
|
68
|
+
if (process.env.LDM_INSTALL_LOCK_PID) return true;
|
|
69
|
+
|
|
67
70
|
if (existsSync(LOCK_PATH)) {
|
|
68
71
|
const lock = JSON.parse(readFileSync(LOCK_PATH, 'utf8'));
|
|
69
72
|
// Re-entrant: if we already hold the lock, allow it
|
|
@@ -82,6 +85,7 @@ function acquireInstallLock() {
|
|
|
82
85
|
}
|
|
83
86
|
mkdirSync(dirname(LOCK_PATH), { recursive: true });
|
|
84
87
|
writeFileSync(LOCK_PATH, JSON.stringify({ pid: process.pid, started: new Date().toISOString() }));
|
|
88
|
+
process.env.LDM_INSTALL_LOCK_PID = String(process.pid);
|
|
85
89
|
|
|
86
90
|
// Clean up on exit
|
|
87
91
|
const cleanup = () => { try { if (existsSync(LOCK_PATH)) { const l = JSON.parse(readFileSync(LOCK_PATH, 'utf8')); if (l.pid === process.pid) unlinkSync(LOCK_PATH); } } catch {} };
|
package/bin/wip-install.js
CHANGED
|
@@ -4,5 +4,21 @@
|
|
|
4
4
|
// If not, installs LDM OS from npm, then delegates.
|
|
5
5
|
// Replaces the standalone 700-line install.js from wip-ai-devops-toolbox.
|
|
6
6
|
|
|
7
|
+
// Handle --version directly to prevent recursive spawn loop (#70)
|
|
8
|
+
// detectCLIBinaries() calls wip-install --version which would trigger
|
|
9
|
+
// ldm install which triggers npm checks which spawn more processes.
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
12
|
+
const { readFileSync } = await import('node:fs');
|
|
13
|
+
const { join, dirname } = await import('node:path');
|
|
14
|
+
const { fileURLToPath } = await import('node:url');
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
|
|
18
|
+
console.log(pkg.version);
|
|
19
|
+
} catch { console.log('unknown'); }
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
|
|
7
23
|
import { run } from '../lib/bootstrap.mjs';
|
|
8
|
-
run(
|
|
24
|
+
run(args);
|
package/lib/deploy.mjs
CHANGED
|
@@ -137,7 +137,7 @@ function findExistingInstalls(toolName, pkg, ocPluginConfig) {
|
|
|
137
137
|
|
|
138
138
|
function runBuildIfNeeded(repoPath) {
|
|
139
139
|
const pkg = readJSON(join(repoPath, 'package.json'));
|
|
140
|
-
if (!pkg) return;
|
|
140
|
+
if (!pkg) return true;
|
|
141
141
|
|
|
142
142
|
const hasBuildScript = !!pkg.scripts?.build;
|
|
143
143
|
const hasTsConfig = existsSync(join(repoPath, 'tsconfig.json'));
|
|
@@ -155,8 +155,10 @@ function runBuildIfNeeded(repoPath) {
|
|
|
155
155
|
ok(`Build complete`);
|
|
156
156
|
} catch (e) {
|
|
157
157
|
fail(`Build failed: ${e.stderr?.toString()?.slice(0, 200) || e.message}`);
|
|
158
|
+
return false;
|
|
158
159
|
}
|
|
159
160
|
}
|
|
161
|
+
return true;
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
// ── Version comparison (fix #7) ──
|
|
@@ -229,13 +231,21 @@ function safeDeployDir(repoPath, destDir, name) {
|
|
|
229
231
|
} catch {}
|
|
230
232
|
}
|
|
231
233
|
|
|
232
|
-
// 3. Verify
|
|
234
|
+
// 3. Verify staged copy is valid
|
|
233
235
|
if (!existsSync(join(tempPath, 'package.json'))) {
|
|
234
236
|
fail(`Deploy verification failed: no package.json in staged copy`);
|
|
235
237
|
rmSync(tempPath, { recursive: true, force: true });
|
|
236
238
|
return false;
|
|
237
239
|
}
|
|
238
240
|
|
|
241
|
+
// 3b. If source has a build script, verify dist/ exists (#69)
|
|
242
|
+
const stagePkg = readJSON(join(tempPath, 'package.json'));
|
|
243
|
+
if (stagePkg?.scripts?.build && !existsSync(join(tempPath, 'dist'))) {
|
|
244
|
+
fail(`Deploy aborted: ${name} has a build script but no dist/. Build failed or was skipped.`);
|
|
245
|
+
rmSync(tempPath, { recursive: true, force: true });
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
|
|
239
249
|
// 4. Swap: old -> backup, temp -> final
|
|
240
250
|
mkdirSync(destDir, { recursive: true });
|
|
241
251
|
if (existsSync(finalPath)) {
|