qaify-playwright-reporter 0.7.0 → 0.8.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 +9 -5
- package/dist/audit.d.ts +4 -0
- package/dist/audit.js +4 -1
- package/dist/cli.js +2 -1
- package/package.json +1 -1
- package/templates/qaify-audit.yml +27 -9
package/README.md
CHANGED
|
@@ -105,11 +105,15 @@ Untuk aplikasi yang repo FE dan BE-nya terpisah dan belum memasang Playwright, Q
|
|
|
105
105
|
|
|
106
106
|
1. Pilih repo runner: repo kosong (mis. `qaify-runner`) atau repo aplikasinya sendiri. Jalankan `npx qaify-playwright-reporter init-runner` di dalamnya. Perintah ini menulis `.github/workflows/qaify-audit.yml`.
|
|
107
107
|
2. Pasang GitHub App Qaify di repo runner, repo FE, dan repo BE.
|
|
108
|
-
3. Di repo runner, isi secret `QA_FACTORY_TOKEN` (token reporter repo runner), dan variable `QA_FACTORY_URL`. Secret `CLAUDE_CODE_OAUTH_TOKEN` bersifat opsional.
|
|
108
|
+
3. Di repo runner, isi secret `QA_FACTORY_TOKEN` (token reporter repo runner), dan variable `QA_FACTORY_URL`. Secret `CLAUDE_CODE_OAUTH_TOKEN` bersifat opsional. Secret ini dibutuhkan untuk [perbaikan temuan oleh Claude](#perbaikan-temuan-audit-oleh-claude-pr-ke-repo-febe) dan audit mode Claude.
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
-
|
|
110
|
+
Mode audit dipilih di Qaify: **Tanpa AI** (default) atau **Claude**, sebagai setelan aplikasi, dan bisa diganti di dialog **Audit sekarang**. Jadi Claude bisa dipakai hanya untuk memperbaiki temuan, sementara auditnya tetap tanpa AI. Mode Claude tanpa secret di atas dijalankan sebagai Tanpa AI (dengan peringatan di run).
|
|
111
|
+
|
|
112
|
+
- **Tanpa AI** (`qaify audit-static`): build, test, `composer audit` / `npm audit`, route GET publik BE, dan smoke test Playwright FE (desktop + mobile, screenshot setiap halaman untuk lampiran laporan PDF). Smoke test juga memeriksa elemen yang meluap, gambar rusak, tombol yang tertutup elemen lain, error JavaScript, request API, dan aset yang gagal. Setiap jenis masalah difoto lagi dengan kotak merah di elemennya atau banner berisi pesan errornya. Temuan smoke diberi halaman dan berkas sumber bila bisa ditebak (route FE → komponen halaman, route BE → method controller). Request FE yang gagal dipetakan ke controller BE, dan route BE yang error dihubungkan ke halaman FE yang memanggilnya.
|
|
113
|
+
- **Claude**: Claude yang mengaudit. Hasilnya lebih dalam, termasuk logika bisnis dan kontrak API, tetapi memakan kuota langganan.
|
|
114
|
+
- Variable `QA_FACTORY_AUDIT_MODE` (`static` / `claude`) hanya dipakai bila backend Qaify belum mengirim mode (versi lama).
|
|
115
|
+
|
|
116
|
+
Runner yang dibuat sebelum 0.8 perlu memperbarui workflow: `npx qaify-playwright-reporter init-runner --force`. Tanpa itu, workflow lama tetap memilih mode dari secret dan variable.
|
|
113
117
|
4. Di Qaify → **Aplikasi**, tambahkan aplikasi (repo FE, BE, runner), lalu klik **Audit sekarang**.
|
|
114
118
|
|
|
115
119
|
Alur di workflow:
|
|
@@ -128,7 +132,7 @@ Keamanan:
|
|
|
128
132
|
- `QA_FACTORY_TOKEN` tidak tersedia di step Claude.
|
|
129
133
|
- Isi repo diperlakukan sebagai data, bukan instruksi.
|
|
130
134
|
|
|
131
|
-
Satu audit adalah satu sesi Claude yang panjang (sampai 45 menit), sehingga memakan kuota langganan pemilik runner.
|
|
135
|
+
Satu audit mode Claude adalah satu sesi Claude yang panjang (sampai 45 menit), sehingga memakan kuota langganan pemilik runner. Audit tanpa AI tidak memakai kuota.
|
|
132
136
|
|
|
133
137
|
## Perbaikan temuan audit oleh Claude (PR ke repo FE/BE)
|
|
134
138
|
|
package/dist/audit.d.ts
CHANGED
|
@@ -279,9 +279,13 @@ export declare const defaultExec: Exec;
|
|
|
279
279
|
export interface AuditContextResult {
|
|
280
280
|
ok: boolean;
|
|
281
281
|
commits: Record<string, string>;
|
|
282
|
+
/** auditor pilihan Qaify (static / claude); undefined = backend lama, workflow memilih sendiri */
|
|
283
|
+
mode?: AuditMode;
|
|
282
284
|
/** alasan gagal; juga ditulis ke context-error.txt agar audit-submit bisa melaporkannya */
|
|
283
285
|
error?: string;
|
|
284
286
|
}
|
|
287
|
+
export declare const AUDIT_MODES: readonly ["static", "claude"];
|
|
288
|
+
export type AuditMode = (typeof AUDIT_MODES)[number];
|
|
285
289
|
/**
|
|
286
290
|
* GET /api/ingest/audits/{id}/context → clone apps/<role> → cabut token.
|
|
287
291
|
* Token hanya lewat header git dari environment (tidak pernah di argumen, URL remote, atau disk)
|
package/dist/audit.js
CHANGED
|
@@ -174,6 +174,7 @@ export function parseAuditOutput(raw) {
|
|
|
174
174
|
const execFileAsync = promisify(execFile);
|
|
175
175
|
export const defaultExec = async (file, args, env) => (await execFileAsync(file, args, { env: { ...process.env, ...env }, maxBuffer: 10 * 1024 * 1024 })).stdout;
|
|
176
176
|
const branchOf = (repo) => repo.branch || repo.default_branch;
|
|
177
|
+
export const AUDIT_MODES = ['static', 'claude'];
|
|
177
178
|
const CONTEXT_ERROR_FILE = 'context-error.txt';
|
|
178
179
|
/**
|
|
179
180
|
* GET /api/ingest/audits/{id}/context → clone apps/<role> → cabut token.
|
|
@@ -214,12 +215,14 @@ export async function auditContext(client, auditId, dir, opts = {}) {
|
|
|
214
215
|
return contextFailed(dir, `Clone repo gagal: ${detail}`, commits);
|
|
215
216
|
}
|
|
216
217
|
await revoke(repos, opts.fetch);
|
|
218
|
+
const mode = AUDIT_MODES.includes(ctx.mode) ? ctx.mode : undefined;
|
|
217
219
|
await writeFile(join(dir, 'context.json'), JSON.stringify({
|
|
218
220
|
audit_id: ctx.audit_id,
|
|
221
|
+
mode: mode ?? null,
|
|
219
222
|
project: ctx.project,
|
|
220
223
|
repos: repos.map((r) => ({ role: r.role, full_name: r.full_name, branch: branchOf(r), commit: commits[r.role] ?? null })),
|
|
221
224
|
}, null, 2));
|
|
222
|
-
return { ok: true, commits };
|
|
225
|
+
return { ok: true, commits, mode };
|
|
223
226
|
}
|
|
224
227
|
/** Peringatan (annotation di ringkasan run) + context-error.txt untuk audit-submit. */
|
|
225
228
|
async function contextFailed(dir, error, commits) {
|
package/dist/cli.js
CHANGED
|
@@ -137,8 +137,9 @@ switch (args.command) {
|
|
|
137
137
|
// step merah: tanpa ini auditor & kirim hasil dilewati diam-diam dan audit macet "running"
|
|
138
138
|
process.exitCode = 1;
|
|
139
139
|
}
|
|
140
|
+
// mode kosong = backend lama: workflow memilih dari variable / secret
|
|
140
141
|
if (process.env.GITHUB_OUTPUT)
|
|
141
|
-
await appendFile(process.env.GITHUB_OUTPUT, `ok=${result.ok}\n`);
|
|
142
|
+
await appendFile(process.env.GITHUB_OUTPUT, `ok=${result.ok}\nmode=${('mode' in result && result.mode) || ''}\n`);
|
|
142
143
|
break;
|
|
143
144
|
}
|
|
144
145
|
case 'audit-schema': {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qaify-playwright-reporter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Reporter Playwright untuk QA Factory (Qaify): kirim hasil test dan artefak ke /api/ingest, tanpa pernah menggagalkan test.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ahmdkenz",
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
# Butuh di repo runner ini (Settings → Secrets and variables → Actions):
|
|
4
4
|
# secret QA_FACTORY_TOKEN token reporter repo runner (Pengaturan → Token Reporter)
|
|
5
5
|
# variable QA_FACTORY_URL URL API Qaify
|
|
6
|
-
# secret CLAUDE_CODE_OAUTH_TOKEN opsional: audit
|
|
7
|
-
# variable QA_FACTORY_AUDIT_MODE opsional, `static`
|
|
6
|
+
# secret CLAUDE_CODE_OAUTH_TOKEN opsional: perbaikan temuan & audit mode claude (langganan Claude Pro/Max, `claude setup-token`)
|
|
7
|
+
# variable QA_FACTORY_AUDIT_MODE opsional, `static` / `claude`; hanya dipakai bila Qaify tidak mengirim mode
|
|
8
8
|
# variable QA_FACTORY_AI_MODEL opsional, default sonnet
|
|
9
9
|
# variable QA_FACTORY_MCP_VERSION opsional, versi @playwright/mcp (default latest)
|
|
10
10
|
# GitHub App Qaify harus terpasang di repo ini dan di repo FE + BE. Nama file harus tetap qaify-audit.yml.
|
|
11
|
+
# Mode audit dipilih di Qaify (setelan aplikasi, bisa diganti per audit); mode claude tanpa secret jatuh ke static.
|
|
11
12
|
# Mode static (tanpa AI): build, test, composer/npm audit, dan smoke test Playwright; cepat, tanpa kuota AI,
|
|
12
|
-
# tetapi tanpa analisis logika bisnis / kontrak API dari kode.
|
|
13
|
+
# tetapi tanpa analisis logika bisnis / kontrak API dari kode. Temuannya tetap bisa diperbaiki Claude (qaify-fix.yml).
|
|
13
14
|
# Mode claude: satu sesi Claude yang panjang; kuota langganan dipakai bersama pemakaian pribadi.
|
|
14
15
|
name: Qaify audit
|
|
15
16
|
run-name: audit ${{ inputs.audit_id }}
|
|
@@ -42,9 +43,8 @@ jobs:
|
|
|
42
43
|
env: { POSTGRES_PASSWORD: postgres, POSTGRES_DB: app }
|
|
43
44
|
ports: ['5432:5432']
|
|
44
45
|
options: --health-cmd="pg_isready -U postgres" --health-interval=10s --health-timeout=5s --health-retries=10
|
|
45
|
-
# context runner tidak tersedia di env level job; WORK diisi lewat GITHUB_ENV di step pertama
|
|
46
|
-
|
|
47
|
-
AUDIT_MODE: ${{ vars.QA_FACTORY_AUDIT_MODE || (secrets.CLAUDE_CODE_OAUTH_TOKEN != '' && 'claude' || 'static') }}
|
|
46
|
+
# context runner tidak tersedia di env level job; WORK diisi lewat GITHUB_ENV di step pertama,
|
|
47
|
+
# AUDIT_MODE di step "Tentukan mode audit" (mode baru diketahui dari konteks audit)
|
|
48
48
|
steps:
|
|
49
49
|
- name: Siapkan direktori kerja
|
|
50
50
|
run: echo "WORK=$RUNNER_TEMP/qaify" >> "$GITHUB_ENV"
|
|
@@ -58,9 +58,7 @@ jobs:
|
|
|
58
58
|
tools: composer
|
|
59
59
|
|
|
60
60
|
- name: Pasang Qaify CLI
|
|
61
|
-
run:
|
|
62
|
-
npm install -g qaify-playwright-reporter@0.5 playwright-core@1
|
|
63
|
-
if [ "$AUDIT_MODE" = claude ]; then npm install -g @anthropic-ai/claude-code; fi
|
|
61
|
+
run: npm install -g qaify-playwright-reporter@0.8 playwright-core@1
|
|
64
62
|
|
|
65
63
|
# token clone sekali pakai (read-only, hanya repo FE + BE) dicabut sebelum auditor berjalan
|
|
66
64
|
- name: Ambil konteks & clone repo FE + BE
|
|
@@ -70,6 +68,25 @@ jobs:
|
|
|
70
68
|
QA_FACTORY_TOKEN: ${{ secrets.QA_FACTORY_TOKEN }}
|
|
71
69
|
run: qaify audit-context --audit "${{ inputs.audit_id }}" --dir "$WORK"
|
|
72
70
|
|
|
71
|
+
# pilihan Qaify → variable QA_FACTORY_AUDIT_MODE → claude bila secret ada; claude tanpa secret → static
|
|
72
|
+
- name: Tentukan mode audit
|
|
73
|
+
if: steps.ctx.outputs.ok == 'true'
|
|
74
|
+
env:
|
|
75
|
+
REQUESTED: ${{ steps.ctx.outputs.mode || vars.QA_FACTORY_AUDIT_MODE }}
|
|
76
|
+
HAS_CLAUDE: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN != '' }}
|
|
77
|
+
run: |
|
|
78
|
+
mode="${REQUESTED:-$([ "$HAS_CLAUDE" = true ] && echo claude || echo static)}"
|
|
79
|
+
if [ "$mode" != static ] && [ "$mode" != claude ]; then
|
|
80
|
+
echo "::warning::Mode audit tidak dikenal ($mode); memakai static."
|
|
81
|
+
mode=static
|
|
82
|
+
fi
|
|
83
|
+
if [ "$mode" = claude ] && [ "$HAS_CLAUDE" != true ]; then
|
|
84
|
+
echo "::warning::Mode claude diminta tetapi secret CLAUDE_CODE_OAUTH_TOKEN kosong; audit dijalankan tanpa AI."
|
|
85
|
+
mode=static
|
|
86
|
+
fi
|
|
87
|
+
echo "qa-factory: mode audit $mode"
|
|
88
|
+
echo "AUDIT_MODE=$mode" >> "$GITHUB_ENV"
|
|
89
|
+
|
|
73
90
|
# tanpa secret apa pun: kode aplikasi (composer/npm script) berjalan di step ini
|
|
74
91
|
- name: Audit tanpa AI (Playwright)
|
|
75
92
|
if: steps.ctx.outputs.ok == 'true' && env.AUDIT_MODE == 'static'
|
|
@@ -80,6 +97,7 @@ jobs:
|
|
|
80
97
|
- name: Siapkan instruksi & Playwright MCP
|
|
81
98
|
if: steps.ctx.outputs.ok == 'true' && env.AUDIT_MODE == 'claude'
|
|
82
99
|
run: |
|
|
100
|
+
npm install -g @anthropic-ai/claude-code
|
|
83
101
|
mkdir -p "$WORK/.qaify"
|
|
84
102
|
qaify audit-schema --out "$WORK/.qaify/schema.json" --instructions "$WORK/.qaify/instructions.txt"
|
|
85
103
|
# Google Chrome sudah ada di runner ubuntu-latest
|