Skip to content

[llm-d] Make more reliable - #91

Merged
openshift-merge-bot[bot] merged 26 commits into
openshift-psap:mainfrom
kpouget:llmd
Jun 29, 2026
Merged

openshift-merge-bot[bot] merged 26 commits into
openshift-psap:mainfrom
kpouget:llmd

Conversation

@kpouget

@kpouget kpouget commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added DSL early-return support plus enhanced retry logging.
    • Introduced operator bootstrap/cleanup tooling with richer diagnostics and agent-style failure reports.
    • Added orchestration preflight validation, LeaderWorkerSet integration, and improved CI/test/cleanup flows.
  • Bug Fixes
    • Improved handling for existing installs, manual approval flows, readiness/timeouts, and missing/failed job scenarios.
    • Enhanced targeting to prevent over-deleting resources during cleanup.
  • Documentation
    • Added/expanded changelog entries and standardized changelog structure guidance.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds EarlyReturn control flow to the DSL runtime, new cluster toolbox scripts for LeaderWorkerSet bootstrap and operator cleanup, KServe and GPU bootstrap diagnostics, and llm_d orchestration/config updates for preflight checks, single-path testing, and cleanup behavior.

Changes

DSL early-return and retry logging

Layer / File(s) Summary
EarlyReturn API and export
projects/core/dsl/control_flow.py, projects/core/dsl/__init__.py, projects/core/CHANGELOG-dsl.md
EarlyReturn is defined, re-exported, and documented as a control-flow sentinel.
Runtime early-return handling
projects/core/dsl/runtime.py
The runtime converts EarlyReturn results into a dedicated exception, tracks stopped state, skips pending non-@always tasks, and continues remaining @always tasks.
Retry header suffix
projects/core/dsl/task.py
Retry logging accepts artifact_dirname_suffix and includes it in retry headers.

Cluster operator lifecycle tooling

Layer / File(s) Summary
Bootstrap LWS operator
projects/cluster/toolbox/bootstrap_lws_operator/main.py, projects/cluster/toolbox/bootstrap_lws_operator/templates/leaderworkersetoperator.yaml.j2, projects/cluster/CHANGELOG-toolbox.md
Renders, applies, waits on, and captures state for the LeaderWorkerSetOperator resource.
Cleanup operators toolbox
projects/cluster/toolbox/cleanup_operators/main.py
Validates subscriptions, captures associated resources, deletes operator resources conditionally, and writes a cleanup summary.
CSV gate and InstallPlan approval
projects/cluster/toolbox/cluster_deploy_operator/main.py, projects/cluster/toolbox/cluster_deploy_operator/on_failure_helpers.py
Adds a succeeded-CSV gate, InstallPlan approval handling, safer CSV lookup, and InstallPlan failure analysis output.

GPU operator and KServe diagnostics

Layer / File(s) Summary
ClusterPolicy readiness and namespace
projects/gpu_operator/toolbox/bootstrap_gpu_clusterpolicy/main.py
Resolves the GPU operator namespace, records readiness errors on context, and captures DaemonSet/Pod diagnostics.
GPU failure analysis helper
projects/gpu_operator/toolbox/bootstrap_gpu_clusterpolicy/on_failure_helpers.py, projects/gpu_operator/CHANGELOG-toolbox.md
Writes AGENT.md for ClusterPolicy failures and lists the expected diagnostic artifacts.
LLMInferenceService readiness and diagnostics
projects/kserve/toolbox/deploy_llmisvc/main.py, projects/kserve/toolbox/deploy_llmisvc/on_failure_helpers.py, projects/kserve/CHANGELOG-toolbox.md
Derives service metadata from context, captures describe output, and writes a pod-wait failure post-mortem.
Download wait and pod diagnostics
projects/kserve/toolbox/prepare_hf_model_cache/main.py
wait_for_download raises on missing jobs and emits pod diagnostics before retrying.
KServe changelog updates
projects/kserve/CHANGELOG-toolbox.md
The toolbox changelog expands the deploy and model-cache entries with the new diagnostics and reliability notes.

llm_d orchestration wiring

Layer / File(s) Summary
Platform config, presets, and tests
projects/llm_d/orchestration/config.d/deployments.yaml, projects/llm_d/orchestration/config.d/platform.yaml, projects/llm_d/orchestration/config.yaml, projects/llm_d/orchestration/manifests/leaderworkersetoperator.yaml, projects/llm_d/orchestration/presets.d/presets.yaml, projects/llm_d/tests/test_profiles.py
Deployment defaults move to a single-GPU shape, platform config adds LWS bootstrap metadata and required CRDs, orchestration config adds agentic and cleanup settings, smoke preset overrides benchmark keys, and tests are updated to match.
Preflight CI and CRD checks
projects/llm_d/orchestration/ci.py, projects/llm_d/orchestration/preflight_phase.py
CI runs the preflight toolbox, triggers async config review before tests, and the preflight phase checks required CRDs from config.
LeaderWorkerSet prepare flow
projects/llm_d/orchestration/prepare_phase.py
The prepare phase now invokes the LWS bootstrap and waits for the workload CRD.
Test finalization and cleanup diagnostics
projects/llm_d/orchestration/test_phase.py, projects/llm_d/toolbox/cleanup_test_resources/main.py, projects/llm_d/CHANGELOG-toolbox.md
The test phase consolidates execution under one artifact root with centralized finalizers, and cleanup-test-resources logs pod details before deletion.
Cleanup orchestration with operator deletion
projects/llm_d/orchestration/ci.py, projects/llm_d/orchestration/cleanup_phase.py
Cleanup passes cleanup_subscriptions=true, and operator deletion respects configured preserve lists.

RHOAI wait and CI text

Layer / File(s) Summary
RHOAI wait and CI wording
projects/rhoai/toolbox/apply_datasciencecluster/main.py, projects/core/ci_entrypoint/prepare_ci.py, projects/core/agentic/on_failure/__init__.py
Adds a deployment availability wait task, changes CI notification/status wording to Execution, and formats failure-review artifact paths in bold.
Changelog structure and project changelogs
docs/changelog-structure.md, projects/fournos_launcher/CHANGELOG-orchestration.md, projects/fournos_launcher/CHANGELOG-toolbox.md, projects/llm_d/CHANGELOG-orchestration.md, projects/llm_d/CHANGELOG.md
Adds the changelog structure guide and updates project changelogs for orchestration/toolbox entries and the removed llm_d changelog section.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Suggested reviewers

  • albertoperdomo2

