Skip to content

feat(jobs): add controller diagnostics and per-module E2E config pooling - #440

Merged
ironcommit merged 1 commit into
mainfrom
auth-tests-4/rsadler
Jun 24, 2026
Merged

feat(jobs): add controller diagnostics and per-module E2E config pooling#440
ironcommit merged 1 commit into
mainfrom
auth-tests-4/rsadler

Conversation

@ironcommit

@ironcommit ironcommit commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Add a diagnostics module to the jobs controller that collects a structured snapshot of job/step/task state for debugging stuck or failing jobs. Log snapshots at DEBUG level in the scheduler and reconciler, with a include_job_logs_in_diagnostics config flag (default off) to gate raw log inclusion since logs may contain secrets or PII.

Refactor the E2E harness to support per-module config selection via an e2e_config() pytest mark. Config layers (YAML files + inline overlays) are resolved to a canonical hash and pooled, so modules sharing the same effective config reuse one running services instance and it is torn down as soon as the last consumer finishes. Extract all service lifecycle logic from conftest.py into a new services_pool.py module.

Add e2e/configs/local-subprocess.yaml and a new test_jobs_auth.py suite that enables auth and exercises job principal propagation end-to-end using unsigned JWTs. Add unit tests for diagnostics, scheduler priority ordering, subprocess backend, and timestamp contracts.

Summary by CodeRabbit

  • New Features

    • Added include_job_logs_in_diagnostics (off by default) to optionally include raw job logs in diagnostics snapshots.
    • Introduced pooled local E2E services (with a Docker-less local config) and added auth-enabled E2E job coverage.
    • Added e2e_config(...) pytest marker support for selecting layered E2E configurations.
  • Bug Fixes

    • Improved job step/task workspace scoping, scheduling/reconciliation diagnostics, conflict handling, and subprocess reconciliation behavior when metadata is missing.
  • Tests

    • Expanded unit, integration, and E2E tests covering diagnostics, auth helpers, timestamp parsing, and the services pool.

@ironcommit
ironcommit requested a review from mckornfield June 24, 2026 18:20
@ironcommit
ironcommit requested review from a team as code owners June 24, 2026 18:20
@github-actions github-actions Bot added the feat label Jun 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 20908/27478 76.1% 61.2%
Integration Tests 12108/26247 46.1% 19.5%

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 85d17967-4397-4084-9edc-0c0a9d2348e9

📥 Commits

Reviewing files that changed from the base of the PR and between c3b9646 and f9749fa.

📒 Files selected for processing (27)
  • docs/set-up/config-reference.mdx
  • e2e/configs/local-subprocess.yaml
  • e2e/conftest.py
  • e2e/services_pool.py
  • e2e/test_data_designer.py
  • e2e/test_jobs.py
  • e2e/test_jobs_auth.py
  • packages/nmp_testing/src/nmp/testing/__init__.py
  • packages/nmp_testing/src/nmp/testing/utils.py
  • packages/nmp_testing/tests/unit/test_e2e_harness.py
  • pytest.ini
  • services/core/jobs/src/nmp/core/jobs/api/v2/jobs/endpoints.py
  • services/core/jobs/src/nmp/core/jobs/app/dispatcher.py
  • services/core/jobs/src/nmp/core/jobs/config.py
  • services/core/jobs/src/nmp/core/jobs/controllers/backends/subprocess.py
  • services/core/jobs/src/nmp/core/jobs/controllers/diagnostics.py
  • services/core/jobs/src/nmp/core/jobs/controllers/reconciler.py
  • services/core/jobs/src/nmp/core/jobs/controllers/scheduler.py
  • services/core/jobs/tests/controllers/test_diagnostics.py
  • services/core/jobs/tests/controllers/test_reconciler.py
  • services/core/jobs/tests/controllers/test_scheduler.py
  • services/core/jobs/tests/controllers/test_subprocess_backend.py
  • services/core/jobs/tests/integration/test_task_auth_runtime.py
  • services/core/jobs/tests/test_dispatcher_cross_workspace.py
  • services/core/jobs/tests/test_timestamp_contracts.py
  • tests/test_e2e_jobs_auth.py
  • tests/test_e2e_services_pool.py
