From 943a6d3510d213d258f7e146d2c49ce5597d68fc Mon Sep 17 00:00:00 2001 From: Robert Sigmundsson Date: Mon, 27 Jul 2026 00:58:23 +0200 Subject: [PATCH] ci(lint): pin ruff in both jobs and clear the two RUF errors it reports on main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both `lint` and `security` install ruff unpinned, so those jobs are a moving target. ruff 0.16.0 began reporting two errors on files nobody had touched, which turned `main` and every open PR red on the same day without a line of code changing. Reproduced on clean `main` (no PR applied): $ git switch --detach origin/main $ ruff check src/ tests/ # ruff 0.16.0 RUF100 src/surreal_memory/mcp/version_check_handler.py:214 Unused `noqa` (unused: S310) RUF036 tests/unit/test_version_check.py:87 `None` not at the end of the type union Found 2 errors. $ ruff check src/ tests/ # ruff 0.15.22, same tree All checks passed! The two versions make mutually exclusive demands on the same line, so fixing without pinning would not hold: 0.15.22 raises S310 on the `urllib.request.Request(...)` construction and needs the `noqa`, while 0.16.0 narrowed S310 to the actual open and therefore reports that same `noqa` as unused. No single tree is clean under both. Hence the pin. Pinned to `ruff==0.16.0` (the version CI resolves today) in both jobs, and made `main` green under it: - `version_check_handler.py` — drop the now-dead `noqa: S310` on the `Request(...)` constructor. **The `noqa: S310` on line 218, the `urlopen(...)` call, is untouched and still active** — that is the operation the rule is actually about, and 0.16.0 narrowing the rule to the open rather than the construction looks like the more accurate behaviour. The sibling suppressions in `engine/reranker.py` and `server/app.py` are likewise untouched and still reported as used. - `test_version_check.py` — reorder `VersionInfo | None | str` to `VersionInfo | str | None`. Type-equivalent; no behavioural change. Both edits are ruff's own `--fix` output, not hand-written. Verified on this branch with ruff 0.16.0: ruff check src/ tests/ All checks passed! ruff format --check src/ tests/ 704 files already formatted ruff check src/ --select S --ignore S101,S110,S112,S311,S324 All checks passed! pytest tests/unit/test_version_check.py 12 passed The third line is the `security` job's own command — worth stating explicitly, since this diff removes an `S310` suppression and that job is the one which would notice. If you would rather track patch releases, `ruff>=0.16,<0.17` gives the same protection with less maintenance; the point is only that the version stops being implicit. --- .github/workflows/ci.yml | 10 ++++++++-- src/surreal_memory/mcp/version_check_handler.py | 2 +- tests/unit/test_version_check.py | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d3cd621..b29027e1 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,10 @@ jobs: python-version: "3.11" - name: Install ruff - run: pip install ruff + # Pinned on purpose: an unpinned install makes Lint a moving target. ruff 0.16.0 + # started reporting RUF100/RUF036 on files nobody had touched, so `main` and every + # open PR went red on the same day without a single line of code changing. + run: pip install ruff==0.16.0 - name: Run ruff check run: ruff check src/ tests/ @@ -106,7 +109,10 @@ jobs: python-version: "3.11" - name: Install ruff - run: pip install ruff + # Pinned on purpose: an unpinned install makes Lint a moving target. ruff 0.16.0 + # started reporting RUF100/RUF036 on files nobody had touched, so `main` and every + # open PR went red on the same day without a single line of code changing. + run: pip install ruff==0.16.0 - name: Run security rules run: ruff check src/ --select S --ignore S101,S110,S112,S311,S324 diff --git a/src/surreal_memory/mcp/version_check_handler.py b/src/surreal_memory/mcp/version_check_handler.py index 70b782fd..e1bec2c1 100755 --- a/src/surreal_memory/mcp/version_check_handler.py +++ b/src/surreal_memory/mcp/version_check_handler.py @@ -211,7 +211,7 @@ def _blocking_fetch() -> str | None: try: if not _PYPI_URL.startswith("https://"): return None - req = urllib.request.Request( # noqa: S310 + req = urllib.request.Request( _PYPI_URL, headers={"Accept": "application/json"}, ) diff --git a/tests/unit/test_version_check.py b/tests/unit/test_version_check.py index ab49622c..83e524a1 100755 --- a/tests/unit/test_version_check.py +++ b/tests/unit/test_version_check.py @@ -84,7 +84,7 @@ def test_editable_hint_for_dev_install(self) -> None: def _make_handler( *, update_available: bool = False, - version_info: VersionInfo | None | str = "auto", + version_info: VersionInfo | str | None = "auto", ) -> MagicMock: """Create a mock handler with VersionCheckHandler.get_update_hint.""" from surreal_memory.mcp.version_check_handler import VersionCheckHandler