Poem

🐇 Hop hop, the runtimes now can yield,
Yet @always tasks still roam the field.
LWS and CSVs, the operators gleam,
With AGENT.md artifacts in the stream.
The rabbit nods: “All paths now seem quite neat!” 🌿

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is related to the PR, but it's too vague to convey the main change beyond a generic reliability improvement. Use a specific title that names the main change, e.g. "[llm-d] Add operator bootstrap, cleanup, and early-return reliability improvements".
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@kpouget

kpouget commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full

@psap-forge-bot

Copy link
Copy Markdown

🔴 Test of 'llm_d prepare' failed after 00 hours 07 minutes 16 seconds 🔴

• Link to the test results.

Test configuration:

ci_job.cluster: forge-smoke-testing
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-20260626-094820
ci_job.name: llm_d
ci_job.owner: kpouget
project.args: []
project.name: llm_d

FAILURE REVIEW 001 cluster deploy operator openshift-cert-manager-operator:

001__cluster_deploy_operator__openshift-cert-manager-operator

The wait_for_installplan task failed after exhausting its retry budget, incorrectly halting the deployment of the openshift-cert-manager-operator due to a strict polling logic that required a non-null .status.installPlanRef. This was a false positive caused by a mismatch with OpenShift OLM's idempotent reconciliation state: because the operator was already installed and the subscription spec had not drifted, OLM intentionally left the installPlanRef as null while maintaining a satisfied status, which the task lacked the logic to recognize as a successful outcome.

• Detailed failure analysis report

• Raw failure details
• Execution logs

@psap-forge-bot

Copy link
Copy Markdown

🔴 Test of 'fournos_launcher submit' failed after 00 hours 10 minutes 26 seconds 🔴

• Link to the test results.

• FOURNOS Job Status:

  • ❌ forge-llm-d-20260626-094820: Failed - Tasks Completed: 4 (Failed: 1, Cancelled 0), Skipped: 1

• MLflow Tracking:

• FOURNOS Job Details:

• Task Logs:

Test configuration:

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full

• Failure indicator:

## /logs/artifacts/001__submit_and_wait/FAILURE 
================================================================================
TASK EXECUTION FAILURE
================================================================================
Timestamp: 2026-06-26 09:58:36
Exception Type: TaskExecutionError
Exception Message: ❌ TASK FAILURE: wait_for_job_completion: Wait for FOURNOS job to complete
   projects/fournos_launcher/toolbox/submit_and_wait/main.py:186
   RuntimeError: Job forge-llm-d-20260626-094820 failed: Tasks Completed: 4 (Failed: 1, Cancelled 0), Skipped: 1


[...]

• Execution logs

@kpouget

kpouget commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@psap-forge-bot

Copy link
Copy Markdown

🔴 Test of 'llm_d prepare' failed after 00 hours 07 minutes 42 seconds 🔴

• Link to the test results.

Test configuration:

ci_job.cluster: forge-smoke-testing
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-20260626-125151
ci_job.name: llm_d
ci_job.owner: kpouget
project.args: []
project.name: llm_d

FAILURE REVIEW 003 bootstrap lws operator:

003__bootstrap_lws_operator

The wait_for_lws_operator_ready task failed after exhausting 30 retries because the LeaderWorkerSetOperator/cluster resource never transitioned to a ready state. Detailed analysis of the captured artifact confirms the root cause is an environmental dependency failure: the operator controller encountered a SyncError and stalled during initialization because the required cert-manager-webhook service was missing, preventing the controller from populating the Available status condition.

• Detailed failure analysis report

• Raw failure details
• Execution logs

@psap-forge-bot

Copy link
Copy Markdown

🔴 Test of 'fournos_launcher submit' failed after 00 hours 09 minutes 05 seconds 🔴

• Link to the test results.

• FOURNOS Job Status:

  • ❌ forge-llm-d-20260626-125151: Failed - Tasks Completed: 4 (Failed: 1, Cancelled 0), Skipped: 1

• MLflow Tracking:

• FOURNOS Job Details:

• Task Logs:

Test configuration:

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full

• Failure indicator:

## /logs/artifacts/001__submit_and_wait/FAILURE 
================================================================================
TASK EXECUTION FAILURE
================================================================================
Timestamp: 2026-06-26 13:00:47
Exception Type: TaskExecutionError
Exception Message: ❌ TASK FAILURE: wait_for_job_completion: Wait for FOURNOS job to complete
   projects/fournos_launcher/toolbox/submit_and_wait/main.py:186
   RuntimeError: Job forge-llm-d-20260626-125151 failed: Tasks Completed: 4 (Failed: 1, Cancelled 0), Skipped: 1


[...]

• Execution logs

@kpouget

kpouget commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full
/var cleanup.preserve_operators.openshift-cert-manager-operator: false

@psap-forge-bot

Copy link
Copy Markdown

🔴 Test of 'llm_d prepare' failed after 00 hours 21 minutes 20 seconds 🔴

• Link to the test results.

Test configuration:

ci_job.cluster: forge-smoke-testing
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-20260626-131630
ci_job.name: llm_d
ci_job.owner: kpouget
cleanup.preserve_operators.openshift-cert-manager-operator: 'false'
project.args: []
project.name: llm_d

FAILURE REVIEW 010 bootstrap gpu clusterpolicy:

010__bootstrap_gpu_clusterpolicy

The GPU operator bootstrap failed when the wait_for_clusterpolicy_ready task exhausted 60 retries because the gpu-cluster-policy resource stalled permanently at the state-operator-validation state and never reported ready. This reconciliation stall prevented the operator's validation controller from completing its readiness checks, halting the bootstrap process after all other infrastructure components had successfully resolved.

• Detailed failure analysis report

• Raw failure details
• Execution logs

@psap-forge-bot

Copy link
Copy Markdown

🔴 Test of 'fournos_launcher submit' failed after 00 hours 24 minutes 47 seconds 🔴

• Link to the test results.

• FOURNOS Job Status:

  • ❌ forge-llm-d-20260626-131630: Failed - Tasks Completed: 4 (Failed: 1, Cancelled 0), Skipped: 1

• MLflow Tracking:

• FOURNOS Job Details:

• Task Logs:

Test configuration:

/test fournos llm_d
/var cleanup.preserve_operators.openshift-cert-manager-operator: false
/cluster forge-smoke-testing
/pipeline forge-full

• Failure indicator:

## /logs/artifacts/001__submit_and_wait/FAILURE 
================================================================================
TASK EXECUTION FAILURE
================================================================================
Timestamp: 2026-06-26 13:41:06
Exception Type: TaskExecutionError
Exception Message: ❌ TASK FAILURE: wait_for_job_completion: Wait for FOURNOS job to complete
   projects/fournos_launcher/toolbox/submit_and_wait/main.py:186
   RuntimeError: Job forge-llm-d-20260626-131630 failed: Tasks Completed: 4 (Failed: 1, Cancelled 0), Skipped: 1


[...]

• Execution logs

@kpouget
kpouget force-pushed the llmd branch 2 times, most recently from 7b83bd6 to 4919605 Compare June 26, 2026 14:02
@kpouget

kpouget commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full

@psap-forge-bot

Copy link
Copy Markdown

🔴 Test of 'llm_d test' failed after 00 hours 16 minutes 26 seconds 🔴

• Link to the test results.

• Caliper postprocess completed but no reports generated.

Test configuration:

ci_job.cluster: forge-smoke-testing
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-20260626-140314
ci_job.name: llm_d
ci_job.owner: kpouget
project.args: []
project.name: llm_d

TEST DESCRIPTION:

This test evaluates the llm_d project by applying the approximate-prefix-cache deployment profile and the Qwen/Qwen3-0.6B model configuration to verify the setup and functionality of the approximate prefix caching scheduler.

FAILURE REVIEW 002 run smoke request:

001__llmd_test/002__run_smoke_request

The execute_smoke_request task failed because the curl command targeting the forge-llm-d LLM endpoint timed out after 60 seconds (exit code 28), indicating a failure to establish a connection or receive an HTTP response. This timeout prevented validation of the service endpoint, blocking the smoke test and preventing further test execution.

• Detailed failure analysis report

• Config review report

• Raw failure details
• Execution logs

@psap-forge-bot

Copy link
Copy Markdown

🔴 Test of 'fournos_launcher submit' failed after 00 hours 22 minutes 23 seconds 🔴

• Link to the test results.

• FOURNOS Job Status:

  • ❌ forge-llm-d-20260626-140314: Failed - Tasks Completed: 5 (Failed: 1, Cancelled 0), Skipped: 0

• MLflow Tracking:

• FOURNOS Job Details:

• Task Logs:

Test configuration:

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full

• Failure indicator:

## /logs/artifacts/001__submit_and_wait/FAILURE 
================================================================================
TASK EXECUTION FAILURE
================================================================================
Timestamp: 2026-06-26 14:25:27
Exception Type: TaskExecutionError
Exception Message: ❌ TASK FAILURE: wait_for_job_completion: Wait for FOURNOS job to complete
   projects/fournos_launcher/toolbox/submit_and_wait/main.py:186
   RuntimeError: Job forge-llm-d-20260626-140314 failed: Tasks Completed: 5 (Failed: 1, Cancelled 0), Skipped: 0


[...]

• Execution logs

@kpouget
kpouget force-pushed the llmd branch 2 times, most recently from 3de1374 to ef42ee4 Compare June 26, 2026 14:44
@kpouget

kpouget commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full

@psap-forge-bot

Copy link
Copy Markdown

🔴 Executing of 'llm_d test' failed after 00 hours 05 minutes 46 seconds 🔴

• Link to the test results.

• Caliper postprocess completed but no reports generated.

Test configuration:

ci_job.cluster: forge-smoke-testing
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-20260626-144540
ci_job.name: llm_d
ci_job.owner: kpouget
project.args: []
project.name: llm_d

TEST DESCRIPTION:

This test evaluates the llm_d project's deployment of Qwen/Qwen3-0.6B using the approximate-prefix-cache profile, specifically benchmarking vLLM's prefix caching feature. It executes a short concurrent workload via the Guidellm engine to measure inference throughput and latency under controlled token lengths and request rates.

FAILURE REVIEW 002 run smoke request:

001__llmd_test/002__run_smoke_request

The execute_smoke_request task failed with a curl timeout (exit code 28) after 60 seconds when attempting to reach the LLM service endpoint, indicating the backend was unreachable or unresponsive. This failure suggests the service may not be ready to serve traffic, is experiencing extreme latency due to model initialization, or is being silently dropped by a routing or network policy misconfiguration.

• Detailed failure analysis report

• Config review report

• Raw failure details
• Execution logs

@psap-forge-bot

Copy link
Copy Markdown

🔴 Executing of 'fournos_launcher submit' failed after 00 hours 10 minutes 22 seconds 🔴

• Link to the test results.

• FOURNOS Job Status:

  • ❌ forge-llm-d-20260626-144540: Failed - Tasks Completed: 5 (Failed: 1, Cancelled 0), Skipped: 0

• MLflow Tracking:

• FOURNOS Job Details:

• Task Logs:

Test configuration:

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full

• Failure indicator:

## /logs/artifacts/001__submit_and_wait/FAILURE 
================================================================================
TASK EXECUTION FAILURE
================================================================================
Timestamp: 2026-06-26 14:55:51
Exception Type: TaskExecutionError
Exception Message: ❌ TASK FAILURE: wait_for_job_completion: Wait for FOURNOS job to complete
   projects/fournos_launcher/toolbox/submit_and_wait/main.py:186
   RuntimeError: Job forge-llm-d-20260626-144540 failed: Tasks Completed: 5 (Failed: 1, Cancelled 0), Skipped: 0


[...]

• Execution logs

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

Actionable comments posted: 16

Caution

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

⚠️ Outside diff range comments (1)
fournos/gitops/base/workflows/pipeline-full.yaml (1)

119-136: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

job-step-name does not match the 05-export-artifacts task name.

The task is named 05-export-artifacts but its job-step-name is 04__export-artifacts, so the artifact directory (derived from FOURNOS_STEP_NAME per task-forge-step.yaml) will be misnamed and inconsistent with the task. Should be 05__export-artifacts.

🐛 Proposed fix
         - name: job-step-name
