nikolay-e/AutoQA

Automated post-deploy QA: Playwright crawler + axe accessibility + Schemathesis API fuzzing + OWASP ZAP security scan + Mozilla Observatory + visual regression + AuthZ matrix + baseline diff

View on GitHub

Trust Signals

Scorecard Score
not yet scored
Maintenance Recency
Activelast commit Jul 9, 2026
License
MIT

Pinned Snippet

workflow.ymlSHA-pinned
uses: nikolay-e/autoqa@9c2f6c04bfd7c6d4313f940b4d3b7adb8c0bb14c # v1.0.1

tags can be moved; commit SHAs can't. why a SHA?

namedescriptionrequireddefault
urlBase production URLyes
auth-urlAPI auth endpoint path for Bearer token (e.g., /api/Users/AuthenticateByName)""
auth-bodyJSON body for auth request""
auth-modeHow to acquire the auth token. 'curl' (default): POST to auth-url with auth-body. 'playwright': render auth-login-page in a real browser (set to bypass Cloudflare/Akamai bot challenges that filter curl).curl
auth-login-pageLogin page path used when auth-mode=playwright (e.g., /login). Falls back to crawler-login-url if empty.""
http-basic-usernameUsername for proxy-level HTTP Basic Auth (e.g., Traefik basicAuth middleware in front of the whole site). Applies to crawler + monkey (Playwright httpCredentials) and Schemathesis (Authorization: Basic; a Bearer token from auth-url wins when both are set — one Authorization header). Not supported for Observatory (scans from Mozilla's servers) or ZAP. Empty = off. Ref: issue #26.""
http-basic-passwordPassword for proxy-level HTTP Basic Auth (set as a secret in the downstream workflow).""
crawler-enabledRun Playwright crawlertrue
crawler-usernameForm login username (empty = skip form login)""
crawler-passwordForm login password""
crawler-login-urlLogin page path/login
crawler-login-selector-usernameCSS selector for username inputinput[type="text"], input[type="email"]
crawler-login-selector-passwordCSS selector for password inputinput[type="password"]
crawler-login-selector-submitCSS selector for submit buttonbutton[type="submit"], button
crawler-seed-pagesComma-separated seed paths to start crawling from/
crawler-max-pagesMaximum pages to crawl50
crawler-wait-msWait time between pages in milliseconds2000
crawler-exclude-urlsComma-separated URL patterns to ignore in error reporting""
crawler-console-ignoreComma-separated substrings matched against console message text or source script URL; matching messages are dropped from error reporting (third-party noise such as CDN bot-challenge probes)""
crawler-decorative-pathsComma-separated URL substrings (e.g. /Images/) for optional decorative resources. 4xx network errors / broken links whose URL matches are downgraded by the final gate from a blocking finding to non-blocking info — for assets that are legitimately absent (404 is the correct API answer and the UI renders a placeholder) and whose per-item ids keep them from settling into the baseline. Empty = off.""
crawler-fail-on-violationsFail the composite action when the crawler reports violations (broken links, JS errors, critical axe, CSP, mixed content, network errors). Honored by the final gate step. Ignored when baseline-enabled=true (baseline diff governs instead).true
baseline-enabledDiff crawler findings against cached baseline; fail PRs only on NEW findings (push to main updates baseline)true
baseline-fail-on-newMake NEW crawler findings blocking even on push to main/master. The baseline still updates in the same run, so a regression fails exactly one run and is absorbed for the next (alarm-once). For consumers whose only autoqa runs are post-deploy on main — without this the baseline gate can never block there. First run with no cached baseline never blocks.false
mechanical-fail-on-violationsFail the composite action when Phase 1.5 mechanical checks (M1–M6) report any P0 finding. P1 findings are always informational. Default off because mechanical checks are advisory.false
schemathesis-enabledRun Schemathesis API fuzzingfalse
schemathesis-fail-on-violationsFail the composite action when Schemathesis reports failed/errored cases.true
openapi-urlOpenAPI spec path (e.g., /api/openapi.json)""
schemathesis-base-urlOverride Schemathesis --url (defaults to `url`). Use when the API mounts under a path prefix that differs from the crawler entry, e.g., the PWA serves `/` and the backend is at `/api/*` — set this to `https://host/api` so Schemathesis hits the backend, not the SPA shell.""
schemathesis-exclude-pathsComma-separated API paths to exclude from fuzzing""
schemathesis-exclude-checksComma-separated Schemathesis checks to excludeignored_auth,unsupported_method
zap-enabledRun OWASP ZAP security scanfalse
zap-fail-on-violationsFail the composite action when ZAP reports HIGH-risk alerts.true
zap-rate-limited-pathsComma-separated URL substrings for endpoints fronted by a rate limiter / auth gate (e.g. /api/auth/login). A HIGH ZAP alert (typically boolean-based SQLi) on such a path is a false positive — the differential ZAP measured is the limiter's 429/403, not a DB-level injection; the attack never reached the database. The traditional -J report carries no per-instance HTTP status, so the gate cannot see the 429 directly; instead a HIGH alert is downgraded by the final gate from blocking to non-blocking info only when EVERY one of its instances targets a declared path (an alert that also fires on an un-gated path still blocks). Empty = off. Ref: issue #7.""
observatory-enabledRun MDN HTTP Observatory security-headers scanfalse
observatory-fail-gradeFail if Observatory grade is worse than this (A+ A A- B+ B B- C+ C C- D+ D D- F)B
observatory-fail-on-violationsFail the composite action when Observatory grade is worse than observatory-fail-grade.true
argos-enabledCapture screenshots at 1440x900 and 375x667 viewports and upload to Argos for visual regressionfalse
argos-tokenArgos CI repository token (set as a secret in the downstream workflow)""
authz-enabledRun AuthZ two-token matrix (BOLA / OWASP API1:2023) against resource paths owned by user Afalse
authz-user-a-bodyJSON body for user A login (sent to auth-url)""
authz-user-b-bodyJSON body for user B login (sent to auth-url)""
authz-resource-pathsComma-separated resource paths owned by user A (e.g., /api/notes/1,/api/notes/2). For each: user A must get 2xx, user B must get 401/403/404, no-auth must get 401/403/404.""
authz-fail-on-violationsFail the composite action when the AuthZ matrix reports BOLA / auth-bypass.true
monkey-enabledRun the monkey / chaos UI tester — seeded random Playwright interactions (clicks, fuzz input, keys, navigation) for a time budget, hunting crashes, uncaught JS errors and 5xx responses. Opt-in. Reuses crawler-username/password/login selectors to log in first.false
monkey-duration-msMonkey time budget in milliseconds (default 300000 = 5 minutes). A hard-kill backstop fires 30s after this.300000
monkey-seedSeed for the monkey's PRNG. Same seed + same app replays the same action sequence; the seed is logged in the report so a crash can be reproduced.1337
monkey-seed-pagesComma-separated paths the monkey starts from and resets to when it gets stuck (default '/')./
monkey-avoid-textComma-separated lowercased text / aria-label substrings the monkey will NOT click, so it does not log itself out or delete data and end the session early. Set empty to allow destructive controls.logout,log out,sign out,signout,delete account,deactivate,remove account
monkey-exclude-urlsComma-separated URL substrings to ignore in monkey error reporting (third-party noise).""
monkey-console-ignoreComma-separated substrings matched against monkey console-error text or source script URL; matching messages are dropped from error reporting. Falls back to crawler-console-ignore when empty.""
monkey-fail-on-violationsFail the composite action when the monkey finds a serious issue (crash / uncaught JS error / 5xx). Default off — the monkey is advisory because exploration is inherently variable; console errors and failed requests are always non-blocking info.false
extra-findings-pathPath to a JSON array of custom StandardFindings (fingerprint/severity/category/tool/title/url/…) from your own checks. Merged into the normalized findings.json and the COMPLETE report without forking autoqa. Invalid entries are dropped (warned), never fatal.""
namedescription
report-pathDirectory containing all reports
complete-report-mdPath to the always-on human-readable COMPLETE QA report
findings-jsonPath to the normalized StandardFinding[] (machine-readable)
pages-visitedNumber of pages crawled
js-errorsNumber of JS errors found
axe-violationsNumber of accessibility violations found
broken-linksNumber of broken links found
csp-violationsNumber of CSP violations captured
mixed-contentNumber of mixed-content requests captured
monkey-actionsNumber of monkey actions performed
monkey-seriousNumber of serious monkey findings (crashes / uncaught errors / 5xx)