✅ Files skipped from review due to trivial changes (5)
  • packages/nmp_testing/src/nmp/testing/init.py
  • services/core/jobs/tests/test_timestamp_contracts.py
  • e2e/test_jobs.py
  • docs/set-up/config-reference.mdx
  • services/core/jobs/tests/controllers/test_subprocess_backend.py
🚧 Files skipped from review as they are similar to previous changes (20)
  • pytest.ini
  • services/core/jobs/src/nmp/core/jobs/config.py
  • services/core/jobs/src/nmp/core/jobs/app/dispatcher.py
  • packages/nmp_testing/src/nmp/testing/utils.py
  • services/core/jobs/src/nmp/core/jobs/api/v2/jobs/endpoints.py
  • e2e/configs/local-subprocess.yaml
  • tests/test_e2e_jobs_auth.py
  • services/core/jobs/tests/test_dispatcher_cross_workspace.py
  • services/core/jobs/tests/controllers/test_reconciler.py
  • services/core/jobs/tests/controllers/test_diagnostics.py
  • services/core/jobs/tests/integration/test_task_auth_runtime.py
  • packages/nmp_testing/tests/unit/test_e2e_harness.py
  • services/core/jobs/src/nmp/core/jobs/controllers/backends/subprocess.py
  • services/core/jobs/src/nmp/core/jobs/controllers/diagnostics.py
  • e2e/test_jobs_auth.py
  • services/core/jobs/src/nmp/core/jobs/controllers/scheduler.py
  • services/core/jobs/tests/controllers/test_scheduler.py
  • e2e/conftest.py
  • services/core/jobs/src/nmp/core/jobs/controllers/reconciler.py
  • e2e/test_data_designer.py

📝 Walkthrough

Walkthrough

Adds job diagnostics, workspace-scoped job/task handling, and a pooled local E2E harness with auth-enabled job tests and CLI URL injection.

Changes

Jobs Service Changes

Layer / File(s) Summary
Diagnostics config and collector
services/core/jobs/src/nmp/core/jobs/config.py, services/core/jobs/src/nmp/core/jobs/controllers/diagnostics.py, docs/set-up/config-reference.mdx, services/core/jobs/tests/controllers/test_diagnostics.py
Adds include_job_logs_in_diagnostics, implements diagnostics collection/logging, and tests log inclusion plus error trimming.
Subprocess backend fallback
services/core/jobs/src/nmp/core/jobs/controllers/backends/subprocess.py, services/core/jobs/tests/controllers/test_subprocess_backend.py, services/core/jobs/tests/test_timestamp_contracts.py
Adds missing-metadata fallback, pending-step grace handling, cleanup timestamp changes, and timestamp parsing coverage.
Scheduler, reconciler, and workspace scoping
services/core/jobs/src/nmp/core/jobs/controllers/scheduler.py, services/core/jobs/src/nmp/core/jobs/controllers/reconciler.py, services/core/jobs/src/nmp/core/jobs/api/v2/jobs/endpoints.py, services/core/jobs/src/nmp/core/jobs/app/dispatcher.py, services/core/jobs/tests/controllers/test_scheduler.py, services/core/jobs/tests/controllers/test_reconciler.py, services/core/jobs/tests/test_dispatcher_cross_workspace.py
Adds debug diagnostics during scheduling and reconciliation, typed step filtering, 409 conflict suppression for pending updates, and workspace-scoped task listing with matching tests.
Task auth runtime test refactor
services/core/jobs/tests/integration/test_task_auth_runtime.py
Returns the secret value directly from the task helper and updates the assertions.

E2E Harness Changes

