@yasserkhanorg/e2e-agents 1.1.0 → 1.1.2
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/agent/git.d.ts.map +1 -1
- package/dist/agent/git.js +91 -5
- package/dist/esm/agent/git.js +91 -5
- package/package.json +1 -1
package/dist/agent/git.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/agent/git.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/agent/git.ts"],"names":[],"mappings":"AAqGA,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC;CAC1C;AAED,MAAM,WAAW,gBAAgB;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAChC;AA8CD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe,CA2C3G"}
|
package/dist/agent/git.js
CHANGED
|
@@ -5,6 +5,89 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
5
5
|
exports.getChangedFiles = getChangedFiles;
|
|
6
6
|
const child_process_1 = require("child_process");
|
|
7
7
|
const utils_js_1 = require("./utils.js");
|
|
8
|
+
// Directories that contain CI/tooling/docs — never relevant to impact analysis.
|
|
9
|
+
const IGNORED_DIR_SEGMENTS = [
|
|
10
|
+
'.github',
|
|
11
|
+
'.claude',
|
|
12
|
+
'.vscode',
|
|
13
|
+
'.idea',
|
|
14
|
+
'node_modules',
|
|
15
|
+
];
|
|
16
|
+
// Exact filenames (basename) that are never relevant.
|
|
17
|
+
const IGNORED_BASENAMES = new Set([
|
|
18
|
+
'package.json',
|
|
19
|
+
'package-lock.json',
|
|
20
|
+
'.gitignore',
|
|
21
|
+
'.prettierignore',
|
|
22
|
+
'.prettierrc',
|
|
23
|
+
'.eslintrc',
|
|
24
|
+
'.eslintrc.js',
|
|
25
|
+
'.eslintrc.json',
|
|
26
|
+
'.editorconfig',
|
|
27
|
+
'.npmrc',
|
|
28
|
+
'.mcp.json',
|
|
29
|
+
'CHANGELOG.md',
|
|
30
|
+
'README.md',
|
|
31
|
+
'LICENSE',
|
|
32
|
+
'LICENSE.txt',
|
|
33
|
+
'tsconfig.json',
|
|
34
|
+
'jest.config.js',
|
|
35
|
+
'jest.config.ts',
|
|
36
|
+
'babel.config.js',
|
|
37
|
+
]);
|
|
38
|
+
// Extensions that are never source code.
|
|
39
|
+
const IGNORED_EXTENSIONS = new Set([
|
|
40
|
+
'.md',
|
|
41
|
+
'.txt',
|
|
42
|
+
'.lock',
|
|
43
|
+
'.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico',
|
|
44
|
+
'.woff', '.woff2', '.ttf', '.eot',
|
|
45
|
+
]);
|
|
46
|
+
// File patterns that indicate test/spec files (not production code).
|
|
47
|
+
const TEST_FILE_PATTERNS = [
|
|
48
|
+
/\.spec\.[tj]sx?$/,
|
|
49
|
+
/\.test\.[tj]sx?$/,
|
|
50
|
+
/_test\.go$/,
|
|
51
|
+
/\.stories\.[tj]sx?$/,
|
|
52
|
+
];
|
|
53
|
+
// Config file patterns that are not production source code.
|
|
54
|
+
const CONFIG_FILE_PATTERNS = [
|
|
55
|
+
/\.config\.[tj]sx?$/,
|
|
56
|
+
/\.config\.json$/,
|
|
57
|
+
/\.config\.js$/,
|
|
58
|
+
];
|
|
59
|
+
function isRelevantFile(file) {
|
|
60
|
+
const segments = file.split('/');
|
|
61
|
+
const basename = segments[segments.length - 1] || file;
|
|
62
|
+
if (IGNORED_BASENAMES.has(basename)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
for (const seg of segments) {
|
|
66
|
+
if (IGNORED_DIR_SEGMENTS.includes(seg)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const dotIdx = basename.lastIndexOf('.');
|
|
71
|
+
if (dotIdx > 0) {
|
|
72
|
+
const ext = basename.slice(dotIdx).toLowerCase();
|
|
73
|
+
if (IGNORED_EXTENSIONS.has(ext)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Filter test/spec files — they don't impact production features
|
|
78
|
+
for (const pattern of TEST_FILE_PATTERNS) {
|
|
79
|
+
if (pattern.test(basename)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Filter config files
|
|
84
|
+
for (const pattern of CONFIG_FILE_PATTERNS) {
|
|
85
|
+
if (pattern.test(basename)) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
8
91
|
function runGitRaw(args, cwd) {
|
|
9
92
|
const result = (0, child_process_1.spawnSync)('git', args, {
|
|
10
93
|
cwd,
|
|
@@ -66,23 +149,26 @@ function getChangedFiles(appRoot, since, options) {
|
|
|
66
149
|
baseStrategy = 'merge-base';
|
|
67
150
|
}
|
|
68
151
|
}
|
|
69
|
-
|
|
152
|
+
// Get repo root so we capture ALL changed files (including server/, webapp/, etc.)
|
|
153
|
+
// not just files under the appRoot subdirectory.
|
|
154
|
+
const repoRoot = runGitRaw(['rev-parse', '--show-toplevel'], appRoot)?.trim() || appRoot;
|
|
155
|
+
const diffFiles = runGit(['diff', '--name-only', `${baseRef}..HEAD`], repoRoot);
|
|
70
156
|
if (!diffFiles) {
|
|
71
157
|
return { files: [], error: 'git diff failed' };
|
|
72
158
|
}
|
|
73
159
|
diffFiles.forEach((file) => files.add(file));
|
|
74
160
|
if (options?.includeUncommitted) {
|
|
75
|
-
const staged = runGit(['diff', '--name-only', '--cached'
|
|
161
|
+
const staged = runGit(['diff', '--name-only', '--cached'], repoRoot) || [];
|
|
76
162
|
staged.forEach((file) => files.add(file));
|
|
77
|
-
const unstaged = runGit(['diff', '--name-only'
|
|
163
|
+
const unstaged = runGit(['diff', '--name-only'], repoRoot) || [];
|
|
78
164
|
unstaged.forEach((file) => files.add(file));
|
|
79
|
-
const statusOutput = runGitRaw(['status', '--porcelain'
|
|
165
|
+
const statusOutput = runGitRaw(['status', '--porcelain'], repoRoot);
|
|
80
166
|
if (statusOutput) {
|
|
81
167
|
const statusLines = statusOutput.split('\n').filter(Boolean);
|
|
82
168
|
parseStatusLines(statusLines).forEach((file) => files.add(file));
|
|
83
169
|
}
|
|
84
170
|
}
|
|
85
|
-
return { files: Array.from(files), baseRef, baseStrategy };
|
|
171
|
+
return { files: Array.from(files).filter(isRelevantFile), baseRef, baseStrategy };
|
|
86
172
|
}
|
|
87
173
|
catch {
|
|
88
174
|
return { files: [], error: 'git diff failed' };
|
package/dist/esm/agent/git.js
CHANGED
|
@@ -2,6 +2,89 @@
|
|
|
2
2
|
// See LICENSE.txt for license information.
|
|
3
3
|
import { spawnSync } from 'child_process';
|
|
4
4
|
import { normalizePath } from './utils.js';
|
|
5
|
+
// Directories that contain CI/tooling/docs — never relevant to impact analysis.
|
|
6
|
+
const IGNORED_DIR_SEGMENTS = [
|
|
7
|
+
'.github',
|
|
8
|
+
'.claude',
|
|
9
|
+
'.vscode',
|
|
10
|
+
'.idea',
|
|
11
|
+
'node_modules',
|
|
12
|
+
];
|
|
13
|
+
// Exact filenames (basename) that are never relevant.
|
|
14
|
+
const IGNORED_BASENAMES = new Set([
|
|
15
|
+
'package.json',
|
|
16
|
+
'package-lock.json',
|
|
17
|
+
'.gitignore',
|
|
18
|
+
'.prettierignore',
|
|
19
|
+
'.prettierrc',
|
|
20
|
+
'.eslintrc',
|
|
21
|
+
'.eslintrc.js',
|
|
22
|
+
'.eslintrc.json',
|
|
23
|
+
'.editorconfig',
|
|
24
|
+
'.npmrc',
|
|
25
|
+
'.mcp.json',
|
|
26
|
+
'CHANGELOG.md',
|
|
27
|
+
'README.md',
|
|
28
|
+
'LICENSE',
|
|
29
|
+
'LICENSE.txt',
|
|
30
|
+
'tsconfig.json',
|
|
31
|
+
'jest.config.js',
|
|
32
|
+
'jest.config.ts',
|
|
33
|
+
'babel.config.js',
|
|
34
|
+
]);
|
|
35
|
+
// Extensions that are never source code.
|
|
36
|
+
const IGNORED_EXTENSIONS = new Set([
|
|
37
|
+
'.md',
|
|
38
|
+
'.txt',
|
|
39
|
+
'.lock',
|
|
40
|
+
'.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico',
|
|
41
|
+
'.woff', '.woff2', '.ttf', '.eot',
|
|
42
|
+
]);
|
|
43
|
+
// File patterns that indicate test/spec files (not production code).
|
|
44
|
+
const TEST_FILE_PATTERNS = [
|
|
45
|
+
/\.spec\.[tj]sx?$/,
|
|
46
|
+
/\.test\.[tj]sx?$/,
|
|
47
|
+
/_test\.go$/,
|
|
48
|
+
/\.stories\.[tj]sx?$/,
|
|
49
|
+
];
|
|
50
|
+
// Config file patterns that are not production source code.
|
|
51
|
+
const CONFIG_FILE_PATTERNS = [
|
|
52
|
+
/\.config\.[tj]sx?$/,
|
|
53
|
+
/\.config\.json$/,
|
|
54
|
+
/\.config\.js$/,
|
|
55
|
+
];
|
|
56
|
+
function isRelevantFile(file) {
|
|
57
|
+
const segments = file.split('/');
|
|
58
|
+
const basename = segments[segments.length - 1] || file;
|
|
59
|
+
if (IGNORED_BASENAMES.has(basename)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
for (const seg of segments) {
|
|
63
|
+
if (IGNORED_DIR_SEGMENTS.includes(seg)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const dotIdx = basename.lastIndexOf('.');
|
|
68
|
+
if (dotIdx > 0) {
|
|
69
|
+
const ext = basename.slice(dotIdx).toLowerCase();
|
|
70
|
+
if (IGNORED_EXTENSIONS.has(ext)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Filter test/spec files — they don't impact production features
|
|
75
|
+
for (const pattern of TEST_FILE_PATTERNS) {
|
|
76
|
+
if (pattern.test(basename)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Filter config files
|
|
81
|
+
for (const pattern of CONFIG_FILE_PATTERNS) {
|
|
82
|
+
if (pattern.test(basename)) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
5
88
|
function runGitRaw(args, cwd) {
|
|
6
89
|
const result = spawnSync('git', args, {
|
|
7
90
|
cwd,
|
|
@@ -63,23 +146,26 @@ export function getChangedFiles(appRoot, since, options) {
|
|
|
63
146
|
baseStrategy = 'merge-base';
|
|
64
147
|
}
|
|
65
148
|
}
|
|
66
|
-
|
|
149
|
+
// Get repo root so we capture ALL changed files (including server/, webapp/, etc.)
|
|
150
|
+
// not just files under the appRoot subdirectory.
|
|
151
|
+
const repoRoot = runGitRaw(['rev-parse', '--show-toplevel'], appRoot)?.trim() || appRoot;
|
|
152
|
+
const diffFiles = runGit(['diff', '--name-only', `${baseRef}..HEAD`], repoRoot);
|
|
67
153
|
if (!diffFiles) {
|
|
68
154
|
return { files: [], error: 'git diff failed' };
|
|
69
155
|
}
|
|
70
156
|
diffFiles.forEach((file) => files.add(file));
|
|
71
157
|
if (options?.includeUncommitted) {
|
|
72
|
-
const staged = runGit(['diff', '--name-only', '--cached'
|
|
158
|
+
const staged = runGit(['diff', '--name-only', '--cached'], repoRoot) || [];
|
|
73
159
|
staged.forEach((file) => files.add(file));
|
|
74
|
-
const unstaged = runGit(['diff', '--name-only'
|
|
160
|
+
const unstaged = runGit(['diff', '--name-only'], repoRoot) || [];
|
|
75
161
|
unstaged.forEach((file) => files.add(file));
|
|
76
|
-
const statusOutput = runGitRaw(['status', '--porcelain'
|
|
162
|
+
const statusOutput = runGitRaw(['status', '--porcelain'], repoRoot);
|
|
77
163
|
if (statusOutput) {
|
|
78
164
|
const statusLines = statusOutput.split('\n').filter(Boolean);
|
|
79
165
|
parseStatusLines(statusLines).forEach((file) => files.add(file));
|
|
80
166
|
}
|
|
81
167
|
}
|
|
82
|
-
return { files: Array.from(files), baseRef, baseStrategy };
|
|
168
|
+
return { files: Array.from(files).filter(isRelevantFile), baseRef, baseStrategy };
|
|
83
169
|
}
|
|
84
170
|
catch {
|
|
85
171
|
return { files: [], error: 'git diff failed' };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yasserkhanorg/e2e-agents",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "AI-powered E2E test impact analysis, generation, and healing. Analyzes code changes to identify affected Playwright tests, detects coverage gaps, and generates or repairs specs using pluggable LLM providers (Claude, OpenAI, Ollama). Includes MCP server, traceability, and CI/CD integration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|