@vibe-validate/cli 0.18.3-rc.1 → 0.18.4-rc.1
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/commands/history.d.ts.map +1 -1
- package/dist/commands/history.js +15 -7
- package/dist/commands/history.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +20 -11
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pre-commit.d.ts.map +1 -1
- package/dist/commands/pre-commit.js +46 -29
- package/dist/commands/pre-commit.js.map +1 -1
- package/dist/commands/snapshot.d.ts.map +1 -1
- package/dist/commands/snapshot.js +26 -17
- package/dist/commands/snapshot.js.map +1 -1
- package/dist/commands/state.d.ts.map +1 -1
- package/dist/commands/state.js +3 -1
- package/dist/commands/state.js.map +1 -1
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +17 -134
- package/dist/commands/validate.js.map +1 -1
- package/dist/services/watch-pr-orchestrator.d.ts +8 -0
- package/dist/services/watch-pr-orchestrator.d.ts.map +1 -1
- package/dist/services/watch-pr-orchestrator.js +29 -18
- package/dist/services/watch-pr-orchestrator.js.map +1 -1
- package/dist/utils/check-validation.d.ts.map +1 -1
- package/dist/utils/check-validation.js +26 -11
- package/dist/utils/check-validation.js.map +1 -1
- package/dist/utils/pid-lock.d.ts +27 -28
- package/dist/utils/pid-lock.d.ts.map +1 -1
- package/dist/utils/pid-lock.js +178 -92
- package/dist/utils/pid-lock.js.map +1 -1
- package/dist/utils/temp-files.d.ts +12 -12
- package/dist/utils/temp-files.d.ts.map +1 -1
- package/dist/utils/temp-files.js +67 -36
- package/dist/utils/temp-files.js.map +1 -1
- package/dist/utils/validation-lock-wrapper.d.ts +62 -0
- package/dist/utils/validation-lock-wrapper.d.ts.map +1 -0
- package/dist/utils/validation-lock-wrapper.js +186 -0
- package/dist/utils/validation-lock-wrapper.js.map +1 -0
- package/package.json +9 -7
package/dist/utils/pid-lock.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Advisory locking for single-instance validation execution
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Uses proper-lockfile for cross-platform advisory locking with automatic
|
|
5
|
+
* stale lock detection. Works reliably on Windows, macOS, and Linux.
|
|
6
|
+
*
|
|
7
|
+
* Note: Migrated from manual PID-based locking to proper-lockfile for
|
|
8
|
+
* true advisory locking (99.9% reliability vs ~40% with manual approach).
|
|
6
9
|
*/
|
|
7
|
-
import {
|
|
10
|
+
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
8
11
|
import { join } from 'node:path';
|
|
9
|
-
import {
|
|
12
|
+
import { mkdirSyncReal, normalizedTmpdir } from '@vibe-validate/utils';
|
|
13
|
+
import lockfile from 'proper-lockfile';
|
|
10
14
|
/**
|
|
11
15
|
* Encode directory path for use in lock file name
|
|
12
16
|
*
|
|
@@ -35,147 +39,229 @@ function encodeDirectoryPath(directory) {
|
|
|
35
39
|
*/
|
|
36
40
|
function getLockFilePath(directory, options = {}) {
|
|
37
41
|
const scope = options.scope ?? 'directory';
|
|
42
|
+
const lockDir = join(normalizedTmpdir(), '.vibe-validate', 'locks');
|
|
43
|
+
// Ensure lock directory exists
|
|
44
|
+
if (!existsSync(lockDir)) {
|
|
45
|
+
mkdirSyncReal(lockDir, { recursive: true, mode: 0o755 });
|
|
46
|
+
}
|
|
38
47
|
if (scope === 'project') {
|
|
39
48
|
if (!options.projectId) {
|
|
40
49
|
throw new Error('projectId is required when scope is "project"');
|
|
41
50
|
}
|
|
42
|
-
// Project-scoped: /tmp
|
|
43
|
-
return join(
|
|
51
|
+
// Project-scoped: /tmp/.vibe-validate/locks/project-{projectId}.lock
|
|
52
|
+
return join(lockDir, `project-${options.projectId}.lock`);
|
|
44
53
|
}
|
|
45
|
-
// Directory-scoped (default): /tmp
|
|
54
|
+
// Directory-scoped (default): /tmp/.vibe-validate/locks/dir-{encoded}.lock
|
|
46
55
|
const encoded = encodeDirectoryPath(directory);
|
|
47
|
-
return join(
|
|
56
|
+
return join(lockDir, `dir-${encoded}.lock`);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get metadata file path for a lock file
|
|
60
|
+
*
|
|
61
|
+
* @param lockFile - Lock file path
|
|
62
|
+
* @returns Metadata file path
|
|
63
|
+
*/
|
|
64
|
+
function getMetadataFilePath(lockFile) {
|
|
65
|
+
return `${lockFile}.meta.json`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Write lock metadata to companion file
|
|
69
|
+
*
|
|
70
|
+
* @param lockFile - Lock file path
|
|
71
|
+
* @param metadata - Lock metadata to write
|
|
72
|
+
*/
|
|
73
|
+
function writeMetadata(lockFile, metadata) {
|
|
74
|
+
const metaFile = getMetadataFilePath(lockFile);
|
|
75
|
+
writeFileSync(metaFile, JSON.stringify(metadata), 'utf8');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read lock metadata from companion file
|
|
79
|
+
*
|
|
80
|
+
* @param lockFile - Lock file path
|
|
81
|
+
* @returns Lock metadata or null if file doesn't exist
|
|
82
|
+
*/
|
|
83
|
+
function readMetadata(lockFile) {
|
|
84
|
+
const metaFile = getMetadataFilePath(lockFile);
|
|
85
|
+
try {
|
|
86
|
+
const content = readFileSync(metaFile, 'utf8');
|
|
87
|
+
return JSON.parse(content);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
48
92
|
}
|
|
49
93
|
/**
|
|
50
|
-
*
|
|
94
|
+
* Delete lock metadata file
|
|
51
95
|
*
|
|
52
|
-
*
|
|
53
|
-
|
|
54
|
-
|
|
96
|
+
* @param lockFile - Lock file path
|
|
97
|
+
*/
|
|
98
|
+
function deleteMetadata(lockFile) {
|
|
99
|
+
const metaFile = getMetadataFilePath(lockFile);
|
|
100
|
+
try {
|
|
101
|
+
unlinkSync(metaFile);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Ignore errors - file might not exist
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Acquire validation lock using proper-lockfile
|
|
109
|
+
*
|
|
110
|
+
* Uses advisory locking with automatic stale lock detection.
|
|
111
|
+
* If a lock already exists and is held by a running process, returns acquired=false.
|
|
112
|
+
* Stale locks (from crashed processes) are automatically cleaned up.
|
|
55
113
|
*
|
|
56
114
|
* @param directory - Project directory to lock
|
|
57
115
|
* @param treeHash - Current git tree hash
|
|
58
116
|
* @param options - Lock scope options
|
|
59
|
-
* @returns Lock acquisition result
|
|
117
|
+
* @returns Lock acquisition result with release function
|
|
60
118
|
*/
|
|
61
119
|
export async function acquireLock(directory, treeHash, options = {}) {
|
|
62
120
|
const lockFile = getLockFilePath(directory, options);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
121
|
+
try {
|
|
122
|
+
// Try to acquire lock with proper-lockfile
|
|
123
|
+
// proper-lockfile handles lock metadata internally (PID, timestamp, etc.)
|
|
124
|
+
const release = await lockfile.lock(lockFile, {
|
|
125
|
+
// Stale lock timeout: 60 seconds (consider lock stale if not updated)
|
|
126
|
+
stale: 60000,
|
|
127
|
+
// Update lock every 10 seconds to prove liveness
|
|
128
|
+
update: 10000,
|
|
129
|
+
// Don't retry - we'll handle retries at a higher level
|
|
130
|
+
retries: 0,
|
|
131
|
+
// Don't resolve symlinks (faster, and we control the lock directory)
|
|
132
|
+
realpath: false,
|
|
133
|
+
});
|
|
134
|
+
// Write metadata for API compatibility
|
|
135
|
+
const metadata = {
|
|
136
|
+
pid: process.pid,
|
|
137
|
+
directory,
|
|
138
|
+
treeHash,
|
|
139
|
+
startTime: new Date().toISOString(),
|
|
140
|
+
};
|
|
141
|
+
writeMetadata(lockFile, metadata);
|
|
142
|
+
// Lock acquired! Return with release function
|
|
143
|
+
return {
|
|
144
|
+
acquired: true,
|
|
145
|
+
lockFile,
|
|
146
|
+
release: async () => {
|
|
147
|
+
try {
|
|
148
|
+
deleteMetadata(lockFile);
|
|
149
|
+
await release();
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
// Ignore release errors (lock file might already be removed)
|
|
153
|
+
if (error.code !== 'ENOENT') {
|
|
154
|
+
console.warn(`Warning: Failed to release lock: ${error.message}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
const err = error;
|
|
162
|
+
// Lock is held by another process
|
|
163
|
+
if (err.code === 'ELOCKED') {
|
|
164
|
+
// Read metadata from companion file
|
|
165
|
+
const existingLock = readMetadata(lockFile) ?? {
|
|
166
|
+
pid: 0,
|
|
167
|
+
directory,
|
|
168
|
+
treeHash: 'unknown',
|
|
169
|
+
startTime: new Date().toISOString(),
|
|
170
|
+
};
|
|
171
|
+
return {
|
|
172
|
+
acquired: false,
|
|
173
|
+
lockFile,
|
|
174
|
+
existingLock,
|
|
175
|
+
};
|
|
83
176
|
}
|
|
177
|
+
// Unexpected error
|
|
178
|
+
throw new Error(`Failed to acquire lock: ${err.message}`);
|
|
84
179
|
}
|
|
85
|
-
// Acquire lock
|
|
86
|
-
const lockInfo = {
|
|
87
|
-
pid: process.pid,
|
|
88
|
-
directory,
|
|
89
|
-
treeHash,
|
|
90
|
-
startTime: new Date().toISOString(),
|
|
91
|
-
};
|
|
92
|
-
writeFileSync(lockFile, JSON.stringify(lockInfo, null, 2));
|
|
93
|
-
return {
|
|
94
|
-
acquired: true,
|
|
95
|
-
lockFile,
|
|
96
|
-
};
|
|
97
180
|
}
|
|
98
181
|
/**
|
|
99
182
|
* Release validation lock
|
|
100
183
|
*
|
|
101
|
-
*
|
|
102
|
-
* Safe to call even if lock
|
|
184
|
+
* Calls the release function returned by acquireLock.
|
|
185
|
+
* Safe to call even if lock was already released.
|
|
103
186
|
*
|
|
104
|
-
* @param
|
|
187
|
+
* @param _lockFile - Path to lock file (for backwards compatibility, not used)
|
|
188
|
+
* @param releaseFunc - Release function from acquireLock (preferred)
|
|
105
189
|
*/
|
|
106
|
-
export async function releaseLock(
|
|
107
|
-
if (
|
|
108
|
-
|
|
190
|
+
export async function releaseLock(_lockFile, releaseFunc) {
|
|
191
|
+
if (releaseFunc) {
|
|
192
|
+
await releaseFunc();
|
|
109
193
|
}
|
|
194
|
+
// If no release function provided, lockfile is likely already released
|
|
195
|
+
// (backwards compatibility with old code that just passed lockFile path)
|
|
110
196
|
}
|
|
111
197
|
/**
|
|
112
|
-
* Check
|
|
198
|
+
* Check if a lock exists and is held by a running process
|
|
113
199
|
*
|
|
114
|
-
*
|
|
115
|
-
* Automatically cleans up stale locks.
|
|
116
|
-
*
|
|
117
|
-
* @param directory - Project directory to check
|
|
200
|
+
* @param directory - Project directory
|
|
118
201
|
* @param options - Lock scope options
|
|
119
|
-
* @returns Lock
|
|
202
|
+
* @returns Lock info if lock exists and is valid, null otherwise
|
|
120
203
|
*/
|
|
121
204
|
export async function checkLock(directory, options = {}) {
|
|
122
205
|
const lockFile = getLockFilePath(directory, options);
|
|
123
|
-
if (!existsSync(lockFile)) {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
206
|
try {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
207
|
+
// Try to check if lock is held
|
|
208
|
+
const isLocked = await lockfile.check(lockFile, {
|
|
209
|
+
stale: 60000,
|
|
210
|
+
realpath: false,
|
|
211
|
+
});
|
|
212
|
+
if (isLocked) {
|
|
213
|
+
// Lock exists and is valid - read metadata
|
|
214
|
+
return readMetadata(lockFile) ?? {
|
|
215
|
+
pid: 0,
|
|
216
|
+
directory,
|
|
217
|
+
treeHash: 'unknown',
|
|
218
|
+
startTime: new Date().toISOString(),
|
|
219
|
+
};
|
|
131
220
|
}
|
|
132
|
-
// Stale lock - clean up
|
|
133
|
-
unlinkSync(lockFile);
|
|
134
221
|
return null;
|
|
135
222
|
}
|
|
136
223
|
catch {
|
|
137
|
-
//
|
|
138
|
-
unlinkSync(lockFile);
|
|
224
|
+
// Lock doesn't exist or error checking
|
|
139
225
|
return null;
|
|
140
226
|
}
|
|
141
227
|
}
|
|
142
228
|
/**
|
|
143
|
-
* Wait for lock to be released
|
|
229
|
+
* Wait for an existing lock to be released
|
|
144
230
|
*
|
|
145
231
|
* Polls the lock file until it's released or timeout is reached.
|
|
146
|
-
* Useful for pre-commit hooks that want to wait for background
|
|
147
|
-
* validation to complete before proceeding.
|
|
148
232
|
*
|
|
149
|
-
* @param directory - Project directory
|
|
150
|
-
* @param timeoutSeconds - Maximum time to wait
|
|
151
|
-
* @param
|
|
233
|
+
* @param directory - Project directory
|
|
234
|
+
* @param timeoutSeconds - Maximum time to wait in seconds
|
|
235
|
+
* @param pollInterval - How often to check in milliseconds
|
|
152
236
|
* @param options - Lock scope options
|
|
153
|
-
* @returns
|
|
237
|
+
* @returns Object indicating if wait timed out
|
|
154
238
|
*/
|
|
155
|
-
export async function waitForLock(directory, timeoutSeconds
|
|
239
|
+
export async function waitForLock(directory, timeoutSeconds, pollInterval = 1000, options = {}) {
|
|
240
|
+
const lockFile = getLockFilePath(directory, options);
|
|
156
241
|
const startTime = Date.now();
|
|
157
242
|
const timeoutMs = timeoutSeconds * 1000;
|
|
158
243
|
while (true) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
244
|
+
try {
|
|
245
|
+
const isLocked = await lockfile.check(lockFile, {
|
|
246
|
+
stale: 60000,
|
|
247
|
+
realpath: false,
|
|
248
|
+
});
|
|
249
|
+
if (!isLocked) {
|
|
250
|
+
// Lock released!
|
|
251
|
+
return { timedOut: false };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// Lock doesn't exist (released)
|
|
256
|
+
return { timedOut: false };
|
|
167
257
|
}
|
|
168
258
|
// Check timeout
|
|
169
259
|
const elapsed = Date.now() - startTime;
|
|
170
260
|
if (elapsed >= timeoutMs) {
|
|
171
|
-
return {
|
|
172
|
-
released: false,
|
|
173
|
-
timedOut: true,
|
|
174
|
-
finalLock: lock,
|
|
175
|
-
};
|
|
261
|
+
return { timedOut: true };
|
|
176
262
|
}
|
|
177
|
-
// Wait before next
|
|
178
|
-
await new Promise(
|
|
263
|
+
// Wait before next check
|
|
264
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
179
265
|
}
|
|
180
266
|
}
|
|
181
267
|
//# sourceMappingURL=pid-lock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pid-lock.js","sourceRoot":"","sources":["../../src/utils/pid-lock.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pid-lock.js","sourceRoot":"","sources":["../../src/utils/pid-lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,18 +22,6 @@ export declare function getRunOutputDir(treeHash: string): string;
|
|
|
22
22
|
* Re-exports shared utility from @vibe-validate/core
|
|
23
23
|
*/
|
|
24
24
|
export { ensureDir } from '@vibe-validate/core';
|
|
25
|
-
/**
|
|
26
|
-
* Get temp file storage information
|
|
27
|
-
*/
|
|
28
|
-
export declare function getTempStorageInfo(): Promise<{
|
|
29
|
-
sizeBytes: number;
|
|
30
|
-
runCount: number;
|
|
31
|
-
path: string;
|
|
32
|
-
}>;
|
|
33
|
-
/**
|
|
34
|
-
* Format bytes as human-readable size
|
|
35
|
-
*/
|
|
36
|
-
export declare function formatBytes(bytes: number): string;
|
|
37
25
|
/**
|
|
38
26
|
* Options for cleaning up temp files
|
|
39
27
|
*/
|
|
@@ -61,6 +49,18 @@ export interface CleanupResult {
|
|
|
61
49
|
error: string;
|
|
62
50
|
}>;
|
|
63
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Get temp file storage information
|
|
54
|
+
*/
|
|
55
|
+
export declare function getTempStorageInfo(): Promise<{
|
|
56
|
+
sizeBytes: number;
|
|
57
|
+
runCount: number;
|
|
58
|
+
path: string;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Format bytes as human-readable size
|
|
62
|
+
*/
|
|
63
|
+
export declare function formatBytes(bytes: number): string;
|
|
64
64
|
/**
|
|
65
65
|
* Clean up old temporary files
|
|
66
66
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temp-files.d.ts","sourceRoot":"","sources":["../../src/utils/temp-files.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"temp-files.d.ts","sourceRoot":"","sources":["../../src/utils/temp-files.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAgChD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,wCAAwC;IACxC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAiHD;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAcD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CA6CxB"}
|
package/dist/utils/temp-files.js
CHANGED
|
@@ -57,6 +57,72 @@ async function getDirectorySize(dirPath) {
|
|
|
57
57
|
}
|
|
58
58
|
return totalSize;
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Process a single date directory during cleanup
|
|
62
|
+
*
|
|
63
|
+
* @param dateDirPath - Path to the date directory
|
|
64
|
+
* @param cutoffDate - Files older than this date should be deleted
|
|
65
|
+
* @param deleteAll - Whether to delete all runs
|
|
66
|
+
* @param dryRun - Whether this is a dry run (no actual deletion)
|
|
67
|
+
* @param result - Accumulator for cleanup results
|
|
68
|
+
*/
|
|
69
|
+
async function processDateDirectory(dateDirPath, cutoffDate, deleteAll, dryRun, result) {
|
|
70
|
+
const runDirs = await readdir(dateDirPath, { withFileTypes: true });
|
|
71
|
+
for (const runDir of runDirs) {
|
|
72
|
+
if (!runDir.isDirectory())
|
|
73
|
+
continue;
|
|
74
|
+
const runDirPath = join(dateDirPath, runDir.name);
|
|
75
|
+
try {
|
|
76
|
+
await processRunDirectory(runDirPath, cutoffDate, deleteAll, dryRun, result);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
80
|
+
result.errors.push({ path: runDirPath, error: errorMsg });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Try to remove empty date directories
|
|
84
|
+
if (!dryRun) {
|
|
85
|
+
await cleanupEmptyDirectory(dateDirPath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Process a single run directory during cleanup
|
|
90
|
+
*
|
|
91
|
+
* @param runDirPath - Path to the run directory
|
|
92
|
+
* @param cutoffDate - Files older than this date should be deleted
|
|
93
|
+
* @param deleteAll - Whether to delete all runs
|
|
94
|
+
* @param dryRun - Whether this is a dry run (no actual deletion)
|
|
95
|
+
* @param result - Accumulator for cleanup results
|
|
96
|
+
*/
|
|
97
|
+
async function processRunDirectory(runDirPath, cutoffDate, deleteAll, dryRun, result) {
|
|
98
|
+
const stats = await stat(runDirPath);
|
|
99
|
+
const shouldDelete = deleteAll || stats.mtime < cutoffDate;
|
|
100
|
+
if (!shouldDelete)
|
|
101
|
+
return;
|
|
102
|
+
const dirSize = await getDirectorySize(runDirPath);
|
|
103
|
+
if (!dryRun) {
|
|
104
|
+
await rm(runDirPath, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
result.deletedCount++;
|
|
107
|
+
result.freedBytes += dirSize;
|
|
108
|
+
result.deletedPaths.push(runDirPath);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Remove a directory if it's empty
|
|
112
|
+
*
|
|
113
|
+
* @param dirPath - Path to the directory
|
|
114
|
+
*/
|
|
115
|
+
async function cleanupEmptyDirectory(dirPath) {
|
|
116
|
+
try {
|
|
117
|
+
const remaining = await readdir(dirPath);
|
|
118
|
+
if (remaining.length === 0) {
|
|
119
|
+
await rm(dirPath, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Ignore errors when cleaning up empty directories
|
|
124
|
+
}
|
|
125
|
+
}
|
|
60
126
|
/**
|
|
61
127
|
* Count the number of run directories
|
|
62
128
|
*/
|
|
@@ -110,7 +176,6 @@ export function formatBytes(bytes) {
|
|
|
110
176
|
/**
|
|
111
177
|
* Clean up old temporary files
|
|
112
178
|
*/
|
|
113
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity -- Cleanup logic requires nested loops and error handling for directory traversal
|
|
114
179
|
export async function cleanupOldTempFiles(options = {}) {
|
|
115
180
|
const { olderThanDays = 7, dryRun = false, deleteAll = false, } = options;
|
|
116
181
|
const result = {
|
|
@@ -130,41 +195,7 @@ export async function cleanupOldTempFiles(options = {}) {
|
|
|
130
195
|
continue;
|
|
131
196
|
const dateDirPath = join(runsDir, dateDir.name);
|
|
132
197
|
try {
|
|
133
|
-
|
|
134
|
-
for (const runDir of runDirs) {
|
|
135
|
-
if (!runDir.isDirectory())
|
|
136
|
-
continue;
|
|
137
|
-
const runDirPath = join(dateDirPath, runDir.name);
|
|
138
|
-
try {
|
|
139
|
-
const stats = await stat(runDirPath);
|
|
140
|
-
const shouldDelete = deleteAll || stats.mtime < cutoffDate;
|
|
141
|
-
if (shouldDelete) {
|
|
142
|
-
const dirSize = await getDirectorySize(runDirPath);
|
|
143
|
-
if (!dryRun) {
|
|
144
|
-
await rm(runDirPath, { recursive: true, force: true });
|
|
145
|
-
}
|
|
146
|
-
result.deletedCount++;
|
|
147
|
-
result.freedBytes += dirSize;
|
|
148
|
-
result.deletedPaths.push(runDirPath);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
catch (err) {
|
|
152
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
153
|
-
result.errors.push({ path: runDirPath, error: errorMsg });
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// Try to remove empty date directories
|
|
157
|
-
if (!dryRun) {
|
|
158
|
-
try {
|
|
159
|
-
const remaining = await readdir(dateDirPath);
|
|
160
|
-
if (remaining.length === 0) {
|
|
161
|
-
await rm(dateDirPath, { recursive: true });
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
// Ignore errors when cleaning up empty directories
|
|
166
|
-
}
|
|
167
|
-
}
|
|
198
|
+
await processDateDirectory(dateDirPath, cutoffDate, deleteAll, dryRun, result);
|
|
168
199
|
}
|
|
169
200
|
catch (err) {
|
|
170
201
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temp-files.js","sourceRoot":"","sources":["../../src/utils/temp-files.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"temp-files.js","sourceRoot":"","sources":["../../src/utils/temp-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Lock Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Provides a reusable locking mechanism for validation workflows.
|
|
5
|
+
* Extracts the locking logic from validate.ts to enable consistent
|
|
6
|
+
* lock management across commands (validate, pre-commit, etc.).
|
|
7
|
+
*/
|
|
8
|
+
import type { VibeValidateConfig } from '@vibe-validate/config';
|
|
9
|
+
import type { AgentContext } from './context-detector.js';
|
|
10
|
+
/**
|
|
11
|
+
* Options for validation lock wrapper
|
|
12
|
+
*/
|
|
13
|
+
export interface ValidationLockOptions {
|
|
14
|
+
/** Whether locking is enabled (CLI flag override) */
|
|
15
|
+
lockEnabled?: boolean;
|
|
16
|
+
/** Whether to wait for existing locks */
|
|
17
|
+
waitEnabled?: boolean;
|
|
18
|
+
/** Maximum time to wait for lock (seconds) */
|
|
19
|
+
waitTimeout?: number;
|
|
20
|
+
/** Whether in YAML output mode (suppresses display output) */
|
|
21
|
+
yaml?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Context passed to callback
|
|
25
|
+
*/
|
|
26
|
+
export interface ValidationLockContext {
|
|
27
|
+
/** Loaded configuration */
|
|
28
|
+
config: VibeValidateConfig;
|
|
29
|
+
/** Directory where config was found */
|
|
30
|
+
configDir: string;
|
|
31
|
+
/** Agent context (Claude Code, CI, etc.) */
|
|
32
|
+
context: AgentContext;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Execute a callback with validation lock management
|
|
36
|
+
*
|
|
37
|
+
* This function handles the complete locking workflow:
|
|
38
|
+
* 1. Load configuration with directory detection
|
|
39
|
+
* 2. Detect agent context
|
|
40
|
+
* 3. Determine lock options from config
|
|
41
|
+
* 4. Wait for existing locks (if enabled)
|
|
42
|
+
* 5. Acquire lock (if enabled)
|
|
43
|
+
* 6. Execute callback with context
|
|
44
|
+
* 7. Release lock in finally block
|
|
45
|
+
*
|
|
46
|
+
* @param options - Lock options
|
|
47
|
+
* @param callback - Function to execute with lock held
|
|
48
|
+
* @returns Result from callback
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* await withValidationLock(
|
|
53
|
+
* { lockEnabled: true, waitEnabled: true },
|
|
54
|
+
* async ({ config, configDir, context }) => {
|
|
55
|
+
* // Run validation workflow
|
|
56
|
+
* return runValidateWorkflow(config, options);
|
|
57
|
+
* }
|
|
58
|
+
* );
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function withValidationLock<T>(options: ValidationLockOptions, callback: (_ctx: ValidationLockContext) => Promise<T>): Promise<T>;
|
|
62
|
+
//# sourceMappingURL=validation-lock-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-lock-wrapper.d.ts","sourceRoot":"","sources":["../../src/utils/validation-lock-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAMhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAU1D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,2BAA2B;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,OAAO,EAAE,YAAY,CAAC;CACvB;AAoDD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,OAAO,CAAC,CAAC,CAAC,GACpD,OAAO,CAAC,CAAC,CAAC,CAuHZ"}
|