Layer / File(s) Summary
Services pool core
e2e/services_pool.py, packages/nmp_testing/tests/unit/test_e2e_harness.py
Adds pooled services management, config hashing/rewriting, subprocess lifecycle handling, and helper tests.
conftest and marker wiring
e2e/conftest.py, pytest.ini
Replaces the old fixture flow with pooled fixtures and adds the e2e_config marker.
Local CLI injection
packages/nmp_testing/src/nmp/testing/utils.py, packages/nmp_testing/src/nmp/testing/__init__.py, e2e/test_data_designer.py
Extends run_nemo_local with base URL and workspace injection, and updates the data designer E2E fixture to use it.
Local subprocess config and auth E2E coverage
e2e/configs/local-subprocess.yaml, e2e/test_jobs.py, e2e/test_jobs_auth.py, tests/test_e2e_jobs_auth.py
Adds the local subprocess config, applies it to the jobs E2E module, and adds auth helpers and tests for principal propagation, workspace denial, and admin listing.

Possibly related PRs

Suggested reviewers

  • mckornfield
  • mikeknep
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the two main changes: job controller diagnostics and per-module pooled E2E config handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 auth-tests-4/rsadler

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 OpenGrep (1.23.0)
services/core/jobs/src/nmp/core/jobs/api/v2/jobs/endpoints.py

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

[00.19][ERROR]: unable to find a config; path .coderabbit-opengrep-fallback.yml does not exist

services/core/jobs/src/nmp/core/jobs/app/dispatcher.py

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

[00.22][ERROR]: unable to find a config; path .coderabbit-opengrep-fallback.yml does not exist

services/core/jobs/src/nmp/core/jobs/config.py

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

[00.17][ERROR]: unable to find a config; path .coderabbit-opengrep-fallback.yml does not exist

  • 13 others

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

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
e2e/conftest.py (1)

245-253: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Don't inherit ambient auth env for pooled local services.

This still forwards NMP_ACCESS_TOKEN / NMP_CONTEXT_NAME when _services_instance is the local pooled platform. If those env vars are set, the auth E2Es can run under the wrong principal or combine bearer auth with the injected admin headers. Only pass env credentials on the external-cluster path.

Suggested fix
-    access_token = os.environ.get("NMP_ACCESS_TOKEN")
-    context_name = os.environ.get("NMP_CONTEXT_NAME")
+    use_external_auth = _services_instance.proc is None
+    access_token = os.environ.get("NMP_ACCESS_TOKEN") if use_external_auth else None
+    context_name = os.environ.get("NMP_CONTEXT_NAME") if use_external_auth else None
     headers = admin_headers() if _services_instance.auth_enabled else {}
🤖 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 `@e2e/conftest.py` around lines 245 - 253, The NeMoPlatform construction in the
local service setup is still picking up ambient NMP_ACCESS_TOKEN and
NMP_CONTEXT_NAME even for the pooled local services path. Update the logic
around the NeMoPlatform call to only read and pass those env credentials on the
external-cluster branch, and keep the pooled local path using only the injected
admin_headers from admin_headers() when _services_instance.auth_enabled is true.
Use the existing _services_instance, admin_headers, and NeMoPlatform symbols to
separate the auth sources cleanly.
🧹 Nitpick comments (2)
services/core/jobs/tests/controllers/test_diagnostics.py (1)

37-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a regression for stack truncation.

These tests only cover the job-log flag. Add a case with an oversized traceback in error_details["error"] and assert the snapshot is capped, otherwise the serializer bug above stays invisible.

🤖 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 `@services/core/jobs/tests/controllers/test_diagnostics.py` around lines 37 -
66, Add a regression test for oversized traceback handling in
collect_job_diagnostics, since the current cases only verify the
include_job_logs_in_diagnostics flag. Extend test_diagnostics.py with a scenario
that sets a very large value in error_details["error"] and assert the serialized
diagnostics snapshot is truncated/capped appropriately. Use
collect_job_diagnostics and the existing _make_sdk_with_logs helper so the
serializer behavior stays covered even when raw job logs are disabled.
services/core/jobs/tests/controllers/test_reconciler.py (1)

65-89: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the unexpected-exception branch too.

The reconciler now logs diagnostics from two new paths, but this test only exercises the error-transition one. Add a case where sync() raises and assert the "unexpected reconciliation error" context so that handler cannot regress silently.

