@vibe-validate/cli 0.10.3 ā 0.12.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/README.md +84 -92
- package/dist/bin.js +137 -20
- package/dist/bin.js.map +1 -1
- package/dist/commands/cleanup.d.ts +4 -0
- package/dist/commands/cleanup.d.ts.map +1 -1
- package/dist/commands/cleanup.js +96 -15
- package/dist/commands/cleanup.js.map +1 -1
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +83 -15
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/doctor.d.ts +4 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +385 -82
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/generate-workflow.d.ts +6 -2
- package/dist/commands/generate-workflow.d.ts.map +1 -1
- package/dist/commands/generate-workflow.js +188 -33
- package/dist/commands/generate-workflow.js.map +1 -1
- package/dist/commands/history.d.ts +13 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +415 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +252 -109
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pre-commit.d.ts +4 -0
- package/dist/commands/pre-commit.d.ts.map +1 -1
- package/dist/commands/pre-commit.js +158 -7
- package/dist/commands/pre-commit.js.map +1 -1
- package/dist/commands/state.d.ts +5 -1
- package/dist/commands/state.d.ts.map +1 -1
- package/dist/commands/state.js +192 -23
- package/dist/commands/state.js.map +1 -1
- package/dist/commands/sync-check.d.ts +4 -0
- package/dist/commands/sync-check.d.ts.map +1 -1
- package/dist/commands/sync-check.js +101 -14
- package/dist/commands/sync-check.js.map +1 -1
- package/dist/commands/validate.d.ts +5 -1
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +184 -28
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/watch-pr.d.ts +10 -0
- package/dist/commands/watch-pr.d.ts.map +1 -0
- package/dist/commands/watch-pr.js +443 -0
- package/dist/commands/watch-pr.js.map +1 -0
- package/dist/schemas/watch-pr-schema.d.ts +261 -0
- package/dist/schemas/watch-pr-schema.d.ts.map +1 -0
- package/dist/schemas/watch-pr-schema.js +58 -0
- package/dist/schemas/watch-pr-schema.js.map +1 -0
- package/dist/scripts/generate-watch-pr-schema.d.ts +12 -0
- package/dist/scripts/generate-watch-pr-schema.d.ts.map +1 -0
- package/dist/scripts/generate-watch-pr-schema.js +35 -0
- package/dist/scripts/generate-watch-pr-schema.js.map +1 -0
- package/dist/services/ci-provider-registry.d.ts +38 -0
- package/dist/services/ci-provider-registry.d.ts.map +1 -0
- package/dist/services/ci-provider-registry.js +53 -0
- package/dist/services/ci-provider-registry.js.map +1 -0
- package/dist/services/ci-provider.d.ts +165 -0
- package/dist/services/ci-provider.d.ts.map +1 -0
- package/dist/services/ci-provider.js +11 -0
- package/dist/services/ci-provider.js.map +1 -0
- package/dist/services/ci-providers/github-actions.d.ts +41 -0
- package/dist/services/ci-providers/github-actions.d.ts.map +1 -0
- package/dist/services/ci-providers/github-actions.js +314 -0
- package/dist/services/ci-providers/github-actions.js.map +1 -0
- package/dist/utils/check-validation.d.ts +7 -4
- package/dist/utils/check-validation.d.ts.map +1 -1
- package/dist/utils/check-validation.js +129 -48
- package/dist/utils/check-validation.js.map +1 -1
- package/dist/utils/config-loader.d.ts +15 -3
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +61 -17
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/context-detector.d.ts +1 -1
- package/dist/utils/context-detector.js +1 -1
- package/dist/utils/normalize-line-endings.d.ts +53 -0
- package/dist/utils/normalize-line-endings.d.ts.map +1 -0
- package/dist/utils/normalize-line-endings.js +57 -0
- package/dist/utils/normalize-line-endings.js.map +1 -0
- package/dist/utils/run-validation-with-cache.d.ts +48 -0
- package/dist/utils/run-validation-with-cache.d.ts.map +1 -0
- package/dist/utils/run-validation-with-cache.js +123 -0
- package/dist/utils/run-validation-with-cache.js.map +1 -0
- package/dist/utils/runner-adapter.d.ts +1 -0
- package/dist/utils/runner-adapter.d.ts.map +1 -1
- package/dist/utils/runner-adapter.js +25 -17
- package/dist/utils/runner-adapter.js.map +1 -1
- package/dist/utils/setup-checks/gitignore-check.d.ts +10 -15
- package/dist/utils/setup-checks/gitignore-check.d.ts.map +1 -1
- package/dist/utils/setup-checks/gitignore-check.js +20 -138
- package/dist/utils/setup-checks/gitignore-check.js.map +1 -1
- package/dist/utils/template-discovery.d.ts +40 -0
- package/dist/utils/template-discovery.d.ts.map +1 -0
- package/dist/utils/template-discovery.js +136 -0
- package/dist/utils/template-discovery.js.map +1 -0
- package/dist/utils/validate-workflow.d.ts +28 -0
- package/dist/utils/validate-workflow.d.ts.map +1 -0
- package/dist/utils/validate-workflow.js +247 -0
- package/dist/utils/validate-workflow.js.map +1 -0
- package/dist/utils/validation-cache.d.ts +30 -0
- package/dist/utils/validation-cache.d.ts.map +1 -0
- package/dist/utils/validation-cache.js +57 -0
- package/dist/utils/validation-cache.js.map +1 -0
- package/package.json +19 -16
- package/watch-pr-result.schema.json +204 -0
- package/LICENSE +0 -21
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CIProvider, PullRequest, CheckStatus, FailureLogs, ValidationResultContents } from '../ci-provider.js';
|
|
2
|
+
/**
|
|
3
|
+
* GitHub Actions CI provider implementation
|
|
4
|
+
*
|
|
5
|
+
* Uses GitHub CLI (gh) to interact with GitHub API.
|
|
6
|
+
* Requires:
|
|
7
|
+
* - gh CLI installed and authenticated
|
|
8
|
+
* - Git repository with github.com remote
|
|
9
|
+
*/
|
|
10
|
+
export declare class GitHubActionsProvider implements CIProvider {
|
|
11
|
+
readonly name = "github-actions";
|
|
12
|
+
isAvailable(): Promise<boolean>;
|
|
13
|
+
detectPullRequest(): Promise<PullRequest | null>;
|
|
14
|
+
fetchCheckStatus(prId: number | string): Promise<CheckStatus>;
|
|
15
|
+
fetchFailureLogs(runId: string): Promise<FailureLogs>;
|
|
16
|
+
extractValidationResult(logs: string): ValidationResultContents | null;
|
|
17
|
+
/**
|
|
18
|
+
* Transform GitHub check format to common CheckResult format
|
|
19
|
+
*/
|
|
20
|
+
private transformCheck;
|
|
21
|
+
/**
|
|
22
|
+
* Determine overall status from individual checks
|
|
23
|
+
*/
|
|
24
|
+
private determineOverallStatus;
|
|
25
|
+
/**
|
|
26
|
+
* Determine overall result from individual checks
|
|
27
|
+
*/
|
|
28
|
+
private determineOverallResult;
|
|
29
|
+
/**
|
|
30
|
+
* Extract failed step name from GitHub Actions logs
|
|
31
|
+
*/
|
|
32
|
+
private extractFailedStep;
|
|
33
|
+
/**
|
|
34
|
+
* Extract concise error summary from logs (LLM-friendly format)
|
|
35
|
+
*
|
|
36
|
+
* Returns just the failed step name and command - keeps output minimal.
|
|
37
|
+
* Full details are in the validationResult field.
|
|
38
|
+
*/
|
|
39
|
+
private extractErrorSummary;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=github-actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-actions.d.ts","sourceRoot":"","sources":["../../../src/services/ci-providers/github-actions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,WAAW,EAEX,WAAW,EACX,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;GAOG;AACH,qBAAa,qBAAsB,YAAW,UAAU;IACtD,QAAQ,CAAC,IAAI,oBAAoB;IAE3B,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAa/B,iBAAiB,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAoBhD,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAyB7D,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAkC3D,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB,GAAG,IAAI;IAsFtE;;OAEG;IACH,OAAO,CAAC,cAAc;IAkEtB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAkB9B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAuB9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;CAqB5B"}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { parse as parseYaml } from 'yaml';
|
|
3
|
+
import { extractByStepName } from '@vibe-validate/extractors';
|
|
4
|
+
/**
|
|
5
|
+
* GitHub Actions CI provider implementation
|
|
6
|
+
*
|
|
7
|
+
* Uses GitHub CLI (gh) to interact with GitHub API.
|
|
8
|
+
* Requires:
|
|
9
|
+
* - gh CLI installed and authenticated
|
|
10
|
+
* - Git repository with github.com remote
|
|
11
|
+
*/
|
|
12
|
+
export class GitHubActionsProvider {
|
|
13
|
+
name = 'github-actions';
|
|
14
|
+
async isAvailable() {
|
|
15
|
+
try {
|
|
16
|
+
// Check if gh CLI is available
|
|
17
|
+
execSync('gh --version', { stdio: 'ignore' });
|
|
18
|
+
// Check if we're in a GitHub repo
|
|
19
|
+
const remote = execSync('git remote get-url origin', { encoding: 'utf8' });
|
|
20
|
+
return remote.includes('github.com');
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async detectPullRequest() {
|
|
27
|
+
try {
|
|
28
|
+
const prData = JSON.parse(execSync('gh pr view --json number,title,url,headRefName', {
|
|
29
|
+
encoding: 'utf8',
|
|
30
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
31
|
+
}));
|
|
32
|
+
return {
|
|
33
|
+
id: prData.number,
|
|
34
|
+
title: prData.title,
|
|
35
|
+
url: prData.url,
|
|
36
|
+
branch: prData.headRefName,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async fetchCheckStatus(prId) {
|
|
44
|
+
const data = JSON.parse(execSync(`gh pr view ${prId} --json number,title,url,statusCheckRollup,headRefName`, {
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
47
|
+
}));
|
|
48
|
+
const checks = (data.statusCheckRollup || []).map((check) => this.transformCheck(check));
|
|
49
|
+
return {
|
|
50
|
+
pr: {
|
|
51
|
+
id: data.number,
|
|
52
|
+
title: data.title,
|
|
53
|
+
url: data.url,
|
|
54
|
+
branch: data.headRefName || '',
|
|
55
|
+
},
|
|
56
|
+
status: this.determineOverallStatus(checks),
|
|
57
|
+
result: this.determineOverallResult(checks),
|
|
58
|
+
checks,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async fetchFailureLogs(runId) {
|
|
62
|
+
// Get run details to find the check name
|
|
63
|
+
let checkName = 'Unknown';
|
|
64
|
+
try {
|
|
65
|
+
const runData = JSON.parse(execSync(`gh run view ${runId} --json name`, {
|
|
66
|
+
encoding: 'utf8',
|
|
67
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
68
|
+
}));
|
|
69
|
+
checkName = runData.name || checkName;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Ignore error, use default name
|
|
73
|
+
}
|
|
74
|
+
// Fetch full logs (includes "Display validation state on failure" step)
|
|
75
|
+
const logs = execSync(`gh run view ${runId} --log`, {
|
|
76
|
+
encoding: 'utf8',
|
|
77
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
78
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB buffer to handle large logs
|
|
79
|
+
});
|
|
80
|
+
const validationResult = this.extractValidationResult(logs);
|
|
81
|
+
return {
|
|
82
|
+
checkId: runId,
|
|
83
|
+
checkName,
|
|
84
|
+
rawLogs: logs,
|
|
85
|
+
failedStep: this.extractFailedStep(logs),
|
|
86
|
+
errorSummary: this.extractErrorSummary(logs),
|
|
87
|
+
validationResult: validationResult ?? undefined,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
extractValidationResult(logs) {
|
|
91
|
+
// GitHub Actions logs have format: "Run name\tStep name\tTimestamp <content>"
|
|
92
|
+
// We need to strip prefixes to get actual output
|
|
93
|
+
const lines = logs.split('\n');
|
|
94
|
+
// Helper to extract content from a GitHub Actions log line
|
|
95
|
+
const extractContent = (line) => {
|
|
96
|
+
const parts = line.split('\t');
|
|
97
|
+
if (parts.length < 3)
|
|
98
|
+
return '';
|
|
99
|
+
const contentWithTimestamp = parts.slice(2).join('\t');
|
|
100
|
+
// Strip timestamp (format: "2025-10-21T00:56:24.8654285Z <content>")
|
|
101
|
+
return contentWithTimestamp.replace(/^[0-9T:.Z-]+ /, '').replace(/^[0-9T:.Z-]+$/, '');
|
|
102
|
+
};
|
|
103
|
+
// Find the start: line containing "VALIDATION RESULT"
|
|
104
|
+
// (This header is from the CI workflow displaying the validation result)
|
|
105
|
+
// Skip lines with ANSI codes (those are the commands being echoed, not the output)
|
|
106
|
+
const startIdx = lines.findIndex(l => {
|
|
107
|
+
return l.includes('VALIDATION RESULT') && !l.includes('[36;1m') && !l.includes('[0m');
|
|
108
|
+
});
|
|
109
|
+
if (startIdx < 0) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
// Find the closing separator (next line with ==== that comes after some YAML content)
|
|
113
|
+
// Look for a line with just ========== (40+ chars) after we've seen some YAML (passed:, timestamp:, etc.)
|
|
114
|
+
let endIdx = -1;
|
|
115
|
+
let foundYamlContent = false;
|
|
116
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
117
|
+
const content = extractContent(lines[i]).trim();
|
|
118
|
+
// Check if we've seen YAML content
|
|
119
|
+
if (content.startsWith('passed:') || content.startsWith('timestamp:') || content.startsWith('treeHash:')) {
|
|
120
|
+
foundYamlContent = true;
|
|
121
|
+
}
|
|
122
|
+
// Look for closing separator after we've seen YAML content
|
|
123
|
+
if (foundYamlContent && content.match(/^={40,}$/)) {
|
|
124
|
+
endIdx = i;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (endIdx < 0) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
// Extract YAML content (skip the header separator line, start from actual YAML)
|
|
132
|
+
// The workflow outputs: ==== / VALIDATION RESULT / ==== / <YAML> / ====
|
|
133
|
+
// So YAML starts at startIdx + 2 (skip "VALIDATION RESULT" and separator)
|
|
134
|
+
const yamlStartIdx = startIdx + 2;
|
|
135
|
+
const yamlLines = [];
|
|
136
|
+
for (let i = yamlStartIdx; i < endIdx; i++) {
|
|
137
|
+
// Strip the prefix (job name + step + timestamp) to get actual content
|
|
138
|
+
const content = extractContent(lines[i]);
|
|
139
|
+
yamlLines.push(content);
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const stateYaml = yamlLines.join('\n').trim();
|
|
143
|
+
const result = parseYaml(stateYaml);
|
|
144
|
+
// If validation failed and we have step output, run it through extractors
|
|
145
|
+
// to extract structured failure details (test names, file locations, etc.)
|
|
146
|
+
if (!result.passed && result.failedStep && result.failedStepOutput) {
|
|
147
|
+
const extractorResult = extractByStepName(result.failedStep, result.failedStepOutput);
|
|
148
|
+
// Extract failed tests in "file:line" format from extractor errors
|
|
149
|
+
if (extractorResult.errors && extractorResult.errors.length > 0) {
|
|
150
|
+
result.failedTests = extractorResult.errors
|
|
151
|
+
.filter((e) => e.file && e.line)
|
|
152
|
+
.map((e) => `${e.file}:${e.line}${e.column ? `:${e.column}` : ''} - ${e.message || 'Test failed'}`)
|
|
153
|
+
.slice(0, 10); // Limit to first 10 for display
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
catch (_error) {
|
|
159
|
+
// Failed to parse YAML, return null
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Transform GitHub check format to common CheckResult format
|
|
165
|
+
*/
|
|
166
|
+
transformCheck(ghCheck) {
|
|
167
|
+
// Type guard to ensure ghCheck is an object with expected properties
|
|
168
|
+
const check = ghCheck;
|
|
169
|
+
// GitHub check structure (from statusCheckRollup):
|
|
170
|
+
// {
|
|
171
|
+
// __typename: "CheckRun" | "StatusContext",
|
|
172
|
+
// name: string,
|
|
173
|
+
// status: "QUEUED" | "IN_PROGRESS" | "COMPLETED",
|
|
174
|
+
// conclusion: "SUCCESS" | "FAILURE" | "CANCELLED" | etc,
|
|
175
|
+
// detailsUrl: string
|
|
176
|
+
// }
|
|
177
|
+
let status;
|
|
178
|
+
switch (check.status) {
|
|
179
|
+
case 'QUEUED':
|
|
180
|
+
status = 'queued';
|
|
181
|
+
break;
|
|
182
|
+
case 'IN_PROGRESS':
|
|
183
|
+
status = 'in_progress';
|
|
184
|
+
break;
|
|
185
|
+
case 'COMPLETED':
|
|
186
|
+
status = 'completed';
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
status = 'queued';
|
|
190
|
+
}
|
|
191
|
+
let conclusion = null;
|
|
192
|
+
if (check.conclusion) {
|
|
193
|
+
switch (check.conclusion) {
|
|
194
|
+
case 'SUCCESS':
|
|
195
|
+
conclusion = 'success';
|
|
196
|
+
break;
|
|
197
|
+
case 'FAILURE':
|
|
198
|
+
conclusion = 'failure';
|
|
199
|
+
break;
|
|
200
|
+
case 'CANCELLED':
|
|
201
|
+
conclusion = 'cancelled';
|
|
202
|
+
break;
|
|
203
|
+
case 'SKIPPED':
|
|
204
|
+
conclusion = 'skipped';
|
|
205
|
+
break;
|
|
206
|
+
case 'NEUTRAL':
|
|
207
|
+
conclusion = 'neutral';
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Extract run ID from details URL if available
|
|
212
|
+
let checkId = 'unknown';
|
|
213
|
+
if (typeof check.detailsUrl === 'string') {
|
|
214
|
+
const runIdMatch = check.detailsUrl.match(/\/runs\/(\d+)/);
|
|
215
|
+
if (runIdMatch) {
|
|
216
|
+
checkId = runIdMatch[1];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
id: checkId,
|
|
221
|
+
name: check.name || 'Unknown',
|
|
222
|
+
status,
|
|
223
|
+
conclusion,
|
|
224
|
+
url: check.detailsUrl,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Determine overall status from individual checks
|
|
229
|
+
*/
|
|
230
|
+
determineOverallStatus(checks) {
|
|
231
|
+
if (checks.length === 0) {
|
|
232
|
+
return 'pending';
|
|
233
|
+
}
|
|
234
|
+
const allCompleted = checks.every((c) => c.status === 'completed');
|
|
235
|
+
if (allCompleted) {
|
|
236
|
+
return 'completed';
|
|
237
|
+
}
|
|
238
|
+
const anyInProgress = checks.some((c) => c.status === 'in_progress');
|
|
239
|
+
if (anyInProgress) {
|
|
240
|
+
return 'in_progress';
|
|
241
|
+
}
|
|
242
|
+
return 'pending';
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Determine overall result from individual checks
|
|
246
|
+
*/
|
|
247
|
+
determineOverallResult(checks) {
|
|
248
|
+
if (checks.length === 0) {
|
|
249
|
+
return 'unknown';
|
|
250
|
+
}
|
|
251
|
+
const anyFailure = checks.some((c) => c.conclusion === 'failure');
|
|
252
|
+
if (anyFailure) {
|
|
253
|
+
return 'failure';
|
|
254
|
+
}
|
|
255
|
+
const anyCancelled = checks.some((c) => c.conclusion === 'cancelled');
|
|
256
|
+
if (anyCancelled) {
|
|
257
|
+
return 'cancelled';
|
|
258
|
+
}
|
|
259
|
+
const allSuccess = checks.every((c) => c.conclusion === 'success');
|
|
260
|
+
if (allSuccess) {
|
|
261
|
+
return 'success';
|
|
262
|
+
}
|
|
263
|
+
return 'unknown';
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Extract failed step name from GitHub Actions logs
|
|
267
|
+
*/
|
|
268
|
+
extractFailedStep(logs) {
|
|
269
|
+
// GitHub Actions marks failed steps with ##[error]
|
|
270
|
+
const errorMatch = logs.match(/##\[error\]Process completed with exit code \d+\./);
|
|
271
|
+
if (!errorMatch) {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
// Try to find the step name before the error
|
|
275
|
+
// Look for lines like: "Run pnpm test" or "##[group]Run pnpm test"
|
|
276
|
+
const lines = logs.split('\n');
|
|
277
|
+
const errorIndex = lines.findIndex((line) => line.includes('##[error]'));
|
|
278
|
+
if (errorIndex > 0) {
|
|
279
|
+
// Look backwards for step name
|
|
280
|
+
for (let i = errorIndex - 1; i >= 0; i--) {
|
|
281
|
+
const runMatch = lines[i].match(/##\[group\]Run (.+)/);
|
|
282
|
+
if (runMatch) {
|
|
283
|
+
return runMatch[1];
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Extract concise error summary from logs (LLM-friendly format)
|
|
291
|
+
*
|
|
292
|
+
* Returns just the failed step name and command - keeps output minimal.
|
|
293
|
+
* Full details are in the validationResult field.
|
|
294
|
+
*/
|
|
295
|
+
extractErrorSummary(logs) {
|
|
296
|
+
// Use the validation result which already has parsed failures
|
|
297
|
+
const validationResult = this.extractValidationResult(logs);
|
|
298
|
+
if (validationResult && !validationResult.passed) {
|
|
299
|
+
// Show concise summary: just the failed step and how to rerun
|
|
300
|
+
if (validationResult.failedStep) {
|
|
301
|
+
return `Failed step: ${validationResult.failedStep}\nRerun: ${validationResult.rerunCommand || 'see full logs'}`;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Fallback: Look for ##[error] lines (for non-validation failures)
|
|
305
|
+
const errorLines = logs
|
|
306
|
+
.split('\n')
|
|
307
|
+
.filter((line) => line.includes('##[error]'))
|
|
308
|
+
.slice(0, 5) // First 5 error lines
|
|
309
|
+
.map((line) => line.replace(/##\[error\]/g, '').trim())
|
|
310
|
+
.join('\n');
|
|
311
|
+
return errorLines || undefined;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=github-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-actions.js","sourceRoot":"","sources":["../../../src/services/ci-providers/github-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Validation Status Checker
|
|
3
3
|
*
|
|
4
4
|
* Provides programmatic interface to check if validation has already passed
|
|
5
|
-
* for the current working tree state
|
|
5
|
+
* for the current working tree state using git notes.
|
|
6
6
|
*/
|
|
7
7
|
import type { VibeValidateConfig } from '@vibe-validate/config';
|
|
8
8
|
/**
|
|
@@ -11,8 +11,11 @@ import type { VibeValidateConfig } from '@vibe-validate/config';
|
|
|
11
11
|
* Exit codes:
|
|
12
12
|
* 0 = Validation already passed (skip validation)
|
|
13
13
|
* 1 = Validation not passed or needed (run validation)
|
|
14
|
-
* 2 =
|
|
15
|
-
* 3 = Git tree hash
|
|
14
|
+
* 2 = No history found (run validation)
|
|
15
|
+
* 3 = Git tree hash changed (run validation)
|
|
16
|
+
*
|
|
17
|
+
* @param _config - vibe-validate configuration (unused, kept for API compatibility)
|
|
18
|
+
* @param yaml - If true, output YAML to stdout instead of human-readable text
|
|
16
19
|
*/
|
|
17
|
-
export declare function checkValidationStatus(
|
|
20
|
+
export declare function checkValidationStatus(_config: VibeValidateConfig, yaml?: boolean): Promise<void>;
|
|
18
21
|
//# sourceMappingURL=check-validation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-validation.d.ts","sourceRoot":"","sources":["../../src/utils/check-validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"check-validation.d.ts","sourceRoot":"","sources":["../../src/utils/check-validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,EAAE,IAAI,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA2IpG"}
|
|
@@ -2,76 +2,157 @@
|
|
|
2
2
|
* Validation Status Checker
|
|
3
3
|
*
|
|
4
4
|
* Provides programmatic interface to check if validation has already passed
|
|
5
|
-
* for the current working tree state
|
|
5
|
+
* for the current working tree state using git notes.
|
|
6
6
|
*/
|
|
7
|
-
import { existsSync, readFileSync } from 'fs';
|
|
8
7
|
import { getGitTreeHash } from '@vibe-validate/git';
|
|
8
|
+
import { readHistoryNote } from '@vibe-validate/history';
|
|
9
9
|
import chalk from 'chalk';
|
|
10
|
-
import
|
|
10
|
+
import { stringify as yamlStringify } from 'yaml';
|
|
11
11
|
/**
|
|
12
12
|
* Check validation status for current working tree
|
|
13
13
|
*
|
|
14
14
|
* Exit codes:
|
|
15
15
|
* 0 = Validation already passed (skip validation)
|
|
16
16
|
* 1 = Validation not passed or needed (run validation)
|
|
17
|
-
* 2 =
|
|
18
|
-
* 3 = Git tree hash
|
|
17
|
+
* 2 = No history found (run validation)
|
|
18
|
+
* 3 = Git tree hash changed (run validation)
|
|
19
|
+
*
|
|
20
|
+
* @param _config - vibe-validate configuration (unused, kept for API compatibility)
|
|
21
|
+
* @param yaml - If true, output YAML to stdout instead of human-readable text
|
|
19
22
|
*/
|
|
20
|
-
export async function checkValidationStatus(
|
|
21
|
-
const stateFilePath = config.validation.caching?.statePath || '.vibe-validate-state.yaml';
|
|
22
|
-
// Check if state file exists
|
|
23
|
-
if (!existsSync(stateFilePath)) {
|
|
24
|
-
console.log(chalk.yellow('ā ļø Validation state file not found'));
|
|
25
|
-
console.log(chalk.gray(` Expected: ${stateFilePath}`));
|
|
26
|
-
console.log(chalk.blue('\nš” Run validation:'), chalk.white('npx vibe-validate validate'));
|
|
27
|
-
process.exit(2);
|
|
28
|
-
}
|
|
23
|
+
export async function checkValidationStatus(_config, yaml = false) {
|
|
29
24
|
// Get current tree hash
|
|
30
|
-
|
|
31
|
-
// Read state file
|
|
32
|
-
let state;
|
|
25
|
+
let currentTreeHash;
|
|
33
26
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
currentTreeHash = await getGitTreeHash();
|
|
28
|
+
}
|
|
29
|
+
catch (_error) {
|
|
30
|
+
if (yaml) {
|
|
31
|
+
// YAML mode: Output structured error
|
|
32
|
+
const errorOutput = {
|
|
33
|
+
exists: false,
|
|
34
|
+
error: 'Not in git repository',
|
|
35
|
+
};
|
|
36
|
+
process.stdout.write('---\n');
|
|
37
|
+
process.stdout.write(yamlStringify(errorOutput));
|
|
38
38
|
}
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
else {
|
|
40
|
+
// Human mode: Colored output
|
|
41
|
+
console.log(chalk.yellow('ā ļø Not in git repository'));
|
|
42
|
+
console.log(chalk.blue('\nš” Run validation:'), chalk.white('npx vibe-validate validate'));
|
|
41
43
|
}
|
|
44
|
+
process.exit(2);
|
|
45
|
+
}
|
|
46
|
+
// Check git notes for validation history
|
|
47
|
+
let historyNote;
|
|
48
|
+
try {
|
|
49
|
+
historyNote = await readHistoryNote(currentTreeHash);
|
|
42
50
|
}
|
|
43
|
-
catch (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
catch (_error) {
|
|
52
|
+
if (yaml) {
|
|
53
|
+
// YAML mode: Output structured error
|
|
54
|
+
const errorOutput = {
|
|
55
|
+
exists: false,
|
|
56
|
+
treeHash: currentTreeHash,
|
|
57
|
+
error: 'Failed to read validation history',
|
|
58
|
+
};
|
|
59
|
+
process.stdout.write('---\n');
|
|
60
|
+
process.stdout.write(yamlStringify(errorOutput));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Human mode: Colored output
|
|
64
|
+
console.log(chalk.yellow('ā ļø Failed to read validation history'));
|
|
65
|
+
console.log(chalk.blue('\nš” Run validation:'), chalk.white('npx vibe-validate validate'));
|
|
66
|
+
}
|
|
47
67
|
process.exit(2);
|
|
48
68
|
}
|
|
49
|
-
// Check if
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
// Check if history exists
|
|
70
|
+
if (!historyNote || historyNote.runs.length === 0) {
|
|
71
|
+
if (yaml) {
|
|
72
|
+
// YAML mode: Output structured no-history response
|
|
73
|
+
const noHistoryOutput = {
|
|
74
|
+
exists: false,
|
|
75
|
+
treeHash: currentTreeHash,
|
|
76
|
+
};
|
|
77
|
+
process.stdout.write('---\n');
|
|
78
|
+
process.stdout.write(yamlStringify(noHistoryOutput));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Human mode: Colored output
|
|
82
|
+
console.log(chalk.yellow('ā ļø No validation history for current working tree'));
|
|
83
|
+
console.log(chalk.gray(` Tree hash: ${currentTreeHash.substring(0, 12)}...`));
|
|
84
|
+
console.log(chalk.blue('\nš” Run validation:'), chalk.white('npx vibe-validate validate'));
|
|
85
|
+
}
|
|
86
|
+
process.exit(2);
|
|
56
87
|
}
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
|
|
88
|
+
// Find most recent passing run
|
|
89
|
+
const passingRun = [...historyNote.runs].reverse().find(run => run.passed);
|
|
90
|
+
if (!passingRun) {
|
|
91
|
+
// Last validation failed - show error details (same as fresh failure)
|
|
92
|
+
const mostRecent = historyNote.runs[historyNote.runs.length - 1];
|
|
93
|
+
if (yaml) {
|
|
94
|
+
// YAML mode: Output failed result as YAML to stdout
|
|
95
|
+
process.stdout.write('---\n');
|
|
96
|
+
process.stdout.write(yamlStringify(mostRecent.result));
|
|
97
|
+
// Wait for stdout to flush before exiting
|
|
98
|
+
await new Promise(resolve => {
|
|
99
|
+
if (process.stdout.write('')) {
|
|
100
|
+
resolve();
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
process.stdout.once('drain', resolve);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// Human-readable mode: Display failure details
|
|
109
|
+
console.log(chalk.red('ā Last validation failed for current working tree'));
|
|
110
|
+
console.log(chalk.gray(` Tree hash: ${currentTreeHash.substring(0, 12)}...`));
|
|
111
|
+
console.log(chalk.gray(` Last validated: ${mostRecent.timestamp}`));
|
|
112
|
+
console.log(chalk.gray(` Branch: ${mostRecent.branch}`));
|
|
113
|
+
// Show which phase/step failed (actionable info)
|
|
114
|
+
if (mostRecent.result?.phases) {
|
|
115
|
+
const failedPhase = mostRecent.result.phases.find(p => !p.passed);
|
|
116
|
+
if (failedPhase) {
|
|
117
|
+
console.log(chalk.red(`\n Failed phase: ${failedPhase.name}`));
|
|
118
|
+
const failedStep = failedPhase.steps?.find(s => !s.passed);
|
|
119
|
+
if (failedStep) {
|
|
120
|
+
console.log(chalk.red(` Failed step: ${failedStep.name}`));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
console.log(chalk.blue('\nš View full error details:'), chalk.white('vibe-validate state'));
|
|
125
|
+
console.log(chalk.blue('š” Fix errors and run validation:'), chalk.white('npx vibe-validate validate'));
|
|
64
126
|
}
|
|
65
|
-
console.log(chalk.blue('\nš” Fix errors and run validation:'), chalk.white('npx vibe-validate validate'));
|
|
66
127
|
process.exit(1);
|
|
67
128
|
}
|
|
68
129
|
// Validation passed!
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
130
|
+
if (yaml) {
|
|
131
|
+
// YAML mode: Output validation result as YAML to stdout
|
|
132
|
+
process.stdout.write('---\n');
|
|
133
|
+
process.stdout.write(yamlStringify(passingRun.result));
|
|
134
|
+
// Wait for stdout to flush before exiting
|
|
135
|
+
await new Promise(resolve => {
|
|
136
|
+
if (process.stdout.write('')) {
|
|
137
|
+
resolve();
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
process.stdout.once('drain', resolve);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Human-readable mode: Display status message
|
|
146
|
+
const durationSecs = (passingRun.duration / 1000).toFixed(1);
|
|
147
|
+
console.log(chalk.green('ā
Validation already passed for current working tree'));
|
|
148
|
+
console.log(chalk.gray(` Tree hash: ${currentTreeHash.substring(0, 12)}...`));
|
|
149
|
+
console.log(chalk.gray(` Last validated: ${passingRun.timestamp}`));
|
|
150
|
+
console.log(chalk.gray(` Duration: ${durationSecs}s`));
|
|
151
|
+
console.log(chalk.gray(` Branch: ${passingRun.branch}`));
|
|
152
|
+
if (passingRun.result?.phases) {
|
|
153
|
+
const totalSteps = passingRun.result.phases.reduce((sum, phase) => sum + (phase.steps?.length || 0), 0);
|
|
154
|
+
console.log(chalk.gray(` Phases: ${passingRun.result.phases.length}, Steps: ${totalSteps}`));
|
|
155
|
+
}
|
|
75
156
|
}
|
|
76
157
|
process.exit(0);
|
|
77
158
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-validation.js","sourceRoot":"","sources":["../../src/utils/check-validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"check-validation.js","sourceRoot":"","sources":["../../src/utils/check-validation.ts"],"names":[],"mappings":"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"}
|