Skip to content

Remove mypy ignore_errors from orchestrator/core modules (#68)#72

Open
bradjin8 wants to merge 2 commits into
developfrom
fix/remove-mypy-ignore_errors
Open

Remove mypy ignore_errors from orchestrator/core modules (#68)#72
bradjin8 wants to merge 2 commits into
developfrom
fix/remove-mypy-ignore_errors

Conversation

@bradjin8

@bradjin8 bradjin8 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Remove ignore_errors suppression for 10 in-scope modules: localci.core.orchestrator, progress, queue_builder, registry, results, serialization, workflow, and localci.utils.docker, resources, yq
  • Fix strict mypy errors in those modules (generics, return types, variable shadowing, Rich/psutil typing)
  • Keep all 8 localci.cli.* modules on the override list (CLI typing deferred to a follow-up)
  • Make the pre-commit mypy hook cross-platform (python -m mypy instead of bash -c) so it runs on Windows without WSL

Closes #68

Test plan

  • cd cli && mypy localci/ — Success (47 files)
  • cd cli && pytest -m "not integration" — 587 passed
  • pre-commit run --all-files — all hooks passed (ruff + mypy)
  • CI green on PR (lint, typecheck, test, integration)

Summary by CodeRabbit

  • Bug Fixes
    • Improved robustness when parsing workflow metadata and job/matrix fields, adding safer fallbacks for unexpected YAML shapes.
    • Enhanced execution orchestration to return a clear error status when the worker thread pool is unavailable.
    • Made status serialization more consistent for downstream output.
  • Chores
    • Updated local type-checking tooling to run mypy via the active Python interpreter.
    • Refined mypy configuration/baselines to better align strict checking for legacy vs local modules.

@bradjin8 bradjin8 self-assigned this Jul 8, 2026
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4771f2dc-24a9-4966-9c62-92fdf519c1bf

📥 Commits

Reviewing files that changed from the base of the PR and between 32bf77e and 2fb526b.

📒 Files selected for processing (3)
  • cli/localci/core/orchestrator.py
  • cli/localci/core/progress.py
  • cli/localci/utils/yq.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • cli/localci/core/orchestrator.py

📝 Walkthrough

Walkthrough

This PR tightens type annotations across core and utility modules, adds runtime shape checks in YAML query helpers, refactors orchestrator callback wiring, and updates the pre-commit mypy hook plus mypy override configuration.

Changes

Strict mypy typing cleanup

Layer / File(s) Summary
Core typing and callback flow
cli/localci/core/orchestrator.py, cli/localci/core/progress.py, cli/localci/core/queue_builder.py, cli/localci/core/registry.py, cli/localci/core/results.py, cli/localci/core/serialization.py, cli/localci/core/workflow.py
Core models and helpers switch to typed dict/Any annotations, progress render methods use explicit Rich renderable types, and orchestrator dispatch uses a typed done-callback helper with Future[JobResult].
Utility typing and YAML shape guards
cli/localci/utils/docker.py, cli/localci/utils/resources.py, cli/localci/utils/yq.py
Docker and resource helpers return typed dictionaries and floats, while YqWrapper adds typed caches, stricter return annotations, and runtime guards for query results.
Mypy hook and override config
.pre-commit-config.yaml, cli/pyproject.toml
The mypy pre-commit hook now runs via python -m mypy with an explicit working directory, and the mypy override list drops the core/utils modules from suppression while updating the config comments.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: henry0816191, wpak-ai

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: removing mypy ignore_errors from the core typing cleanup.
Linked Issues check ✅ Passed The changed modules and pyproject edits align with #68: core/utils modules were type-cleaned and CLI modules stayed suppressed.
Out of Scope Changes check ✅ Passed No unrelated code changes are evident; the hook and pyproject edits support the mypy cleanup scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/remove-mypy-ignore_errors

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
cli/localci/core/orchestrator.py (1)

294-299: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Silent job drop if pool is None mid-dispatch.

If self._pool were ever None here, the job already popped via self.queue.next_ready() is dropped without being marked failed/cancelled or requeued, which could leave self.queue.is_done never becoming true (job neither counted as completed nor retried), stalling the dispatch loop indefinitely. In practice self._pool is set once in execute() before _dispatch_loop() runs and is never reset to None, so this branch is likely unreachable today — but it's worth guarding intentionally (e.g. logging and marking the job failed/cancelled) rather than silently continuing, in case future changes ever null out self._pool concurrently.

Optional defensive fix
             pool = self._pool
             if pool is None:
+                logger.warning("Pool unavailable, cannot dispatch %s", job.matrix_entry.name)
+                self.queue.mark_completed(job, success=False)
                 continue
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/localci/core/orchestrator.py` around lines 294 - 299, The dispatch path
in orchestrator._dispatch_loop currently drops a job silently when self._pool is
None after queue.next_ready() has already returned it. Add an explicit defensive
handling branch in _dispatch_loop (or the surrounding dispatch logic) that logs
the condition and marks the job as failed/cancelled or requeues it instead of
just continuing, using the existing _execute_job, _make_done_callback, and queue
handling flow so the job is not lost and is still accounted for.
cli/localci/core/progress.py (1)

411-420: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider RenderableType instead of Any for render helpers.

These methods return Rich renderables (Panel, Text, Table, Group); rich.console.RenderableType (ConsoleRenderable | RichCast | str) is the precise type Rich itself uses for such returns and for Live/Live.update() arguments. Using Any satisfies strict mypy but discards type-checking on these composition points.

♻️ Example
+from rich.console import RenderableType

-    def _render_live(self) -> Any:
+    def _render_live(self) -> RenderableType:
         """Render the complete live display."""
         from rich.console import Group

-        parts: list[Any] = []
+        parts: list[RenderableType] = []

Also applies to: 422-422, 439-439, 457-457, 474-474

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/localci/core/progress.py` around lines 411 - 420, The render helper
return types are too loose: `_render_live` and the related render methods should
use Rich’s `RenderableType` instead of `Any` so type-checking is preserved for
these composition points. Update the return annotations on `_render_live`,
`_render_header`, `_render_progress_bar`, `_render_priority_levels`, and
`_render_job_table` to the precise Rich renderable type used by `Live` and
`Live.update()`, keeping the existing return values unchanged.
cli/localci/utils/yq.py (1)

376-389: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

job_runs_on/job_timeout lack the shape validation applied to sibling methods.

Unlike concurrency, job_container, job_defaults, and matrix_strategy, which now validate the queried value's type before returning, job_runs_on (-> str) and job_timeout (-> int) still just do query(...) or default. Since query() returns Any, mypy won't flag a malformed workflow (e.g., timeout-minutes: "10" or a non-scalar runs-on) returning the wrong runtime type, unlike the pattern used elsewhere in this diff.

♻️ Suggested fix for consistency
     def job_runs_on(self, file: Path, job_id: str) -> str:
         """Extract job ``runs-on``."""
-        return self.query(file, f".jobs.{job_id}.runs-on") or "ubuntu-latest"
+        result = self.query(file, f".jobs.{job_id}.runs-on")
+        return result if isinstance(result, str) else "ubuntu-latest"

     def job_container(self, file: Path, job_id: str) -> dict[str, Any] | None:
         ...

     def job_timeout(self, file: Path, job_id: str) -> int:
         """Extract job timeout in minutes."""
-        return self.query(file, f".jobs.{job_id}.timeout-minutes") or 60
+        result = self.query(file, f".jobs.{job_id}.timeout-minutes")
+        return result if isinstance(result, int) else 60
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/localci/utils/yq.py` around lines 376 - 389, `job_runs_on` and
`job_timeout` still return raw `query()` results with a fallback, so they can
silently pass through malformed workflow values instead of enforcing `str`/`int`
like the sibling validators. Update these methods in `Yq` to mirror the existing
type-checking pattern used by `concurrency`, `job_container`, `job_defaults`,
and `matrix_strategy`: fetch the value, validate its shape/type, return the
typed value only when valid, and otherwise fall back to the default
(`"ubuntu-latest"` / `60`).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cli/localci/core/orchestrator.py`:
- Around line 294-299: The dispatch path in orchestrator._dispatch_loop
currently drops a job silently when self._pool is None after queue.next_ready()
has already returned it. Add an explicit defensive handling branch in
_dispatch_loop (or the surrounding dispatch logic) that logs the condition and
marks the job as failed/cancelled or requeues it instead of just continuing,
using the existing _execute_job, _make_done_callback, and queue handling flow so
the job is not lost and is still accounted for.

In `@cli/localci/core/progress.py`:
- Around line 411-420: The render helper return types are too loose:
`_render_live` and the related render methods should use Rich’s `RenderableType`
instead of `Any` so type-checking is preserved for these composition points.
Update the return annotations on `_render_live`, `_render_header`,
`_render_progress_bar`, `_render_priority_levels`, and `_render_job_table` to
the precise Rich renderable type used by `Live` and `Live.update()`, keeping the
existing return values unchanged.

In `@cli/localci/utils/yq.py`:
- Around line 376-389: `job_runs_on` and `job_timeout` still return raw
`query()` results with a fallback, so they can silently pass through malformed
workflow values instead of enforcing `str`/`int` like the sibling validators.
Update these methods in `Yq` to mirror the existing type-checking pattern used
by `concurrency`, `job_container`, `job_defaults`, and `matrix_strategy`: fetch
the value, validate its shape/type, return the typed value only when valid, and
otherwise fall back to the default (`"ubuntu-latest"` / `60`).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 084a88d0-dd64-4208-bb5e-e82e10b0bbf3

📥 Commits

Reviewing files that changed from the base of the PR and between 1fb8bd3 and 32bf77e.

📒 Files selected for processing (12)
  • .pre-commit-config.yaml
  • cli/localci/core/orchestrator.py
  • cli/localci/core/progress.py
  • cli/localci/core/queue_builder.py
  • cli/localci/core/registry.py
  • cli/localci/core/results.py
  • cli/localci/core/serialization.py
  • cli/localci/core/workflow.py
  • cli/localci/utils/docker.py
  • cli/localci/utils/resources.py
  • cli/localci/utils/yq.py
  • cli/pyproject.toml

@bradjin8 bradjin8 requested a review from henry0816191 July 8, 2026 20:01
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.

Remove mypy ignore_errors suppression across orchestrator/core modules

1 participant