🤖 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 `@services/core/jobs/tests/controllers/test_reconciler.py` around lines 65 -
89, The reconciler test only covers the error-status transition path in
JobReconciler.step; add coverage for the unexpected-exception branch as well.
Extend the test around JobReconciler and log_job_diagnostics_if_debug so that a
patched test_backend.sync raises an exception, then assert
log_job_diagnostics_if_debug is called with the same mock_client and
test_step_active but with context set to "unexpected reconciliation error" and
the JobReconciler logger.
🤖 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.

Inline comments:
In `@e2e/services_pool.py`:
- Around line 405-415: The HTTP-only wait loops in _wait_for_healthy and the
other startup polling helpers keep sleeping even after the child process has
already exited, so update these checks to inspect the spawned process state
during the wait and abort early when it terminates. In the functions that poll
readiness for services in services_pool.py, add a process-exit check alongside
the existing httpx status polling, and return failure immediately if the child
is no longer running instead of consuming the full timeout.
- Around line 101-104: The acquire_for_module path currently forces external_url
runs to use RunningServices with auth_enabled=False, which ignores the module’s
marker-derived auth mode. Update acquire_for_module to preserve the auth setting
inferred earlier for the module instead of hard-coding unauthenticated behavior,
using the existing RunningServices constructor and any auth-related state
already determined by the harness.

In `@e2e/test_jobs_auth.py`:
- Around line 227-229: The jobs listing assertion is only checking the first
page returned by jobs.list(workspace=ALL_WORKSPACES), so it can miss the target
job when results are paginated. Update the test to either filter by the specific
job/workspace using the jobs.list call or the related jobs API helper, or
iterate through all pages before asserting; use the existing jobs.list and
jobs.pagination/data handling in the test to locate the job reliably.
- Around line 78-79: These tests create workspaces directly via
admin_sdk.workspaces.create and grant_workspace_role, bypassing the workspace
fixture cleanup path and risking leaked resources. Update the affected tests in
test_jobs_auth.py to ensure every created workspace is always torn down, either
by wrapping the test body in try/finally cleanup that removes the workspace and
associated grants/filesets/jobs, or by introducing and using an admin workspace
fixture with teardown. Apply the same cleanup pattern to the other direct
workspace-creation spots in this file so the lifecycle matches the existing
workspace fixture contract.

In `@services/core/jobs/src/nmp/core/jobs/controllers/backends/subprocess.py`:
- Around line 374-379: Normalize the fallback timestamp used in the subprocess
recovery path before selecting the latest task: in the logic that computes
latest_task with max() in the subprocess backend, make sure the default value
matches the timezone-aware timestamp contract used by task.updated_at and
task.created_at. Replace the naive datetime.datetime.min fallback with a
timezone-aware minimum and keep the comparison within the existing task
selection flow so max() can safely compare tasks even when some metadata
timestamps are missing.

In `@services/core/jobs/src/nmp/core/jobs/controllers/diagnostics.py`:
- Around line 36-61: The debug serializers in _task_dict, _step_dict, and
_job_dict pass through error_details without limiting traceback size, so apply
the same trimming used by _trim_error_stack to any traceback stored under
error_details (especially the "error" field) before returning the snapshot. Add
or reuse a small helper near _trim_error_stack to cap long strings inside
error_details, and make sure all three dict builders call it so task, step, and
job payloads stay bounded.

In `@services/core/jobs/tests/controllers/test_subprocess_backend.py`:
- Around line 320-323: The test currently removes the subprocess registry entry
before stopping the spawned process, which can leave the real sleep process
orphaned. In test_subprocess_backend.py, update the cleanup around
_schedule_without_otel_export and SubprocessProcessKey so the process is
explicitly terminated or waited on first, and only then pop the entry from
backend._process_registry. Make sure the test uses the tracked handle from the
registry to stop the child before discarding it.

---

