comfy-qa 1.26.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/package.json +1 -2
- package/src/cli.ts +14 -14
- package/src/commands/full.ts +1 -1
- package/src/commands/issue.ts +3 -3
- package/src/commands/pr.ts +3 -3
- package/src/utils/github.ts +38 -28
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ E2E QA automation for user-facing frontend repos. AI-driven Playwright tests wit
|
|
|
7
7
|
Tell your AI agent (Claude Code, Cursor, etc.):
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
run npx
|
|
10
|
+
run npx comfy-qa setup
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
The agent reads the emitted prompt and automatically:
|
|
@@ -20,21 +20,21 @@ The agent reads the emitted prompt and automatically:
|
|
|
20
20
|
- Creates starter `tests/e2e/qa.spec.ts` covering your key routes
|
|
21
21
|
- Updates `.gitignore`
|
|
22
22
|
|
|
23
|
-
Re-running `npx
|
|
23
|
+
Re-running `npx comfy-qa setup` updates existing files without overwriting what's already correct.
|
|
24
24
|
|
|
25
25
|
## QA a PR or issue
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
# Paste a GitHub URL — auto-detects PR vs issue
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
comfy-qa https://github.com/org/repo/pull/123
|
|
30
|
+
comfy-qa https://github.com/org/repo/issues/456
|
|
31
31
|
|
|
32
32
|
# Or use subcommands
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
comfy-qa pr https://github.com/org/repo/pull/123
|
|
34
|
+
comfy-qa issue org/repo#456
|
|
35
35
|
|
|
36
36
|
# Batch QA recent open issues
|
|
37
|
-
|
|
37
|
+
comfy-qa full org/repo --limit 5
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Each run produces in `.comfy-qa/<slug>/`:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comfy-qa",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "ComfyUI QA automation CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
"type": "module",
|
|
12
12
|
"bin": {
|
|
13
13
|
"comfy-qa": "./src/cli.ts",
|
|
14
|
-
"cmqa": "./src/cli.ts",
|
|
15
14
|
"qabot": "./bot/cli.ts"
|
|
16
15
|
},
|
|
17
16
|
"files": [
|
package/src/cli.ts
CHANGED
|
@@ -10,17 +10,17 @@ const args = Bun.argv.slice(2);
|
|
|
10
10
|
const cmd = args[0];
|
|
11
11
|
const rest = args.slice(1);
|
|
12
12
|
|
|
13
|
-
const HELP = `
|
|
13
|
+
const HELP = `comfy-qa — E2E QA automation for frontend repos
|
|
14
14
|
|
|
15
15
|
USAGE
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
comfy-qa setup Emit setup prompt for your agent
|
|
17
|
+
comfy-qa <github-url> Auto-detect PR or issue from URL
|
|
18
|
+
comfy-qa pr <github-url | owner/repo#N> Research & QA a pull request
|
|
19
|
+
comfy-qa issue <github-url | owner/repo#N> Research & QA an issue / bug report
|
|
20
|
+
comfy-qa full <owner/repo> Batch QA recent open issues
|
|
21
21
|
|
|
22
22
|
SETUP (one-shot)
|
|
23
|
-
Tell your agent: "run npx
|
|
23
|
+
Tell your agent: "run npx comfy-qa setup"
|
|
24
24
|
The agent reads the emitted prompt and sets up a complete QA workflow
|
|
25
25
|
for the current repo — Playwright config, E2E tests, skill files, etc.
|
|
26
26
|
|
|
@@ -33,12 +33,12 @@ OPTIONS
|
|
|
33
33
|
-v, --version Show version
|
|
34
34
|
|
|
35
35
|
EXAMPLES
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
comfy-qa setup
|
|
37
|
+
comfy-qa https://github.com/org/repo/pull/123
|
|
38
|
+
comfy-qa https://github.com/org/repo/issues/456
|
|
39
|
+
comfy-qa pr org/repo#123
|
|
40
|
+
comfy-qa issue org/repo#456 --no-record
|
|
41
|
+
comfy-qa full org/repo --limit 3
|
|
42
42
|
`;
|
|
43
43
|
|
|
44
44
|
if (!cmd || cmd === "-h" || cmd === "--help") {
|
|
@@ -72,7 +72,7 @@ if (urlParsed) {
|
|
|
72
72
|
await commandFull(rest);
|
|
73
73
|
break;
|
|
74
74
|
default:
|
|
75
|
-
console.error(`Unknown command: ${cmd}\nRun '
|
|
75
|
+
console.error(`Unknown command: ${cmd}\nRun 'comfy-qa --help' for usage.`);
|
|
76
76
|
process.exit(1);
|
|
77
77
|
}
|
|
78
78
|
}
|
package/src/commands/full.ts
CHANGED
|
@@ -10,7 +10,7 @@ export async function commandFull(args: string[]): Promise<void> {
|
|
|
10
10
|
const comfyUrl = comfyUrlIdx >= 0 ? args[comfyUrlIdx + 1] : undefined;
|
|
11
11
|
|
|
12
12
|
if (!repoRef) {
|
|
13
|
-
console.error("Usage:
|
|
13
|
+
console.error("Usage: comfy-qa full <owner/repo> [--limit N] [--no-record]");
|
|
14
14
|
process.exit(1);
|
|
15
15
|
}
|
|
16
16
|
|
package/src/commands/issue.ts
CHANGED
|
@@ -7,15 +7,15 @@ export async function commandIssue(args: string[]): Promise<void> {
|
|
|
7
7
|
const comfyUrlIdx = args.indexOf("--comfy-url");
|
|
8
8
|
const comfyUrl = comfyUrlIdx >= 0 ? args[comfyUrlIdx + 1] : undefined;
|
|
9
9
|
|
|
10
|
-
// Accept GitHub URL:
|
|
10
|
+
// Accept GitHub URL: comfy-qa issue https://github.com/org/repo/issues/456
|
|
11
11
|
if (ref) {
|
|
12
12
|
const parsed = parseGitHubUrl(ref);
|
|
13
13
|
if (parsed) ref = parsed.ref;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
if (!ref) {
|
|
17
|
-
console.error("Usage:
|
|
18
|
-
console.error("
|
|
17
|
+
console.error("Usage: comfy-qa issue <github-url | owner/repo#number>");
|
|
18
|
+
console.error(" comfy-qa issue https://github.com/org/repo/issues/456");
|
|
19
19
|
process.exit(1);
|
|
20
20
|
}
|
|
21
21
|
|
package/src/commands/pr.ts
CHANGED
|
@@ -7,15 +7,15 @@ export async function commandPR(args: string[]): Promise<void> {
|
|
|
7
7
|
const comfyUrlIdx = args.indexOf("--comfy-url");
|
|
8
8
|
const comfyUrl = comfyUrlIdx >= 0 ? args[comfyUrlIdx + 1] : undefined;
|
|
9
9
|
|
|
10
|
-
// Accept GitHub URL:
|
|
10
|
+
// Accept GitHub URL: comfy-qa pr https://github.com/org/repo/pull/123
|
|
11
11
|
if (ref) {
|
|
12
12
|
const parsed = parseGitHubUrl(ref);
|
|
13
13
|
if (parsed) ref = parsed.ref;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
if (!ref) {
|
|
17
|
-
console.error("Usage:
|
|
18
|
-
console.error("
|
|
17
|
+
console.error("Usage: comfy-qa pr <github-url | owner/repo#number>");
|
|
18
|
+
console.error(" comfy-qa pr https://github.com/org/repo/pull/123");
|
|
19
19
|
process.exit(1);
|
|
20
20
|
}
|
|
21
21
|
|
package/src/utils/github.ts
CHANGED
|
@@ -37,46 +37,56 @@ export function parseRef(ref: string): { owner: string; repo: string; number?: n
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export async function fetchPR(owner: string, repo: string, number: number): Promise<PRInfo> {
|
|
40
|
-
const
|
|
41
|
-
|
|
40
|
+
const [prJson, filesJson, commentsJson] = await Promise.all([
|
|
41
|
+
$`gh api repos/${owner}/${repo}/pulls/${number}`.text(),
|
|
42
|
+
$`gh api repos/${owner}/${repo}/pulls/${number}/files --paginate`.text(),
|
|
43
|
+
$`gh api repos/${owner}/${repo}/issues/${number}/comments --paginate`.text(),
|
|
44
|
+
]);
|
|
45
|
+
const pr = JSON.parse(prJson);
|
|
46
|
+
const files = JSON.parse(filesJson);
|
|
47
|
+
const comments = JSON.parse(commentsJson);
|
|
42
48
|
return {
|
|
43
|
-
number:
|
|
44
|
-
title:
|
|
45
|
-
body:
|
|
46
|
-
state:
|
|
47
|
-
headRefName:
|
|
48
|
-
baseRefName:
|
|
49
|
-
author:
|
|
50
|
-
labels: (
|
|
51
|
-
url:
|
|
52
|
-
files:
|
|
53
|
-
path: f.
|
|
49
|
+
number: pr.number,
|
|
50
|
+
title: pr.title,
|
|
51
|
+
body: pr.body || "",
|
|
52
|
+
state: pr.state,
|
|
53
|
+
headRefName: pr.head.ref,
|
|
54
|
+
baseRefName: pr.base.ref,
|
|
55
|
+
author: pr.user?.login || "unknown",
|
|
56
|
+
labels: (pr.labels || []).map((l: any) => l.name),
|
|
57
|
+
url: pr.html_url,
|
|
58
|
+
files: files.map((f: any) => ({
|
|
59
|
+
path: f.filename,
|
|
54
60
|
additions: f.additions,
|
|
55
61
|
deletions: f.deletions,
|
|
56
62
|
})),
|
|
57
|
-
comments:
|
|
58
|
-
author: c.
|
|
63
|
+
comments: comments.map((c: any) => ({
|
|
64
|
+
author: c.user?.login || "unknown",
|
|
59
65
|
body: c.body || "",
|
|
60
|
-
createdAt: c.
|
|
66
|
+
createdAt: c.created_at,
|
|
61
67
|
})),
|
|
62
68
|
};
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
export async function fetchIssue(owner: string, repo: string, number: number): Promise<IssueInfo> {
|
|
66
|
-
const
|
|
67
|
-
|
|
72
|
+
const [issueJson, commentsJson] = await Promise.all([
|
|
73
|
+
$`gh api repos/${owner}/${repo}/issues/${number}`.text(),
|
|
74
|
+
$`gh api repos/${owner}/${repo}/issues/${number}/comments --paginate`.text(),
|
|
75
|
+
]);
|
|
76
|
+
const issue = JSON.parse(issueJson);
|
|
77
|
+
const comments = JSON.parse(commentsJson);
|
|
68
78
|
return {
|
|
69
|
-
number:
|
|
70
|
-
title:
|
|
71
|
-
body:
|
|
72
|
-
state:
|
|
73
|
-
author:
|
|
74
|
-
labels: (
|
|
75
|
-
url:
|
|
76
|
-
comments:
|
|
77
|
-
author: c.
|
|
79
|
+
number: issue.number,
|
|
80
|
+
title: issue.title,
|
|
81
|
+
body: issue.body || "",
|
|
82
|
+
state: issue.state,
|
|
83
|
+
author: issue.user?.login || "unknown",
|
|
84
|
+
labels: (issue.labels || []).map((l: any) => l.name),
|
|
85
|
+
url: issue.html_url,
|
|
86
|
+
comments: comments.map((c: any) => ({
|
|
87
|
+
author: c.user?.login || "unknown",
|
|
78
88
|
body: c.body || "",
|
|
79
|
-
createdAt: c.
|
|
89
|
+
createdAt: c.created_at,
|
|
80
90
|
})),
|
|
81
91
|
};
|
|
82
92
|
}
|