feat(jobs): add watch command to stream job and deployment events - #1031
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR adds synchronous and asynchronous job watching with typed status, log, and warning events. It integrates watch and wait modes into job and deployment creation, adds generated-command support, updates CLI rendering and validation, and documents the new lifecycle options. ChangesJob Watch
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant JobsClient
participant watch_job
participant PlatformAPI
User->>CLI: Run jobs watch or create --watch
CLI->>JobsClient: Start watch_job
JobsClient->>watch_job: Pass filters, timeout, and polling
watch_job->>PlatformAPI: Poll status and fetch logs
PlatformAPI-->>watch_job: Status and log responses
watch_job-->>JobsClient: Emit JobWatchEvent values
JobsClient-->>CLI: Return event stream
CLI-->>User: Render status, logs, warnings, and completion
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py (1)
156-203: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winFix: string-replace corrupts generated code when the resource name contains
--wait.
_render_lifecycle_codebuilds the prelude with the literal text--wait, then doesprelude.replace("--wait", "--watch")forplatform_job. This replace is not scoped to the error message. It also rewrites any occurrence of--waitinside the interpolated resource-name literal. If a job'snamecontains the substring--wait(for examplenightly--wait-job), the generated code's quoted name literal is silently corrupted tonightly--watch-job.Compute the flag name once from
lifecycle_typeand interpolate it directly instead of doing a blind substring replace after the fact.🐛 Proposed fix
resource_name = 'getattr(response, "name", None)' if args.get("name") is not None: resource_name = f"{resource_name} or {_format_python_literal(args['name'])}" + flag_name = "--watch" if lifecycle_type == "platform_job" else "--wait" prelude = dedent( f""" resource_name = {resource_name} if not resource_name: - raise RuntimeError("Unable to determine created resource name for --wait") + raise RuntimeError("Unable to determine created resource name for {flag_name}") """ ).strip() if lifecycle_type == "inference_deployment": ... if lifecycle_type == "platform_job": - prelude = prelude.replace("--wait", "--watch") return "\n\n".join( [ prelude, _render_platform_job_watch_code(args, timeout, poll_interval), ] ) raise ValueError(f"Unsupported lifecycle config type: {lifecycle_type!r}")🤖 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 `@packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py` around lines 156 - 203, Update _render_lifecycle_code to compute the lifecycle flag name from lifecycle_type before constructing prelude, using --watch for platform_job and --wait otherwise, then interpolate that value into the error message. Remove the prelude.replace("--wait", "--watch") call so resource-name literals containing --wait remain unchanged.tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2 (1)
32-41: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winReject methods that configure both
waitandwatch.Both configurations are accepted independently. The template then emits duplicate
timeoutandpoll_intervalparameters, causing a PythonSyntaxError.🤖 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 `@tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2` around lines 32 - 41, Update the template conditions around the watch_config and wait_config blocks so generated commands cannot enable both configurations simultaneously. Preserve each configuration’s existing parameters when used alone, and ensure timeout and poll_interval are emitted only once to avoid duplicate function parameters.
🧹 Nitpick comments (1)
packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py (1)
199-228: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMove the function-local imports to module scope.
Line 28 already imports from
nemo_platform_ext.jobs.watchat module level, so the deferred imports on Line 213 and Line 408 cannot break an import cycle. Importwatch_jobandasync_watch_jobnormally.Also add docstrings; every other public method on this client is documented.
As per coding guidelines: "prefer concrete type hints over string-based type hints, and do not import those types only under `TYPE_CHECKING`; import them normally when possible."♻️ Proposed change
-from nemo_platform_ext.jobs.watch import JobWatchEvent +from nemo_platform_ext.jobs.watch import JobWatchEvent, async_watch_job, watch_job) -> Iterator[JobWatchEvent]: - from nemo_platform_ext.jobs.watch import watch_job - return watch_job(🤖 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 `@packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py` around lines 199 - 228, Move watch_job and async_watch_job imports from their methods to module scope alongside the existing nemo_platform_ext.jobs.watch import, then remove the function-local imports. Add concise docstrings to the public watch_job and async_watch_job client methods while preserving their current delegation and parameters.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 `@packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py`:
- Around line 312-334: Update _drain_logs at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py:312-334 to track
visited cursors, return when _next_page produces a cursor already seen or
otherwise fails to advance, and enforce the deadline on every loop iteration.
Apply the same cursor-advance guard and per-iteration deadline check in
_async_drain_logs at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py:352-374.
- Around line 126-150: Update the polling loop around _drain_logs to persist and
reuse the latest next_page cursor across cycles instead of resetting to the
original page_cursor. When the server invalidates that cursor, fall back to the
existing full re-scan behavior; otherwise advance the cursor after each
successful drain while preserving terminal-status handling.
- Around line 126-146: Update the log-draining flow around _drain_logs so
history_seen becomes true immediately after the first page is recorded,
including when pagination later raises a transient error. Preserve suppression
of pre-existing history for include_history=False while allowing newly fetched
lines to emit on the retry, and remove reliance on setting history_seen only
after the entire drain succeeds.
- Around line 102-105: Make both watcher entry points validate eagerly by
converting watch_job at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py:102-105 and
async_watch_job at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py:168-171 into
non-generator wrappers. Keep the poll_interval checks and _sync_jobs_client or
_async_jobs_client resolution in each wrapper, then return inner generator or
async-generator functions containing the existing iteration logic.
---
Outside diff comments:
In `@packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py`:
- Around line 156-203: Update _render_lifecycle_code to compute the lifecycle
flag name from lifecycle_type before constructing prelude, using --watch for
platform_job and --wait otherwise, then interpolate that value into the error
message. Remove the prelude.replace("--wait", "--watch") call so resource-name
literals containing --wait remain unchanged.
In
`@tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2`:
- Around line 32-41: Update the template conditions around the watch_config and
wait_config blocks so generated commands cannot enable both configurations
simultaneously. Preserve each configuration’s existing parameters when used
alone, and ensure timeout and poll_interval are emitted only once to avoid
duplicate function parameters.
---
Nitpick comments:
In `@packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py`:
- Around line 199-228: Move watch_job and async_watch_job imports from their
methods to module scope alongside the existing nemo_platform_ext.jobs.watch
import, then remove the function-local imports. Add concise docstrings to the
public watch_job and async_watch_job client methods while preserving their
current delegation and parameters.
🪄 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: 75f56093-22d4-4101-9ce3-7b89b2a6a52a
⛔ Files ignored due to path filters (11)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/jobs/watch.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (20)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.pypackages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
|
e7a5748 to
a5ff80c
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py (1)
923-1016: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a watch-only platform-job render test. No test covers a
platform_jobwatch config without a wait config. That case is exactly where the template emits an unusedwait_for_platform_jobimport (see the template comment).🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py` around lines 923 - 1016, Add a test alongside test_create_platform_job_watch_config_renders_wait_and_watch covering a create configuration with watch type platform_job but no wait block. Render the command and assert watch-related options/imports and job-watch behavior are present while the wait_for_platform_job import and wait-only rendering are absent, matching the template’s watch-only output.
🤖 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
`@tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2`:
- Around line 24-30: Update the conditional import for wait_for_platform_job in
the create command template so it is generated only when has_platform_job_wait
is enabled; keep the separate job-watch imports unchanged, since the watch-only
branch does not use wait_for_platform_job.
---
Nitpick comments:
In `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py`:
- Around line 923-1016: Add a test alongside
test_create_platform_job_watch_config_renders_wait_and_watch covering a create
configuration with watch type platform_job but no wait block. Render the command
and assert watch-related options/imports and job-watch behavior are present
while the wait_for_platform_job import and wait-only rendering are absent,
matching the template’s watch-only output.
🪄 Autofix
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: 7a009706-6d46-4524-9341-85bd84fb0ee0
⛔ Files ignored due to path filters (15)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/jobs/watch.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/telemetry/test_job_events.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (24)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.pypackages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.pypackages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/core/test_waiters.pypackages/nemo_platform_ext/tests/cli/telemetry/test_job_events.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
🚧 Files skipped from review as they are similar to previous changes (10)
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py
- tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yaml
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.py
- packages/nemo_platform_ext/tests/cli/test_app.py
- packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.py
- packages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py
a5ff80c to
18140ca
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py (1)
794-811: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winFixture annotations do not match the real
watch_jobcontract.
watch_jobreturnsIterator[JobWatchEvent]andasync_watch_jobreturnsAsyncIterator[JobWatchEvent], not a bareJobWatchEvent. The fixture is a stand-in forenhanced.py, so a wrong annotation here weakens the vendor-rewrite test. It also leaves line 826 asserting thatAsyncIteratorandIteratorare imported while the fixture never uses either name, so that assertion no longer proves anything about the rewritten watch signatures.Use the real return types, then assert each signature separately instead of
count(...) == 2on line 837.♻️ Suggested fixture change
- def watch_job(self, name: str) -> JobWatchEvent: + def watch_job(self, name: str) -> Iterator[JobWatchEvent]: \"\"\"Watch a job.\"\"\" return watch_job(self, name)- def watch_job(self, name: str) -> JobWatchEvent: + def watch_job(self, name: str) -> AsyncIterator[JobWatchEvent]: \"\"\"Watch a job asynchronously.\"\"\" return async_watch_job(self, name)Add the matching import to the fixture source and update the assertions:
- assert updated.count("def watch_job(self, name: str) -> JobWatchEvent:") == 2 + assert "def watch_job(self, name: str) -> Iterator[JobWatchEvent]:" in updated + assert "def watch_job(self, name: str) -> AsyncIterator[JobWatchEvent]:" in updated🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py` around lines 794 - 811, Update the fixture’s NeMoPlatform.watch_job and AsyncNeMoPlatform.watch_job annotations to use Iterator[JobWatchEvent] and AsyncIterator[JobWatchEvent], respectively, matching the real enhanced.py contract. Add Iterator and AsyncIterator to the fixture imports, then replace the combined import-count assertion with separate signature assertions for the synchronous and asynchronous methods.
🧹 Nitpick comments (5)
packages/nemo_platform_ext/tests/cli/core/test_code_generator.py (2)
243-253: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThe label test does not assert what its name claims.
test_generate_python_code_with_platform_job_watch_ignores_label_formattingpasses a label with quotes and{label}, then only checkscompileand the--watcherror string. Neither assertion proves the label was escaped or ignored. Assert that the raw label does not leak into the generated code.💚 Suggested assertion
compile(code, "<generated-code>", "exec") assert 'raise RuntimeError("Unable to determine created resource name for --watch")' in code + assert 'customization "job" {label}' not in 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 `@packages/nemo_platform_ext/tests/cli/core/test_code_generator.py` around lines 243 - 253, Update test_generate_python_code_with_platform_job_watch_ignores_label_formatting to assert that the raw watch_config resource_label, including its quotes and {label} placeholder, is absent from the generated code. Keep the existing compilation and RuntimeError assertions unchanged.
209-240: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd coverage for missing
watchtimeout validation.
_require_timeoutvalidateswatchmode, but the test covers only thewaiterror path. Add the proposedwatch_options={"poll_interval": 10}test.🤖 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 `@packages/nemo_platform_ext/tests/cli/core/test_code_generator.py` around lines 209 - 240, Add a test beside test_generate_python_code_with_inference_deployment_wait_requires_timeout covering create generation with watch_config for inference_deployment and watch_options containing only poll_interval. Assert generate_python_code raises ValueError with the watch lifecycle timeout validation message, exercising _require_timeout for watch mode.packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py (1)
393-426: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff
seen_logsretains one entry per log line for the whole watch. Both drain functions share the same unbounded dedupe map. Now that the cursor advances between polls, only the recent page window needs dedupe coverage.
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L393-L426: bound theseen_logsmap in_drain_logs, for example by evicting keys behind the advanced cursor.packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L429-L477: apply the same bounding in_async_drain_logs.🤖 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 `@packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py` around lines 393 - 426, Bound the shared seen_logs deduplication map to the active recent page window instead of retaining every log key indefinitely. Update both _drain_logs at packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L393-L426 and _async_drain_logs at packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L429-L477 to evict keys that fall behind the advanced page cursor while preserving deduplication for logs still covered by the current window.tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py (2)
963-964: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueTighten the timeout-default assertions.
assert "] = None" in renderedandassert "] = 1200" in renderedmatch any parameter default in the file, not thetimeoutparameter. They pass even iftimeoutloses its default. Assert the full annotated declaration instead.Also applies to: 1004-1005
🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py` around lines 963 - 964, In the timeout generation assertions around the existing `rendered` checks, replace the broad substring checks for `] = None` and `] = 1200` with assertions matching the complete `timeout` annotated parameter declaration and its expected default. Apply the same tightening to both affected test cases so unrelated parameter defaults cannot satisfy the assertions.
700-709: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winShare the Jinja environment setup between production and tests.
Extract the inline setup from
SimpleGenerator.__init__into a factory and use it in_render_create_command. The test currently uses a differentto_kebabimplementation than production.🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py` around lines 700 - 709, Extract the Jinja Environment configuration from SimpleGenerator.__init__ into a shared factory, preserving the production loader, options, and filters. Update _render_create_command to obtain its environment through that factory and remove the duplicate inline setup so both production and tests use the same to_kebab behavior.
🤖 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 `@packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py`:
- Around line 170-186: Cap retries for terminal-status log draining in both the
synchronous watcher loop at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L170-L186 and the
asynchronous watcher loop at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L271-L288. Track
failures from the final drain, emit a warning when the configured cap is
reached, and return instead of continuing indefinitely when timeout is None;
apply the same behavior consistently to both loops.
In `@packages/nemo_platform_ext/tests/jobs/test_watch.py`:
- Around line 484-488: Update the monotonic_values fixture in the watch_job
timeout test to provide a fallback value after the scripted 0.0, 0.0, and 10.0
readings, preventing unrelated calls to watch_module.time.monotonic from
exhausting the iterator. Preserve the existing timeout assertion and timing
sequence while ensuring additional calls do not raise StopIteration.
---
Outside diff comments:
In `@tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py`:
- Around line 794-811: Update the fixture’s NeMoPlatform.watch_job and
AsyncNeMoPlatform.watch_job annotations to use Iterator[JobWatchEvent] and
AsyncIterator[JobWatchEvent], respectively, matching the real enhanced.py
contract. Add Iterator and AsyncIterator to the fixture imports, then replace
the combined import-count assertion with separate signature assertions for the
synchronous and asynchronous methods.
---
Nitpick comments:
In `@packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py`:
- Around line 393-426: Bound the shared seen_logs deduplication map to the
active recent page window instead of retaining every log key indefinitely.
Update both _drain_logs at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L393-L426 and
_async_drain_logs at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L429-L477 to
evict keys that fall behind the advanced page cursor while preserving
deduplication for logs still covered by the current window.
In `@packages/nemo_platform_ext/tests/cli/core/test_code_generator.py`:
- Around line 243-253: Update
test_generate_python_code_with_platform_job_watch_ignores_label_formatting to
assert that the raw watch_config resource_label, including its quotes and
{label} placeholder, is absent from the generated code. Keep the existing
compilation and RuntimeError assertions unchanged.
- Around line 209-240: Add a test beside
test_generate_python_code_with_inference_deployment_wait_requires_timeout
covering create generation with watch_config for inference_deployment and
watch_options containing only poll_interval. Assert generate_python_code raises
ValueError with the watch lifecycle timeout validation message, exercising
_require_timeout for watch mode.
In `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py`:
- Around line 963-964: In the timeout generation assertions around the existing
`rendered` checks, replace the broad substring checks for `] = None` and `] =
1200` with assertions matching the complete `timeout` annotated parameter
declaration and its expected default. Apply the same tightening to both affected
test cases so unrelated parameter defaults cannot satisfy the assertions.
- Around line 700-709: Extract the Jinja Environment configuration from
SimpleGenerator.__init__ into a shared factory, preserving the production
loader, options, and filters. Update _render_create_command to obtain its
environment through that factory and remove the duplicate inline setup so both
production and tests use the same to_kebab behavior.
🪄 Autofix
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: 0127b6ea-560c-48e8-b381-796c88784c7b
⛔ Files ignored due to path filters (15)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/jobs/watch.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/telemetry/test_job_events.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (24)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.pypackages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.pypackages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/core/test_waiters.pypackages/nemo_platform_ext/tests/cli/telemetry/test_job_events.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
🚧 Files skipped from review as they are similar to previous changes (19)
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yaml
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.py
- packages/nemo_platform_ext/tests/cli/telemetry/test_job_events.py
- packages/nemo_platform_ext/tests/cli/test_app.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/init.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/init.py
- packages/nemo_platform_ext/tests/cli/core/test_waiters.py
- packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py
- tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.py
- docs/cli/reference.mdx
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2
- packages/nemo_platform_ext/tests/cli/commands/test_create_wait.py
- packages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.py
18140ca to
dfa04bc
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/nemo_platform_ext/tests/cli/core/test_code_generator.py (1)
243-253: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the escaping this test claims to verify.
The test name states label formatting is ignored, but the assertions only check compilation and the error string. A generator that interpolated the label unescaped into a docstring or comment could still pass. Add an assertion that the raw label is not injected outside a quoted literal.
♻️ Suggested assertion
compile(code, "<generated-code>", "exec") assert 'raise RuntimeError("Unable to determine created resource name for --watch")' in code + assert 'customization "job" {label}' not in 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 `@packages/nemo_platform_ext/tests/cli/core/test_code_generator.py` around lines 243 - 253, Strengthen test_generate_python_code_with_platform_job_watch_ignores_label_formatting by asserting that the raw resource_label text is not injected into the generated source outside a quoted literal, while retaining the existing compilation and RuntimeError assertions.tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py (1)
700-709: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the production Jinja environment in
_render_create_command.Extract the environment setup into a shared factory. The test currently replaces
caseutil.to_kebabwith a lambda that only replaces underscores, so it can render different command paths.🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py` around lines 700 - 709, Update _render_create_command to obtain its Jinja Environment from the same shared production environment factory used by the CLI generator, rather than constructing a test-specific environment with a local to_kebab lambda. Preserve loading create_command.py.j2 and rendering with the existing context, and remove the duplicated environment/filter setup.
🤖 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 `@packages/nemo_platform_ext/tests/cli/core/test_code_generator.py`:
- Around line 243-253: Strengthen
test_generate_python_code_with_platform_job_watch_ignores_label_formatting by
asserting that the raw resource_label text is not injected into the generated
source outside a quoted literal, while retaining the existing compilation and
RuntimeError assertions.
In `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py`:
- Around line 700-709: Update _render_create_command to obtain its Jinja
Environment from the same shared production environment factory used by the CLI
generator, rather than constructing a test-specific environment with a local
to_kebab lambda. Preserve loading create_command.py.j2 and rendering with the
existing context, and remove the duplicated environment/filter setup.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 050f3e33-c204-48d3-b41d-a24a883ee02b
⛔ Files ignored due to path filters (15)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/jobs/watch.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/telemetry/test_job_events.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (26)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.pypackages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.pypackages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/core/test_waiters.pypackages/nemo_platform_ext/tests/cli/telemetry/test_job_events.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/client/adapter.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/client.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
🚧 Files skipped from review as they are similar to previous changes (21)
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yaml
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.py
- tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py
- packages/nemo_platform_ext/tests/cli/test_app.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.py
- packages/nemo_platform_ext/tests/cli/core/test_waiters.py
- packages/nemo_platform_ext/tests/cli/telemetry/test_job_events.py
- packages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.py
- tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.py
- packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py
- packages/nemo_platform_ext/tests/cli/commands/test_create_wait.py
- docs/cli/reference.mdx
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/init.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/init.py
- packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py
Fresh open inline threads (not replies on resolved conversations):
Still open
Fixed since prior review (no action)R3 Live timer, R4 Optional / debt
|
tylersbray
left a comment
There was a problem hiding this comment.
+1'ing Matt's approval so you are not blocked. Will be a nice feature to ship.
58580df to
cc46405
Compare
|
Addressed the human review feedback in cc46405:
Validation:
|
cc46405 to
2784e4b
Compare
|
Small correction to my previous validation comment: after a cleanup pass, the final commit |
984a97c to
674025a
Compare
anastasia-nesterenko
left a comment
There was a problem hiding this comment.
left some nit comments, @ironcommit if they make sense I can add a commit for them
parkanzky
left a comment
There was a problem hiding this comment.
LGTM looking forward to this
6bacd89 to
adbd3f6
Compare
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
adbd3f6 to
864075f
Compare
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com> Signed-off-by: Nick Goncharenko <ngoncharenko@nvidia.com>
Summary
Adds a
nemo jobs watchCLI command and corresponding SDK watcher methods that stream job lifecycle events - status transitions, log lines, and warnings - directly to the terminal or programmatic consumers. The sync and async Jobs SDK clients both exposewatch_job(...); the async client returns an async iterator backed byasync_watch_job(...).Changes
Core watch engine (
jobs/watch.py)JobWatchEventobjects (status, log, warning)attempt_id,step_id, andtask_idpoll_intervalCLI command (
nemo jobs watch)--timeout,--poll-interval,--history/--no-history,--attempt-id,--step-id,--task-id,--limit,--workspaceinclude_logs=Falseis SDK-only--watchflag on create commandsnemo jobs create --watchandnemo inference deployments create --watchautomatically watch after creation--waitflag--watchsupport for configured create commands viacli_config.yamlSDK client integration
client.jobs.watch_job(name, ...)-> sync iterator ofJobWatchEventasync_client.jobs.watch_job(name, ...)-> async iterator ofJobWatchEventNeMoPlatformclients through the Jobs resourceWaiters refactor
Testing
test_watch.py)nemo jobs watchand--watchon create commands (test_app.py,test_create_wait.py)test_job_watch_renderer.py)test_code_generator.py,test_config.py)Summary by CodeRabbit
jobs watchto stream job status, logs, warnings, and completion results.--watchsupport for job and inference deployment creation, with timeout and polling controls.--waitand--watchtogether.