fix(ci): make quality-gate verify pass end-to-end#27
Open
yuzushi-dev wants to merge 1 commit into
Open
Conversation
The `verify` gate (scripts/verify.sh) was red on main and therefore on all
open PRs. Because the script runs under `set -e` and ruff is the first check,
CI aborted at ruff and every PR showed the identical failure. Running the full
gate locally revealed main was actually broken at three independent steps.
Backend / ruff (33 errors): unused imports, unsorted imports, redefinitions,
two unused locals, a mutable default arg, an unnecessary comprehension, and one
pyupgrade. Fixed via `ruff --fix` plus manual edits; all behavior-preserving.
Notably removed a dead `is_primary` block in the failover `chat()` method (it is
never read there, unlike its two sibling methods) and a dead `total` count in
the chat-history admin route.
Backend / mypy (16 errors, all in src/cli/*): fixed the real bugs and added
minimal annotations, without touching the per-module override list:
* eval.py / tui.py: `typer.Exit("string")` passed a str where an int exit
code is expected -> now `typer.echo(msg, err=True); raise typer.Exit(1)`.
* tui/app.py: `Widget` has no `.press()` -> `query_one(id, Button)` so the
real Button API is used.
* remaining no-any-return / arg-type / unused-ignore / missing-annotation /
sufficiency.py `**kwargs` splat: resolved with casts, precise annotations,
and `kwargs: dict[str, Any]`. `_session.session_scope` is annotated to yield
a loosely-typed session on purpose (see its docstring): the CLI operates over
legacy Column-style ORM models, and a precise AsyncSession type would surface
pre-existing SQLAlchemy stub errors across the CLI that are out of scope here.
Frontend / eslint (2 errors): `react-hooks/set-state-in-effect` in
DocumentLibrary.tsx. Both are intentional state syncs (reset page on filter
change; prune selection against current docs); suppressed with targeted
eslint-disable-next-line comments explaining why they are safe.
Tooling pinning: ruff and mypy were unpinned (`>=`) and eslint-plugin-react-hooks
used a caret range, so newer releases silently introduced the failures above.
Pinned to the currently-resolved versions (ruff==0.15.14, mypy==2.1.0,
eslint-plugin-react-hooks 7.0.1) to prevent recurrence.
Verified end-to-end in a clean worktree from origin/main: ruff, import-linter,
mypy, pytest (unit), eslint, frontend build, and frontend tests all pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
verify(thequality-gateworkflow →scripts/verify.sh all) was red onmain, so it failed identically on all 5 open PRs.verify.shruns underset -eand ruff is the first check, so CI aborted at ruff and every PR surfaced the same error. Running the entire gate locally against a cleanorigin/mainworktree revealedmainwas actually broken at three independent steps — the later ones were simply never reached in CI:origin/mainsrc/cli/*+sufficiency.py(not in the override list)react-hooks/set-state-in-effectinDocumentLibrary.tsxUnderlying reason:
mainwas pushed while its own gate was failing, compounded by unpinned tooling —ruff>=0.1.0,mypy>=1.8.0, andeslint-plugin-react-hooks@^7.0.1pulled newer, stricter releases than the code was written against.What this PR fixes
ruff (33):
ruff --fixfor the safe fixes + manual edits, all behavior-preserving. Removed a deadis_primaryblock in the failoverchat()method (never read there, unlike its two sibling methods) and a deadtotalcount in the chat-history admin route.unit_of_workmutable defaultgroup_ids=[]→None(ctor already normalized vialist(...)).mypy (16) — real bugs fixed, no override-list additions:
eval.py/tui.py:typer.Exit("string")passed a str where an int exit code is expected →typer.echo(msg, err=True); raise typer.Exit(1)(preserves the stderr message + non-zero exit).tui/app.py:Widgethas no.press()→query_one(id, Button)uses the real Button API (textual 8.x).no-any-return/arg-type/unused-ignore/ missing annotations /sufficiency.py**kwargssplat → resolved with casts, precise annotations, andkwargs: dict[str, Any]._session.session_scopeis intentionally annotated to yield a loosely-typed session (documented in its docstring): the CLI operates over legacyColumn-style ORM models, and a preciseAsyncSessiontype would un-mask ~19 pre-existing SQLAlchemy stub assignment errors across the CLI that are out of scope for this gate fix (the same debt the rest of the repo handles via the mypy override list). This keeps behavior and the CI error surface unchanged.eslint (2): both flagged
setState-in-effect calls are intentional state syncs (reset pagination on filter change; prune selection against the current document set — the functional update is a no-op when nothing changed, so it cannot loop). Suppressed with targeted// eslint-disable-next-line react-hooks/set-state-in-effect+ explanatory comments. No refactor.Tooling pinned to the currently-resolved versions to prevent recurrence:
ruff==0.15.14,mypy==2.1.0,eslint-plugin-react-hooks 7.0.1(exact; lockfile re-synced).Verification
Ran the full gate in a clean worktree checked out from
origin/main:Once merged, the 5 open PRs should go green after a rebase/merge from
main.