-          value: 04__export-artifacts
+          value: 05__export-artifacts
🤖 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 `@fournos/gitops/base/workflows/pipeline-full.yaml` around lines 119 - 136, The
`05-export-artifacts` task in `pipeline-full.yaml` has a mismatched
`job-step-name` value, which will cause the artifact directory naming used by
`forge-step` and `task-forge-step.yaml` to be inconsistent. Update the
`job-step-name` parameter in the `05-export-artifacts` task to match the task’s
step number so it follows the same `FOURNOS_STEP_NAME`-derived pattern as the
other tasks, using the `05__export-artifacts` naming convention.
🧹 Nitpick comments (6)
fournos/gitops/base/workflows/pipeline-prepare-test.yaml (1)

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

Stale job-step-name numbering on 01-prepare.

The task 01-prepare still uses job-step-name: 001__prepare while the rest of this file moved to the two-digit 0N__ scheme (e.g. 02__preflight, 04__export-artifacts). Align it to 01__prepare for a consistent artifact-dir naming.

🤖 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 `@fournos/gitops/base/workflows/pipeline-prepare-test.yaml` around lines 20 -
37, The `01-prepare` task in the pipeline manifest still uses the old
`job-step-name` value `001__prepare`; update it to match the file’s current
two-digit naming convention used by other steps like `02__preflight` and
`04__export-artifacts`. Make the change in the `job-step-name` param for
`01-prepare` so artifact directory naming stays consistent across the workflow.
fournos/gitops/base/workflows/pipeline-full.yaml (1)

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

Duplicate 02 prefix for two distinct tasks.

Both 02-preflight and 02-test share the 02 numbering, breaking the otherwise sequential ordering convention (compare pipeline-prepare-test.yaml, where preflight is 02 and test is 03). Consider renaming the test task to 03-test and its job-step-name to 03__test for consistency.

🤖 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 `@fournos/gitops/base/workflows/pipeline-full.yaml` around lines 59 - 79, The
pipeline task names are using the same 02 prefix for two different steps, which
breaks the sequential naming convention. Update the task identifier for the test
stage from 02-test to 03-test, and adjust the corresponding job-step-name in the
same task from 02__test to 03__test so it matches the ordering used by the
pipeline task definitions.
projects/kserve/toolbox/prepare_hf_model_cache/main.py (1)

340-343: 🔒 Security & Privacy | 🔵 Trivial

Prefer the list form for shell.run to avoid shell interpolation

shell.run accepts str | list[str] and defaults to shell=True. Passing an argument list with shell=False removes the shell interpolation risk and is more robust to unusual characters in namespace or job_name.

Both values are derived from cache_spec, which is built deterministically in this module and always includes namespace and download_job_name.

♻️ Proposed change
-    shell.run(
-        f"oc get pods -n {namespace} -l job-name={job_name}",
-        check=False,
-    )
+    shell.run(
+        ["oc", "get", "pods", "-n", namespace, "-l", f"job-name={job_name}"],
+        check=False,
+        shell=False,
+    )
🤖 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 `@projects/kserve/toolbox/prepare_hf_model_cache/main.py` around lines 340 -
343, The `shell.run` call in `prepare_hf_model_cache/main.py` is using a
shell-form string, which leaves room for shell interpolation; update the `oc get
pods` invocation to use the argument-list form with `shell=False`. Keep the same
command semantics while passing `namespace` and `job_name` as separate arguments
so `shell.run` handles them safely and robustly. Use the existing `shell.run`
call site around the pod lookup logic to locate the change.
projects/llm_d/toolbox/cleanup_test_resources/main.py (1)

208-212: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Drop or persist the unused JSON pod fetch.

This command discards stdout and does not feed the deletion check, so it only adds an extra API-server call on every retry. Keep the plain-text diagnostic, or write the JSON output to an artifact if it is needed.

Proposed cleanup
-    shell.run(
-        f"oc get pods -n {args.namespace} -l app.kubernetes.io/name={args.inference_service_name} -o json",
-        check=False,
-        log_stdout=False,
-    )
-
🤖 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 `@projects/llm_d/toolbox/cleanup_test_resources/main.py` around lines 208 -
212, The extra JSON pod fetch in the cleanup flow is unused and just adds
another API-server call on each retry. Update the retry logic around shell.run
in cleanup_test_resources/main.py so the diagnostic remains plain-text only, or
persist the JSON output to an artifact if it is actually needed by the deletion
check; remove the discarded json call from the retry path.
projects/llm_d/orchestration/test_phase.py (1)

57-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Align run_finalizers’ return type with its actual contract.

Line 104 returns a pair, so the annotation should describe (primary_exc, finalizer_exc) rather than one exception tuple.

Proposed cleanup
 def run_finalizers(
     endpoint_url: str | None,
     primary_exc: tuple[type[BaseException], BaseException, Any] | None,
     finalizer_exc: tuple[type[BaseException], BaseException, Any] | None,
-) -> tuple[type[BaseException], BaseException, Any] | None:
+) -> tuple[
+    tuple[type[BaseException], BaseException, Any] | None,
+    tuple[type[BaseException], BaseException, Any] | None,
+]:

Also applies to: 104-104

🤖 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 `@projects/llm_d/orchestration/test_phase.py` around lines 57 - 61,
`run_finalizers`’ return annotation does not match what the function actually
returns: it returns both `primary_exc` and `finalizer_exc`, not a single
exception tuple. Update the `run_finalizers` signature and any related type
hints in `test_phase.py` to reflect a pair/tuple of the two exception tuples,
and make sure the return statement at the end of `run_finalizers` matches that
contract.
projects/gpu_operator/toolbox/bootstrap_gpu_clusterpolicy/main.py (1)

167-208: 🔒 Security & Privacy | 🔵 Trivial

Replace f-string shell commands with argv lists and shell=False

The shell.run() wrapper explicitly supports list-style arguments and the shell flag. Interpolating namespace into shell strings needlessly exposes command arguments to shell parsing. Convert all six oc invocations in this block to use the list form.

     shell.run(
-        f"oc get daemonsets -n {namespace} -oyaml",
+        ["oc", "get", "daemonsets", "-n", namespace, "-oyaml"],
+        shell=False,
         stdout_dest=args.artifact_dir / "artifacts" / "gpu-operator-daemonsets.yaml",
         check=False,
     )

Apply this pattern to all remaining calls in the block.

🤖 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 `@projects/gpu_operator/toolbox/bootstrap_gpu_clusterpolicy/main.py` around
lines 167 - 208, The `shell.run()` calls in the GPU operator artifact capture
block are still using interpolated shell strings, which should be replaced with
argv lists. Update each `oc` invocation in `main.py` to pass command arguments
as a list using the `shell.run` wrapper’s list-style form, keeping `namespace`
as a separate argument and not embedded in an f-string. Apply this change
consistently to the six capture calls in the block, including the `get`,
`describe`, and `-owide` commands, so they all run with `shell=False`.
🤖 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 `@fournos/gitops/base/workflows/pipeline-full.yaml`:
- Around line 79-97: The 02-test task in the pipeline is invoking the wrong job
step, so testing never runs and preflight is duplicated. Update the `job-step`
parameter in `pipeline-full.yaml` for the `02-test` task from preflight to test,
keeping the surrounding `forge-step` task configuration and `job-step-name`
as-is so the step name matches the intended test execution.

In `@fournos/gitops/base/workflows/pipeline-prepare-test.yaml`:
- Around line 59-60: The 03-test task in the pipeline workflow has an invalid
runAfter dependency because it points to a task name that does not exist. Update
the runAfter reference on 03-test to match the actual preflight task identifier,
02-preflight, so the Tekton DAG resolves correctly and the pipeline definition
validates.

In `@fournos/gitops/base/workflows/pipeline-test-only.yaml`:
- Line 39: The `01-test` task in the pipeline is missing a `runAfter` dependency
on `00-preflight`, so preflight can run in parallel instead of gating the test.
Update the Tekton workflow definition for `01-test` to depend on `00-preflight`,
following the same pattern used in `pipeline-prepare-only.yaml`, so the
preflight step completes before the test starts.

In `@projects/cluster/toolbox/bootstrap_lws_operator/main.py`:
- Around line 16-22: The `run` function’s `timeout_seconds` parameter is
currently unused because readiness waits are controlled by the fixed retry
decorators in `run` rather than by caller input. Either remove `timeout_seconds`
and its docstring from `run`, or thread it into the waiting logic by replacing
the fixed retries with timeout-based polling in the readiness checks so the
caller can actually influence the wait duration.

In `@projects/cluster/toolbox/cleanup_operators/main.py`:
- Around line 114-124: The per-operator artifact filenames in the cleanup flow
are missing the namespace, so repeated subscription names can overwrite each
other’s diagnostics. Update the filename construction in the `shell.run` calls
that write the CSV and InstallPlan artifacts to include both `subscription_name`
and `namespace`, and apply the same change in the other matching block
referenced by the comment. Keep the existing artifact destinations and command
behavior unchanged.
- Around line 161-175: The cleanup logic in the subscription check is failing
open because it treats an unsuccessful oc get subscription call as zero
subscriptions, which can trigger unsafe deletion of shared OperatorGroups.
Update the subscription-counting flow in cleanup_operators/main.py so the code
using shell.run and remaining_subscriptions first verifies the command succeeded
before inspecting result.stdout, and if it fails, skip deletion and log or raise
an error instead of proceeding to delete operator groups. Keep the deletion
guard around the existing logger.info and oc delete operatorgroup path so
OperatorGroups are only removed when the subscription query is known to be
valid.

In `@projects/cluster/toolbox/cluster_deploy_operator/main.py`:
- Around line 66-112: The early-return logic in check_existing_csv can bypass
validate_parameters, letting reused cluster state hide invalid inputs. Reorder
the task flow so validate_parameters runs before check_existing_csv, ensuring
source_name, channel, approval mode, and install mode are validated first while
keeping the existing EarlyReturn behavior in check_existing_csv unchanged.
- Around line 456-466: The Subscription failure check in the operator logic only
inspects the second entry in conditions, so it can miss a ResolutionFailed
condition when ordering changes. Update the condition handling in main.py to
iterate through all items in subscription_data["status"]["conditions"] and raise
the same ValueError as soon as any condition_type equals ResolutionFailed, using
the matching message and reason from that condition.

In `@projects/core/ci_entrypoint/prepare_ci.py`:
- Line 588: The user-visible notification text built in prepare_ci.py is
inconsistent and ungrammatical, using both “Executing of” and “Execution of”
around the notification_status formatting. Update the status message
construction at the affected notification points so they all use one consistent,
grammatical phrasing (for example, the same “Execution of '{project}
{operation}' ...” form) in the prepare_ci flow, including the logic around
notification_status.

In `@projects/core/dsl/runtime.py`:
- Around line 369-376: The early-return path in runtime.py drops any context
changes because EarlyReturnException is raised in the task handling block before
the shared_context write-back runs. Update the task execution flow around the
EarlyReturn check so the context persistence loop executes before raising
EarlyReturnException, or otherwise ensure context is saved as part of the
early-return path. Use the existing task_status, EarlyReturn, and shared_context
logic in the runtime task runner to keep values set by the task available to
downstream `@always` tasks like capture_csv.

In `@projects/gpu_operator/toolbox/bootstrap_gpu_clusterpolicy/main.py`:
- Around line 84-91: The namespace fallback in the ClusterPolicy readiness flow
is getting stuck on the default value instead of refreshing from the latest
status. Update the logic in the ClusterPolicy retry/readiness path, especially
the code that reads `result.stdout` and the loop that rechecks status on each
retry, so `ctx.gpu_operator_namespace` is reassigned whenever
`.status.namespace` becomes available. Keep the existing fallback behavior only
until a real namespace is observed, and make sure the final diagnostics use the
refreshed value from `ctx.gpu_operator_namespace`.

In `@projects/kserve/toolbox/deploy_llmisvc/main.py`:
- Around line 136-149: The pod-appearance wait in wait_pods_appear was shortened
too much, which can cause slow KServe/LLMInferenceService reconciliations to
fail before readiness checks run. Update wait_pods_appear in
deploy_llmisvc/main.py to restore a longer wait window or make the retry
duration configurable, keeping the existing service_name, selector, and
oc_get_json flow intact.
- Around line 166-178: The diagnostic artifact writing for the `oc` calls
currently saves only `stdout`, so failures from `describe` and `get replicaset`
can lose the real error details. Update the artifact generation around the
`oc(...)` result handling in `main.py` so the saved files include `stderr`
whenever `check=False` is used, and make sure this is applied to both the
`llminferenceservice` describe path and the replicaset diagnostic path. Use the
existing `result` object and artifact writes like `llmisv_desc_path` to locate
and append the error output alongside the normal output.

In `@projects/llm_d/orchestration/ci.py`:
- Around line 89-96: The pre_cleanup() step is deleting non-preserved operator
subscriptions before prepare(), which forces rhods-operator and related
operators to be torn down and reinstalled on every run. Update the cleanup flow
in pre_cleanup() so full cleanup with cleanup_subscriptions=True is moved to
post_cleanup(), or adjust runtime_config/config.yaml preserve settings to
include rhods-operator, rhcl-operator, and leader-worker-set if they must
survive pre-run cleanup. Make sure the fix is applied in the pre_cleanup and
cleanup_toolbox_run path so prepare() no longer triggers unnecessary operator
churn.

In `@projects/llm_d/orchestration/cleanup_phase.py`:
- Around line 58-74: The cleanup flow in cleanup_phase.py is currently
fail-open: when cleanup_config or preserve_operators is missing,
_identify_operators_to_delete can mark all platform operators for deletion
before cleanup_operators_command.run is called. Update the cleanup logic to
default to preserving operators unless an explicit allowlist/opt-in is present,
and make _identify_operators_to_delete (and any callers in this phase) return no
deletions when the preserve list is absent or incomplete. Ensure the guard
happens before invoking cleanup_operators_command.run so platform operators are
not removed accidentally.

In `@projects/llm_d/orchestration/config.yaml`:
- Line 71: The hardcoded model_key value is invalid and will break model
resolution; update the config entry in the orchestration config to a valid
registry key such as qwen3-0_6b/qwen3-0-6b, and make sure the default MODEL_KEY
in config_review/__init__.py matches the same valid identifier used by
runtime.yaml and the test suite.

---

Outside diff comments:
In `@fournos/gitops/base/workflows/pipeline-full.yaml`:
- Around line 119-136: The `05-export-artifacts` task in `pipeline-full.yaml`
has a mismatched `job-step-name` value, which will cause the artifact directory
naming used by `forge-step` and `task-forge-step.yaml` to be inconsistent.
Update the `job-step-name` parameter in the `05-export-artifacts` task to match
the task’s step number so it follows the same `FOURNOS_STEP_NAME`-derived
pattern as the other tasks, using the `05__export-artifacts` naming convention.

---

Nitpick comments:
In `@fournos/gitops/base/workflows/pipeline-full.yaml`:
- Around line 59-79: The pipeline task names are using the same 02 prefix for
two different steps, which breaks the sequential naming convention. Update the
task identifier for the test stage from 02-test to 03-test, and adjust the
corresponding job-step-name in the same task from 02__test to 03__test so it
matches the ordering used by the pipeline task definitions.

In `@fournos/gitops/base/workflows/pipeline-prepare-test.yaml`:
- Around line 20-37: The `01-prepare` task in the pipeline manifest still uses
the old `job-step-name` value `001__prepare`; update it to match the file’s
current two-digit naming convention used by other steps like `02__preflight` and
`04__export-artifacts`. Make the change in the `job-step-name` param for
`01-prepare` so artifact directory naming stays consistent across the workflow.

In `@projects/gpu_operator/toolbox/bootstrap_gpu_clusterpolicy/main.py`:
- Around line 167-208: The `shell.run()` calls in the GPU operator artifact
capture block are still using interpolated shell strings, which should be
replaced with argv lists. Update each `oc` invocation in `main.py` to pass
command arguments as a list using the `shell.run` wrapper’s list-style form,
keeping `namespace` as a separate argument and not embedded in an f-string.
Apply this change consistently to the six capture calls in the block, including
the `get`, `describe`, and `-owide` commands, so they all run with
`shell=False`.

In `@projects/kserve/toolbox/prepare_hf_model_cache/main.py`:
- Around line 340-343: The `shell.run` call in `prepare_hf_model_cache/main.py`
is using a shell-form string, which leaves room for shell interpolation; update
the `oc get pods` invocation to use the argument-list form with `shell=False`.
Keep the same command semantics while passing `namespace` and `job_name` as
separate arguments so `shell.run` handles them safely and robustly. Use the
existing `shell.run` call site around the pod lookup logic to locate the change.

In `@projects/llm_d/orchestration/test_phase.py`:
- Around line 57-61: `run_finalizers`’ return annotation does not match what the
function actually returns: it returns both `primary_exc` and `finalizer_exc`,
not a single exception tuple. Update the `run_finalizers` signature and any
related type hints in `test_phase.py` to reflect a pair/tuple of the two
exception tuples, and make sure the return statement at the end of
`run_finalizers` matches that contract.

In `@projects/llm_d/toolbox/cleanup_test_resources/main.py`:
- Around line 208-212: The extra JSON pod fetch in the cleanup flow is unused
and just adds another API-server call on each retry. Update the retry logic
around shell.run in cleanup_test_resources/main.py so the diagnostic remains
plain-text only, or persist the JSON output to an artifact if it is actually
needed by the deletion check; remove the discarded json call from the retry
path.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e4e2f9a-4e5a-4b96-ad58-9a10f65452d1

📥 Commits

Reviewing files that changed from the base of the PR and between 1659dde and 8d27be1.

📒 Files selected for processing (33)
  • fournos/gitops/base/workflows/pipeline-full.yaml
  • fournos/gitops/base/workflows/pipeline-prepare-only.yaml
  • fournos/gitops/base/workflows/pipeline-prepare-test.yaml
  • fournos/gitops/base/workflows/pipeline-test-only.yaml
  • projects/cluster/toolbox/bootstrap_lws_operator/main.py
  • projects/cluster/toolbox/bootstrap_lws_operator/templates/leaderworkersetoperator.yaml.j2
  • projects/cluster/toolbox/cleanup_operators/main.py
  • projects/cluster/toolbox/cluster_deploy_operator/main.py
  • projects/cluster/toolbox/cluster_deploy_operator/on_failure_helpers.py
  • projects/core/agentic/on_failure/__init__.py
  • projects/core/ci_entrypoint/prepare_ci.py
  • projects/core/dsl/__init__.py
  • projects/core/dsl/control_flow.py
  • projects/core/dsl/runtime.py
  • projects/core/dsl/task.py
  • projects/gpu_operator/toolbox/bootstrap_gpu_clusterpolicy/main.py
  • projects/gpu_operator/toolbox/bootstrap_gpu_clusterpolicy/on_failure_helpers.py
  • projects/kserve/toolbox/deploy_llmisvc/main.py
  • projects/kserve/toolbox/deploy_llmisvc/on_failure_helpers.py
  • projects/kserve/toolbox/prepare_hf_model_cache/main.py
  • projects/llm_d/orchestration/ci.py
  • projects/llm_d/orchestration/cleanup_phase.py
  • projects/llm_d/orchestration/config.d/deployments.yaml
  • projects/llm_d/orchestration/config.d/platform.yaml
  • projects/llm_d/orchestration/config.yaml
  • projects/llm_d/orchestration/manifests/leaderworkersetoperator.yaml
  • projects/llm_d/orchestration/preflight_phase.py
  • projects/llm_d/orchestration/prepare_phase.py
  • projects/llm_d/orchestration/test_phase.py
  • projects/llm_d/tests/test_profiles.py
  • projects/llm_d/toolbox/cleanup_test_resources/main.py
  • projects/rhaiis/orchestration/ci.py
  • projects/skeleton/orchestration/ci.py

Comment thread fournos/gitops/base/workflows/pipeline-full.yaml
Comment on lines +59 to +60
- name: 03-test
runAfter: [01-preflight]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

03-test references a nonexistent task in runAfter.

runAfter: [01-preflight] points to a task that does not exist — the preflight task is named 02-preflight (Line 39). Tekton will reject this pipeline with a DAG validation error ("task ... runAfter refers to nonexistent task"). Update the reference to 02-preflight.

🐛 Proposed fix
     - name: 03-test
-      runAfter: [01-preflight]
+      runAfter: [02-preflight]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: 03-test
runAfter: [01-preflight]
- name: 03-test
runAfter: [02-preflight]
🤖 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 `@fournos/gitops/base/workflows/pipeline-prepare-test.yaml` around lines 59 -
60, The 03-test task in the pipeline workflow has an invalid runAfter dependency
because it points to a task name that does not exist. Update the runAfter
reference on 03-test to match the actual preflight task identifier,
02-preflight, so the Tekton DAG resolves correctly and the pipeline definition
validates.

- name: job-step-name
value: 00__preflight

- name: 01-test

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

01-test has no runAfter on 00-preflight, so preflight does not gate the test.

Without a runAfter dependency, Tekton schedules 00-preflight and 01-test in parallel. If the intent of adding preflight is to validate prerequisites before running the test, the gate is ineffective here (contrast pipeline-prepare-only.yaml, where preflight runAfter: [00-prepare]). Add the dependency.

🐛 Proposed fix
     - name: 01-test
+      runAfter: [00-preflight]
       taskRef:
         name: forge-step
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: 01-test
- name: 01-test
runAfter: [00-preflight]
🤖 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 `@fournos/gitops/base/workflows/pipeline-test-only.yaml` at line 39, The
`01-test` task in the pipeline is missing a `runAfter` dependency on
`00-preflight`, so preflight can run in parallel instead of gating the test.
Update the Tekton workflow definition for `01-test` to depend on `00-preflight`,
following the same pattern used in `pipeline-prepare-only.yaml`, so the
preflight step completes before the test starts.

Comment thread projects/cluster/toolbox/bootstrap_lws_operator/main.py Outdated
Comment on lines +114 to +124
stdout_dest=artifact_dir / "artifacts" / f"{subscription_name}-csvs.yaml",
check=False,
log_stdout=False,
)

# Capture InstallPlans
shell.run(
f"oc get installplan -n {namespace} "
f"-l operators.coreos.com/{subscription_name}.{namespace} "
"-o yaml",
stdout_dest=artifact_dir / "artifacts" / f"{subscription_name}-installplans.yaml",

@coderabbitai coderabbitai Bot Jun 26, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Include namespace in per-operator artifact filenames.

{subscription_name}-csvs.yaml and {subscription_name}-installplans.yaml collide when the same subscription name is cleaned from multiple namespaces, overwriting diagnostics.

🧾 Proposed fix
-        stdout_dest=artifact_dir / "artifacts" / f"{subscription_name}-csvs.yaml",
+        stdout_dest=artifact_dir / "artifacts" / f"{namespace}-{subscription_name}-csvs.yaml",
...
-        stdout_dest=artifact_dir / "artifacts" / f"{subscription_name}-installplans.yaml",
+        stdout_dest=artifact_dir / "artifacts" / f"{namespace}-{subscription_name}-installplans.yaml",
...
-            f.write(f"  - {operator_name}-csvs.yaml\n")
-            f.write(f"  - {operator_name}-installplans.yaml\n")
+            f.write(f"  - {namespace}-{operator_name}-csvs.yaml\n")
+            f.write(f"  - {namespace}-{operator_name}-installplans.yaml\n")

Also applies to: 212-216

🤖 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 `@projects/cluster/toolbox/cleanup_operators/main.py` around lines 114 - 124,
The per-operator artifact filenames in the cleanup flow are missing the
namespace, so repeated subscription names can overwrite each other’s
diagnostics. Update the filename construction in the `shell.run` calls that
write the CSV and InstallPlan artifacts to include both `subscription_name` and
`namespace`, and apply the same change in the other matching block referenced by
the comment. Keep the existing artifact destinations and command behavior
unchanged.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

no need for that

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kpouget, understood — leaving this as-is.

Comment thread projects/kserve/toolbox/deploy_llmisvc/main.py
Comment on lines +166 to +178
result = oc(
"describe",
"llminferenceservice",
service_name,
"-n",
args.namespace,
log_stdout=False,
check=False,
)

llmisv_desc_path = artifacts_dir / "llmisv_description.txt"
with open(llmisv_desc_path, "w", encoding="utf-8") as f:
f.write(result.stdout)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Include stderr when diagnostic oc calls fail.

These calls use check=False, but the artifacts only write stdout. If oc describe / oc get replicaset fails, the saved file can be empty or say “No replicasets found” while the real cause is in stderr.

Proposed diagnostic artifact fix
-        with open(llmisv_desc_path, "w", encoding="utf-8") as f:
-            f.write(result.stdout)
+        with open(llmisv_desc_path, "w", encoding="utf-8") as f:
+            f.write(result.stdout)
+            if result.stderr:
+                f.write("\n\n--- stderr ---\n")
+                f.write(result.stderr)
-            else:
+            elif rs_result.returncode == 0:
                 f.write("No replicasets found for the service")
+            else:
+                f.write("Failed to list replicasets for the service")
+                if rs_result.stderr:
+                    f.write("\n\n--- stderr ---\n")
+                    f.write(rs_result.stderr)

Also applies to: 201-236

🧰 Tools
🪛 ast-grep (0.44.0)

[warning] 176-176: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(llmisv_desc_path, "w", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

🤖 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 `@projects/kserve/toolbox/deploy_llmisvc/main.py` around lines 166 - 178, The
diagnostic artifact writing for the `oc` calls currently saves only `stdout`, so
failures from `describe` and `get replicaset` can lose the real error details.
Update the artifact generation around the `oc(...)` result handling in `main.py`
so the saved files include `stderr` whenever `check=False` is used, and make
sure this is applied to both the `llminferenceservice` describe path and the
replicaset diagnostic path. Use the existing `result` object and artifact writes
like `llmisv_desc_path` to locate and append the error output alongside the
normal output.

Comment thread projects/llm_d/orchestration/ci.py
Comment thread projects/llm_d/orchestration/cleanup_phase.py
Comment thread projects/llm_d/orchestration/config.yaml
@kpouget

kpouget commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full
/var platform.status_address_name: gateway-internal

@psap-forge-bot

Copy link
Copy Markdown

🔴 Executing of 'llm_d test' failed after 00 hours 06 minutes 16 seconds 🔴

• Link to the test results.

• Caliper postprocess completed but no reports generated.

Test configuration:

ci_job.cluster: forge-smoke-testing
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-20260627-080240
ci_job.name: llm_d
ci_job.owner: kpouget
platform.status_address_name: gateway-internal
project.args: []
project.name: llm_d

TEST DESCRIPTION:

This test evaluates the llm_d project by applying the benchmark-short preset with the deployment-approximate-prefix-cache profile to validate baseline inference performance. It runs a lightweight workload (256 input/128 output tokens, 1 concurrent request) to test deployment stability and vLLM prefix caching functionality.

FAILURE REVIEW 002 run smoke request:

001__llmd_test/002__run_smoke_request

The execute_smoke_request task failed with a curl connection timeout (exit code 28) because the LLMInferenceService controller reported a reconciliation error due to a missing HTTPRoute resource (llm-d-kserve-route). This routing failure left the service in a Progressing state with RouterReady: False, causing the external LoadBalancer endpoint to be unable to forward traffic to the backend pods.

• Detailed failure analysis report

• Config review report

• Raw failure details
• Execution logs

@psap-forge-bot

Copy link
Copy Markdown

🔴 Executing of 'fournos_launcher submit' failed after 00 hours 10 minutes 38 seconds 🔴

• Link to the test results.

• FOURNOS Job Status:

  • ❌ forge-llm-d-20260627-080240: Failed - Tasks Completed: 5 (Failed: 1, Cancelled 0), Skipped: 0

• MLflow Tracking:

• FOURNOS Job Details:

• Task Logs:

Test configuration:

/test fournos llm_d
/var platform.status_address_name: gateway-internal
/cluster forge-smoke-testing
/pipeline forge-full

• Failure indicator:

## /logs/artifacts/001__submit_and_wait/FAILURE 
================================================================================
TASK EXECUTION FAILURE
================================================================================
Timestamp: 2026-06-27 08:13:08
Exception Type: TaskExecutionError
Exception Message: ❌ TASK FAILURE: wait_for_job_completion: Wait for FOURNOS job to complete
   projects/fournos_launcher/toolbox/submit_and_wait/main.py:186
   RuntimeError: Job forge-llm-d-20260627-080240 failed: Tasks Completed: 5 (Failed: 1, Cancelled 0), Skipped: 0


[...]

• Execution logs

@kpouget

kpouget commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

/test fournos llm_d
/cluster forge-smoke-testing
/pipeline forge-full
/var platform.gateway.status_address_name: gateway-internal

@psap-forge-bot

Copy link
Copy Markdown

🟢 Executing of 'llm_d test' succeeded after 00 hours 03 minutes 10 seconds 🟢

• Link to the test results.

• Caliper postprocess completed but no reports generated.

Test configuration:

ci_job.cluster: forge-smoke-testing
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-20260629-072203
ci_job.name: llm_d
ci_job.owner: kpouget
platform.gateway.status_address_name: gateway-internal
project.args: []
project.name: llm_d

TEST DESCRIPTION:

This test evaluates the llm_d project by benchmarking the Qwen3-0.6B model using the approximate-prefix-cache deployment profile. It runs a short concurrent workload (1 request/sec, 256 input/128 output tokens) to measure inference throughput and prefix caching efficiency under light load.

• Config review report
• Execution logs

kpouget added 19 commits June 29, 2026 14:25
@psap-forge-bot

Copy link
Copy Markdown

🟢 Execution of 'llm_d test' succeeded after 00 hours 06 minutes 54 seconds 🟢

• Link to the test results.

• Generated 1 Caliper report(s):

  • report_00_guidellm_performance_analysis.html

Test configuration:

ci_job.cluster: forge-smoke-testing
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-20260629-122249
ci_job.name: llm_d smoke
ci_job.owner: kpouget
project.args:
- smoke
project.name: llm_d

TEST DESCRIPTION:

This test performs a smoke validation for the llm_d project, specifically evaluating the approximate-prefix-cache deployment profile using the lightweight Qwen/Qwen3-0.6B model. It executes a short, low-rate benchmark to verify basic inference endpoint functionality and gateway routing under minimal load.

• Config review report
• Execution logs

@psap-forge-bot

Copy link
Copy Markdown

🟢 Execution of 'fournos_launcher submit' succeeded after 00 hours 13 minutes 08 seconds 🟢

• Link to the test results.

• FOURNOS Job Status:

  • ✅ forge-llm-d-20260629-122249: Succeeded - Pipeline completed successfully

• MLflow Tracking:

• FOURNOS Job Details:

• Task Logs:

Test configuration:

/test fournos llm_d smoke
/cluster forge-smoke-testing
/pipeline forge-full

• Execution logs

@albertoperdomo2

Copy link
Copy Markdown
Collaborator

/lgtm
/approve

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jun 29, 2026
@openshift-ci

openshift-ci Bot commented Jun 29, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: albertoperdomo2

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 29, 2026
@openshift-merge-bot
openshift-merge-bot Bot merged commit 58c4446 into openshift-psap:main Jun 29, 2026
6 checks passed
@kpouget
kpouget deleted the llmd branch June 29, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants