@vibe-validate/cli 0.12.1 → 0.13.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/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +115 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/services/ci-provider.d.ts +0 -3
- package/dist/services/ci-provider.d.ts.map +1 -1
- package/dist/utils/pid-lock.d.ts +98 -0
- package/dist/utils/pid-lock.d.ts.map +1 -0
- package/dist/utils/pid-lock.js +198 -0
- package/dist/utils/pid-lock.js.map +1 -0
- package/dist/utils/project-id.d.ts +40 -0
- package/dist/utils/project-id.d.ts.map +1 -0
- package/dist/utils/project-id.js +110 -0
- package/dist/utils/project-id.js.map +1 -0
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkLtD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAiK9C"}
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
import { loadConfig } from '../utils/config-loader.js';
|
|
7
7
|
import { detectContext } from '../utils/context-detector.js';
|
|
8
8
|
import { runValidateWorkflow } from '../utils/validate-workflow.js';
|
|
9
|
+
import { acquireLock, releaseLock, checkLock, waitForLock } from '../utils/pid-lock.js';
|
|
10
|
+
import { detectProjectId } from '../utils/project-id.js';
|
|
11
|
+
import { getGitTreeHash } from '@vibe-validate/git';
|
|
9
12
|
import chalk from 'chalk';
|
|
10
13
|
export function validateCommand(program) {
|
|
11
14
|
program
|
|
@@ -15,9 +18,26 @@ export function validateCommand(program) {
|
|
|
15
18
|
.option('-v, --verbose', 'Show detailed progress and output')
|
|
16
19
|
.option('-y, --yaml', 'Output validation result as YAML to stdout')
|
|
17
20
|
.option('-c, --check', 'Check if validation has already passed (do not run)')
|
|
21
|
+
.option('--no-lock', 'Allow concurrent validation runs (disables single-instance mode)')
|
|
22
|
+
.option('--no-wait', 'Exit immediately if validation is already running (for background hooks)')
|
|
23
|
+
.option('--wait-timeout <seconds>', 'Maximum time to wait for running validation (default: 300)', '300')
|
|
18
24
|
.action(async (options) => {
|
|
25
|
+
let lockFile = null;
|
|
19
26
|
try {
|
|
20
|
-
//
|
|
27
|
+
// Normalize conflicting options
|
|
28
|
+
// When using --check (just checking state, not running validation):
|
|
29
|
+
// - lock is meaningless (no validation process to lock)
|
|
30
|
+
// - force is meaningless (no validation to force)
|
|
31
|
+
if (options.check) {
|
|
32
|
+
options.lock = false;
|
|
33
|
+
options.force = false;
|
|
34
|
+
}
|
|
35
|
+
// Default behavior: lock is enabled (single-instance mode)
|
|
36
|
+
// Users can opt out with --no-lock for concurrent runs
|
|
37
|
+
if (options.lock === undefined) {
|
|
38
|
+
options.lock = true;
|
|
39
|
+
}
|
|
40
|
+
// Load configuration first (needed for lock config)
|
|
21
41
|
const config = await loadConfig();
|
|
22
42
|
if (!config) {
|
|
23
43
|
console.error(chalk.red('❌ No configuration found'));
|
|
@@ -25,6 +45,94 @@ export function validateCommand(program) {
|
|
|
25
45
|
}
|
|
26
46
|
// Detect context (Claude Code, CI, etc.)
|
|
27
47
|
const context = detectContext();
|
|
48
|
+
// Determine lock options from config
|
|
49
|
+
const lockConfig = config.locking ?? { enabled: true, concurrencyScope: 'directory' };
|
|
50
|
+
// If config disables locking, override CLI flag
|
|
51
|
+
if (!lockConfig.enabled) {
|
|
52
|
+
options.lock = false;
|
|
53
|
+
}
|
|
54
|
+
let lockOptions = {};
|
|
55
|
+
if (lockConfig.concurrencyScope === 'project') {
|
|
56
|
+
// Project-scoped locking - need projectId
|
|
57
|
+
const projectId = lockConfig.projectId ?? detectProjectId();
|
|
58
|
+
if (!projectId) {
|
|
59
|
+
console.error(chalk.red('❌ ERROR: concurrencyScope=project but projectId cannot be detected'));
|
|
60
|
+
console.error(chalk.yellow('Solutions:'));
|
|
61
|
+
console.error(' 1. Add locking.projectId to vibe-validate.config.yaml');
|
|
62
|
+
console.error(' 2. Ensure git remote is configured');
|
|
63
|
+
console.error(' 3. Ensure package.json has name field');
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
lockOptions = { scope: 'project', projectId };
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Directory-scoped locking (default)
|
|
70
|
+
lockOptions = { scope: 'directory' };
|
|
71
|
+
}
|
|
72
|
+
// Default behavior: wait is enabled (wait for running validation)
|
|
73
|
+
// Users can opt out with --no-wait for background hooks
|
|
74
|
+
const shouldWait = options.wait !== false;
|
|
75
|
+
// Handle wait mode (default: wait for running validation to complete)
|
|
76
|
+
if (shouldWait) {
|
|
77
|
+
const cwd = process.cwd();
|
|
78
|
+
const existingLock = await checkLock(cwd, lockOptions);
|
|
79
|
+
if (existingLock) {
|
|
80
|
+
const waitTimeout = parseInt(options.waitTimeout, 10) || 300;
|
|
81
|
+
if (!options.yaml) {
|
|
82
|
+
console.log(chalk.yellow('⏳ Waiting for running validation to complete...'));
|
|
83
|
+
console.log(` PID: ${existingLock.pid}`);
|
|
84
|
+
console.log(` Started: ${new Date(existingLock.startTime).toLocaleTimeString()}`);
|
|
85
|
+
console.log(` Timeout: ${waitTimeout}s`);
|
|
86
|
+
}
|
|
87
|
+
const waitResult = await waitForLock(cwd, waitTimeout, 1000, lockOptions);
|
|
88
|
+
if (waitResult.timedOut) {
|
|
89
|
+
if (!options.yaml) {
|
|
90
|
+
console.log(chalk.yellow('⏱️ Wait timed out, proceeding with validation'));
|
|
91
|
+
}
|
|
92
|
+
// Continue with normal validation flow
|
|
93
|
+
}
|
|
94
|
+
else if (!options.yaml) {
|
|
95
|
+
console.log(chalk.green('✓ Background validation completed'));
|
|
96
|
+
// Continue to check cache/run validation
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// If no lock exists, proceed normally
|
|
100
|
+
}
|
|
101
|
+
// Handle lock mode (single-instance execution)
|
|
102
|
+
if (options.lock) {
|
|
103
|
+
const cwd = process.cwd();
|
|
104
|
+
const treeHash = await getGitTreeHash();
|
|
105
|
+
const lockResult = await acquireLock(cwd, treeHash, lockOptions);
|
|
106
|
+
if (!lockResult.acquired && lockResult.existingLock) {
|
|
107
|
+
// Another validation is already running
|
|
108
|
+
// If --no-wait specified, exit immediately (for background hooks)
|
|
109
|
+
if (!shouldWait) {
|
|
110
|
+
const existing = lockResult.existingLock;
|
|
111
|
+
const isCurrentHash = existing.treeHash === treeHash;
|
|
112
|
+
const hashStatus = isCurrentHash
|
|
113
|
+
? 'same as current'
|
|
114
|
+
: `stale - current is ${treeHash.substring(0, 7)}`;
|
|
115
|
+
const elapsed = Math.floor((Date.now() - new Date(existing.startTime).getTime()) / 1000);
|
|
116
|
+
const elapsedStr = elapsed < 60
|
|
117
|
+
? `${elapsed} seconds ago`
|
|
118
|
+
: `${Math.floor(elapsed / 60)} minutes ago`;
|
|
119
|
+
if (!options.yaml) {
|
|
120
|
+
console.log(chalk.yellow('⚠️ Validation already running'));
|
|
121
|
+
console.log(` Directory: ${existing.directory}`);
|
|
122
|
+
console.log(` Tree Hash: ${existing.treeHash.substring(0, 7)} (${hashStatus})`);
|
|
123
|
+
console.log(` PID: ${existing.pid}`);
|
|
124
|
+
console.log(` Started: ${elapsedStr}`);
|
|
125
|
+
}
|
|
126
|
+
process.exit(0); // Exit 0 to not trigger errors in hooks
|
|
127
|
+
}
|
|
128
|
+
// If wait is enabled (default), the wait logic above already handled it
|
|
129
|
+
// Just don't try to acquire lock again
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// Lock acquired successfully
|
|
133
|
+
lockFile = lockResult.lockFile;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
28
136
|
// Run shared validation workflow
|
|
29
137
|
const result = await runValidateWorkflow(config, {
|
|
30
138
|
force: options.force,
|
|
@@ -49,6 +157,12 @@ export function validateCommand(program) {
|
|
|
49
157
|
// Error already logged by runValidateWorkflow
|
|
50
158
|
process.exit(1);
|
|
51
159
|
}
|
|
160
|
+
finally {
|
|
161
|
+
// Always release lock when done
|
|
162
|
+
if (lockFile) {
|
|
163
|
+
await releaseLock(lockFile);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
52
166
|
});
|
|
53
167
|
}
|
|
54
168
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,aAAa,EAAE,yCAAyC,CAAC;SAChE,MAAM,CAAC,eAAe,EAAE,mCAAmC,CAAC;SAC5D,MAAM,CAAC,YAAY,EAAE,4CAA4C,CAAC;SAClE,MAAM,CAAC,aAAa,EAAE,qDAAqD,CAAC;SAC5E,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAoB,MAAM,sBAAsB,CAAC;AAC1G,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,aAAa,EAAE,yCAAyC,CAAC;SAChE,MAAM,CAAC,eAAe,EAAE,mCAAmC,CAAC;SAC5D,MAAM,CAAC,YAAY,EAAE,4CAA4C,CAAC;SAClE,MAAM,CAAC,aAAa,EAAE,qDAAqD,CAAC;SAC5E,MAAM,CAAC,WAAW,EAAE,kEAAkE,CAAC;SACvF,MAAM,CAAC,WAAW,EAAE,0EAA0E,CAAC;SAC/F,MAAM,CAAC,0BAA0B,EAAE,4DAA4D,EAAE,KAAK,CAAC;SACvG,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,QAAQ,GAAkB,IAAI,CAAC;QACnC,IAAI,CAAC;YACH,gCAAgC;YAChC,oEAAoE;YACpE,wDAAwD;YACxD,kDAAkD;YAClD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC;gBACrB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;YACxB,CAAC;YAED,2DAA2D;YAC3D,uDAAuD;YACvD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC/B,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACtB,CAAC;YAED,oDAAoD;YACpD,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;YAClC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,CAAC;gBACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,yCAAyC;YACzC,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;YAEhC,qCAAqC;YACrC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC;YAEtF,gDAAgD;YAChD,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC;YACvB,CAAC;YAED,IAAI,WAAW,GAAgB,EAAE,CAAC;YAClC,IAAI,UAAU,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBAC9C,0CAA0C;gBAC1C,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,IAAI,eAAe,EAAE,CAAC;gBAC5D,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC,CAAC;oBAC/F,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;oBAC1C,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;oBACzE,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;oBACtD,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;oBACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;gBACD,WAAW,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,qCAAqC;gBACrC,WAAW,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;YACvC,CAAC;YAED,kEAAkE;YAClE,wDAAwD;YACxD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,KAAK,KAAK,CAAC;YAE1C,sEAAsE;YACtE,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;gBAC1B,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;gBAEvD,IAAI,YAAY,EAAE,CAAC;oBACjB,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;oBAE7D,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;wBAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,iDAAiD,CAAC,CAAC,CAAC;wBAC7E,OAAO,CAAC,GAAG,CAAC,UAAU,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC;wBAC1C,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;wBACnF,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW,GAAG,CAAC,CAAC;oBAC5C,CAAC;oBAED,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;oBAE1E,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;wBACxB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;4BAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,gDAAgD,CAAC,CAAC,CAAC;wBAC9E,CAAC;wBACD,uCAAuC;oBACzC,CAAC;yBAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;wBACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;wBAC9D,yCAAyC;oBAC3C,CAAC;gBACH,CAAC;gBACD,sCAAsC;YACxC,CAAC;YAED,+CAA+C;YAC/C,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;gBACjB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,cAAc,EAAE,CAAC;gBAExC,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;gBAEjE,IAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,UAAU,CAAC,YAAY,EAAE,CAAC;oBACpD,wCAAwC;oBAExC,kEAAkE;oBAClE,IAAI,CAAC,UAAU,EAAE,CAAC;wBAChB,MAAM,QAAQ,GAAG,UAAU,CAAC,YAAY,CAAC;wBACzC,MAAM,aAAa,GAAG,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC;wBACrD,MAAM,UAAU,GAAG,aAAa;4BAC9B,CAAC,CAAC,iBAAiB;4BACnB,CAAC,CAAC,sBAAsB,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;wBAErD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACxB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAC7D,CAAC;wBACF,MAAM,UAAU,GACd,OAAO,GAAG,EAAE;4BACV,CAAC,CAAC,GAAG,OAAO,cAAc;4BAC1B,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,cAAc,CAAC;wBAEhD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;4BAClB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAC/C,CAAC;4BACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;4BAClD,OAAO,CAAC,GAAG,CACT,gBAAgB,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,UAAU,GAAG,CACpE,CAAC;4BACF,OAAO,CAAC,GAAG,CAAC,UAAU,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;4BACtC,OAAO,CAAC,GAAG,CAAC,cAAc,UAAU,EAAE,CAAC,CAAC;wBAC1C,CAAC;wBAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,wCAAwC;oBAC3D,CAAC;oBAED,wEAAwE;oBACxE,uCAAuC;gBACzC,CAAC;qBAAM,CAAC;oBACN,6BAA6B;oBAC7B,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;gBACjC,CAAC;YACH,CAAC;YAED,iCAAiC;YACjC,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE;gBAC/C,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,OAAO;aACR,CAAC,CAAC;YAEH,gDAAgD;YAChD,4EAA4E;YAC5E,MAAM,eAAe,GAAG,MAAqD,CAAC;YAC9E,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC;YACD,qEAAqE;QACvE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,6CAA6C;YAC7C,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBACvE,MAAM,KAAK,CAAC;YACd,CAAC;YACD,8CAA8C;YAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;gBAAS,CAAC;YACT,gCAAgC;YAChC,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Jb,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -52,9 +52,6 @@ export interface CheckStatus {
|
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Validation result extracted from CI logs
|
|
55
|
-
*
|
|
56
|
-
* Note: This is NOT about the deprecated .vibe-validate-state.yaml file.
|
|
57
|
-
* This represents the validation result that's displayed in CI logs.
|
|
58
55
|
*/
|
|
59
56
|
export interface ValidationResultContents {
|
|
60
57
|
/** Whether validation passed */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-provider.d.ts","sourceRoot":"","sources":["../../src/services/ci-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,MAAM,EAAE,QAAQ,GAAG,aAAa,GAAG,WAAW,CAAC;IAC/C,2CAA2C;IAC3C,UAAU,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;IAC/E,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,uBAAuB;IACvB,EAAE,EAAE,WAAW,CAAC;IAChB,uCAAuC;IACvC,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,kEAAkE;IAClE,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IACxD,+BAA+B;IAC/B,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED
|
|
1
|
+
{"version":3,"file":"ci-provider.d.ts","sourceRoot":"","sources":["../../src/services/ci-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PID-based locking for single-instance validation execution
|
|
3
|
+
*
|
|
4
|
+
* Prevents concurrent validation runs using PID file mechanism.
|
|
5
|
+
* Cross-platform (Node.js), works on Windows, macOS, Linux.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Lock file information
|
|
9
|
+
*/
|
|
10
|
+
export interface LockInfo {
|
|
11
|
+
/** Process ID holding the lock */
|
|
12
|
+
pid: number;
|
|
13
|
+
/** Project directory path */
|
|
14
|
+
directory: string;
|
|
15
|
+
/** Git tree hash at time of lock acquisition */
|
|
16
|
+
treeHash: string;
|
|
17
|
+
/** ISO timestamp when lock was acquired */
|
|
18
|
+
startTime: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of lock acquisition attempt
|
|
22
|
+
*/
|
|
23
|
+
export interface LockResult {
|
|
24
|
+
/** Whether lock was successfully acquired */
|
|
25
|
+
acquired: boolean;
|
|
26
|
+
/** Path to lock file */
|
|
27
|
+
lockFile: string;
|
|
28
|
+
/** Information about existing lock (if acquisition failed) */
|
|
29
|
+
existingLock?: LockInfo;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Lock scope options
|
|
33
|
+
*/
|
|
34
|
+
export interface LockOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Concurrency scope for lock files
|
|
37
|
+
* - 'directory': Each working directory has its own lock (default, allows parallel worktrees)
|
|
38
|
+
* - 'project': All directories for the same project share a lock (prevents port/DB conflicts)
|
|
39
|
+
*/
|
|
40
|
+
scope?: 'directory' | 'project';
|
|
41
|
+
/**
|
|
42
|
+
* Project identifier for project-scoped locking
|
|
43
|
+
* Used when scope='project' to generate lock filename
|
|
44
|
+
*/
|
|
45
|
+
projectId?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Acquire validation lock
|
|
49
|
+
*
|
|
50
|
+
* Attempts to create a lock file for single-instance execution.
|
|
51
|
+
* If a lock already exists, checks if the process is still running.
|
|
52
|
+
* Stale locks (dead processes) are automatically cleaned up.
|
|
53
|
+
*
|
|
54
|
+
* @param directory - Project directory to lock
|
|
55
|
+
* @param treeHash - Current git tree hash
|
|
56
|
+
* @param options - Lock scope options
|
|
57
|
+
* @returns Lock acquisition result
|
|
58
|
+
*/
|
|
59
|
+
export declare function acquireLock(directory: string, treeHash: string, options?: LockOptions): Promise<LockResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Release validation lock
|
|
62
|
+
*
|
|
63
|
+
* Removes the lock file to allow other processes to run.
|
|
64
|
+
* Safe to call even if lock file doesn't exist.
|
|
65
|
+
*
|
|
66
|
+
* @param lockFile - Path to lock file to release
|
|
67
|
+
*/
|
|
68
|
+
export declare function releaseLock(lockFile: string): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Check current lock status
|
|
71
|
+
*
|
|
72
|
+
* Returns information about existing lock, or null if no lock exists.
|
|
73
|
+
* Automatically cleans up stale locks.
|
|
74
|
+
*
|
|
75
|
+
* @param directory - Project directory to check
|
|
76
|
+
* @param options - Lock scope options
|
|
77
|
+
* @returns Lock information or null
|
|
78
|
+
*/
|
|
79
|
+
export declare function checkLock(directory: string, options?: LockOptions): Promise<LockInfo | null>;
|
|
80
|
+
/**
|
|
81
|
+
* Wait for lock to be released
|
|
82
|
+
*
|
|
83
|
+
* Polls the lock file until it's released or timeout is reached.
|
|
84
|
+
* Useful for pre-commit hooks that want to wait for background
|
|
85
|
+
* validation to complete before proceeding.
|
|
86
|
+
*
|
|
87
|
+
* @param directory - Project directory to check
|
|
88
|
+
* @param timeoutSeconds - Maximum time to wait (default: 300 seconds / 5 minutes)
|
|
89
|
+
* @param pollIntervalMs - How often to check lock status (default: 1000ms)
|
|
90
|
+
* @param options - Lock scope options
|
|
91
|
+
* @returns Lock info when released, or null if timeout
|
|
92
|
+
*/
|
|
93
|
+
export declare function waitForLock(directory: string, timeoutSeconds?: number, pollIntervalMs?: number, options?: LockOptions): Promise<{
|
|
94
|
+
released: boolean;
|
|
95
|
+
timedOut: boolean;
|
|
96
|
+
finalLock: LockInfo | null;
|
|
97
|
+
}>;
|
|
98
|
+
//# sourceMappingURL=pid-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pid-lock.d.ts","sourceRoot":"","sources":["../../src/utils/pid-lock.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,QAAQ,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8DD;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAyCrB;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjE;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAuBtG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,cAAc,GAAE,MAAY,EAC5B,cAAc,GAAE,MAAa,EAC7B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,QAAQ,GAAG,IAAI,CAAA;CAAE,CAAC,CA6B/E"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PID-based locking for single-instance validation execution
|
|
3
|
+
*
|
|
4
|
+
* Prevents concurrent validation runs using PID file mechanism.
|
|
5
|
+
* Cross-platform (Node.js), works on Windows, macOS, Linux.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'fs';
|
|
8
|
+
import { tmpdir } from 'os';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
/**
|
|
11
|
+
* Encode directory path for use in lock file name
|
|
12
|
+
*
|
|
13
|
+
* Replaces path separators and special characters to create
|
|
14
|
+
* a human-readable lock file name.
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* - /Users/jeff/project → _Users_jeff_project.lock
|
|
18
|
+
* - C:\Users\jeff\project → C-_Users_jeff_project.lock
|
|
19
|
+
*
|
|
20
|
+
* @param directory - Project directory path
|
|
21
|
+
* @returns Encoded path suitable for filename
|
|
22
|
+
*/
|
|
23
|
+
function encodeDirectoryPath(directory) {
|
|
24
|
+
return directory
|
|
25
|
+
.replace(/^([A-Za-z]):/, '$1-') // Windows drive letter (C: → C-)
|
|
26
|
+
.replace(/\\/g, '_') // Windows backslashes
|
|
27
|
+
.replace(/\//g, '_'); // Unix forward slashes
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get lock file path based on scope
|
|
31
|
+
*
|
|
32
|
+
* @param directory - Project directory
|
|
33
|
+
* @param options - Lock scope options
|
|
34
|
+
* @returns Lock file path
|
|
35
|
+
*/
|
|
36
|
+
function getLockFilePath(directory, options = {}) {
|
|
37
|
+
const scope = options.scope ?? 'directory';
|
|
38
|
+
if (scope === 'project') {
|
|
39
|
+
if (!options.projectId) {
|
|
40
|
+
throw new Error('projectId is required when scope is "project"');
|
|
41
|
+
}
|
|
42
|
+
// Project-scoped: /tmp/vibe-validate-project-{projectId}.lock
|
|
43
|
+
return join(tmpdir(), `vibe-validate-project-${options.projectId}.lock`);
|
|
44
|
+
}
|
|
45
|
+
// Directory-scoped (default): /tmp/vibe-validate-{encoded-dir}.lock
|
|
46
|
+
const encoded = encodeDirectoryPath(directory);
|
|
47
|
+
return join(tmpdir(), `vibe-validate-${encoded}.lock`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if a process is running
|
|
51
|
+
*
|
|
52
|
+
* Cross-platform process check using Node.js process.kill(pid, 0)
|
|
53
|
+
* which doesn't actually kill the process, just tests if it exists.
|
|
54
|
+
*/
|
|
55
|
+
function isProcessRunning(pid) {
|
|
56
|
+
try {
|
|
57
|
+
// Signal 0 tests for process existence without killing it
|
|
58
|
+
process.kill(pid, 0);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch (_err) {
|
|
62
|
+
// ESRCH = no such process
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Acquire validation lock
|
|
68
|
+
*
|
|
69
|
+
* Attempts to create a lock file for single-instance execution.
|
|
70
|
+
* If a lock already exists, checks if the process is still running.
|
|
71
|
+
* Stale locks (dead processes) are automatically cleaned up.
|
|
72
|
+
*
|
|
73
|
+
* @param directory - Project directory to lock
|
|
74
|
+
* @param treeHash - Current git tree hash
|
|
75
|
+
* @param options - Lock scope options
|
|
76
|
+
* @returns Lock acquisition result
|
|
77
|
+
*/
|
|
78
|
+
export async function acquireLock(directory, treeHash, options = {}) {
|
|
79
|
+
const lockFile = getLockFilePath(directory, options);
|
|
80
|
+
// Check for existing lock
|
|
81
|
+
if (existsSync(lockFile)) {
|
|
82
|
+
try {
|
|
83
|
+
const lockData = JSON.parse(readFileSync(lockFile, 'utf-8'));
|
|
84
|
+
// Verify process is actually running
|
|
85
|
+
if (isProcessRunning(lockData.pid)) {
|
|
86
|
+
// Lock is valid - another process is running
|
|
87
|
+
return {
|
|
88
|
+
acquired: false,
|
|
89
|
+
lockFile,
|
|
90
|
+
existingLock: lockData,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// Stale lock - process no longer exists
|
|
94
|
+
// Clean it up and proceed
|
|
95
|
+
unlinkSync(lockFile);
|
|
96
|
+
}
|
|
97
|
+
catch (_err) {
|
|
98
|
+
// Corrupted lock file - remove and proceed
|
|
99
|
+
unlinkSync(lockFile);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Acquire lock
|
|
103
|
+
const lockInfo = {
|
|
104
|
+
pid: process.pid,
|
|
105
|
+
directory,
|
|
106
|
+
treeHash,
|
|
107
|
+
startTime: new Date().toISOString(),
|
|
108
|
+
};
|
|
109
|
+
writeFileSync(lockFile, JSON.stringify(lockInfo, null, 2));
|
|
110
|
+
return {
|
|
111
|
+
acquired: true,
|
|
112
|
+
lockFile,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Release validation lock
|
|
117
|
+
*
|
|
118
|
+
* Removes the lock file to allow other processes to run.
|
|
119
|
+
* Safe to call even if lock file doesn't exist.
|
|
120
|
+
*
|
|
121
|
+
* @param lockFile - Path to lock file to release
|
|
122
|
+
*/
|
|
123
|
+
export async function releaseLock(lockFile) {
|
|
124
|
+
if (existsSync(lockFile)) {
|
|
125
|
+
unlinkSync(lockFile);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check current lock status
|
|
130
|
+
*
|
|
131
|
+
* Returns information about existing lock, or null if no lock exists.
|
|
132
|
+
* Automatically cleans up stale locks.
|
|
133
|
+
*
|
|
134
|
+
* @param directory - Project directory to check
|
|
135
|
+
* @param options - Lock scope options
|
|
136
|
+
* @returns Lock information or null
|
|
137
|
+
*/
|
|
138
|
+
export async function checkLock(directory, options = {}) {
|
|
139
|
+
const lockFile = getLockFilePath(directory, options);
|
|
140
|
+
if (!existsSync(lockFile)) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
const lockData = JSON.parse(readFileSync(lockFile, 'utf-8'));
|
|
145
|
+
// Verify process is still running
|
|
146
|
+
if (isProcessRunning(lockData.pid)) {
|
|
147
|
+
return lockData;
|
|
148
|
+
}
|
|
149
|
+
// Stale lock - clean up
|
|
150
|
+
unlinkSync(lockFile);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
catch (_err) {
|
|
154
|
+
// Corrupted lock file - clean up
|
|
155
|
+
unlinkSync(lockFile);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Wait for lock to be released
|
|
161
|
+
*
|
|
162
|
+
* Polls the lock file until it's released or timeout is reached.
|
|
163
|
+
* Useful for pre-commit hooks that want to wait for background
|
|
164
|
+
* validation to complete before proceeding.
|
|
165
|
+
*
|
|
166
|
+
* @param directory - Project directory to check
|
|
167
|
+
* @param timeoutSeconds - Maximum time to wait (default: 300 seconds / 5 minutes)
|
|
168
|
+
* @param pollIntervalMs - How often to check lock status (default: 1000ms)
|
|
169
|
+
* @param options - Lock scope options
|
|
170
|
+
* @returns Lock info when released, or null if timeout
|
|
171
|
+
*/
|
|
172
|
+
export async function waitForLock(directory, timeoutSeconds = 300, pollIntervalMs = 1000, options = {}) {
|
|
173
|
+
const startTime = Date.now();
|
|
174
|
+
const timeoutMs = timeoutSeconds * 1000;
|
|
175
|
+
while (true) {
|
|
176
|
+
const lock = await checkLock(directory, options);
|
|
177
|
+
// Lock released (or never existed)
|
|
178
|
+
if (!lock) {
|
|
179
|
+
return {
|
|
180
|
+
released: true,
|
|
181
|
+
timedOut: false,
|
|
182
|
+
finalLock: null,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// Check timeout
|
|
186
|
+
const elapsed = Date.now() - startTime;
|
|
187
|
+
if (elapsed >= timeoutMs) {
|
|
188
|
+
return {
|
|
189
|
+
released: false,
|
|
190
|
+
timedOut: true,
|
|
191
|
+
finalLock: lock,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
// Wait before next poll
|
|
195
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=pid-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pid-lock.js","sourceRoot":"","sources":["../../src/utils/pid-lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project ID Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects a unique project identifier for lock scoping.
|
|
5
|
+
* Used when locking.concurrencyScope=project to ensure
|
|
6
|
+
* multiple directories (worktrees, clones) share the same lock.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Get project ID from git remote
|
|
10
|
+
*
|
|
11
|
+
* Tries to extract project name from git remote URL.
|
|
12
|
+
* Works for GitHub, GitLab, Bitbucket, and other git hosts.
|
|
13
|
+
*
|
|
14
|
+
* @param cwd - Directory to check (defaults to process.cwd())
|
|
15
|
+
* @returns Project ID or null
|
|
16
|
+
*/
|
|
17
|
+
export declare function getProjectIdFromGit(cwd?: string): string | null;
|
|
18
|
+
/**
|
|
19
|
+
* Get project ID from package.json
|
|
20
|
+
*
|
|
21
|
+
* Extracts the "name" field from package.json.
|
|
22
|
+
* Removes scope prefix (e.g., @scope/package → package).
|
|
23
|
+
*
|
|
24
|
+
* @param cwd - Directory to check (defaults to process.cwd())
|
|
25
|
+
* @returns Project ID or null
|
|
26
|
+
*/
|
|
27
|
+
export declare function getProjectIdFromPackageJson(cwd?: string): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Detect project ID with fallback chain
|
|
30
|
+
*
|
|
31
|
+
* Detection priority:
|
|
32
|
+
* 1. Git remote URL (e.g., github.com/user/repo → repo)
|
|
33
|
+
* 2. package.json name field (removes scope prefix)
|
|
34
|
+
* 3. null (no detection possible)
|
|
35
|
+
*
|
|
36
|
+
* @param cwd - Directory to check (defaults to process.cwd())
|
|
37
|
+
* @returns Detected project ID or null
|
|
38
|
+
*/
|
|
39
|
+
export declare function detectProjectId(cwd?: string): string | null;
|
|
40
|
+
//# sourceMappingURL=project-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-id.d.ts","sourceRoot":"","sources":["../../src/utils/project-id.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA6BH;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAkB9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAoBtF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAe1E"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project ID Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects a unique project identifier for lock scoping.
|
|
5
|
+
* Used when locking.concurrencyScope=project to ensure
|
|
6
|
+
* multiple directories (worktrees, clones) share the same lock.
|
|
7
|
+
*/
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
import { readFileSync, existsSync } from 'fs';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
/**
|
|
12
|
+
* Extract project name from git remote URL
|
|
13
|
+
*
|
|
14
|
+
* Supports common formats:
|
|
15
|
+
* - https://github.com/user/repo.git → repo
|
|
16
|
+
* - git@github.com:user/repo.git → repo
|
|
17
|
+
* - https://github.com/user/repo → repo
|
|
18
|
+
*
|
|
19
|
+
* @param remoteUrl - Git remote URL
|
|
20
|
+
* @returns Project name or null
|
|
21
|
+
*/
|
|
22
|
+
function extractProjectFromGitUrl(remoteUrl) {
|
|
23
|
+
// Remove .git suffix if present
|
|
24
|
+
const cleaned = remoteUrl.replace(/\.git$/, '');
|
|
25
|
+
// Extract repo name from various formats
|
|
26
|
+
// HTTPS: https://github.com/user/repo
|
|
27
|
+
// SSH: git@github.com:user/repo
|
|
28
|
+
const match = cleaned.match(/[/:]([^/]+)$/);
|
|
29
|
+
return match ? match[1] : null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get project ID from git remote
|
|
33
|
+
*
|
|
34
|
+
* Tries to extract project name from git remote URL.
|
|
35
|
+
* Works for GitHub, GitLab, Bitbucket, and other git hosts.
|
|
36
|
+
*
|
|
37
|
+
* @param cwd - Directory to check (defaults to process.cwd())
|
|
38
|
+
* @returns Project ID or null
|
|
39
|
+
*/
|
|
40
|
+
export function getProjectIdFromGit(cwd = process.cwd()) {
|
|
41
|
+
try {
|
|
42
|
+
// Get remote URL for origin
|
|
43
|
+
const remoteUrl = execSync('git config --get remote.origin.url', {
|
|
44
|
+
cwd,
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
47
|
+
}).trim();
|
|
48
|
+
if (!remoteUrl) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return extractProjectFromGitUrl(remoteUrl);
|
|
52
|
+
}
|
|
53
|
+
catch (_err) {
|
|
54
|
+
// Not a git repo or no remote configured
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get project ID from package.json
|
|
60
|
+
*
|
|
61
|
+
* Extracts the "name" field from package.json.
|
|
62
|
+
* Removes scope prefix (e.g., @scope/package → package).
|
|
63
|
+
*
|
|
64
|
+
* @param cwd - Directory to check (defaults to process.cwd())
|
|
65
|
+
* @returns Project ID or null
|
|
66
|
+
*/
|
|
67
|
+
export function getProjectIdFromPackageJson(cwd = process.cwd()) {
|
|
68
|
+
try {
|
|
69
|
+
const packageJsonPath = join(cwd, 'package.json');
|
|
70
|
+
if (!existsSync(packageJsonPath)) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
74
|
+
const name = packageJson.name;
|
|
75
|
+
if (!name || typeof name !== 'string') {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
// Remove scope prefix (@scope/package → package)
|
|
79
|
+
return name.replace(/^@[^/]+\//, '');
|
|
80
|
+
}
|
|
81
|
+
catch (_err) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Detect project ID with fallback chain
|
|
87
|
+
*
|
|
88
|
+
* Detection priority:
|
|
89
|
+
* 1. Git remote URL (e.g., github.com/user/repo → repo)
|
|
90
|
+
* 2. package.json name field (removes scope prefix)
|
|
91
|
+
* 3. null (no detection possible)
|
|
92
|
+
*
|
|
93
|
+
* @param cwd - Directory to check (defaults to process.cwd())
|
|
94
|
+
* @returns Detected project ID or null
|
|
95
|
+
*/
|
|
96
|
+
export function detectProjectId(cwd = process.cwd()) {
|
|
97
|
+
// Try git remote first (most reliable for worktrees/clones)
|
|
98
|
+
const gitProject = getProjectIdFromGit(cwd);
|
|
99
|
+
if (gitProject) {
|
|
100
|
+
return gitProject;
|
|
101
|
+
}
|
|
102
|
+
// Fall back to package.json
|
|
103
|
+
const packageProject = getProjectIdFromPackageJson(cwd);
|
|
104
|
+
if (packageProject) {
|
|
105
|
+
return packageProject;
|
|
106
|
+
}
|
|
107
|
+
// No detection possible
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=project-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-id.js","sourceRoot":"","sources":["../../src/utils/project-id.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B;;;;;;;;;;GAUG;AACH,SAAS,wBAAwB,CAAC,SAAiB;IACjD,gCAAgC;IAChC,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEhD,yCAAyC;IACzC,sCAAsC;IACtC,gCAAgC;IAChC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAE5C,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC7D,IAAI,CAAC;QACH,4BAA4B;QAC5B,MAAM,SAAS,GAAG,QAAQ,CAAC,oCAAoC,EAAE;YAC/D,GAAG;YACH,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEV,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,wBAAwB,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,IAAI,EAAE,CAAC;QACd,yCAAyC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACrE,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAElD,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;QAE9B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,iDAAiD;QACjD,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,IAAI,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACzD,4DAA4D;IAC5D,MAAM,UAAU,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,4BAA4B;IAC5B,MAAM,cAAc,GAAG,2BAA2B,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,wBAAwB;IACxB,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-validate/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Command-line interface for vibe-validate validation framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
"yaml": "^2.6.1",
|
|
60
60
|
"zod": "^3.24.1",
|
|
61
61
|
"zod-to-json-schema": "^3.24.6",
|
|
62
|
-
"@vibe-validate/config": "0.
|
|
63
|
-
"@vibe-validate/
|
|
64
|
-
"@vibe-validate/core": "0.
|
|
65
|
-
"@vibe-validate/
|
|
66
|
-
"@vibe-validate/history": "0.
|
|
62
|
+
"@vibe-validate/config": "0.13.0",
|
|
63
|
+
"@vibe-validate/extractors": "0.13.0",
|
|
64
|
+
"@vibe-validate/core": "0.13.0",
|
|
65
|
+
"@vibe-validate/git": "0.13.0",
|
|
66
|
+
"@vibe-validate/history": "0.13.0"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@types/node": "^20.14.8",
|