Outside diff comments:
In `@e2e/conftest.py`:
- Around line 245-253: The NeMoPlatform construction in the local service setup
is still picking up ambient NMP_ACCESS_TOKEN and NMP_CONTEXT_NAME even for the
pooled local services path. Update the logic around the NeMoPlatform call to
only read and pass those env credentials on the external-cluster branch, and
keep the pooled local path using only the injected admin_headers from
admin_headers() when _services_instance.auth_enabled is true. Use the existing
_services_instance, admin_headers, and NeMoPlatform symbols to separate the auth
sources cleanly.

---

Nitpick comments:
In `@services/core/jobs/tests/controllers/test_diagnostics.py`:
- Around line 37-66: Add a regression test for oversized traceback handling in
collect_job_diagnostics, since the current cases only verify the
include_job_logs_in_diagnostics flag. Extend test_diagnostics.py with a scenario
that sets a very large value in error_details["error"] and assert the serialized
diagnostics snapshot is truncated/capped appropriately. Use
collect_job_diagnostics and the existing _make_sdk_with_logs helper so the
serializer behavior stays covered even when raw job logs are disabled.

In `@services/core/jobs/tests/controllers/test_reconciler.py`:
- Around line 65-89: The reconciler test only covers the error-status transition
path in JobReconciler.step; add coverage for the unexpected-exception branch as
well. Extend the test around JobReconciler and log_job_diagnostics_if_debug so
that a patched test_backend.sync raises an exception, then assert
log_job_diagnostics_if_debug is called with the same mock_client and
test_step_active but with context set to "unexpected reconciliation error" and
the JobReconciler logger.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 61f1d69c-0792-4e63-b660-c4bf29600712

📥 Commits

Reviewing files that changed from the base of the PR and between ed04d87 and 15acc2c.

📒 Files selected for processing (25)
  • docs/set-up/config-reference.mdx
  • e2e/configs/local-subprocess.yaml
  • e2e/conftest.py
  • e2e/services_pool.py
  • e2e/test_data_designer.py
  • e2e/test_jobs.py
  • e2e/test_jobs_auth.py
  • packages/nmp_testing/src/nmp/testing/__init__.py
  • packages/nmp_testing/src/nmp/testing/utils.py
  • packages/nmp_testing/tests/unit/test_e2e_harness.py
  • pytest.ini
  • services/core/jobs/src/nmp/core/jobs/api/v2/jobs/endpoints.py
  • services/core/jobs/src/nmp/core/jobs/app/dispatcher.py
  • services/core/jobs/src/nmp/core/jobs/config.py
  • services/core/jobs/src/nmp/core/jobs/controllers/backends/subprocess.py
  • services/core/jobs/src/nmp/core/jobs/controllers/diagnostics.py
  • services/core/jobs/src/nmp/core/jobs/controllers/reconciler.py
  • services/core/jobs/src/nmp/core/jobs/controllers/scheduler.py
  • services/core/jobs/tests/controllers/test_diagnostics.py
  • services/core/jobs/tests/controllers/test_reconciler.py
  • services/core/jobs/tests/controllers/test_scheduler.py
  • services/core/jobs/tests/controllers/test_subprocess_backend.py
  • services/core/jobs/tests/integration/test_task_auth_runtime.py
  • services/core/jobs/tests/test_dispatcher_cross_workspace.py
  • services/core/jobs/tests/test_timestamp_contracts.py

Comment thread e2e/services_pool.py Outdated
Comment thread e2e/services_pool.py Outdated
Comment thread e2e/test_jobs_auth.py Outdated
Comment thread e2e/test_jobs_auth.py Outdated
Comment thread services/core/jobs/src/nmp/core/jobs/controllers/backends/subprocess.py Outdated
Comment thread services/core/jobs/src/nmp/core/jobs/controllers/diagnostics.py
Comment thread services/core/jobs/tests/controllers/test_subprocess_backend.py

@matthewgrossman matthewgrossman 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.

like the e2e config hashing mechanism!

@ironcommit
ironcommit force-pushed the auth-tests-4/rsadler branch 2 times, most recently from ab87b4e to c3b9646 Compare June 24, 2026 19:00
@ironcommit
ironcommit enabled auto-merge June 24, 2026 19:02

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
services/core/jobs/tests/controllers/test_subprocess_backend.py (1)

