Skip to content

ci: add ruff lint with F821/F811 rules - #44

Merged
ar7casper merged 2 commits into
knostic:release/2026-05-10from
joshbouncesecurity:ci/issue16-02-ruff-lint
May 10, 2026
Merged

ci: add ruff lint with F821/F811 rules#44
ar7casper merged 2 commits into
knostic:release/2026-05-10from
joshbouncesecurity:ci/issue16-02-ruff-lint

Conversation

@joshbouncesecurity

Copy link
Copy Markdown
Contributor

Summary

Adds a ruff lint step to the test workflow with two rules: F821 (undefined name) and F811 (redefined unused name). Python won't report an undefined name until that code path executes, so a missing import can ship undetected. F821 + F811 catch that statically with zero false positives and no style noise.

Configured to run before pytest so CI fails fast on missing imports.

Verified clean against upstream/master baseline after fixing one pre-existing violation:

  • libs/openant-core/core/analyzer.py:393analyze() called tracker.add_prior_usage(...) without defining tracker locally. Replaced with get_global_tracker().add_prior_usage(...) to match the pattern already used elsewhere in the same file (e.g. line 489). This is a real bug — the line would NameError at runtime whenever resuming with non-zero prior token usage.

Addresses item 2 from #16 (does not close the issue).

Test plan

  • ruff check . exits 0 on a clean checkout (verified locally).
  • CI runs ruff before pytest; failure short-circuits.
  • Existing pytest suite still passes (verified locally: 38 passed, 10 skipped).

Adds a ruff lint step to the test workflow with two rules:
F821 (undefined name) and F811 (redefined unused name). Python
won't report an undefined name until that code path executes,
so a missing import or typo can ship undetected. F821 + F811
catch that statically with zero false positives and no style
noise.

Lint runs before pytest so CI fails fast on missing imports.

Also fixes a pre-existing F821 in core/analyzer.py: the
analyze() function called tracker.add_prior_usage() without
defining tracker locally; replaced with get_global_tracker()
to match the pattern used elsewhere in the file.

Refs #16 (item 2).
@joshbouncesecurity

Copy link
Copy Markdown
Contributor Author

Manual verification

  • cd libs/openant-core && pip install ruff && ruff check . --select F821,F811: exits 0 on a clean checkout.
  • Trip the lint: add foo_undefined() somewhere in production code, push to a branch — CI's lint step short-circuits with a clear F821 error before pytest runs.
  • Verify the analyzer.py F821 fix at runtime: run openant scan <small-repo> to completion, kill before completion to create a checkpoint, then resume. The token tracker should report prior usage without raising NameError on the tracker.add_prior_usage line that was previously broken.
  • CI on this PR: lint step appears in python-tests job logs, runs before pytest.

@joshbouncesecurity

Copy link
Copy Markdown
Contributor Author

Local test results

Ran the configured ruff rules locally on Windows from this branch.

Commands run:

pip install ruff
cd libs/openant-core
ruff check . --select F821,F811

Output:

All checks passed!

Outcome:

  • ruff check . --select F821,F811 exits 0 — no undefined names, no redefinitions ✅

@joshbouncesecurity
joshbouncesecurity marked this pull request as ready for review May 7, 2026 11:21

@ar7casper ar7casper left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny + finds a real bug — exactly what a tooling PR should look like. The rationale comment in pyproject.toml ("zero false positives, no style noise") is the right framing and will protect against future "let's add a few more rules" creep.

Two non-blocking suggestions before merge:

1. Move lint to its own job. Currently the ruff check . step lives inside python-tests, which is matrix'd over ubuntu/macos/windows. Ruff is platform-independent, so you're paying for 3 identical lint runs per PR. A separate single-OS lint job (~5 LOC) saves 2× CI minutes, parallelizes with the matrix tests instead of serializing inside them, and gives clearer "lint failed" vs "tests failed" feedback. Skip the full pip install ".[dev]" while you're at it — ruff doesn't execute the code, just parses, so it doesn't need the project's runtime deps.

2. Consider adding F823 to the rule set. F823 (local variable referenced before assignment) catches a real-bug subset of F821 in local-scope flow analysis. Same zero-FP profile as F821/F811, no style noise. F841 (unused var) and F401 (unused import) would be useful but introduce conditional-import / __init__.py re-export noise — your current selection rightly excludes them.

Neither is a merge blocker. (1) is the higher-value change; (2) is a "while you're in there."

- Extracts ruff check into a standalone `lint` job on ubuntu-latest,
  parallel to the matrix jobs instead of running 3x inside them
- Installs only ruff (no runtime deps needed for static parsing)
- Adds F823 (local var referenced before assignment) to rule set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@joshbouncesecurity joshbouncesecurity left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the thorough review! Both suggestions addressed in the latest commit:

  1. Lint job — extracted ruff check into a standalone lint job on ubuntu-latest only. Installs just ruff directly (no .[dev]), so it runs in parallel with the matrix jobs rather than 3× inside them.

  2. F823 — added to the rule set alongside F821/F811. Same zero-FP profile as you noted.

@joshbouncesecurity
joshbouncesecurity changed the base branch from master to release/2026-05-10 May 10, 2026 12:48
@ar7casper
ar7casper merged commit a0e9841 into knostic:release/2026-05-10 May 10, 2026
9 checks passed
ar7casper pushed a commit that referenced this pull request May 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants