Skip to content

[caliper] Progress with the parser and plotter#57

Open
kpouget wants to merge 16 commits into
openshift-psap:mainfrom
kpouget:caliper-skeleton
Open

[caliper] Progress with the parser and plotter#57
kpouget wants to merge 16 commits into
openshift-psap:mainfrom
kpouget:caliper-skeleton

Conversation

@kpouget
Copy link
Copy Markdown
Contributor

@kpouget kpouget commented May 12, 2026

Summary by CodeRabbit

  • New Features

    • Skeleton postprocess: artifact parsing, KPI computation, HTML reports (summary table, throughput chart).
    • GuideLLM postprocess: parsing, KPI computation, Plotly reports, AI-eval payload builder, plugin integration.
    • CLI: new command to import artifacts from MLflow and a replot workflow to re-run postprocessing.
  • Improvements

    • CLI: clearer error/help display for missing/invalid commands; simplified flag aliases to single canonical options.
    • Kubernetes job names: validation, sanitization, and suggested normalized names.
  • Configuration

    • Added replot configuration and a /replot.url directive.

Review Change Stack

@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 12, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign tosokin for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

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

Splits Skeleton postprocess into parser/KPI/plot modules; adds GuideLLM parser/models/KPI/plugin; introduces HelpfulGroup and adopts it across orchestration CLIs; simplifies Caliper CLI options and adds an artifacts import subcommand; adds a replot helper/command and FOURNOS directive; sanitizes and validates Fournos job names.

Changes

Skeleton Plugin Component Separation

Layer / File(s) Summary
Metrics Parsing Component
projects/skeleton/postprocess/default/parsing/__init__.py, projects/skeleton/postprocess/default/parsing/parsers.py
SkeletonParser extracts node labels, reads and validates metrics.json, and builds UnifiedResultRecords with defaults and warnings.
KPI Catalog and Computation
projects/skeleton/postprocess/default/parsing/kpis.py
SkeletonKpiHandler defines throughput (higher better) and latency (lower better) KPIs and computes KPI records from unified results with float conversion and UTC timestamps.
Plotting Components
projects/skeleton/postprocess/default/plotting/__init__.py, projects/skeleton/postprocess/default/plotting/summary_table.py, projects/skeleton/postprocess/default/plotting/throughput_chart.py
SummaryTablePlot produces an HTML summary table; ThroughputChartPlot produces a Plotly throughput bar chart from unified result records.
Plugin Coordinator Refactoring
projects/skeleton/postprocess/default/plugin.py
SkeletonDefaultPlugin delegates parse/visualize/kpi_catalog/compute_kpis to the new parser, KPI handler, and plot classes.

GuideLLM Postprocess Plugin

Layer / File(s) Summary
GuideLLM datamodels & exports
projects/caliper/postprocess/guidellm/parsing/__init__.py, projects/caliper/postprocess/guidellm/parsing/models.py
Adds GuideLLMBenchmark and GuideLLMConfiguration dataclasses and package exports.
GuideLLM parser
projects/caliper/postprocess/guidellm/parsing/parsers.py
Adds GuideLLMParser with parsing of benchmarks.json, per-benchmark extraction, concurrency fallback logic, and unified record emission with warnings.
GuideLLM KPI handler
projects/caliper/postprocess/guidellm/parsing/kpis.py
Adds GuideLLMKpiHandler with KPI catalog and compute_kpis mapping parsed metrics to KPI records.
GuideLLM plugin
projects/caliper/postprocess/guidellm/plugin.py
Adds GuideLLMPlugin wiring parser and KPI handler, visualization chart generators, kpi_catalog/compute_kpis delegation, build_ai_eval_payload, and get_plugin() factory.

CLI Infrastructure: Error Handling and Caliper CLI Updates

Layer / File(s) Summary
HelpfulGroup Error Handler
projects/core/library/ci.py
Adds HelpfulGroup (subclass of click.Group) that prints a missing-command error and the group's help to stderr and exits with code 2.
HelpfulGroup Adoption Across Orchestrations
projects/jump_ci/orchestration/ci.py, projects/foreign_testing/orchestration/ci.py, projects/fournos_launcher/orchestration/ci.py, projects/llm_d/orchestration/ci.py, projects/llm_d_legacy/orchestration/ci.py, projects/skeleton/orchestration/ci.py
Click group decorators updated to @click.group(cls=ci_lib.HelpfulGroup) and necessary imports added.
Caliper CLI Option Simplification & Import artifacts
projects/caliper/cli/main.py
Removes --base-dir and --plugin-module aliases (keeps --artifacts-dir and --plugin), drops explicit cache_path=None in ai-eval-export call, adds artifacts import subcommand (MLflow artifact download), and catches click.ClickException in run_cli to print help/exception and exit code 2.

Replot Helper and FOURNOS Directive

Layer / File(s) Summary
Replot implementation
projects/core/library/replot.py
Adds _download_mlflow_artifacts implementing MLflow run-id/URI parsing and authenticated artifact download, updates run_replot to skip existing downloads, run postprocess, manage cleanup, and produce structured status.
Replot command & FOURNOS directive
projects/core/library/replot.py, projects/fournos_launcher/orchestration/pr_args.py
Adds the replot Click wrapper and registers /replot.url FOURNOS directive via handle_replot_url_directive.
Replot config additions
projects/llm_d_legacy/testing/config.yaml, projects/skeleton/orchestration/config.yaml
Adds caliper.replot and caliper.postprocess configuration blocks used by the replot flow.

Fournos Launcher: Job-name Validation & Sanitization

Layer / File(s) Summary
Sanitize names on submit
projects/fournos_launcher/orchestration/submit.py
Imports sanitize_k8s_name and sanitizes generated parallel and single job names before submission and cleanup.
User-provided job-name validation
projects/fournos_launcher/toolbox/submit_and_wait/main.py
Adds is_valid_k8s_name and validates user-provided job names, raising ValueError with the suggested normalized name when invalid; sanitizes auto-generated names before storing.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • openshift-psap/forge#37: Both PRs modify projects/caliper/cli/main.py around Caliper’s artifact-related Click commands (export/import option handling).
  • openshift-psap/forge#55: Prior Caliper CLI expansion and exception handling work that this PR refines.

Poem

A rabbit polishes the CLI bright,
Parsers parse and plots take flight,
HelpfulGroup guides lost commands anew,
Replot fetches runs and shows the view,
🐇 — small hops, big tidy delight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title '[caliper] Progress with the parser and plotter' is vague and generic, using non-descriptive language that doesn't convey the specific changes made in the changeset. Consider using a more descriptive title that clearly highlights the main change, such as 'Add GuideLLM parser and plotting plugin for Caliper' or 'Refactor Skeleton plugin to use dedicated parser/plotter components'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate 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 and usage tips.

@kpouget kpouget force-pushed the caliper-skeleton branch from 6e158e7 to 4acdf79 Compare May 12, 2026 08:32
@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 12, 2026

/test fournos llm_d
/var fournos.namespace: psap-automation-wip
/cluster psap-mgmt

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d
/var fournos.namespace: psap-automation-wip
/cluster psap-mgmt

• Failure indicator: Empty.
Execution logs

@kpouget kpouget force-pushed the caliper-skeleton branch from 4acdf79 to fdfe6b6 Compare May 12, 2026 09:01
@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 12, 2026

/test fournos llm_d
/var fournos.namespace: psap-automation-wip
/cluster psap-mgmt

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d
/var fournos.namespace: psap-automation-wip
/cluster psap-mgmt

• Failure indicator: Empty.
Execution logs

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
projects/skeleton/postprocess/default/plugin.py (1)

54-58: ⚡ Quick win

Silently skipping unknown report IDs may hide configuration errors.

When a requested report_id doesn't exist in self.plots, it's silently ignored. Users might not realize why an expected report wasn't generated, especially if the ID contains a typo.

📝 Proposed improvement to warn about unknown IDs
         for report_id in wanted:
             if report_id in self.plots:
                 plot_class = self.plots[report_id]
                 path = plot_class.generate(model, output_dir)
                 paths.append(path)
+            else:
+                # Log or collect warning about unknown report_id
+                pass

Alternatively, consider validating report IDs upfront or documenting the silent-skip behavior.

🤖 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/skeleton/postprocess/default/plugin.py` around lines 54 - 58, The
loop that iterates over wanted and silently skips report IDs not in self.plots
should surface a warning or validation: in the block where report_id is checked
against self.plots (the for report_id in wanted loop that calls
plot_class.generate), add logic to collect or log unknown IDs (e.g., using the
module/class logger or raising a clear ValueError) so users are notified when a
requested report_id is missing; you can either validate all wanted IDs up-front
against self.plots (and raise/log all unknown IDs) or log a warning for each
missing report_id before continuing to call plot_class.generate for known IDs.
projects/skeleton/postprocess/default/plotting/summary_table.py (1)

28-30: ⚡ Quick win

Consider using "N/A" for missing metric values.

Empty string defaults for missing scenario, throughput, and latency_ms values will render as blank table cells, which may be unclear to users. Consider using "N/A" or similar placeholder text to explicitly indicate missing data.

📋 Proposed improvement
         for r in model.unified_result_records:
-            scenario = r.distinguishing_labels.get("scenario", "")
-            tp = r.metrics.get("throughput", "")
-            lat = r.metrics.get("latency_ms", "")
+            scenario = r.distinguishing_labels.get("scenario", "N/A")
+            tp = r.metrics.get("throughput", "N/A")
+            lat = r.metrics.get("latency_ms", "N/A")
🤖 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/skeleton/postprocess/default/plotting/summary_table.py` around lines
28 - 30, Change the empty-string defaults for missing labels/metrics to a clear
placeholder so table cells show "N/A" instead of blank; update the lines that
set scenario, tp, and lat (currently using
r.distinguishing_labels.get("scenario", "") and r.metrics.get("throughput", "")
/ r.metrics.get("latency_ms", "")) to use "N/A" as the default value; ensure any
downstream code that formats or displays these variables (e.g., the summary
table rendering for scenario, tp, lat) continues to treat them as strings.
🤖 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 `@projects/skeleton/postprocess/default/parsing/kpis.py`:
- Around line 56-65: The float conversions for tp_raw and lat_raw currently
swallow errors and set values to 0.0, hiding bad input; update the try/except
blocks that set tp and lat (variables tp_raw, lat_raw -> tp, lat in
projects/skeleton/postprocess/default/parsing/kpis.py) to catch exceptions but
log a warning/error including the offending raw value and exception details (use
the module's logger or process logger), then assign a sentinel like None (or
math.nan) instead of 0.0 so downstream code can detect malformed data and handle
it explicitly; also adjust any downstream consumers to tolerate None/NaN if
needed.

In `@projects/skeleton/postprocess/default/parsing/parsers.py`:
- Around line 16-24: In _labels_from_node, avoid calling raw.get("labels") on
node.labels when node.labels may not be a dict: first check if raw (node.labels)
is a dict, then attempt inner = raw.get("labels"); if inner is a dict return a
shallow copy, if not but raw is a dict return a shallow copy of raw; for all
other non-dict raw values (None, str, etc.) return the default {"facet":
"default"}; update the logic in _labels_from_node to use isinstance(raw, dict)
before any .get calls to prevent AttributeError.
- Around line 45-47: In the except json.JSONDecodeError block inside the JSON
parsing routine (the except json.JSONDecodeError as e where warnings.append(...)
is called), stop returning the sentinel dict {"_parse_error": True} and instead
return an empty dict so downstream logic like the metrics fallback check (the
`if metrics else {"throughput": 0.0}` branch) will kick in; ensure the function
still returns ({}, warnings) so UnifiedResultRecord and other consumers receive
an empty metrics dict rather than a truthy error marker.

In `@projects/skeleton/postprocess/default/plotting/throughput_chart.py`:
- Around line 34-37: The try/except that coerces raw to float (the block
converting variable raw into y) currently swallows TypeError/ValueError and sets
y=0.0; change it to log a warning when conversion fails, e.g. call
logger.warning or logging.warning with the offending raw value and any
identifying context (timestamp/index/metric name if available) before assigning
y=0.0 so malformed inputs are visible; locate the conversion of raw -> y in
throughput_chart.py (the try/except handling TypeError/ValueError) and add the
warning call using the module logger (or import logging and create one if
absent).

---

Nitpick comments:
In `@projects/skeleton/postprocess/default/plotting/summary_table.py`:
- Around line 28-30: Change the empty-string defaults for missing labels/metrics
to a clear placeholder so table cells show "N/A" instead of blank; update the
lines that set scenario, tp, and lat (currently using
r.distinguishing_labels.get("scenario", "") and r.metrics.get("throughput", "")
/ r.metrics.get("latency_ms", "")) to use "N/A" as the default value; ensure any
downstream code that formats or displays these variables (e.g., the summary
table rendering for scenario, tp, lat) continues to treat them as strings.

In `@projects/skeleton/postprocess/default/plugin.py`:
- Around line 54-58: The loop that iterates over wanted and silently skips
report IDs not in self.plots should surface a warning or validation: in the
block where report_id is checked against self.plots (the for report_id in wanted
loop that calls plot_class.generate), add logic to collect or log unknown IDs
(e.g., using the module/class logger or raising a clear ValueError) so users are
notified when a requested report_id is missing; you can either validate all
wanted IDs up-front against self.plots (and raise/log all unknown IDs) or log a
warning for each missing report_id before continuing to call plot_class.generate
for known IDs.
🪄 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: e6e1d1d4-bb8a-4f9b-a3f9-23ed64ac918b

📥 Commits

Reviewing files that changed from the base of the PR and between 3838b87 and fdfe6b6.

📒 Files selected for processing (15)
  • projects/caliper/cli/main.py
  • projects/core/library/ci.py
  • projects/foreign_testing/orchestration/ci.py
  • projects/fournos_launcher/orchestration/ci.py
  • projects/jump_ci/orchestration/ci.py
  • projects/llm_d/orchestration/ci.py
  • projects/llm_d_legacy/orchestration/ci.py
  • projects/skeleton/orchestration/ci.py
  • projects/skeleton/postprocess/default/parsing/__init__.py
  • projects/skeleton/postprocess/default/parsing/kpis.py
  • projects/skeleton/postprocess/default/parsing/parsers.py
  • projects/skeleton/postprocess/default/plotting/__init__.py
  • projects/skeleton/postprocess/default/plotting/summary_table.py
  • projects/skeleton/postprocess/default/plotting/throughput_chart.py
  • projects/skeleton/postprocess/default/plugin.py

Comment on lines +56 to +65
try:
tp = float(tp_raw)
except (TypeError, ValueError):
tp = 0.0

# Convert latency to float
try:
lat = float(lat_raw)
except (TypeError, ValueError):
lat = 0.0
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Silent conversion failures mask data quality issues.

Similar to throughput_chart.py (lines 34-37), failed float conversions default silently to 0.0. This pattern appears in multiple places and may hide malformed input data.

🔍 Proposed improvement
             # Convert throughput to float
             try:
                 tp = float(tp_raw)
             except (TypeError, ValueError):
+                # Could log: f"Invalid throughput {tp_raw!r} in {r.test_base_path}"
                 tp = 0.0
 
             # Convert latency to float
             try:
                 lat = float(lat_raw)
             except (TypeError, ValueError):
+                # Could log: f"Invalid latency {lat_raw!r} in {r.test_base_path}"
                 lat = 0.0
📝 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
try:
tp = float(tp_raw)
except (TypeError, ValueError):
tp = 0.0
# Convert latency to float
try:
lat = float(lat_raw)
except (TypeError, ValueError):
lat = 0.0
try:
tp = float(tp_raw)
except (TypeError, ValueError):
# Could log: f"Invalid throughput {tp_raw!r} in {r.test_base_path}"
tp = 0.0
# Convert latency to float
try:
lat = float(lat_raw)
except (TypeError, ValueError):
# Could log: f"Invalid latency {lat_raw!r} in {r.test_base_path}"
lat = 0.0
🤖 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/skeleton/postprocess/default/parsing/kpis.py` around lines 56 - 65,
The float conversions for tp_raw and lat_raw currently swallow errors and set
values to 0.0, hiding bad input; update the try/except blocks that set tp and
lat (variables tp_raw, lat_raw -> tp, lat in
projects/skeleton/postprocess/default/parsing/kpis.py) to catch exceptions but
log a warning/error including the offending raw value and exception details (use
the module's logger or process logger), then assign a sentinel like None (or
math.nan) instead of 0.0 so downstream code can detect malformed data and handle
it explicitly; also adjust any downstream consumers to tolerate None/NaN if
needed.

Comment on lines +16 to +24
def _labels_from_node(node: TestBaseNode) -> dict[str, Any]:
"""Extract labels from a test node."""
raw = node.labels
inner = raw.get("labels")
if isinstance(inner, dict):
return dict(inner)
if isinstance(raw, dict):
return dict(raw)
return {"facet": "default"}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

AttributeError if node.labels is not a dict.

Line 19 calls raw.get("labels") without first checking if raw (which is node.labels) is a dictionary. If node.labels is None, a string, or any other non-dict type, this will raise an AttributeError.

🛡️ Proposed fix
 def _labels_from_node(node: TestBaseNode) -> dict[str, Any]:
     """Extract labels from a test node."""
     raw = node.labels
+    if not isinstance(raw, dict):
+        return {"facet": "default"}
     inner = raw.get("labels")
     if isinstance(inner, dict):
         return dict(inner)
-    if isinstance(raw, dict):
-        return dict(raw)
-    return {"facet": "default"}
+    return dict(raw)
🤖 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/skeleton/postprocess/default/parsing/parsers.py` around lines 16 -
24, In _labels_from_node, avoid calling raw.get("labels") on node.labels when
node.labels may not be a dict: first check if raw (node.labels) is a dict, then
attempt inner = raw.get("labels"); if inner is a dict return a shallow copy, if
not but raw is a dict return a shallow copy of raw; for all other non-dict raw
values (None, str, etc.) return the default {"facet": "default"}; update the
logic in _labels_from_node to use isinstance(raw, dict) before any .get calls to
prevent AttributeError.

Comment thread projects/skeleton/postprocess/default/parsing/parsers.py
Comment on lines +34 to +37
try:
y = float(raw)
except (TypeError, ValueError):
y = 0.0
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Consider logging conversion failures.

Failed float conversions silently default to 0.0, which may mask data quality issues. Users won't be alerted when throughput values are malformed or invalid.

📊 Proposed improvement to add warning
             try:
                 y = float(raw)
             except (TypeError, ValueError):
+                # Could log or collect warning: f"Invalid throughput value {raw!r} in {label}"
                 y = 0.0
🤖 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/skeleton/postprocess/default/plotting/throughput_chart.py` around
lines 34 - 37, The try/except that coerces raw to float (the block converting
variable raw into y) currently swallows TypeError/ValueError and sets y=0.0;
change it to log a warning when conversion fails, e.g. call logger.warning or
logging.warning with the offending raw value and any identifying context
(timestamp/index/metric name if available) before assigning y=0.0 so malformed
inputs are visible; locate the conversion of raw -> y in throughput_chart.py
(the try/except handling TypeError/ValueError) and add the warning call using
the module logger (or import logging and create one if absent).

@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 12, 2026

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-wip
/cluster psap-mgmt

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-wip
/cluster psap-mgmt

• Failure indicator: Empty.
Execution logs

@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 12, 2026

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-wip
/cluster psap-mgmt

@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 12, 2026

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-staging
/cluster psap-mgmt

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-staging
/cluster psap-mgmt

• Failure indicator: Empty.
Execution logs

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@projects/core/library/replot.py`:
- Around line 24-29: The function run_replot currently ignores the passed
artifact_directory because subsequent path computations use env.ARTIFACT_DIR
directly; update all usages in run_replot (and any helper calls it invokes) to
reference the local parameter artifact_directory (falling back to
env.ARTIFACT_DIR only when the parameter is None) instead of directly using
env.ARTIFACT_DIR — search for symbols artifact_directory and env.ARTIFACT_DIR in
run_replot and replace hard-coded env.ARTIFACT_DIR references (including where
download/output paths are built) so the --artifact-directory argument actually
overrides those paths.
- Around line 95-99: Add a timeout to the subprocess.run that executes the
caliper import command: pass a sensible timeout (e.g., timeout=120) to
subprocess.run(cmd, timeout=..., capture_output=True, text=True, check=False)
and wrap the call in a try/except for subprocess.TimeoutExpired to raise a clear
RuntimeError (e.g., "Caliper import timed out") so a hung child cannot stall CI;
keep using the existing cmd variable and existing error-handling for non-zero
return codes (result.returncode) unchanged.
- Around line 64-93: The initial conditional incorrectly groups "s3://" with
MLflow URLs causing s3 URLs to hit the unsupported branch; update the logic in
replot.py so replot_url.startswith("s3://") is not combined with the MLflow
check: either remove "s3://" from the outer condition and only check "mlflow" in
replot_url.lower() (so the MLflow run-id parsing block using
re.search(r"/runs/([^/]+)", ...) and the cmd construction runs for MLflow URLs),
or add a distinct branch for s3 handling before/after the MLflow branch that
constructs the appropriate caliper import command for S3 instead of raising the
ValueError. Ensure the ValueError raising lines (the else that raises
"Unsupported replot URL type") only run for genuinely unsupported URLs.

In `@projects/fournos_launcher/orchestration/pr_args.py`:
- Around line 207-212: The current parsing uses line.removeprefix("/replot.url
") so a bare "/replot.url" (no trailing space/value) is treated as a non-empty
literal and bypasses the empty check; update the extraction to remove the
"/replot.url" prefix regardless of a following space and then strip whitespace
before validating. Concretely, replace the removeprefix("/replot.url ") usage
with logic that detects and strips "/replot.url" (e.g., remove prefix
"/replot.url" then call .lstrip()/.strip()), assign to replot_url, and keep the
existing ValueError check so an empty or whitespace-only value raises; reference
the replot_url variable and the current removeprefix call in pr_args.py.
🪄 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: 7bee74c8-96d6-453f-be9b-2e9fcd774eea

📥 Commits

Reviewing files that changed from the base of the PR and between c0f86c8 and 873f560.

📒 Files selected for processing (12)
  • projects/caliper/cli/main.py
  • projects/caliper/postprocess/__init__.py
  • projects/caliper/postprocess/guidellm/__init__.py
  • projects/caliper/postprocess/guidellm/parsing/__init__.py
  • projects/caliper/postprocess/guidellm/parsing/kpis.py
  • projects/caliper/postprocess/guidellm/parsing/models.py
  • projects/caliper/postprocess/guidellm/parsing/parsers.py
  • projects/caliper/postprocess/guidellm/plotting/__init__.py
  • projects/caliper/postprocess/guidellm/plugin.py
  • projects/core/library/replot.py
  • projects/fournos_launcher/orchestration/pr_args.py
  • projects/llm_d_legacy/orchestration/ci.py
✅ Files skipped from review due to trivial changes (1)
  • projects/caliper/postprocess/guidellm/parsing/init.py

Comment thread projects/core/library/replot.py Outdated
Comment thread projects/core/library/replot.py Outdated
Comment thread projects/core/library/replot.py Outdated
Comment thread projects/fournos_launcher/orchestration/pr_args.py Outdated
@kpouget kpouget force-pushed the caliper-skeleton branch from 873f560 to 5c5eaf1 Compare May 12, 2026 18:48
@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 12, 2026

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-staging
/cluster psap-mgmt
/pipeline forge-replot
/replot.url s3://aperdomo-mlflow/mlflow/42/992c1fcecbbc42ec95f3886bb1bede80/artifacts/001__llm_d_testing/000__flavor_intelligentrouting-tp2-x4

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-staging
/cluster psap-mgmt
/pipeline forge-replot
/replot.url s3://aperdomo-mlflow/mlflow/42/992c1fcecbbc42ec95f3886bb1bede80/artifacts/001__llm_d_testing/000__flavor_intelligentrouting-tp2-x4

• Failure indicator: Empty.
Execution logs

@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 12, 2026

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-staging
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/var fournos.namespace: psap-automation-staging
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

• Failure indicator: Empty.
Execution logs

@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 12, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@psap-forge-bot
Copy link
Copy Markdown

🔴 Test of 'fournos_launcher submit' failed after 00 hours 02 minutes 11 seconds 🔴

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

• Failure indicator: Empty.
Execution logs

@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 13, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

• Failure indicator: Empty.
Execution logs

@kpouget kpouget force-pushed the caliper-skeleton branch from 5c5eaf1 to 794cd10 Compare May 13, 2026 04:49
@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 13, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@kpouget kpouget force-pushed the caliper-skeleton branch from 794cd10 to fb11f22 Compare May 13, 2026 04:55
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@projects/caliper/cli/main.py`:
- Around line 609-615: The exception handling for click.ClickException currently
prints only the help text when exc.ctx exists and drops the actual error
message; update the handler so it calls exc.show(sys.stderr) first to print the
exception message (e.g., from MissingParameter or NoArgsIsHelpError) and then,
if exc.ctx is present, call click.echo(exc.ctx.get_help(), err=True) to also
display the help page; keep the existing sys.exit(2) behavior.
- Around line 527-598: Add the same MLflow auth/TLS options and setup used by
the artifacts export flow to the import_command: add CLI options
--mlflow-secrets, --mlflow-config, and --mlflow-insecure-tls (in addition to
mlflow_tracking_uri) and, before calling mlflow.set_tracking_uri / MlflowClient
in import_command, call the shared MLflow setup function used by export (reuse
the existing export-side initializer — e.g., configure_mlflow_client or
create_mlflow_client if present) to apply credentials, TLS overrides, and config
from the provided flags; ensure the new flags are parsed into the shared setup
and only fall back to mlflow.set_tracking_uri/MlflowClient after that.
🪄 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: e2a9b411-8177-40e3-98d4-c26e39e6a619

📥 Commits

Reviewing files that changed from the base of the PR and between 873f560 and 794cd10.

📒 Files selected for processing (15)
  • projects/caliper/cli/main.py
  • projects/caliper/engine/file_export/runner.py
  • projects/caliper/postprocess/__init__.py
  • projects/caliper/postprocess/guidellm/__init__.py
  • projects/caliper/postprocess/guidellm/parsing/__init__.py
  • projects/caliper/postprocess/guidellm/parsing/kpis.py
  • projects/caliper/postprocess/guidellm/parsing/models.py
  • projects/caliper/postprocess/guidellm/parsing/parsers.py
  • projects/caliper/postprocess/guidellm/plotting/__init__.py
  • projects/caliper/postprocess/guidellm/plugin.py
  • projects/core/library/replot.py
  • projects/fournos_launcher/orchestration/pr_args.py
  • projects/llm_d_legacy/orchestration/ci.py
  • projects/llm_d_legacy/testing/config.yaml
  • projects/skeleton/orchestration/config.yaml
✅ Files skipped from review due to trivial changes (2)
  • projects/caliper/postprocess/guidellm/parsing/init.py
  • projects/caliper/engine/file_export/runner.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • projects/caliper/postprocess/guidellm/plugin.py
  • projects/caliper/postprocess/guidellm/parsing/kpis.py
  • projects/fournos_launcher/orchestration/pr_args.py
  • projects/llm_d_legacy/orchestration/ci.py
  • projects/caliper/postprocess/guidellm/parsing/parsers.py
  • projects/core/library/replot.py

Comment thread projects/caliper/cli/main.py
Comment on lines +609 to +615
except click.ClickException as exc:
# Handle click exceptions including NoArgsIsHelpError and MissingParameter
if hasattr(exc, "ctx") and exc.ctx:
click.echo(exc.ctx.get_help(), err=True)
else:
exc.show(sys.stderr)
sys.exit(2)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In Click 8.1.0, does click.Context.get_help()include the original exception text forMissingParameterandNoSuchOption, or is exc.show(...) required to preserve it?

💡 Result:

In Click 8.1.0, click.Context.get_help does NOT include the original exception text for MissingParameter or NoSuchOption. In other words, exc.show(...) is required if you want the exception’s message (e.g., the “Missing parameter …” or “No such option …” text) to be preserved and displayed. Reasoning grounded in the code: - Context.get_help just returns the formatted help page generated from the command (it calls command.get_help/format_help) and has no access to any active exception or its message. [1] - ClickException.show is the method responsible for rendering the exception message to stderr/file (including adding the “Try '… --help' for help” hint and then echoing “Error: {message}”). [2] - MissingParameter and NoSuchOption both implement their own message formatting via ClickException.format_message / str logic (so the message lives on the exception object, not on the help text). [2] So: if you call ctx.get_help (or command.get_help(ctx)) in an exception handler without also showing the exception, you will get only usage/help text, not the original exception message; to include it you must call exc.show(...).

Citations:


Preserve error messages when showing help for Click exceptions.

When exc.ctx is present, the current code shows only the help text and loses the actual error message (e.g., "Missing parameter …" or "No such option …"). Click's Context.get_help() returns only the formatted help page; exc.show() is required to display the exception message. Call exc.show(sys.stderr) first, then optionally show help:

Proposed fix
     except click.ClickException as exc:
-        # Handle click exceptions including NoArgsIsHelpError and MissingParameter
-        if hasattr(exc, "ctx") and exc.ctx:
-            click.echo(exc.ctx.get_help(), err=True)
-        else:
-            exc.show(sys.stderr)
+        # Preserve Click's error text, then add command help when available.
+        exc.show(sys.stderr)
+        if getattr(exc, "ctx", None):
+            click.echo("", err=True)
+            click.echo(exc.ctx.get_help(), err=True)
         sys.exit(2)
📝 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
except click.ClickException as exc:
# Handle click exceptions including NoArgsIsHelpError and MissingParameter
if hasattr(exc, "ctx") and exc.ctx:
click.echo(exc.ctx.get_help(), err=True)
else:
exc.show(sys.stderr)
sys.exit(2)
except click.ClickException as exc:
# Preserve Click's error text, then add command help when available.
exc.show(sys.stderr)
if getattr(exc, "ctx", None):
click.echo("", err=True)
click.echo(exc.ctx.get_help(), err=True)
sys.exit(2)
🤖 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/caliper/cli/main.py` around lines 609 - 615, The exception handling
for click.ClickException currently prints only the help text when exc.ctx exists
and drops the actual error message; update the handler so it calls
exc.show(sys.stderr) first to print the exception message (e.g., from
MissingParameter or NoArgsIsHelpError) and then, if exc.ctx is present, call
click.echo(exc.ctx.get_help(), err=True) to also display the help page; keep the
existing sys.exit(2) behavior.

@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 13, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

• Failure indicator: Empty.
Execution logs

@kpouget kpouget force-pushed the caliper-skeleton branch from de6412e to 7ee092b Compare May 13, 2026 10:24
@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 13, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@psap-forge-bot
Copy link
Copy Markdown

🔴 Test of 'llm_d_legacy replot' failed after 00 hours 00 minutes 03 seconds 🔴

• Link to the test results.

• No reports generated...

Test configuration:

caliper.replot.url: https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e
ci_job.cluster: psap-mgmt
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-legacy-20260513-102436
ci_job.name: llm_d_legacy
ci_job.owner: kpouget
project.args: []
project.name: llm_d_legacy

Failure indicator:

## /workspace/artifacts/000__replot/FAILURE 
--- 📍RuntimeError STACKTRACE ---
--- 📍MLflow artifact download failed: Unable to locate credentials

   Traceback (most recent call last):
     File "/app/forge/projects/core/library/replot.py", line 137, in _download_mlflow_artifacts
       downloaded_path = client.download_artifacts(
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/tracking/client.py", line 3739, in download_artifacts
       return self._tracking_client.download_artifacts(run_id, path, dst_path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/tracking/_tracking_service/client.py", line 752, in download_artifacts
       return download_artifacts(
              ^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/artifacts/__init__.py", line 106, in download_artifacts
       return artifact_repo.download_artifacts(artifact_path, dst_path=dst_path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/artifact_repo.py", line 297, in download_artifacts
       root_listing = self.list_artifacts(artifact_path)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/s3_artifact_repo.py", line 417, in list_artifacts
       for result in self._iterate_s3_paginated_results(bucket, prefix):
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/s3_artifact_repo.py", line 379, in _iterate_s3_paginated_results
       for result in results:
                     ^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/paginate.py", line 272, in __iter__
       response = self._make_request(current_kwargs)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/context.py", line 123, in wrapper
       return func(*args, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/paginate.py", line 360, in _make_request
       return self._method(**current_kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 606, in _api_call
       return self._make_api_call(operation_name, kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/context.py", line 123, in wrapper
       return func(*args, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 1076, in _make_api_call
       http, parsed_response = self._make_request(
                               ^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 1100, in _make_request
       return self._endpoint.make_request(operation_model, request_dict)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 119, in make_request
       return self._send_request(request_dict, operation_model)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 196, in _send_request
       request = self.create_request(request_dict, operation_model)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 132, in create_request
       self._event_emitter.emit(
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 412, in emit
       return self._emitter.emit(aliased_event_name, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 256, in emit
       return self._emit(event_name, kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 239, in _emit
       response = handler(**kwargs)
                  ^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/signers.py", line 108, in handler
       return self.sign(operation_name, request)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/signers.py", line 200, in sign
       auth.add_auth(request)
     File "/usr/local/lib/python3.12/site-packages/botocore/auth.py", line 429, in add_auth
       raise NoCredentialsError()
   botocore.exceptions.NoCredentialsError: Unable to locate credentials
   
   The above exception was the direct cause of the following exception:
   
   Traceback (most recent call last):
     File "/app/forge/projects/core/library/ci.py", line 118, in wrapper
       exit_code = command_func(*args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 330, in replot_command
       status = run_replot(artifact_directory=artifact_directory)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 251, in run_replot
       download_result = _download_mlflow_artifacts(replot_url, replot_download_dir)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 171, in _download_mlflow_artifacts
       raise RuntimeError(f"MLflow artifact download failed: {e}") from e
   RuntimeError: MLflow artifact download failed: Unable to locate credentials

[...]

Execution logs

@psap-forge-bot
Copy link
Copy Markdown

🔴 Test of 'fournos_launcher submit' failed after 00 hours 01 minutes 29 seconds 🔴

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

• Failure indicator: Empty.
Execution logs

@kpouget kpouget force-pushed the caliper-skeleton branch 2 times, most recently from 44df45a to 086b37e Compare May 13, 2026 11:21
@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 13, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@psap-forge-bot
Copy link
Copy Markdown

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

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

• Failure indicator: Empty.
Execution logs

@kpouget kpouget force-pushed the caliper-skeleton branch from 086b37e to 2657a6e Compare May 13, 2026 11:26
@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 13, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@psap-forge-bot
Copy link
Copy Markdown

🔴 Test of 'llm_d_legacy replot' failed after 00 hours 00 minutes 03 seconds 🔴

• Link to the test results.

• No reports generated...

Test configuration:

caliper.replot.url: https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e
ci_job.cluster: psap-mgmt
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-legacydn52l
ci_job.name: llm_d_legacy
ci_job.owner: kpouget
project.args: []
project.name: llm_d_legacy

Failure indicator:

## /workspace/artifacts/000__replot/FAILURE 
--- 📍RuntimeError STACKTRACE ---
--- 📍MLflow artifact download failed: Unable to locate credentials

   Traceback (most recent call last):
     File "/app/forge/projects/core/library/replot.py", line 137, in _download_mlflow_artifacts
       downloaded_path = client.download_artifacts(
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/tracking/client.py", line 3739, in download_artifacts
       return self._tracking_client.download_artifacts(run_id, path, dst_path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/tracking/_tracking_service/client.py", line 752, in download_artifacts
       return download_artifacts(
              ^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/artifacts/__init__.py", line 106, in download_artifacts
       return artifact_repo.download_artifacts(artifact_path, dst_path=dst_path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/artifact_repo.py", line 297, in download_artifacts
       root_listing = self.list_artifacts(artifact_path)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/s3_artifact_repo.py", line 417, in list_artifacts
       for result in self._iterate_s3_paginated_results(bucket, prefix):
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/s3_artifact_repo.py", line 379, in _iterate_s3_paginated_results
       for result in results:
                     ^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/paginate.py", line 272, in __iter__
       response = self._make_request(current_kwargs)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/context.py", line 123, in wrapper
       return func(*args, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/paginate.py", line 360, in _make_request
       return self._method(**current_kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 606, in _api_call
       return self._make_api_call(operation_name, kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/context.py", line 123, in wrapper
       return func(*args, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 1076, in _make_api_call
       http, parsed_response = self._make_request(
                               ^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 1100, in _make_request
       return self._endpoint.make_request(operation_model, request_dict)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 119, in make_request
       return self._send_request(request_dict, operation_model)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 196, in _send_request
       request = self.create_request(request_dict, operation_model)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 132, in create_request
       self._event_emitter.emit(
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 412, in emit
       return self._emitter.emit(aliased_event_name, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 256, in emit
       return self._emit(event_name, kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 239, in _emit
       response = handler(**kwargs)
                  ^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/signers.py", line 108, in handler
       return self.sign(operation_name, request)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/signers.py", line 200, in sign
       auth.add_auth(request)
     File "/usr/local/lib/python3.12/site-packages/botocore/auth.py", line 429, in add_auth
       raise NoCredentialsError()
   botocore.exceptions.NoCredentialsError: Unable to locate credentials
   
   The above exception was the direct cause of the following exception:
   
   Traceback (most recent call last):
     File "/app/forge/projects/core/library/ci.py", line 118, in wrapper
       exit_code = command_func(*args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 330, in replot_command
       status = run_replot(artifact_directory=artifact_directory)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 251, in run_replot
       download_result = _download_mlflow_artifacts(replot_url, replot_download_dir)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 171, in _download_mlflow_artifacts
       raise RuntimeError(f"MLflow artifact download failed: {e}") from e
   RuntimeError: MLflow artifact download failed: Unable to locate credentials

[...]

Execution logs

@psap-forge-bot
Copy link
Copy Markdown

🔴 Test of 'llm_d_legacy replot' failed after 00 hours 00 minutes 03 seconds 🔴

• Link to the test results.

• No reports generated...

Test configuration:

caliper.replot.url: https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e
ci_job.cluster: psap-mgmt
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-legacy-7mm48
ci_job.name: llm_d_legacy
ci_job.owner: kpouget
project.args: []
project.name: llm_d_legacy

Failure indicator:

## /workspace/artifacts/000__replot/FAILURE 
--- 📍RuntimeError STACKTRACE ---
--- 📍MLflow artifact download failed: Unable to locate credentials

   Traceback (most recent call last):
     File "/app/forge/projects/core/library/replot.py", line 137, in _download_mlflow_artifacts
       downloaded_path = client.download_artifacts(
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/tracking/client.py", line 3739, in download_artifacts
       return self._tracking_client.download_artifacts(run_id, path, dst_path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/tracking/_tracking_service/client.py", line 752, in download_artifacts
       return download_artifacts(
              ^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/artifacts/__init__.py", line 106, in download_artifacts
       return artifact_repo.download_artifacts(artifact_path, dst_path=dst_path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/artifact_repo.py", line 297, in download_artifacts
       root_listing = self.list_artifacts(artifact_path)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/s3_artifact_repo.py", line 417, in list_artifacts
       for result in self._iterate_s3_paginated_results(bucket, prefix):
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/mlflow/store/artifact/s3_artifact_repo.py", line 379, in _iterate_s3_paginated_results
       for result in results:
                     ^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/paginate.py", line 272, in __iter__
       response = self._make_request(current_kwargs)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/context.py", line 123, in wrapper
       return func(*args, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/paginate.py", line 360, in _make_request
       return self._method(**current_kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 606, in _api_call
       return self._make_api_call(operation_name, kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/context.py", line 123, in wrapper
       return func(*args, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 1076, in _make_api_call
       http, parsed_response = self._make_request(
                               ^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/client.py", line 1100, in _make_request
       return self._endpoint.make_request(operation_model, request_dict)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 119, in make_request
       return self._send_request(request_dict, operation_model)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 196, in _send_request
       request = self.create_request(request_dict, operation_model)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/endpoint.py", line 132, in create_request
       self._event_emitter.emit(
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 412, in emit
       return self._emitter.emit(aliased_event_name, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 256, in emit
       return self._emit(event_name, kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/hooks.py", line 239, in _emit
       response = handler(**kwargs)
                  ^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/signers.py", line 108, in handler
       return self.sign(operation_name, request)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/usr/local/lib/python3.12/site-packages/botocore/signers.py", line 200, in sign
       auth.add_auth(request)
     File "/usr/local/lib/python3.12/site-packages/botocore/auth.py", line 429, in add_auth
       raise NoCredentialsError()
   botocore.exceptions.NoCredentialsError: Unable to locate credentials
   
   The above exception was the direct cause of the following exception:
   
   Traceback (most recent call last):
     File "/app/forge/projects/core/library/ci.py", line 118, in wrapper
       exit_code = command_func(*args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 330, in replot_command
       status = run_replot(artifact_directory=artifact_directory)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 251, in run_replot
       download_result = _download_mlflow_artifacts(replot_url, replot_download_dir)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/core/library/replot.py", line 171, in _download_mlflow_artifacts
       raise RuntimeError(f"MLflow artifact download failed: {e}") from e
   RuntimeError: MLflow artifact download failed: Unable to locate credentials

[...]

Execution logs

@psap-forge-bot
Copy link
Copy Markdown

🟢 Test of 'fournos_launcher submit' succeeded after 00 hours 01 minutes 28 seconds 🟢

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

Execution logs

@kpouget kpouget force-pushed the caliper-skeleton branch from 2657a6e to ed039a3 Compare May 13, 2026 12:06
@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 13, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

@psap-forge-bot
Copy link
Copy Markdown

🟢 Test of 'fournos_launcher submit' succeeded after 00 hours 01 minutes 29 seconds 🟢

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/cluster psap-mgmt
/pipeline forge-replot
/replot.url https://mlflow.apps.aperdomo-lab.ibm.rhperfscale.org/#/experiments/0/runs/7e76d29f069a41bca3d5b8ff0655246e

Execution logs

@kpouget
Copy link
Copy Markdown
Contributor Author

kpouget commented May 13, 2026

/test fournos llm_d_legacy
/cluster psap-mgmt

@psap-forge-bot
Copy link
Copy Markdown

🔴 Test of 'llm_d_legacy test' failed after 00 hours 00 minutes 01 seconds 🔴

• Link to the test results.

• No reports generated...

Test configuration:

ci_job.cluster: psap-mgmt
ci_job.exclusive: true
ci_job.fjob: forge-llm-d-legacy-20260513-123156
ci_job.name: llm_d_legacy
ci_job.owner: kpouget
project.args: []
project.name: llm_d_legacy

Failure indicator:

## /workspace/artifacts/000__test/FAILURE 
--- 📍RuntimeError STACKTRACE ---
--- 📍No GPU nodes found in the cluster. GPU nodes are required for LLM inference testing. Ensure prepare_gpu() was called.

   Traceback (most recent call last):
     File "/app/forge/projects/core/library/ci.py", line 118, in wrapper
       exit_code = command_func(*args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/app/forge/projects/llm_d_legacy/orchestration/ci.py", line 85, in test
       failed = test_llmd.test()
                ^^^^^^^^^^^^^^^^
     File "/app/forge/projects/llm_d_legacy/testing/test_llmd.py", line 134, in test
       prepare_for_test()
     File "/app/forge/projects/llm_d_legacy/testing/test_llmd.py", line 194, in prepare_for_test
       ensure_gpu_nodes_available()
     File "/app/forge/projects/llm_d_legacy/testing/test_llmd.py", line 1351, in ensure_gpu_nodes_available
       raise RuntimeError(
   RuntimeError: No GPU nodes found in the cluster. GPU nodes are required for LLM inference testing. Ensure prepare_gpu() was called.

[...]

Execution logs

@psap-forge-bot
Copy link
Copy Markdown

🔴 Test of 'fournos_launcher submit' failed after 00 hours 01 minutes 18 seconds 🔴

• Link to the test results.

• No reports generated...

Test configuration:

/test fournos llm_d_legacy
/cluster psap-mgmt

• Failure indicator: Empty.
Execution logs

@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 13, 2026

@kpouget: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/fournos ed039a3 link true /test fournos

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant