Adds a Gitea Actions quality-gate workflow (.gitea/workflows/ci.yml) with four jobs: security, lint, e2e, ai-review. Also adds ESLint (flat config), a Playwright smoke test, jscpd config, and CI.md. Existing lint/format findings are cleaned up so the gates are green from day one. No app behaviour changes.
Commit 1 is a pure cargo fmt reformat of src-tauri (default rustfmt config, no rustfmt.toml). It is mechanical and large, so review it separately (or skip it) and review commits 2 to 4 for the real changes.
Commits
style(src-tauri): cargo fmt - rustfmt only. Checked that the only non-whitespace changes are trailing commas, brace wrapping and else { return } becoming else { return; }.
ci: add quality-gate workflow, ESLint and Playwright smoke test - ci.yml, CI.md, .jscpd.json, eslint.config.js, playwright.config.ts, e2e/smoke.spec.ts, lint and e2e npm scripts, exact-pinned devDependencies (eslint, @eslint/js, typescript-eslint, eslint-plugin-react-hooks, globals, @playwright/test), lockfile, .gitignore entries for Playwright output.
fix: eslint findings - 91 initial findings. Real fixes: dead code and unused imports/variables, useless assignments, one prefer-const. Config tuning (commented in eslint.config.js): _-prefixed unused names allowed, intentional BOM/NBSP allowed in strings/templates/regexes, the React Compiler rules (set-state-in-effect, refs, immutability) and no-explicit-any in src/pdf/testing set to warn. One line-scoped eslint-disable-next-line no-control-regex with reason. 45 warnings remain (visible, non-blocking).
chore: semgrep triage - compare.mjs now passes a constant format string to console.log (identical output) instead of a suppression. The four github-actions-mutable-action-tag warnings in windows-build.yml get # nosemgrep comments only.
Jobs
security: Semgrep 1.178.0 (p/default, p/owasp-top-ten), --error. Also the only job on the weekly schedule.
npm run build && npx playwright test (CI=1, chromium): 2 passed.
ci.yml parses as YAML; actionlint reports only Gitea false positives.
Deviations and judgment calls
Pinned rustfmt toolchain is 1.99.0 (the version used to format), not the crate MSRV 1.95, so cargo fmt --check and the committed formatting agree.
windows-build.yml is annotated only. It needs a windows runner that does not exist; behaviour is unchanged and it was left alone.
React Compiler rules are warnings, not errors, to avoid blind rewrites of effect-heavy views.
Removed an unused totals/words memo in NewInvoice.tsx (dead code that ESLint flagged).
Smoke test has two cases: without Tauri (app shows its "Could not start Voiced" error screen and throws no uncaught errors) and with a stubbed __TAURI_INTERNALS__ (app shell navigation renders). No app code was changed for it.
jscpd pinned to 4.3.0 (latest 4.x; latest overall is 5.x).
Clippy on src-tauri is deferred (needs webkit2gtk/gtk and a full compile on the shared host).
Not exercised locally: the workflow itself on a runner (no push was made), and the ai-review job (needs secrets).
Rollback
Revert this PR. Relax branch protection first if it requires these checks.
Runner verification
The shared workflow was run on the real bongbetic-ci runner on a scratch repo: security, lint and ai-review all passed (ai-review skips with a notice until the two secrets exist). A first scratch run exposed an --entrypoint "" override that made the pr-agent container exit; it is not in this workflow. This repo's own CI run on this PR is the first real run of its repo-specific steps.
## Summary
Adds a Gitea Actions quality-gate workflow (`.gitea/workflows/ci.yml`) with four jobs: `security`, `lint`, `e2e`, `ai-review`. Also adds ESLint (flat config), a Playwright smoke test, jscpd config, and `CI.md`. Existing lint/format findings are cleaned up so the gates are green from day one. No app behaviour changes.
Commit 1 is a pure `cargo fmt` reformat of `src-tauri` (default rustfmt config, no `rustfmt.toml`). It is mechanical and large, so review it separately (or skip it) and review commits 2 to 4 for the real changes.
## Commits
1. `style(src-tauri): cargo fmt` - rustfmt only. Checked that the only non-whitespace changes are trailing commas, brace wrapping and `else { return }` becoming `else { return; }`.
2. `ci: add quality-gate workflow, ESLint and Playwright smoke test` - `ci.yml`, `CI.md`, `.jscpd.json`, `eslint.config.js`, `playwright.config.ts`, `e2e/smoke.spec.ts`, `lint` and `e2e` npm scripts, exact-pinned devDependencies (eslint, @eslint/js, typescript-eslint, eslint-plugin-react-hooks, globals, @playwright/test), lockfile, `.gitignore` entries for Playwright output.
3. `fix: eslint findings` - 91 initial findings. Real fixes: dead code and unused imports/variables, useless assignments, one `prefer-const`. Config tuning (commented in `eslint.config.js`): `_`-prefixed unused names allowed, intentional BOM/NBSP allowed in strings/templates/regexes, the React Compiler rules (`set-state-in-effect`, `refs`, `immutability`) and `no-explicit-any` in `src/pdf/testing` set to warn. One line-scoped `eslint-disable-next-line no-control-regex` with reason. 45 warnings remain (visible, non-blocking).
4. `chore: semgrep triage` - `compare.mjs` now passes a constant format string to `console.log` (identical output) instead of a suppression. The four `github-actions-mutable-action-tag` warnings in `windows-build.yml` get `# nosemgrep` comments only.
## Jobs
- `security`: Semgrep 1.178.0 (`p/default`, `p/owasp-top-ten`), `--error`. Also the only job on the weekly schedule.
- `lint`: `npm ci`, `tsc --noEmit`, ESLint, `cargo fmt --check` (pinned rustup toolchain 1.99.0, rustfmt only, installer checksum verified), jscpd 4.3.0 at threshold 4.5%.
- `e2e`: `mcr.microsoft.com/playwright:v1.63.0-noble`, `npm run build`, Playwright (chromium, 1 worker) against `vite preview`.
- `ai-review`: PR-Agent 0.47.0, pull requests only, advisory (`continue-on-error`), skipped with a notice when secrets are empty.
Required secrets/vars: `OPENROUTER_API_KEY`, `PR_AGENT_GITEA_TOKEN`; optional var `PR_AGENT_MODEL`. See `CI.md`.
## Verification (local, branch tip)
- Semgrep (podman, 1.178.0, `p/default` + `p/owasp-top-ten`, `--error`): exit 0, no findings (main baseline: 5).
- `npm ci && npx tsc --noEmit && npx eslint .`: exit 0 (0 errors, 45 warnings).
- `npm test`: 60 files, 1656 passed | 6 skipped, identical to `origin/main`.
- `cargo fmt --check` in `src-tauri`: clean.
- jscpd 4.3.0: 3.64% duplicated lines (threshold 4.5%, main baseline 3.66%), exit 0.
- `npm run build && npx playwright test` (CI=1, chromium): 2 passed.
- `ci.yml` parses as YAML; actionlint reports only Gitea false positives.
## Deviations and judgment calls
- Pinned `rustfmt` toolchain is 1.99.0 (the version used to format), not the crate MSRV 1.95, so `cargo fmt --check` and the committed formatting agree.
- `windows-build.yml` is annotated only. It needs a `windows` runner that does not exist; behaviour is unchanged and it was left alone.
- React Compiler rules are warnings, not errors, to avoid blind rewrites of effect-heavy views.
- Removed an unused `totals`/`words` memo in `NewInvoice.tsx` (dead code that ESLint flagged).
- Smoke test has two cases: without Tauri (app shows its "Could not start Voiced" error screen and throws no uncaught errors) and with a stubbed `__TAURI_INTERNALS__` (app shell navigation renders). No app code was changed for it.
- jscpd pinned to 4.3.0 (latest 4.x; latest overall is 5.x).
- `actionlint` reports only Gitea false positives (`gitea` context, unknown `bongbetic-ci` label).
- Clippy on `src-tauri` is deferred (needs webkit2gtk/gtk and a full compile on the shared host).
- Not exercised locally: the workflow itself on a runner (no push was made), and the `ai-review` job (needs secrets).
## Rollback
Revert this PR. Relax branch protection first if it requires these checks.
## Runner verification
The shared workflow was run on the real `bongbetic-ci` runner on a scratch repo: `security`, `lint` and `ai-review` all passed (`ai-review` skips with a notice until the two secrets exist). A first scratch run exposed an `--entrypoint ""` override that made the pr-agent container exit; it is not in this workflow. This repo's own CI run on this PR is the first real run of its repo-specific steps.
Remove dead code and unused imports, drop useless assignments, and tune
rules in eslint.config.js (underscore-prefixed unused names, intentional BOM/NBSP,
React Compiler rules from eslint-plugin-react-hooks 7 as warnings).
Pass a constant format string to console.log in compare.mjs (same output).
Annotate the mutable action tags in the Windows fallback workflow with
nosemgrep; workflow behaviour is unchanged.
The runner starts job containers with entrypoint /bin/sleep 3600 and copies the workspace in. An empty --entrypoint override made the pr-agent container exit at once (RWLayer is unexpectedly nil). The image already has pr-agent on PATH.
xavierk
merged commit 2083d2ff6a into main2026-10-05 14:27:41 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Adds a Gitea Actions quality-gate workflow (
.gitea/workflows/ci.yml) with four jobs:security,lint,e2e,ai-review. Also adds ESLint (flat config), a Playwright smoke test, jscpd config, andCI.md. Existing lint/format findings are cleaned up so the gates are green from day one. No app behaviour changes.Commit 1 is a pure
cargo fmtreformat ofsrc-tauri(default rustfmt config, norustfmt.toml). It is mechanical and large, so review it separately (or skip it) and review commits 2 to 4 for the real changes.Commits
style(src-tauri): cargo fmt- rustfmt only. Checked that the only non-whitespace changes are trailing commas, brace wrapping andelse { return }becomingelse { return; }.ci: add quality-gate workflow, ESLint and Playwright smoke test-ci.yml,CI.md,.jscpd.json,eslint.config.js,playwright.config.ts,e2e/smoke.spec.ts,lintande2enpm scripts, exact-pinned devDependencies (eslint, @eslint/js, typescript-eslint, eslint-plugin-react-hooks, globals, @playwright/test), lockfile,.gitignoreentries for Playwright output.fix: eslint findings- 91 initial findings. Real fixes: dead code and unused imports/variables, useless assignments, oneprefer-const. Config tuning (commented ineslint.config.js):_-prefixed unused names allowed, intentional BOM/NBSP allowed in strings/templates/regexes, the React Compiler rules (set-state-in-effect,refs,immutability) andno-explicit-anyinsrc/pdf/testingset to warn. One line-scopedeslint-disable-next-line no-control-regexwith reason. 45 warnings remain (visible, non-blocking).chore: semgrep triage-compare.mjsnow passes a constant format string toconsole.log(identical output) instead of a suppression. The fourgithub-actions-mutable-action-tagwarnings inwindows-build.ymlget# nosemgrepcomments only.Jobs
security: Semgrep 1.178.0 (p/default,p/owasp-top-ten),--error. Also the only job on the weekly schedule.lint:npm ci,tsc --noEmit, ESLint,cargo fmt --check(pinned rustup toolchain 1.99.0, rustfmt only, installer checksum verified), jscpd 4.3.0 at threshold 4.5%.e2e:mcr.microsoft.com/playwright:v1.63.0-noble,npm run build, Playwright (chromium, 1 worker) againstvite preview.ai-review: PR-Agent 0.47.0, pull requests only, advisory (continue-on-error), skipped with a notice when secrets are empty.Required secrets/vars:
OPENROUTER_API_KEY,PR_AGENT_GITEA_TOKEN; optional varPR_AGENT_MODEL. SeeCI.md.Verification (local, branch tip)
p/default+p/owasp-top-ten,--error): exit 0, no findings (main baseline: 5).npm ci && npx tsc --noEmit && npx eslint .: exit 0 (0 errors, 45 warnings).npm test: 60 files, 1656 passed | 6 skipped, identical toorigin/main.cargo fmt --checkinsrc-tauri: clean.npm run build && npx playwright test(CI=1, chromium): 2 passed.ci.ymlparses as YAML; actionlint reports only Gitea false positives.Deviations and judgment calls
rustfmttoolchain is 1.99.0 (the version used to format), not the crate MSRV 1.95, socargo fmt --checkand the committed formatting agree.windows-build.ymlis annotated only. It needs awindowsrunner that does not exist; behaviour is unchanged and it was left alone.totals/wordsmemo inNewInvoice.tsx(dead code that ESLint flagged).__TAURI_INTERNALS__(app shell navigation renders). No app code was changed for it.actionlintreports only Gitea false positives (giteacontext, unknownbongbetic-cilabel).src-tauriis deferred (needs webkit2gtk/gtk and a full compile on the shared host).ai-reviewjob (needs secrets).Rollback
Revert this PR. Relax branch protection first if it requires these checks.
Runner verification
The shared workflow was run on the real
bongbetic-cirunner on a scratch repo:security,lintandai-reviewall passed (ai-reviewskips with a notice until the two secrets exist). A first scratch run exposed an--entrypoint ""override that made the pr-agent container exit; it is not in this workflow. This repo's own CI run on this PR is the first real run of its repo-specific steps.