324-327: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use backend cleanup helpers before dropping registry entry.

process.terminate() can miss child processes for /bin/sh -c ..., and popping without _finish_logs() skips log-thread/logger cleanup. Use backend-managed termination/finish, then pop.

Suggested fix
-    metadata.process.terminate()
-    assert metadata.process.wait(timeout=5) is not None
-    backend._process_registry.pop(key)
+    backend._terminate_process(metadata, force=True)
+    backend._finish_logs(metadata)
+    backend._process_registry.pop(key)
🤖 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 `@services/core/jobs/tests/controllers/test_subprocess_backend.py` around lines
324 - 327, The subprocess test is bypassing backend-managed shutdown by calling
metadata.process.terminate() and removing the registry entry directly, which
skips child-process handling and log cleanup. Update the test to use the backend
cleanup path exposed by SubprocessBackend, making sure the process is terminated
through the backend helper and _finish_logs() runs before
backend._process_registry.pop(key) is called. Use the existing metadata, key,
and backend references in test_subprocess_backend.py to locate the cleanup
sequence.
🧹 Nitpick comments (1)
tests/test_e2e_jobs_auth.py (1)

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

Use a concrete type hint instead of the string forward reference.

list["_StubPage"] is string-based. Add from __future__ import annotations at the top so this can be written as list[_StubPage].

♻️ Proposed change
+from __future__ import annotations
+
 import pytest
-    def __init__(self, pages: list["_StubPage"], job_names: list[str]) -> None:
+    def __init__(self, pages: list[_StubPage], job_names: list[str]) -> None:

As per coding guidelines: "Always prefer concrete type hints over string-based ones in Python code".

🤖 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 `@tests/test_e2e_jobs_auth.py` at line 29, Add future annotations support at
the top of the test module so the constructor in the stub class can use a
concrete type hint instead of the string forward reference. Update the __init__
signature that currently uses list["_StubPage"] to use list[_StubPage], and keep
the rest of the stub/test code unchanged.

Source: Coding guidelines

🤖 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.

Inline comments:
In `@e2e/services_pool.py`:
- Line 6: Remove the unnecessary postponed-annotations import from this module.
In e2e/services_pool.py, delete the from __future__ import annotations statement
and keep the existing type hints concrete; there is no forward-reference
requirement here, so the file should follow the project’s rule against
string-based annotations and use regular imports where needed.

---

Duplicate comments:
In `@services/core/jobs/tests/controllers/test_subprocess_backend.py`:
- Around line 324-327: The subprocess test is bypassing backend-managed shutdown
by calling metadata.process.terminate() and removing the registry entry
directly, which skips child-process handling and log cleanup. Update the test to
use the backend cleanup path exposed by SubprocessBackend, making sure the
process is terminated through the backend helper and _finish_logs() runs before
backend._process_registry.pop(key) is called. Use the existing metadata, key,
and backend references in test_subprocess_backend.py to locate the cleanup
sequence.

---

Nitpick comments:
In `@tests/test_e2e_jobs_auth.py`:
- Line 29: Add future annotations support at the top of the test module so the
constructor in the stub class can use a concrete type hint instead of the string
forward reference. Update the __init__ signature that currently uses
list["_StubPage"] to use list[_StubPage], and keep the rest of the stub/test
code unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0bc81dc7-0512-4196-b3ee-8ab33ea3c454

📥 Commits

Reviewing files that changed from the base of the PR and between 15acc2c and ab87b4e.

