@vibe-validate/cli 0.9.11 → 0.10.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/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +151 -38
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +228 -109
- package/dist/commands/init.js.map +1 -1
- package/dist/utils/config-loader.d.ts +3 -7
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +7 -19
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/git-detection.d.ts +41 -0
- package/dist/utils/git-detection.d.ts.map +1 -0
- package/dist/utils/git-detection.js +109 -0
- package/dist/utils/git-detection.js.map +1 -0
- package/dist/utils/runner-adapter.js +3 -3
- package/dist/utils/runner-adapter.js.map +1 -1
- package/dist/utils/setup-checks/gitignore-check.d.ts +23 -0
- package/dist/utils/setup-checks/gitignore-check.d.ts.map +1 -0
- package/dist/utils/setup-checks/gitignore-check.js +156 -0
- package/dist/utils/setup-checks/gitignore-check.js.map +1 -0
- package/dist/utils/setup-checks/hooks-check.d.ts +27 -0
- package/dist/utils/setup-checks/hooks-check.d.ts.map +1 -0
- package/dist/utils/setup-checks/hooks-check.js +175 -0
- package/dist/utils/setup-checks/hooks-check.js.map +1 -0
- package/dist/utils/setup-checks/workflow-check.d.ts +22 -0
- package/dist/utils/setup-checks/workflow-check.d.ts.map +1 -0
- package/dist/utils/setup-checks/workflow-check.js +147 -0
- package/dist/utils/setup-checks/workflow-check.js.map +1 -0
- package/dist/utils/setup-engine.d.ts +155 -0
- package/dist/utils/setup-engine.d.ts.map +1 -0
- package/dist/utils/setup-engine.js +31 -0
- package/dist/utils/setup-engine.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Detection Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared utilities for detecting git configuration (main branch, remote origin).
|
|
5
|
+
* Used by both init and doctor commands.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import { GIT_DEFAULTS } from '@vibe-validate/config';
|
|
9
|
+
/**
|
|
10
|
+
* Detects git configuration from the current repository.
|
|
11
|
+
*
|
|
12
|
+
* This function attempts to auto-detect the main branch and remote origin
|
|
13
|
+
* by inspecting the git repository. It follows this detection strategy:
|
|
14
|
+
*
|
|
15
|
+
* 1. Check if we're in a git repository
|
|
16
|
+
* 2. Detect available remotes (prefer 'upstream' > 'origin' > first available)
|
|
17
|
+
* 3. Try to detect main branch from remote HEAD reference
|
|
18
|
+
* 4. If remote HEAD is not set, check for common branch names (main > master > develop)
|
|
19
|
+
* 5. Fall back to defaults if detection fails
|
|
20
|
+
*
|
|
21
|
+
* @returns {DetectedGitConfig} The detected or default git configuration
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const gitConfig = detectGitConfig();
|
|
26
|
+
* console.log(gitConfig.mainBranch); // 'main'
|
|
27
|
+
* console.log(gitConfig.remoteOrigin); // 'origin'
|
|
28
|
+
* console.log(gitConfig.detected); // true if detected, false if defaults
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function detectGitConfig() {
|
|
32
|
+
const defaults = {
|
|
33
|
+
mainBranch: GIT_DEFAULTS.MAIN_BRANCH,
|
|
34
|
+
remoteOrigin: GIT_DEFAULTS.REMOTE_ORIGIN,
|
|
35
|
+
detected: false,
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
// Check if we're in a git repository
|
|
39
|
+
execSync('git rev-parse --git-dir', { stdio: 'pipe' });
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Not a git repository - use defaults
|
|
43
|
+
return defaults;
|
|
44
|
+
}
|
|
45
|
+
let mainBranch = GIT_DEFAULTS.MAIN_BRANCH;
|
|
46
|
+
let remoteOrigin = GIT_DEFAULTS.REMOTE_ORIGIN;
|
|
47
|
+
let detected = false;
|
|
48
|
+
// Try to detect main branch from remote HEAD
|
|
49
|
+
try {
|
|
50
|
+
// First, get list of remotes
|
|
51
|
+
const remotesOutput = execSync('git remote', { encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
52
|
+
const remotes = remotesOutput.split('\n').filter(Boolean);
|
|
53
|
+
if (remotes.length > 0) {
|
|
54
|
+
// Prefer 'upstream' if it exists (forked repo workflow), otherwise use first remote
|
|
55
|
+
if (remotes.includes('upstream')) {
|
|
56
|
+
remoteOrigin = 'upstream';
|
|
57
|
+
}
|
|
58
|
+
else if (remotes.includes('origin')) {
|
|
59
|
+
remoteOrigin = 'origin';
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
remoteOrigin = remotes[0]; // Use first available remote
|
|
63
|
+
}
|
|
64
|
+
// Try to detect main branch from remote HEAD
|
|
65
|
+
try {
|
|
66
|
+
const headRef = execSync(`git symbolic-ref refs/remotes/${remoteOrigin}/HEAD`, {
|
|
67
|
+
encoding: 'utf8',
|
|
68
|
+
stdio: 'pipe',
|
|
69
|
+
}).trim();
|
|
70
|
+
mainBranch = headRef.replace(`refs/remotes/${remoteOrigin}/`, '');
|
|
71
|
+
detected = true;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Remote HEAD not set, try to detect from common branch names
|
|
75
|
+
try {
|
|
76
|
+
const branches = execSync(`git ls-remote --heads ${remoteOrigin}`, {
|
|
77
|
+
encoding: 'utf8',
|
|
78
|
+
stdio: 'pipe',
|
|
79
|
+
}).trim();
|
|
80
|
+
// Check for common main branch names in order of preference
|
|
81
|
+
if (branches.includes('refs/heads/main')) {
|
|
82
|
+
mainBranch = 'main';
|
|
83
|
+
detected = true;
|
|
84
|
+
}
|
|
85
|
+
else if (branches.includes('refs/heads/master')) {
|
|
86
|
+
mainBranch = 'master';
|
|
87
|
+
detected = true;
|
|
88
|
+
}
|
|
89
|
+
else if (branches.includes('refs/heads/develop')) {
|
|
90
|
+
mainBranch = 'develop';
|
|
91
|
+
detected = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Failed to list remote branches - use defaults
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Failed to detect - use defaults
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
mainBranch,
|
|
105
|
+
remoteOrigin,
|
|
106
|
+
detected,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=git-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-detection.js","sourceRoot":"","sources":["../../src/utils/git-detection.ts"],"names":[],"mappings":"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"}
|
|
@@ -54,10 +54,10 @@ function createVerboseCallbacks() {
|
|
|
54
54
|
},
|
|
55
55
|
onStepComplete: (step, result) => {
|
|
56
56
|
if (result.passed) {
|
|
57
|
-
console.log(chalk.green(` ✅ ${step.name} (${result.
|
|
57
|
+
console.log(chalk.green(` ✅ ${step.name} (${result.durationSecs}s)`));
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
60
|
-
console.log(chalk.red(` ❌ ${step.name} failed (${result.
|
|
60
|
+
console.log(chalk.red(` ❌ ${step.name} failed (${result.durationSecs}s)`));
|
|
61
61
|
if (result.output) {
|
|
62
62
|
console.log(chalk.red(` Error: ${result.output}`));
|
|
63
63
|
}
|
|
@@ -81,7 +81,7 @@ function createMinimalCallbacks() {
|
|
|
81
81
|
console.log(` step_start: ${step.name}`);
|
|
82
82
|
},
|
|
83
83
|
onStepComplete: (step, result) => {
|
|
84
|
-
console.log(` step_complete: ${step.name} (${result.passed ? 'passed' : 'failed'}, ${result.
|
|
84
|
+
console.log(` step_complete: ${step.name} (${result.passed ? 'passed' : 'failed'}, ${result.durationSecs}s)`);
|
|
85
85
|
},
|
|
86
86
|
};
|
|
87
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-adapter.js","sourceRoot":"","sources":["../../src/utils/runner-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAA0B,EAC1B,OAAsB;IAEtB,kFAAkF;IAClF,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED,sCAAsC;IACtC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO;QAC/B,CAAC,CAAC,sBAAsB,EAAE;QAC1B,CAAC,CAAC,sBAAsB,EAAE,CAAC;IAE7B,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,EAAE;QACvC,cAAc,EAAE,IAAI,EAAE,wDAAwD;QAC9E,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,4BAA4B;QACrD,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,mDAAmD;QAC7E,GAAG,EAAE,OAAO;QACZ,aAAa,EAAE,2BAA2B;QAC1C,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB;IAC7B,OAAO;QACL,YAAY,EAAE,CAAC,KAAsB,EAAE,EAAE;YACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,eAAe,EAAE,CAAC,KAAsB,EAAE,MAAmB,EAAE,EAAE;YAC/D,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,KAAK,CAAC,IAAI,yBAAyB,CAAC,CAAC,CAAC;YAC3E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QACD,WAAW,EAAE,CAAC,IAAoB,EAAE,EAAE;YACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,cAAc,EAAE,CAAC,IAAoB,EAAE,MAAkB,EAAE,EAAE;YAC3D,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"runner-adapter.js","sourceRoot":"","sources":["../../src/utils/runner-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gitignore Setup Check
|
|
3
|
+
*
|
|
4
|
+
* Ensures that .vibe-validate-state.yaml is listed in .gitignore
|
|
5
|
+
* to prevent committing validation state files.
|
|
6
|
+
*/
|
|
7
|
+
import type { SetupCheck, CheckResult, FixResult, PreviewResult, FixOptions } from '../setup-engine.js';
|
|
8
|
+
export declare class GitignoreSetupCheck implements SetupCheck {
|
|
9
|
+
readonly id = "gitignore";
|
|
10
|
+
readonly name = "Gitignore Setup";
|
|
11
|
+
check(options?: FixOptions): Promise<CheckResult>;
|
|
12
|
+
preview(options?: FixOptions): Promise<PreviewResult>;
|
|
13
|
+
fix(options?: FixOptions): Promise<FixResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Generate content for a new .gitignore file
|
|
16
|
+
*/
|
|
17
|
+
private generateNewGitignoreContent;
|
|
18
|
+
/**
|
|
19
|
+
* Add state file entry to existing .gitignore content
|
|
20
|
+
*/
|
|
21
|
+
private addEntryToGitignore;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=gitignore-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore-check.d.ts","sourceRoot":"","sources":["../../../src/utils/setup-checks/gitignore-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACX,MAAM,oBAAoB,CAAC;AAI5B,qBAAa,mBAAoB,YAAW,UAAU;IACpD,QAAQ,CAAC,EAAE,eAAe;IAC1B,QAAQ,CAAC,IAAI,qBAAqB;IAE5B,KAAK,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAmCjD,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IA4CrD,GAAG,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IA8DnD;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAMnC;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAY5B"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gitignore Setup Check
|
|
3
|
+
*
|
|
4
|
+
* Ensures that .vibe-validate-state.yaml is listed in .gitignore
|
|
5
|
+
* to prevent committing validation state files.
|
|
6
|
+
*/
|
|
7
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
8
|
+
import { existsSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
const STATE_FILE_ENTRY = '.vibe-validate-state.yaml';
|
|
11
|
+
export class GitignoreSetupCheck {
|
|
12
|
+
id = 'gitignore';
|
|
13
|
+
name = 'Gitignore Setup';
|
|
14
|
+
async check(options) {
|
|
15
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
16
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
17
|
+
// Check if .gitignore exists
|
|
18
|
+
if (!existsSync(gitignorePath)) {
|
|
19
|
+
return {
|
|
20
|
+
passed: false,
|
|
21
|
+
message: '.gitignore not found',
|
|
22
|
+
suggestion: `Create .gitignore and add ${STATE_FILE_ENTRY}`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// Read .gitignore content
|
|
26
|
+
const content = await readFile(gitignorePath, 'utf-8');
|
|
27
|
+
// Check if state file entry exists (with flexible whitespace)
|
|
28
|
+
const hasEntry = content
|
|
29
|
+
.split('\n')
|
|
30
|
+
.some(line => line.trim() === STATE_FILE_ENTRY);
|
|
31
|
+
if (!hasEntry) {
|
|
32
|
+
return {
|
|
33
|
+
passed: false,
|
|
34
|
+
message: `.gitignore missing ${STATE_FILE_ENTRY} entry`,
|
|
35
|
+
suggestion: `Add ${STATE_FILE_ENTRY} to .gitignore`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
passed: true,
|
|
40
|
+
message: '.gitignore correctly configured with state file entry',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async preview(options) {
|
|
44
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
45
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
46
|
+
// Check current state
|
|
47
|
+
const checkResult = await this.check(options);
|
|
48
|
+
if (checkResult.passed) {
|
|
49
|
+
return {
|
|
50
|
+
description: '.gitignore already configured correctly',
|
|
51
|
+
filesAffected: [],
|
|
52
|
+
changes: [],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// If .gitignore doesn't exist
|
|
56
|
+
if (!existsSync(gitignorePath)) {
|
|
57
|
+
const content = this.generateNewGitignoreContent();
|
|
58
|
+
return {
|
|
59
|
+
description: 'Create new .gitignore with vibe-validate state file entry',
|
|
60
|
+
filesAffected: ['.gitignore'],
|
|
61
|
+
changes: [
|
|
62
|
+
{
|
|
63
|
+
file: '.gitignore',
|
|
64
|
+
action: 'create',
|
|
65
|
+
content,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// If .gitignore exists but missing entry
|
|
71
|
+
return {
|
|
72
|
+
description: `Add ${STATE_FILE_ENTRY} entry to existing .gitignore`,
|
|
73
|
+
filesAffected: ['.gitignore'],
|
|
74
|
+
changes: [
|
|
75
|
+
{
|
|
76
|
+
file: '.gitignore',
|
|
77
|
+
action: 'modify',
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async fix(options) {
|
|
83
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
84
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
85
|
+
const dryRun = options?.dryRun ?? false;
|
|
86
|
+
// Check current state
|
|
87
|
+
const checkResult = await this.check(options);
|
|
88
|
+
if (checkResult.passed && !options?.force) {
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
message: '.gitignore already configured correctly',
|
|
92
|
+
filesChanged: [],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (dryRun) {
|
|
96
|
+
return {
|
|
97
|
+
success: true,
|
|
98
|
+
message: '[dry-run] Would update .gitignore',
|
|
99
|
+
filesChanged: [],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// If .gitignore doesn't exist, create it
|
|
103
|
+
if (!existsSync(gitignorePath)) {
|
|
104
|
+
const content = this.generateNewGitignoreContent();
|
|
105
|
+
await writeFile(gitignorePath, content, 'utf-8');
|
|
106
|
+
return {
|
|
107
|
+
success: true,
|
|
108
|
+
message: 'Created .gitignore with state file entry',
|
|
109
|
+
filesChanged: ['.gitignore'],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// If .gitignore exists, add entry if missing
|
|
113
|
+
const content = await readFile(gitignorePath, 'utf-8');
|
|
114
|
+
const hasEntry = content
|
|
115
|
+
.split('\n')
|
|
116
|
+
.some(line => line.trim() === STATE_FILE_ENTRY);
|
|
117
|
+
if (hasEntry) {
|
|
118
|
+
// Entry already exists (idempotent)
|
|
119
|
+
return {
|
|
120
|
+
success: true,
|
|
121
|
+
message: '.gitignore already contains state file entry',
|
|
122
|
+
filesChanged: [],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// Add entry to existing .gitignore
|
|
126
|
+
const updatedContent = this.addEntryToGitignore(content);
|
|
127
|
+
await writeFile(gitignorePath, updatedContent, 'utf-8');
|
|
128
|
+
return {
|
|
129
|
+
success: true,
|
|
130
|
+
message: `Added ${STATE_FILE_ENTRY} to .gitignore`,
|
|
131
|
+
filesChanged: ['.gitignore'],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Generate content for a new .gitignore file
|
|
136
|
+
*/
|
|
137
|
+
generateNewGitignoreContent() {
|
|
138
|
+
return `# vibe-validate
|
|
139
|
+
${STATE_FILE_ENTRY}
|
|
140
|
+
`;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Add state file entry to existing .gitignore content
|
|
144
|
+
*/
|
|
145
|
+
addEntryToGitignore(content) {
|
|
146
|
+
// Ensure content ends with newline
|
|
147
|
+
let updatedContent = content;
|
|
148
|
+
if (!content.endsWith('\n')) {
|
|
149
|
+
updatedContent += '\n';
|
|
150
|
+
}
|
|
151
|
+
// Add vibe-validate section
|
|
152
|
+
updatedContent += `\n# vibe-validate\n${STATE_FILE_ENTRY}\n`;
|
|
153
|
+
return updatedContent;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=gitignore-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore-check.js","sourceRoot":"","sources":["../../../src/utils/setup-checks/gitignore-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hooks Setup Check
|
|
3
|
+
*
|
|
4
|
+
* Ensures that husky pre-commit hook is configured to run vibe-validate.
|
|
5
|
+
* This check creates/modifies .husky/pre-commit to include the vibe-validate
|
|
6
|
+
* pre-commit command.
|
|
7
|
+
*
|
|
8
|
+
* Note: This check does NOT install husky as a dependency. Users should
|
|
9
|
+
* install husky manually via `npm install -D husky` or `pnpm add -D husky`.
|
|
10
|
+
*/
|
|
11
|
+
import type { SetupCheck, CheckResult, FixResult, PreviewResult, FixOptions } from '../setup-engine.js';
|
|
12
|
+
export declare class HooksSetupCheck implements SetupCheck {
|
|
13
|
+
readonly id = "hooks";
|
|
14
|
+
readonly name = "Pre-commit Hook Setup";
|
|
15
|
+
check(options?: FixOptions): Promise<CheckResult>;
|
|
16
|
+
preview(options?: FixOptions): Promise<PreviewResult>;
|
|
17
|
+
fix(options?: FixOptions): Promise<FixResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Generate content for a new pre-commit hook
|
|
20
|
+
*/
|
|
21
|
+
private generateNewPreCommitHook;
|
|
22
|
+
/**
|
|
23
|
+
* Add vibe-validate command to existing pre-commit hook
|
|
24
|
+
*/
|
|
25
|
+
private addCommandToPreCommit;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=hooks-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-check.d.ts","sourceRoot":"","sources":["../../../src/utils/setup-checks/hooks-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACX,MAAM,oBAAoB,CAAC;AAI5B,qBAAa,eAAgB,YAAW,UAAU;IAChD,QAAQ,CAAC,EAAE,WAAW;IACtB,QAAQ,CAAC,IAAI,2BAA2B;IAElC,KAAK,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IA2CjD,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IA6CrD,GAAG,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IAoEnD;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAQhC;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAY9B"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hooks Setup Check
|
|
3
|
+
*
|
|
4
|
+
* Ensures that husky pre-commit hook is configured to run vibe-validate.
|
|
5
|
+
* This check creates/modifies .husky/pre-commit to include the vibe-validate
|
|
6
|
+
* pre-commit command.
|
|
7
|
+
*
|
|
8
|
+
* Note: This check does NOT install husky as a dependency. Users should
|
|
9
|
+
* install husky manually via `npm install -D husky` or `pnpm add -D husky`.
|
|
10
|
+
*/
|
|
11
|
+
import { readFile, writeFile, mkdir, chmod } from 'fs/promises';
|
|
12
|
+
import { existsSync } from 'fs';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
const VIBE_VALIDATE_COMMAND = 'npx vibe-validate pre-commit';
|
|
15
|
+
export class HooksSetupCheck {
|
|
16
|
+
id = 'hooks';
|
|
17
|
+
name = 'Pre-commit Hook Setup';
|
|
18
|
+
async check(options) {
|
|
19
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
20
|
+
const huskyDir = join(cwd, '.husky');
|
|
21
|
+
const preCommitPath = join(huskyDir, 'pre-commit');
|
|
22
|
+
// Check if .husky directory exists
|
|
23
|
+
if (!existsSync(huskyDir)) {
|
|
24
|
+
return {
|
|
25
|
+
passed: false,
|
|
26
|
+
message: '.husky directory not found',
|
|
27
|
+
suggestion: 'Install husky: npm install -D husky && npx husky init',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// Check if pre-commit hook exists
|
|
31
|
+
if (!existsSync(preCommitPath)) {
|
|
32
|
+
return {
|
|
33
|
+
passed: false,
|
|
34
|
+
message: 'pre-commit hook not found',
|
|
35
|
+
suggestion: 'Create .husky/pre-commit with vibe-validate command',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// Read pre-commit content
|
|
39
|
+
const content = await readFile(preCommitPath, 'utf-8');
|
|
40
|
+
// Check if vibe-validate command exists
|
|
41
|
+
const hasCommand = content.includes('vibe-validate pre-commit');
|
|
42
|
+
if (!hasCommand) {
|
|
43
|
+
return {
|
|
44
|
+
passed: false,
|
|
45
|
+
message: 'pre-commit hook missing vibe-validate command',
|
|
46
|
+
suggestion: `Add "${VIBE_VALIDATE_COMMAND}" to .husky/pre-commit`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
passed: true,
|
|
51
|
+
message: 'pre-commit hook configured correctly',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
async preview(options) {
|
|
55
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
56
|
+
const huskyDir = join(cwd, '.husky');
|
|
57
|
+
const preCommitPath = join(huskyDir, 'pre-commit');
|
|
58
|
+
// Check current state
|
|
59
|
+
const checkResult = await this.check(options);
|
|
60
|
+
if (checkResult.passed) {
|
|
61
|
+
return {
|
|
62
|
+
description: 'pre-commit hook already configured correctly',
|
|
63
|
+
filesAffected: [],
|
|
64
|
+
changes: [],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// If .husky/pre-commit doesn't exist
|
|
68
|
+
if (!existsSync(preCommitPath)) {
|
|
69
|
+
const content = this.generateNewPreCommitHook();
|
|
70
|
+
return {
|
|
71
|
+
description: 'Install husky and create .husky/pre-commit hook with vibe-validate command',
|
|
72
|
+
filesAffected: ['.husky/pre-commit'],
|
|
73
|
+
changes: [
|
|
74
|
+
{
|
|
75
|
+
file: '.husky/pre-commit',
|
|
76
|
+
action: 'create',
|
|
77
|
+
content,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// If pre-commit exists but missing vibe-validate command
|
|
83
|
+
return {
|
|
84
|
+
description: 'Add vibe-validate command to existing pre-commit hook',
|
|
85
|
+
filesAffected: ['.husky/pre-commit'],
|
|
86
|
+
changes: [
|
|
87
|
+
{
|
|
88
|
+
file: '.husky/pre-commit',
|
|
89
|
+
action: 'modify',
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
async fix(options) {
|
|
95
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
96
|
+
const huskyDir = join(cwd, '.husky');
|
|
97
|
+
const preCommitPath = join(huskyDir, 'pre-commit');
|
|
98
|
+
const dryRun = options?.dryRun ?? false;
|
|
99
|
+
// Check current state
|
|
100
|
+
const checkResult = await this.check(options);
|
|
101
|
+
if (checkResult.passed && !options?.force) {
|
|
102
|
+
return {
|
|
103
|
+
success: true,
|
|
104
|
+
message: 'pre-commit hook already configured correctly',
|
|
105
|
+
filesChanged: [],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (dryRun) {
|
|
109
|
+
return {
|
|
110
|
+
success: true,
|
|
111
|
+
message: '[dry-run] Would create/update .husky/pre-commit',
|
|
112
|
+
filesChanged: [],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Ensure .husky directory exists
|
|
116
|
+
if (!existsSync(huskyDir)) {
|
|
117
|
+
await mkdir(huskyDir, { recursive: true });
|
|
118
|
+
}
|
|
119
|
+
// If pre-commit doesn't exist, create it
|
|
120
|
+
if (!existsSync(preCommitPath)) {
|
|
121
|
+
const content = this.generateNewPreCommitHook();
|
|
122
|
+
await writeFile(preCommitPath, content, 'utf-8');
|
|
123
|
+
// Make file executable
|
|
124
|
+
await chmod(preCommitPath, 0o755);
|
|
125
|
+
return {
|
|
126
|
+
success: true,
|
|
127
|
+
message: 'Created .husky/pre-commit hook (Note: Install husky as dev dependency if not already installed)',
|
|
128
|
+
filesChanged: ['.husky/pre-commit'],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// If pre-commit exists, check if command is already there
|
|
132
|
+
const content = await readFile(preCommitPath, 'utf-8');
|
|
133
|
+
const hasCommand = content.includes('vibe-validate pre-commit');
|
|
134
|
+
if (hasCommand) {
|
|
135
|
+
// Command already exists (idempotent)
|
|
136
|
+
return {
|
|
137
|
+
success: true,
|
|
138
|
+
message: 'pre-commit hook already contains vibe-validate command',
|
|
139
|
+
filesChanged: [],
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// Add command to existing pre-commit hook
|
|
143
|
+
const updatedContent = this.addCommandToPreCommit(content);
|
|
144
|
+
await writeFile(preCommitPath, updatedContent, 'utf-8');
|
|
145
|
+
return {
|
|
146
|
+
success: true,
|
|
147
|
+
message: 'Added vibe-validate command to pre-commit hook',
|
|
148
|
+
filesChanged: ['.husky/pre-commit'],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Generate content for a new pre-commit hook
|
|
153
|
+
*/
|
|
154
|
+
generateNewPreCommitHook() {
|
|
155
|
+
return `#!/bin/sh
|
|
156
|
+
|
|
157
|
+
# vibe-validate pre-commit check
|
|
158
|
+
${VIBE_VALIDATE_COMMAND}
|
|
159
|
+
`;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Add vibe-validate command to existing pre-commit hook
|
|
163
|
+
*/
|
|
164
|
+
addCommandToPreCommit(content) {
|
|
165
|
+
// Ensure content ends with newline
|
|
166
|
+
let updatedContent = content;
|
|
167
|
+
if (!content.endsWith('\n')) {
|
|
168
|
+
updatedContent += '\n';
|
|
169
|
+
}
|
|
170
|
+
// Add vibe-validate command
|
|
171
|
+
updatedContent += `\n# vibe-validate pre-commit check\n${VIBE_VALIDATE_COMMAND}\n`;
|
|
172
|
+
return updatedContent;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=hooks-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-check.js","sourceRoot":"","sources":["../../../src/utils/setup-checks/hooks-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Setup Check
|
|
3
|
+
*
|
|
4
|
+
* Ensures that .github/workflows/validate.yml exists and is configured
|
|
5
|
+
* to run vibe-validate validation in CI.
|
|
6
|
+
*
|
|
7
|
+
* This check reuses the existing workflow generation logic from the
|
|
8
|
+
* generate-workflow command to create a standard GitHub Actions workflow.
|
|
9
|
+
*/
|
|
10
|
+
import type { SetupCheck, CheckResult, FixResult, PreviewResult, FixOptions } from '../setup-engine.js';
|
|
11
|
+
export declare class WorkflowSetupCheck implements SetupCheck {
|
|
12
|
+
readonly id = "workflow";
|
|
13
|
+
readonly name = "GitHub Actions Workflow Setup";
|
|
14
|
+
check(options?: FixOptions): Promise<CheckResult>;
|
|
15
|
+
preview(options?: FixOptions): Promise<PreviewResult>;
|
|
16
|
+
fix(options?: FixOptions): Promise<FixResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Generate workflow content using the existing workflow generator
|
|
19
|
+
*/
|
|
20
|
+
private generateWorkflowContent;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=workflow-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-check.d.ts","sourceRoot":"","sources":["../../../src/utils/setup-checks/workflow-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACX,MAAM,oBAAoB,CAAC;AAI5B,qBAAa,kBAAmB,YAAW,UAAU;IACnD,QAAQ,CAAC,EAAE,cAAc;IACzB,QAAQ,CAAC,IAAI,mCAAmC;IAE1C,KAAK,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAuCjD,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAuCrD,GAAG,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IAqDnD;;OAEG;YACW,uBAAuB;CAgBtC"}
|