📒 Files selected for processing (27)
  • docs/set-up/config-reference.mdx
  • e2e/configs/local-subprocess.yaml
  • e2e/conftest.py
  • e2e/services_pool.py
  • e2e/test_data_designer.py
  • e2e/test_jobs.py
  • e2e/test_jobs_auth.py
  • packages/nmp_testing/src/nmp/testing/__init__.py
  • packages/nmp_testing/src/nmp/testing/utils.py
  • packages/nmp_testing/tests/unit/test_e2e_harness.py
  • pytest.ini
  • services/core/jobs/src/nmp/core/jobs/api/v2/jobs/endpoints.py
  • services/core/jobs/src/nmp/core/jobs/app/dispatcher.py
  • services/core/jobs/src/nmp/core/jobs/config.py
  • services/core/jobs/src/nmp/core/jobs/controllers/backends/subprocess.py
  • services/core/jobs/src/nmp/core/jobs/controllers/diagnostics.py
  • services/core/jobs/src/nmp/core/jobs/controllers/reconciler.py
  • services/core/jobs/src/nmp/core/jobs/controllers/scheduler.py
  • services/core/jobs/tests/controllers/test_diagnostics.py
  • services/core/jobs/tests/controllers/test_reconciler.py
  • services/core/jobs/tests/controllers/test_scheduler.py
  • services/core/jobs/tests/controllers/test_subprocess_backend.py
  • services/core/jobs/tests/integration/test_task_auth_runtime.py
  • services/core/jobs/tests/test_dispatcher_cross_workspace.py
  • services/core/jobs/tests/test_timestamp_contracts.py
  • tests/test_e2e_jobs_auth.py
  • tests/test_e2e_services_pool.py
✅ Files skipped from review due to trivial changes (3)
  • e2e/test_jobs.py
  • docs/set-up/config-reference.mdx
  • packages/nmp_testing/src/nmp/testing/init.py
🚧 Files skipped from review as they are similar to previous changes (19)
  • services/core/jobs/src/nmp/core/jobs/config.py
  • services/core/jobs/src/nmp/core/jobs/api/v2/jobs/endpoints.py
  • services/core/jobs/tests/test_timestamp_contracts.py
  • services/core/jobs/tests/test_dispatcher_cross_workspace.py
  • pytest.ini
  • packages/nmp_testing/src/nmp/testing/utils.py
  • e2e/test_data_designer.py
  • services/core/jobs/tests/controllers/test_reconciler.py
  • services/core/jobs/src/nmp/core/jobs/app/dispatcher.py
  • packages/nmp_testing/tests/unit/test_e2e_harness.py
  • services/core/jobs/tests/controllers/test_scheduler.py
  • services/core/jobs/tests/integration/test_task_auth_runtime.py
  • e2e/configs/local-subprocess.yaml
  • services/core/jobs/src/nmp/core/jobs/controllers/backends/subprocess.py
  • services/core/jobs/src/nmp/core/jobs/controllers/scheduler.py
  • e2e/test_jobs_auth.py
  • services/core/jobs/src/nmp/core/jobs/controllers/diagnostics.py
  • e2e/conftest.py
  • services/core/jobs/src/nmp/core/jobs/controllers/reconciler.py

Comment thread e2e/services_pool.py Outdated
Add a `diagnostics` module to the jobs controller that collects a structured
snapshot of job/step/task state for debugging stuck or failing jobs. Log
snapshots at DEBUG level in the scheduler and reconciler, with a
`include_job_logs_in_diagnostics` config flag (default off) to gate raw log
inclusion since logs may contain secrets or PII.

Refactor the E2E harness to support per-module config selection via an
`e2e_config()` pytest mark. Config layers (YAML files + inline overlays) are
resolved to a canonical hash and pooled, so modules sharing the same effective
config reuse one running services instance and it is torn down as soon as the
last consumer finishes. Extract all service lifecycle logic from conftest.py
into a new `services_pool.py` module.

Add `e2e/configs/local-subprocess.yaml` and a new `test_jobs_auth.py` suite
that enables auth and exercises job principal propagation end-to-end using
unsigned JWTs. Add unit tests for diagnostics, scheduler priority ordering,
subprocess backend, and timestamp contracts.

Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
@ironcommit
ironcommit force-pushed the auth-tests-4/rsadler branch from c3b9646 to f9749fa Compare June 24, 2026 19:45
@ironcommit
ironcommit added this pull request to the merge queue Jun 24, 2026
Merged via the queue into main with commit c6fe97b Jun 24, 2026
54 of 55 checks passed
@ironcommit
ironcommit deleted the auth-tests-4/rsadler branch June 24, 2026 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants