Skip to content

[rhoai-2.25] fix(build): derive native ONNX/pyarrow versions from pylock.toml#2519

Merged
jiridanek merged 5 commits into
rhoai-2.25from
fix/rhoai-2.25-ws3-arch-matrix
Jul 22, 2026
Merged

[rhoai-2.25] fix(build): derive native ONNX/pyarrow versions from pylock.toml#2519
jiridanek merged 5 commits into
rhoai-2.25from
fix/rhoai-2.25-ws3-arch-matrix

Conversation

@jiridanek

@jiridanek jiridanek commented Jul 11, 2026

Copy link
Copy Markdown
Member

Description

Replace hardcoded ARG ONNX_VERSION / ARG PYARROW_VERSION with a stdlib-only scripts/pylock_version.py helper that reads pinned versions from each workbench pylock.toml using PEP 508-style platform markers.

Scope (images touched):

  • jupyter/datascience, runtimes/datascience — ppc64le ONNX + pyarrow native builds; s390x pyarrow
  • jupyter/trustyaidevel_env_setup.sh ppc64le wheel builds (torch/pyarrow/pillow/accelerate)

scripts/pylock_version.py:

  • Stdlib-only (tomllib + ast marker evaluator); runs in UBI python-312 before uv is installed
  • Prints raw PEP 440 versions; shell applies prefixes (v${ONNX_VERSION}, apache-arrow-${PYARROW_VERSION}, ${TORCH_VERSION%%+*} for git tags)
  • Marker evaluation via ast.parse — supports nested and/or/not, in tuples, .* wildcards; rejects unsupported operators loudly

Also in this PR:

  • ONNX 1.22.0 (from pylock) removed upstream requirements.txt — ppc64le onnx-builder uses requirements-min.txt
  • Trustyai devel_env_setup.sh shell quoting + unset-safe LD_LIBRARY_PATH under set -u
  • Semgrep shell-unquoted-var-in-dangerous-cmd hardened (word boundaries; stop at |, ||, ;, &, &&)
  • tests/with_subtests.py decorator for iterable-driven subtests (quieter alternative to manual for/with subtests.test) — tracks opendatahub-io/notebooks#4140

Commits (5):

  1. feat(scripts): add stdlib pylock_version helper
  2. fix(build): derive native ONNX/pyarrow versions from pylock.toml
  3. fix(trustyai): resolve pins via pylock and quote shell vars
  4. fix(semgrep): harden shell-unquoted-var-in-dangerous-cmd
  5. test: add with_subtests helper for iterable static checks

How Has This Been Tested?

  • uv run pytest on tests/unit/scripts/test_pylock_version.py, tests/test_native_build_versions.py, tests/unit/test_subtests.py, tests/unit/test_semgrep_shell_unquoted.py
  • python3.12 -S scripts/pylock_version.py smoke test on host and in registry.access.redhat.com/ubi9/python-312:latest
  • uv run prek --all-files (ruff green; pre-existing pyright noise on unrelated runtime_test.py)
  • Konflux: jupyter/runtime datascience ppc64le after merge (openblas follow-up is [rhoai-2.25] fix(ppc64le): openblas-devel for ONNX numpy builds #2534)

Self checklist:

  • Targeted unit tests run before review
  • Konflux-specific changes are in Dockerfile.konflux.* under rhds/notebooks as required for rhoai-2.25

Merge criteria

  • Focused thematic commits (not one mega-squash)
  • Testing instructions in PR body
  • Review / lgtm / approve

Out of scope / follow-ups

  • #2534openblas-devel in onnx-builder for ppc64le numpy sdist (stacked after this merges)
  • Broader adoption of with_subtests across the suite — ODH #4140
  • whl-cache dedup (trustyai double uv pip install)

Summary by CodeRabbit

  • Improvements
    • Native CPU and runtime images now derive ONNX and PyArrow versions from the lockfile, producing matching architecture-specific tags (including ppc64le and s390x).
    • TrustyAI wheel caching now includes the version-resolution helper for consistent builds.
    • ONNX native builds now install from a minimal dependency set.
  • Build/Configuration
    • Added lock-aware pylock_version tooling and use it during Docker builds and development setup (with a configurable DATASCIENCE_SOURCE_CODE build argument).
  • Tests
    • Added coverage validating Dockerfiles and marker-based version resolution follow the lockfile, plus new unit tests for the helper, Semgrep rule, and subtest behavior.
  • Chores
    • Reduced noisy pytest subtest output and tightened the Semgrep shell-variable detection rule.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds lockfile-based dependency version resolution to native builds, updates setup scripts and Dockerfiles, adds resolver validation, tightens a shell-analysis rule with regression tests, and introduces a quiet/noisy pytest subtest decorator.

Changes

Pylock-driven native dependency builds

Layer / File(s) Summary
Pylock version resolver
scripts/pylock_version.py
Adds restricted marker evaluation, architecture/Python-aware package selection, duplicate detection, and CLI version output.
Jupyter native source checkouts
jupyter/datascience/ubi9-python-3.12/Dockerfile*
Derives Apache Arrow branches and ONNX tags from pylock.toml during native builds.
Runtime native version wiring
runtimes/datascience/ubi9-python-3.12/Dockerfile*
Replaces hardcoded ONNX and PyArrow versions with lockfile-derived values for ppc64le and s390x builders.
Setup scripts and validation
jupyter/trustyai/ubi9-python-3.12/*, tests/*
Uses the resolver in setup flows, copies it into wheel-cache stages, and adds resolver and Dockerfile wiring tests.

Semgrep dangerous-command detection

Layer / File(s) Summary
Regex refinement and regression coverage
semgrep.yaml, tests/unit/test_semgrep_shell_unquoted.py
Tightens dangerous shell variable matching and tests quoted, unquoted, and command-separator cases.

Pytest subtest utility

Layer / File(s) Summary
Subtest execution utility
tests/with_subtests.py, tests/unit/test_subtests.py, pytest.ini
Adds quiet and noisy iterable subtest execution and suppresses successful subtest output.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested labels: lgtm, approved

Suggested reviewers: daniellutz, dibryant, ysok

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main build change.
Description check ✅ Passed The PR body includes the required sections and concrete testing details, with only some checklist items left unchecked.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/rhoai-2.25-ws3-arch-matrix

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
tests/unit/scripts/test_pylock_version.py (1)

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

Add descriptive messages to single assert statements.

As per coding guidelines, plain assert statements should include descriptive messages for single assertions. For example, assert result.stdout.strip() == "1.22.0" should be assert result.stdout.strip() == "1.22.0", f"expected onnx ppc64le version, got {result.stdout.strip()}".

Also applies to: 19-19, 30-30, 47-47, 68-68, 82-82

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

In `@tests/unit/scripts/test_pylock_version.py` at line 15, Add descriptive
failure messages to each single assert in test_pylock_version.py, including the
assertions around pylock_version.format_version and the other referenced test
cases. Keep each assertion’s existing condition unchanged and make each message
identify the expected result and the actual value.

Source: Coding guidelines

scripts/pylock_version.py (1)

88-88: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

fnmatch.fnmatchcase treats ? and [] as special characters.

When expected ends with .*, fnmatch is used for wildcard matching. Besides *, fnmatch also treats ? and [seq] as glob patterns. If a marker expected value contains ? or [, it would be interpreted as a glob pattern rather than a literal. For version strings this is unlikely, but a simpler check like actual.startswith(expected[:-2]) would be more precise for the .* wildcard case.

🤖 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 `@scripts/pylock_version.py` at line 88, Update the version comparison logic in
pylock_version.py so the expected-ending-`.*` case uses a literal prefix check
via actual.startswith(expected[:-2]) instead of fnmatch.fnmatchcase. Preserve
exact equality for expected values without the `.*` suffix, ensuring characters
such as `?` and `[` remain literal.
jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh (2)

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

Quote ${TORCH_TAG} in the git clone command.

The variable ${TORCH_TAG} is unquoted on line 54. While the value originates from pylock_version.py and is expected to be a clean tag like v2.7.1, quoting it prevents globbing/word splitting if the script ever returns an unexpected value.

♻️ Suggested fix
-    git clone --recursive https://github.com/pytorch/pytorch.git -b ${TORCH_TAG}
+    git clone --recursive https://github.com/pytorch/pytorch.git -b "${TORCH_TAG}"
🤖 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 `@jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh` around lines 51 - 54,
Quote the ${TORCH_TAG} argument in the git clone command within the devel
environment setup script, preserving the existing recursive clone and repository
branch selection.

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

Quote command substitution on the accelerate install line.

The $(python3 ./pylock_version.py accelerate --platform x86_64) substitution is unquoted. Quote it to prevent word splitting.

♻️ Suggested fix
-    uv pip install --refresh ${WHEELS_DIR}/*.whl accelerate==$(python3 ./pylock_version.py accelerate --platform x86_64)
+    uv pip install --refresh ${WHEELS_DIR}/*.whl "accelerate==$(python3 ./pylock_version.py accelerate --platform x86_64)"
🤖 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 `@jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh` at line 101, Quote the
command substitution used for the accelerate version in the install command so
its output is passed as a single argument. Update only the accelerate version
expression on the uv pip install line, preserving the existing package and
platform arguments.
🤖 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 `@runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu`:
- Around line 64-73: Update the version lookups in the ppc64le profile to
request formatted values from pylock_version.py: use the git-tag format for ONNX
and apache-arrow-branch for PyArrow. Adjust the downstream onnx-builder and
arrow-builder references, plus the corresponding s390x builder lookups, to
consume these formatted values without manually prepending v or apache-arrow-.
Preserve the existing version variables and platform-specific behavior.

---

Nitpick comments:
In `@jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh`:
- Around line 51-54: Quote the ${TORCH_TAG} argument in the git clone command
within the devel environment setup script, preserving the existing recursive
clone and repository branch selection.
- Line 101: Quote the command substitution used for the accelerate version in
the install command so its output is passed as a single argument. Update only
the accelerate version expression on the uv pip install line, preserving the
existing package and platform arguments.

In `@scripts/pylock_version.py`:
- Line 88: Update the version comparison logic in pylock_version.py so the
expected-ending-`.*` case uses a literal prefix check via
actual.startswith(expected[:-2]) instead of fnmatch.fnmatchcase. Preserve exact
equality for expected values without the `.*` suffix, ensuring characters such
as `?` and `[` remain literal.

In `@tests/unit/scripts/test_pylock_version.py`:
- Line 15: Add descriptive failure messages to each single assert in
test_pylock_version.py, including the assertions around
pylock_version.format_version and the other referenced test cases. Keep each
assertion’s existing condition unchanged and make each message identify the
expected result and the actual value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 885da1da-c633-4460-b966-3211a0a29c60

📥 Commits

Reviewing files that changed from the base of the PR and between 08f4fe3 and ff50ef8.

📒 Files selected for processing (14)
  • codeserver/ubi9-python-3.12/Dockerfile.cpu
  • codeserver/ubi9-python-3.12/Dockerfile.konflux.cpu
  • codeserver/ubi9-python-3.12/devel_env_setup.sh
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py
  • tests/conftest.py
  • tests/test_native_build_versions.py
  • tests/unit/scripts/test_pylock_version.py

Comment thread runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
@jiridanek

Copy link
Copy Markdown
Member Author

/build-konflux

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
scripts/pylock_version.py (1)

174-197: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Tuple metavar with nargs="+" causes a crash when displaying help, and displays arguments in the wrong order.

The test case "explicit-pylock" (line 40-48 in test_pylock_version.py) confirms the actual argument contract is PYLOCK PACKAGE, but metavar=("PACKAGE", "PYLOCK") displays them in reverse order.

Additionally, calling --help crashes with ValueError: too many values to unpack (expected 1) when argparse tries to format the metavar for the help message. While the crash occurs at help-formatting time (not at add_argument() time), it makes the help unavailable in practice.

🛡️ Proposed fix
     parser.add_argument(
         "positional",
         nargs="+",
-        metavar=("PACKAGE", "PYLOCK"),
+        metavar="PACKAGE_OR_PYLOCK_PACKAGE",
         help="PACKAGE, or PYLOCK PACKAGE when pylock.toml is not in the cwd",
     )
🤖 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 `@scripts/pylock_version.py` around lines 174 - 197, Update the positional
argument definition in _parse_args so nargs="+" uses a single safe metavar
rather than a two-item tuple, preventing argparse help formatting from crashing.
Ensure the help text reflects the actual accepted forms, especially the
two-argument PYLOCK PACKAGE order, while preserving the existing argument
parsing behavior.
🧹 Nitpick comments (1)
tests/unit/scripts/test_pylock_version.py (1)

101-107: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use subtests for the per-marker loop.

test_native_build_pylocks_have_parseable_markers iterates over every marker in a lockfile and stops at the first failure, hiding any other bad markers in the same run. As per coding guidelines, tests/**/*.py should Use subtests from pytest-subtests plugin for iterating over multiple items with per-item assertions.

♻️ Proposed refactor using `subtests`
-def test_native_build_pylocks_have_parseable_markers(pylock_version, pylock: Path) -> None:
+def test_native_build_pylocks_have_parseable_markers(pylock_version, subtests, pylock: Path) -> None:
     doc = tomllib.loads(pylock.read_text())
     markers = {entry["marker"] for entry in doc.get("packages", []) if entry.get("marker")}
     assert markers, f"expected markers in {pylock}"
     env = pylock_version.marker_env(python_minor="3.12", platform_machine="x86_64")
     for marker in markers:
-        pylock_version.evaluate_marker(marker, env)
+        with subtests.test(marker=marker):
+            pylock_version.evaluate_marker(marker, env)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/scripts/test_pylock_version.py` around lines 101 - 107, Update
test_native_build_pylocks_have_parseable_markers to use the pytest-subtests
fixture for the per-marker loop, wrapping each marker evaluation in its own
named subtest so all markers are evaluated and failures are reported
independently.

Source: Coding guidelines

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

Inline comments:
In `@scripts/pylock_version.py`:
- Around line 34-48: Update _ALLOWED_NAMES to match the keys actually populated
by marker_env(): either add os_name, platform_release, platform_version, and
extra to marker_env() with correct values, or remove them from _ALLOWED_NAMES so
_eval_marker() rejects unsupported markers with ValueError instead of evaluating
empty defaults.

---

Outside diff comments:
In `@scripts/pylock_version.py`:
- Around line 174-197: Update the positional argument definition in _parse_args
so nargs="+" uses a single safe metavar rather than a two-item tuple, preventing
argparse help formatting from crashing. Ensure the help text reflects the actual
accepted forms, especially the two-argument PYLOCK PACKAGE order, while
preserving the existing argument parsing behavior.

---

Nitpick comments:
In `@tests/unit/scripts/test_pylock_version.py`:
- Around line 101-107: Update test_native_build_pylocks_have_parseable_markers
to use the pytest-subtests fixture for the per-marker loop, wrapping each marker
evaluation in its own named subtest so all markers are evaluated and failures
are reported independently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6403627d-11b8-48c4-9153-f9e9fbcb227a

📥 Commits

Reviewing files that changed from the base of the PR and between ff50ef8 and 07d0d99.

📒 Files selected for processing (8)
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py
  • tests/test_native_build_versions.py
  • tests/unit/scripts/test_pylock_version.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu

Comment thread scripts/pylock_version.py
@jiridanek jiridanek changed the title fix(build): derive native ONNX/pyarrow versions from pylock.toml [rhoai-2.25] fix(build): derive native ONNX/pyarrow versions from pylock.toml Jul 12, 2026
@jiridanek

Copy link
Copy Markdown
Member Author

/build-konflux

@jiridanek

Copy link
Copy Markdown
Member Author

/hold this reveals additional build problems, https://redhat-internal.slack.com/archives/C0BD6LZUEGJ/p1783859157800919

@jiridanek

Copy link
Copy Markdown
Member Author

/unhold 2.25.10 development is now open

@jiridanek
jiridanek force-pushed the fix/rhoai-2.25-ws3-arch-matrix branch from 622ceb8 to 76a32de Compare July 21, 2026 16:19

@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: 2

🧹 Nitpick comments (1)
tests/test_native_build_versions.py (1)

26-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use subtests for the Dockerfile loop. Wrap each Dockerfile/pattern/package check in a named subtests.test(...) scope so failures point to the specific item instead of the whole loop.

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

In `@tests/test_native_build_versions.py` around lines 26 - 33, Update the
Dockerfile validation loop in the test to wrap each dockerfile,
forbidden-pattern, and package assertion in a named subtests.test(...) scope,
using the relevant Dockerfile and item names so failures identify the specific
check while preserving the existing assertions.

Source: Coding guidelines

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

Inline comments:
In `@tests/test_native_build_versions.py`:
- Around line 31-33: Update the regex assertion in the test loop over onnx and
pyarrow so it matches the pylock_version.py resolver invocation together with
the target package as its argument, rather than allowing unrelated later
mentions via re.DOTALL. Keep the assertion tied to each package and preserve the
existing failure message.
- Around line 16-17: Assign Allure metadata to every affected test: add the
missing allure import, then add matching `@allure.description`() and
`@allure.issue`(...) decorators to tests/test_native_build_versions.py lines 16-17
and 36-37, and tests/unit/scripts/test_pylock_version.py lines 54, 65, 70, 80,
85, 108, and 119-125. Preserve the existing test behavior and use the matching
issue links for each test.

---

Nitpick comments:
In `@tests/test_native_build_versions.py`:
- Around line 26-33: Update the Dockerfile validation loop in the test to wrap
each dockerfile, forbidden-pattern, and package assertion in a named
subtests.test(...) scope, using the relevant Dockerfile and item names so
failures identify the specific check while preserving the existing assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 3887ae48-93cb-4a14-8645-c723bc32fe46

📥 Commits

Reviewing files that changed from the base of the PR and between 622ceb8 and 76a32de.

📒 Files selected for processing (11)
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py
  • tests/conftest.py
  • tests/test_native_build_versions.py
  • tests/unit/scripts/test_pylock_version.py
🚧 Files skipped from review as they are similar to previous changes (7)
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • tests/conftest.py
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py

Comment thread tests/test_native_build_versions.py Outdated
Comment thread tests/test_native_build_versions.py Outdated
@jiridanek

Copy link
Copy Markdown
Member Author

@coderabbitai Code Review: PR #2519 — [rhoai-2.25] fix(build): derive native ONNX/pyarrow versions from pylock.toml

Overview

Replaces hardcoded ARG ONNX_VERSION=v1.20.1 / ARG PYARROW_VERSION=17.0.0 across 8 Dockerfiles (4 ODH .cpu + 4 Konflux .konflux.cpu) with a new stdlib-only scripts/pylock_version.py that reads pinned versions from each workbench's pylock.toml. Also adds a PEP 508 marker evaluator, ONNX 1.22.0
requirements-min.txt fix, and shell quoting improvements in devel_env_setup.sh.

11 files changed, +465 / -51.


Positives

  • Single source of truth: Eliminates the version-drift problem where Dockerfile ARGs and pylock pins diverge after lock regeneration.
  • Stdlib-only script: pylock_version.py uses only tomllib + ast, so it runs in bare UBI python-312 before uv is installed — correct for the build stage ordering.
  • Solid marker evaluator: The ast.parse approach with an explicit _ALLOWED_NAMES whitelist and ValueError for unknown variables/operators is defensive and auditable. Much better than regex-grepping pylock.toml.
  • Good test coverage: 19 tests covering CLI invocation modes, marker edge cases, missing packages, and Dockerfile-aware integration checks.
  • Shell quoting fixes: "${ONNX_TAG}", "${TORCH_TAG}", quoted WHEEL_DIR in trustyai/codeserver address real semgrep findings.

Issues

  1. --platform x86_64 inside a ppc64le block (confusing, not wrong)

devel_env_setup.sh:138 and :171:
if [[ $(uname -m) == "ppc64le" ]]; then
TORCH_VERSION=$(python3 ./pylock_version.py torch --platform x86_64)
...
uv pip install ... "accelerate==$(python3 ./pylock_version.py accelerate --platform x86_64)"
These resolve the x86_64 version because torch/accelerate only have x86_64 markers in the pylock (no ppc64le wheel exists — it's built from source). This is functionally correct but a maintenance trap: a future reader will think it's a copy-paste bug. A one-line comment explaining "torch is pinned under x86_64
markers; we build the same version from source on ppc64le" would prevent a well-intentioned "fix."

  1. Unquoted ${PYARROW_VERSION} in git clone (pre-existing, but newly constructed)

devel_env_setup.sh:155:
git clone --recursive https://github.com/apache/arrow.git -b apache-arrow-${PYARROW_VERSION}
${PILLOW_VERSION} at line 164 and ${WHEELS_DIR}/*.whl at line 171 are also unquoted. The torch one was correctly quoted as "${TORCH_TAG}". Since this PR already fixed quoting for TORCH_TAG, it would be consistent to quote the remaining variable expansions in the same block. Word splitting on a version string is
unlikely but free to prevent.

  1. Heredoc escaping in runtime-datascience profile script is correct but fragile

runtimes/datascience/.../Dockerfile.cpu:197-208: The heredoc switched from <<'PROFILE_EOF' (literal) to <<PROFILE_EOF (expanding) to inject ${ONNX_VERSION} and ${PYARROW_VERSION}. The $ escapes on LD_LIBRARY_PATH and PATH are correct. However, adding any new $VAR line to this profile script in the future will
silently expand at build time instead of at login time. Consider a comment at the heredoc marker: # NB: unquoted heredoc — escape $ for vars that must expand at login.

  1. re.DOTALL false positive in test assertion

tests/test_native_build_versions.py:33:
lookup = re.compile(rf"pylock_version.py.*\b{package}\b", re.DOTALL)
re.DOTALL makes . match newlines, so this succeeds if pylock_version.py appears on line 10 and onnx appears on line 200 in any unrelated context (e.g., a pip install onnx comment). CodeRabbit flagged this too. Dropping re.DOTALL (or using their single-line regex) would make the assertion meaningful.

  1. conftest.py fixture uses importlib — consider sys.path insert instead

@pytest.fixture(scope="session")
def pylock_version():
spec = importlib.util.spec_from_file_location("pylock_version", _SCRIPTS / "pylock_version.py")
...
This works but means pylock_version isn't importable the normal way anywhere else in the test suite. Since scripts/ isn't a package (no init.py), this is the right call. But if more scripts get tested this way, a conftest that does sys.path.insert(0, str(_SCRIPTS)) once would be simpler. Not blocking — just
a style note for when it recurs.

  1. test_pylock_pins_resolve_for_native_arches asserts pyarrow_ppc64le == pyarrow_s390x

tests/test_native_build_versions.py:40:
assert pyarrow_ppc64le == pyarrow_s390x
This enforces that both arches pin the same pyarrow version. If they ever diverge intentionally (e.g., s390x needs a patched version), this test breaks. Consider whether this is an intended contract or an incidental coincidence — if incidental, remove it.

  1. python_minor_from_path fallback to "3.12" is silent

scripts/pylock_version.py:49:
return match.group(1) if match else "3.12"
If the pylock path doesn't contain python-X.Y, this silently defaults to 3.12. For a lockfile at /tmp/pylock.toml (as used in Dockerfiles), the path won't match — so the default is always used. This is fine today (everything is 3.12) but could mask a real mismatch when 3.13 arrives. A --python CLI flag exists
as an override, which mitigates this. Low priority.

  1. Minor: _parse_args metavar is misleading

metavar=("PACKAGE", "PYLOCK"),
The actual order is PYLOCK PACKAGE (pylock first, package second) per the code at line 178-179. The metavar tuple should be ("PYLOCK", "PACKAGE") to match the positional semantics. Currently --help shows them backwards.


Security

  • No injection risk: TARGETARCH comes from Docker's constrained ARG; pylock paths are build-context-local.
  • The ast.parse(marker, mode="eval") approach is safe — eval mode only parses expressions, never exec/import. The _eval_marker function never calls eval() on the AST.

Summary

Well-structured change that solves a real version-drift problem. The marker evaluator is solid, the test coverage is good, and the Dockerfile changes are mechanically correct. The main actionable items are:

  1. Add a comment explaining the --platform x86_64 usage inside ppc64le blocks in devel_env_setup.sh
  2. Drop re.DOTALL from the test regex to avoid false positives
  3. Fix the metavar order in _parse_args
  4. Consider quoting the remaining ${PYARROW_VERSION} and ${PILLOW_VERSION} expansions for consistency

@jiridanek jiridanek left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Nice change — single source of truth for native build versions is a real improvement. The marker evaluator is solid and the ast.parse approach is safe.

Main actionable items in the inline comments:

  1. Comment the --platform x86_64 inside ppc64le blocks — correct but looks like a bug to future readers
  2. Drop re.DOTALL from the test regex — currently matches across unrelated lines
  3. Fix metavar order in _parse_args--help shows args backwards
  4. Quote remaining ${PYARROW_VERSION} / ${PILLOW_VERSION} in devel_env_setup.sh for consistency with the TORCH_TAG fix

# Torch
cd ${CURDIR}
TORCH_VERSION=$(grep -A1 '"torch"' pylock.toml | grep -Eo '\b[0-9\.]+\b')
TORCH_VERSION=$(python3 ./pylock_version.py torch --platform x86_64)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This resolves the x86_64 marker version inside a ppc64le block. It's correct — torch only has x86_64 markers in the pylock (no ppc64le wheel exists, it's built from source) — but a future reader will think it's a copy-paste bug.

A one-line comment would prevent a well-intentioned "fix":

# torch is pinned under x86_64 markers; we build the same version from source on ppc64le
TORCH_VERSION=$(python3 ./pylock_version.py torch --platform x86_64)

Same applies to the accelerate call on line 101.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@jiridanek, agreed. Resolving against the x86_64 marker is intentional for the ppc64le source-build path, and both Torch and Accelerate calls should document that rationale to avoid a misleading future “fix.”


✏️ Learnings added
Learnt from: jiridanek
Repo: red-hat-data-services/notebooks PR: 2519
File: jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh:51-51
Timestamp: 2026-07-21T16:31:44.220Z
Learning: In `jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh`, the ppc64le native-wheel build intentionally resolves Torch and Accelerate versions with `scripts/pylock_version.py --platform x86_64`: Torch has no ppc64le wheel lock entry because it is built from source on ppc64le, and the x86_64 marker selects the canonical pinned version. Future reviews should not treat these x86_64 platform arguments as copy-paste errors; explanatory comments at both call sites are appropriate.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed in e9e299c — added comments above the torch and accelerate --platform x86_64 lookups explaining that the pylock pins use x86_64 markers while we build/install the same version on ppc64le.

cd ${CURDIR}
# Pyarrow
PYARROW_VERSION=$(grep -A1 '"pyarrow"' pylock.toml | grep -Eo '\b[0-9\.]+\b')
PYARROW_VERSION=$(python3 ./pylock_version.py pyarrow --platform ppc64le)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This PR already fixed quoting for TORCH_TAG (nice), but PYARROW_VERSION here is still unquoted. Same for PILLOW_VERSION on line 90. Word splitting on a version string is unlikely but free to prevent:

git clone --recursive https://github.com/apache/arrow.git -b "apache-arrow-${PYARROW_VERSION}"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@jiridanek Agreed—good catch. Both the PyArrow and Pillow git clone -b arguments should be quoted, matching the existing TORCH_TAG handling:

git clone --recursive https://github.com/apache/arrow.git -b "apache-arrow-${PYARROW_VERSION}"
git clone --recursive https://github.com/python-pillow/Pillow.git -b "${PILLOW_VERSION}"

✏️ Learnings added
Learnt from: jiridanek
Repo: red-hat-data-services/notebooks PR: 2519
File: jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh:67-67
Timestamp: 2026-07-21T16:31:52.445Z
Learning: In `jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh`, quote dynamically expanded version/tag arguments passed to shell commands (including `git clone -b`) to prevent word splitting and preserve consistency with the quoted `TORCH_TAG` usage.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed in e9e299c — quoted apache-arrow-${PYARROW_VERSION} and "${PILLOW_VERSION}" in the git clone -b args.

if [ "$TARGETARCH" = "ppc64le" ]; then
ONNX_VERSION=$(python3 /tmp/pylock_version.py /tmp/pylock.toml onnx --platform ppc64le)
PYARROW_VERSION=$(python3 /tmp/pylock_version.py /tmp/pylock.toml pyarrow --platform ppc64le)
cat > /etc/profile.d/ppc64le.sh <<PROFILE_EOF

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The heredoc switched from <<'PROFILE_EOF' (literal, no expansion) to <<PROFILE_EOF (expanding) so ${ONNX_VERSION} and ${PYARROW_VERSION} are injected at build time. The \$ escapes on LD_LIBRARY_PATH and PATH are correct.

However, this is a subtle trap: adding any new $VAR line to this profile script in the future will silently expand at build time instead of at login time. Consider a comment at the heredoc marker:

    # NB: unquoted heredoc — escape $ for vars that must expand at login
    cat > /etc/profile.d/ppc64le.sh <<PROFILE_EOF

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@jiridanek, agreed. The proposed comment clearly documents the intentional unquoted-heredoc behavior and the need to escape variables that must remain runtime-expanded. This would be a worthwhile maintainability safeguard.


✏️ Learnings added
Learnt from: jiridanek
Repo: red-hat-data-services/notebooks PR: 2519
File: runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu:67-67
Timestamp: 2026-07-21T16:31:48.430Z
Learning: In `runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu`, the unquoted `PROFILE_EOF` heredoc that generates `/etc/profile.d/ppc64le.sh` intentionally expands the resolved ONNX and PyArrow versions during the image build. Any variables intended to expand when the profile is sourced must be escaped as `\$VAR`; document this behavior at the heredoc marker when modifying the block.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed in e9e299c — added # NB: unquoted heredoc — escape $ for vars that must expand at login above the PROFILE_EOF heredoc in both runtime datascience Dockerfiles.

assert "pylock_version.py" in text, f"{dockerfile.name} should copy pylock_version.py"
for package in ("onnx", "pyarrow"):
lookup = re.compile(rf"pylock_version\.py.*\b{package}\b", re.DOTALL)
assert lookup.search(text), f"{dockerfile.name} should resolve {package} via pylock_version.py"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

re.DOTALL makes . match newlines, so this succeeds if pylock_version.py appears on line 10 and onnx appears on line 200 in any unrelated context (e.g., a pip install onnx comment). Drop re.DOTALL to make the assertion meaningful:

lookup = re.compile(rf"pylock_version\.py\s+(?:\S+\s+)?{package}\b")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@jiridanek, agreed. re.DOTALL makes this test susceptible to unrelated later occurrences of onnx or pyarrow, so it does not prove that the resolver is invoked for that package.

  • Update tests/test_native_build_versions.py to replace the DOTALL-based lookup with the constrained same-command pattern:
    lookup = re.compile(rf"pylock_version\.py\s+(?:\S+\s+)?{package}\b")
  • This retains support for both supported CLI forms—pylock_version.py PACKAGE and pylock_version.py PYLOCK PACKAGE—while preventing cross-line unrelated matches.

✏️ Learnings added
Learnt from: jiridanek
Repo: red-hat-data-services/notebooks PR: 2519
File: tests/test_native_build_versions.py:33-33
Timestamp: 2026-07-21T16:31:54.516Z
Learning: In `tests/test_native_build_versions.py`, Dockerfile assertions that verify `scripts/pylock_version.py` resolves a package must bind the resolver path and package argument to the same command context. Do not use a `re.DOTALL` pattern such as `pylock_version\.py.*\b{package}\b`, because it can match unrelated later Dockerfile content; use a constrained pattern that allows the optional pylock path and then requires the package argument.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


Failed to handle agent chat message. Please try again.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed in e9e299c — dropped re.DOTALL and tightened the pattern to \bpylock_version\.py\s+(?:\S+\s+)?{package}\b so it only matches the resolver invocation.

Comment thread tests/test_native_build_versions.py Outdated
def test_pylock_pins_resolve_for_native_arches(image_dir: Path, pylock_version) -> None:
pylock = image_dir / "pylock.toml"
locked_version = pylock_version.locked_version
onnx_ppc64le = locked_version(pylock, "onnx", platform_machine="ppc64le")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This enforces that ppc64le and s390x pin the same pyarrow version. Is this an intended contract or an incidental coincidence? If they ever diverge intentionally (e.g., s390x needs a patched version), this test breaks. Consider removing this assertion or adding a comment explaining the invariant.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== test outline and relevant lines ==='
ast-grep outline tests/test_native_build_versions.py --items all || true
sed -n '1,120p' tests/test_native_build_versions.py

printf '%s\n' '=== PyArrow lock entries and platform markers ==='
for pylock in \
  jupyter/datascience/ubi9-python-3.12/pylock.toml \
  runtimes/datascience/ubi9-python-3.12/pylock.toml
do
  printf '\n--- %s ---\n' "$pylock"
  rg -n -i -C 5 'name\s*=\s*"pyarrow"|marker|version\s*=' "$pylock"
done

printf '%s\n' '=== Other references to the cross-architecture assertion ==='
rg -n -C 3 'pyarrow_(ppc64le|s390x)|ppc64le.*s390x|s390x.*ppc64le' \
  tests scripts jupyter runtimes

Length of output: 201226


@jiridanek, agreed. The lockfile currently uses one pyarrow 17.0.0 entry whose marker covers both architectures, but that is current data rather than an established cross-architecture contract. Since this PR adds platform-marker-aware resolution, the equality assertion would wrongly reject a future intentional s390x-specific pin.

I support removing the pyarrow_ppc64le == pyarrow_s390x assertion and retaining independent resolution/non-empty checks for each architecture.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed in e9e299c — removed the pyarrow_ppc64le == pyarrow_s390x equality check. The test now only asserts that each arch resolves a non-empty pin independently.

Comment thread scripts/pylock_version.py
f"package {package!r} not found in {pylock_path} "
f"for platform_machine={platform_machine!r} python={resolved_python!r}"
)
return packages[package]["version"]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Minor: the metavar tuple says ("PACKAGE", "PYLOCK") but the actual positional order is PYLOCK PACKAGE (pylock first when two args are given, per the match at line 178). This makes --help show them backwards:

positional arguments:
  PACKAGE     ...
  PYLOCK      ...

Should be metavar=("PYLOCK", "PACKAGE") or metavar=("ARG",).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline scripts/pylock_version.py --items all --type function --match '_parse_args|main'
nl -ba scripts/pylock_version.py | sed -n '165,215p'

Length of output: 696


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '172,215p' scripts/pylock_version.py

Length of output: 1720


@jiridanek, confirmed. scripts/pylock_version.py parses the two-argument form as PYLOCK PACKAGE, but Line 177 declares the metavars in reverse order. Updating it to the following will make --help consistent with the actual CLI contract:

metavar=("PYLOCK", "PACKAGE")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed in e9e299c — switched to metavar="ARG" so --help no longer shows the positionals backwards. The help text still documents the PACKAGE / PYLOCK PACKAGE contract.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline scripts/pylock_version.py --items all
ast-grep outline tests/test_native_build_versions.py --items all
ast-grep outline tests/conftest.py --items all

for f in \
  jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu \
  tests/test_native_build_versions.py \
  tests/conftest.py \
  scripts/pylock_version.py
do
  echo "===== $f ====="
  nl -ba "$f" | sed -n '1,260p'
done

echo "===== pylock package entries and architecture markers ====="
rg -n -A10 -B2 'name = "(torch|accelerate|pyarrow|onnx|pillow)"|marker' \
  jupyter/trustyai/ubi9-python-3.12/pylock.toml \
  jupyter/datascience/ubi9-python-3.12/pylock.toml \
  runtimes/datascience/ubi9-python-3.12/pylock.toml

Length of output: 2654


🏁 Script executed:

#!/bin/bash
set -euo pipefail

print_numbered() {
  local file="$1"
  echo "===== $file ====="
  sed -n '=' "$file" | sed 'N;s/\n/\t/'
}

for f in \
  jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu \
  tests/test_native_build_versions.py \
  tests/conftest.py \
  scripts/pylock_version.py
do
  print_numbered "$f"
done

echo "===== pylock package entries and architecture markers ====="
rg -n -A12 -B2 'name = "(torch|accelerate|pyarrow|onnx|pillow)"|marker' \
  jupyter/trustyai/ubi9-python-3.12/pylock.toml \
  jupyter/datascience/ubi9-python-3.12/pylock.toml \
  runtimes/datascience/ubi9-python-3.12/pylock.toml

Length of output: 201214


🏁 Script executed:

#!/bin/bash
set -euo pipefail

show_range() {
  local file="$1"
  local range="$2"
  echo "===== $file:$range ====="
  sed -n "${range}p" "$file" | awk '{ printf "%6d  %s\n", NR, $0 }'
}

show_range jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh '125,180'
show_range runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu '185,215'
show_range tests/test_native_build_versions.py '1,80'
show_range tests/conftest.py '1,60'
show_range scripts/pylock_version.py '40,215'

echo '===== relevant TrustyAI package tables ====='
awk '
  /^\[\[packages\]\]$/ {
    if (block ~ /^name = "(torch|accelerate|pyarrow|pillow)"$/m) print block
    block = ""
  }
  { block = block $0 ORS }
  END { if (block ~ /^name = "(torch|accelerate|pyarrow|pillow)"$/m) print block }
' jupyter/trustyai/ubi9-python-3.12/pylock.toml

Length of output: 201343


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '===== recovered cited source ranges ====='
sed -n '1,320p' /tmp/coderabbit-shell-logs/shell-output-GItlpj

echo '===== TrustyAI package marker summaries ====='
awk '
  /^\[\[packages\]\]$/ { name = version = marker = "" }
  /^name = "(torch|accelerate|pyarrow|pillow)"$/ { name = $0 }
  /^version = / { if (name != "") version = $0 }
  /^marker = / {
    if (name != "") {
      marker = $0
      print name ORS version ORS marker ORS ""
    }
  }
' jupyter/trustyai/ubi9-python-3.12/pylock.toml

Length of output: 22509


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '===== TrustyAI native-build constructs ====='
rg -n -C3 -- \
  'pylock_version\.py|TORCH_VERSION|PYARROW_VERSION|PILLOW_VERSION|WHEELS_DIR|git clone|uname -m|--platform x86_64' \
  jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh || true

echo '===== runtime profile heredoc and deferred expansions ====='
rg -n -C5 -- \
  'PROFILE_EOF|ppc64le\.sh|LD_LIBRARY_PATH|PYTHONPATH|(^|[^\\])\$\{?[A-Za-z_][A-Za-z0-9_]*\}?' \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu

echo '===== matching Konflux runtime profile construction, if any ====='
rg -n -C5 -- \
  'PROFILE_EOF|ppc64le\.sh|LD_LIBRARY_PATH|PYTHONPATH' \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu || true

Length of output: 17048


@jiridanek I independently verified the review against the current PR head and agree with the four prioritized actions:

  1. Document the x86_64 marker lookup in the ppc64le block. The TrustyAI lockfile has no ppc64le entries for Torch or Accelerate (only aarch64/x86_64), while PyArrow and Pillow do include ppc64le. A comment prevents an apparently incorrect “fix.”
  2. Remove re.DOTALL in tests/test_native_build_versions.py; the current expression can match unrelated occurrences across Dockerfile lines.
  3. Swap the CLI metavariables in scripts/pylock_version.py to ("PYLOCK", "PACKAGE").
  4. Quote the remaining shell expansions where appropriate:
    • -b "apache-arrow-${PYARROW_VERSION}"
    • -b "${PILLOW_VERSION}"
    • "${WHEELS_DIR}"/*.whl — quote the directory prefix while preserving glob expansion.

The unquoted PROFILE_EOF heredoc in both runtime Datascience Dockerfiles is currently correct, but a short comment warning that login-time variables must be escaped would make it safer to maintain.

I’d treat the PyArrow cross-architecture equality assertion and the implicit Python 3.12 fallback as lower-priority policy decisions. The importlib fixture is appropriate for the current non-package scripts/ layout; a global sys.path mutation would add test-wide state without a present need.


✏️ Learnings added
Learnt from: jiridanek
URL: https://github.com/red-hat-data-services/notebooks/pull/2519

Timestamp: 2026-07-21T16:31:27.807Z
Learning: In `jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh`, the ppc64le source-build path resolves Torch and Accelerate with `--platform x86_64` because `jupyter/trustyai/ubi9-python-3.12/pylock.toml` has no ppc64le marker entries for those packages; the selected lockfile versions are used to build compatible artifacts from source.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

jiridanek added a commit that referenced this pull request Jul 21, 2026
Document intentional x86_64 marker lookups on ppc64le, quote pyarrow
and pillow git refs, note the expanding ppc64le profile heredoc, tighten
Dockerfile pylock lookup regexes, stop requiring identical pyarrow pins
across arches, and fix CLI metavar display for --help.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jiridanek

Copy link
Copy Markdown
Member Author

Addressed the open review items in e9e299c:

  1. Comments for intentional --platform x86_64 lookups (torch/accelerate) inside the ppc64le block
  2. Quoted ${PYARROW_VERSION} / ${PILLOW_VERSION} git refs
  3. NB comment on the expanding ppc64le.sh profile heredoc
  4. Dropped re.DOTALL from Dockerfile pylock lookup regex
  5. Removed cross-arch pyarrow equality assertion
  6. Fixed CLI metavar (metavar="ARG") so --help display matches the contract

Skipped CodeRabbit’s Allure metadata suggestion for these unit/script tests (Allure is used in container e2e tests).

@coderabbitai recheck

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git show --format=fuller --stat --find-renames e9e299c87
git diff e9e299c87^ e9e299c87 -- \
  jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu \
  tests/test_native_build_versions.py \
  scripts/pylock_version.py

echo '===== TrustyAI ppc64le native-build block ====='
nl -ba jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh | sed -n '125,180p'

echo '===== Runtime Datascience profile heredocs ====='
rg -n -C5 -- 'PROFILE_EOF|ppc64le\.sh|LD_LIBRARY_PATH|PYTHONPATH' \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu

echo '===== Native version test ====='
nl -ba tests/test_native_build_versions.py | sed -n '1,100p'

echo '===== CLI argument declaration ====='
rg -n -C5 -- 'add_argument|metavar|nargs' scripts/pylock_version.py

Length of output: 8474


@jiridanek Rechecked e9e299c87 and confirmed the reported review items are addressed:

  • Intentional x86_64 marker lookups are documented for Torch and Accelerate on ppc64le.
  • PyArrow and Pillow git branch arguments are quoted.
  • Both runtime Datascience Dockerfiles document the expanding profile heredoc and login-time $ escaping requirement.
  • The Dockerfile lookup test no longer uses re.DOTALL and now matches resolver invocations on a single line.
  • The PyArrow cross-architecture equality assertion is removed; each architecture is resolved independently.
  • The CLI help metavariable is now the neutral ARG, consistent with the one- or two-argument contract.

Skipping Allure metadata is reasonable for these unit/script tests when that convention applies only to container E2E coverage. The focused source-range command was unavailable because nl is missing in the sandbox, but the complete commit diff was sufficient to verify the fixes.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@jiridanek

Copy link
Copy Markdown
Member Author

Addressed the open review items on #2519 in e9e299c87.

Fixed

Feedback Change
Comment --platform x86_64 in ppc64le block Comments above torch + accelerate lookups
Quote PYARROW_VERSION / PILLOW_VERSION Quoted git -b args
Expanding profile heredoc trap # NB: unquoted heredoc… in both runtime Dockerfiles
Drop re.DOTALL Tightened Dockerfile lookup regex
Cross-arch pyarrow equality Removed; resolve each arch independently
Backwards CLI metavar metavar="ARG"

Skipped (with reply)

  • Allure metadata on unit/script tests — Allure is for tests/containers/, not these
  • subtests nit — low value given short loops + clear assert messages

Already resolved earlier

  • --format / shell formatting consistency
  • _ALLOWED_NAMES aligned with marker_env (+ os_name)

Replies posted on each thread + a summary comment asking @coderabbitai recheck. Tests: 20 passed.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@jiridanek Thanks for the detailed follow-up. The listed fixes in e9e299c87 address the open review items, and the scope decisions for Allure metadata and subtests are reasonable. Noted that the focused test suite passes with 20 passed.

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

♻️ Duplicate comments (1)
tests/test_native_build_versions.py (1)

32-34: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Prevent newline-spanning resolver matches.

Removing re.DOTALL is insufficient because \s+ still matches newlines, so pylock_version.py on one line and onnx or pyarrow later can satisfy this assertion. Use [ \t]+ (and a non-newline optional argument pattern), or explicitly model shell continuations.

python - <<'PY'
import re

pattern = re.compile(r"\bpylock_version\.py\s+(?:\S+\s+)?onnx\b")
assert pattern.search("pylock_version.py\nunrelated\nonnx")
PY
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_native_build_versions.py` around lines 32 - 34, Update the
resolver regex in the test assertion around lookup so whitespace separators
cannot cross lines: replace \s+ with [ \t]+ and constrain the optional argument
to non-newline characters, or explicitly support shell continuations if
required. Preserve matching valid same-line resolver invocations for each
package while preventing unrelated lines from satisfying the assertion.
🧹 Nitpick comments (1)
tests/test_native_build_versions.py (1)

31-34: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use subtests for per-package assertions.

This loop performs independent assertions for onnx and pyarrow; wrap each iteration in subtests.test(...) so failures identify the package while allowing the remaining checks to run.

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

In `@tests/test_native_build_versions.py` around lines 31 - 34, Update the package
loop in the test to wrap each independent assertion in subtests.test(...) using
the current package as the identifier, so failures report whether onnx or
pyarrow failed while allowing the other assertion to run.

Source: Coding guidelines

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

Duplicate comments:
In `@tests/test_native_build_versions.py`:
- Around line 32-34: Update the resolver regex in the test assertion around
lookup so whitespace separators cannot cross lines: replace \s+ with [ \t]+ and
constrain the optional argument to non-newline characters, or explicitly support
shell continuations if required. Preserve matching valid same-line resolver
invocations for each package while preventing unrelated lines from satisfying
the assertion.

---

Nitpick comments:
In `@tests/test_native_build_versions.py`:
- Around line 31-34: Update the package loop in the test to wrap each
independent assertion in subtests.test(...) using the current package as the
identifier, so failures report whether onnx or pyarrow failed while allowing the
other assertion to run.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 19df70e4-ac42-411b-aada-7bc1e4dd608d

📥 Commits

Reviewing files that changed from the base of the PR and between 76a32de and e9e299c.

📒 Files selected for processing (5)
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py
  • tests/test_native_build_versions.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py

@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: 1

🤖 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 `@tests/test_native_build_versions.py`:
- Around line 42-44: Add descriptive failure messages to the three
locked_version assertions in the native build version tests, identifying both
the package and target architecture (ppc64le or s390x) for each assertion. Keep
the existing validation calls unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 696f7ebd-1dff-43a5-8847-00767126f8ad

📥 Commits

Reviewing files that changed from the base of the PR and between 76a32de and a1abfd3.

📒 Files selected for processing (5)
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py
  • tests/test_native_build_versions.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu

Comment thread tests/test_native_build_versions.py Outdated
@jiridanek

Copy link
Copy Markdown
Member Author

/build-konflux

@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: 1

🤖 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 `@semgrep.yaml`:
- Around line 1871-1873: Update the pattern-regex in the dangerous-command rule
so variable matches cannot cross shell command separators, especially &amp;&amp;
and ||, while preserving quote-aware handling and existing word-boundary
behavior. Ensure the regex treats these separators as command boundaries rather
than part of the matched command, and add regression coverage for commands such
as rm "$FILE" &amp;&amp; echo $OTHER and the equivalent || case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 3e1624f1-97fc-4e39-b4b4-3b2b8ae20026

📥 Commits

Reviewing files that changed from the base of the PR and between a1abfd3 and d953fc8.

📒 Files selected for processing (3)
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • semgrep.yaml
  • tests/test_native_build_versions.py

Comment thread semgrep.yaml Outdated
@jiridanek

Copy link
Copy Markdown
Member Author

/build-konflux

@jiridanek

Copy link
Copy Markdown
Member Author

Konflux — #2519 @ 429c811d3

Outcome Pipelines
Pass runtime-minimal, runtime-pytorch-cuda, runtime-pytorch-llmcompressor, runtime-tensorflow-cuda, codeserver
Fail (this PR) jupyter-datascience, runtime-datascience
Fail (unrelated) jupyter-minimal / pytorch / tensorflow / trustyai (cpu+cuda+rocm)
Timeout 4h runtime-pytorch-rocm, runtime-tensorflow-rocm

Datascience (real, PR-owned): ppc64le onnx-builderpip install -r requirements-min.txt builds numpy==1.26.0 from sdist → No BLAS library detected! / openblas found: NO. Same on jupyter + runtime. That is exactly what #2534 fixes.

Everything else: install_pdf_deps.sh can’t fetch TexLive from ftp.math.utah.edu — curl 28 (timeout) or 60 (SSL issuer). Not caused by the pylock/ONNX changes. ROCm runtimes hit the 4h PipelineRun limit.


Konflux — #2534 @ 94f1b11df

No PipelineRuns for the current tip (KubeArchive + live empty). Last /build-konflux was before the restack; tip never got a Konflux rebuild.

GHA subscription builds that did run fail the same TexLive curl path on amd64 (install_pdf_deps.sh exit 28); ppc64le/s390x jobs hit ~6h timeouts — not a signal on openblas yet.


Bottom line: The only stack-owned Konflux break on #2519 is datascience onnx/numpy needing OpenBLAS on ppc64le. Comment /build-konflux on #2534 (and optionally re-run datascience-only on #2519 after merge) to confirm the fix; ignore/retrigger the TexLive and ROCm timeout noise.

@openshift-ci

openshift-ci Bot commented Jul 22, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: ide-developer
Once this PR has been reviewed and has the lgtm label, please assign jstourac 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

@jiridanek
jiridanek force-pushed the fix/rhoai-2.25-ws3-arch-matrix branch from 429c811 to 8834a43 Compare July 22, 2026 06:56
@openshift-ci openshift-ci Bot removed the lgtm label Jul 22, 2026
@openshift-ci

openshift-ci Bot commented Jul 22, 2026

Copy link
Copy Markdown

New changes are detected. LGTM label has been removed.

@jiridanek

Copy link
Copy Markdown
Member Author

@coderabbitai review PR comments and whether they have been satisfactorily addressed

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="red-hat-data-services/notebooks"
pr="2519"

echo "===== PR `#2519` metadata ====="
gh pr view "$pr" --repo "$repo" --json number,state,isDraft,headRefName,headRefOid,baseRefName,mergeable,reviews,comments \
  --jq '{number,state,isDraft,headRefName,headRefOid,baseRefName,mergeable,reviews:[.reviews[]|{author:.author.login,state,submittedAt,body}],comments:[.comments[]|{author:.author.login,createdAt,body}]}'

echo "===== PR `#2519` review comments ====="
gh api --paginate "repos/$repo/pulls/$pr/comments?per_page=100" \
  --jq '.[] | {id, user:.user.login, path, line, original_line, created_at, body, in_reply_to_id}'

echo "===== PR `#2519` review threads and resolution state ====="
gh api graphql -F owner="red-hat-data-services" -F name="notebooks" -F number="$pr" -f query='
query($owner:String!, $name:String!, $number:Int!) {
  repository(owner:$owner, name:$name) {
    pullRequest(number:$number) {
      reviewThreads(first:100) {
        nodes {
          isResolved
          isOutdated
          path
          line
          comments(first:20) {
            nodes { author { login } body createdAt }
          }
        }
      }
    }
  }
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | {isResolved,isOutdated,path,line,comments:[.comments.nodes[]|{author:.author.login,body,createdAt}]}'

echo "===== PR `#2534` status ====="
gh pr view 2534 --repo "$repo" --json number,state,headRefName,headRefOid,mergeable,statusCheckRollup,comments \
  --jq '{number,state,headRefName,headRefOid,mergeable,statusCheckRollup:[.statusCheckRollup[]?|{name,conclusion,status}],comments:[.comments[]|{author:.author.login,createdAt,body}]}'

echo "===== relevant files at PR `#2519` head ====="
for file in \
  jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu \
  jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu \
  jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh \
  tests/test_native_build_versions.py \
  scripts/pylock_version.py
do
  echo "===== $file ====="
  rg -n -C3 -- 'requirements-min|openblas|OPENBLAS|onnx-builder|ONNX_VERSION|pylock_version|PROFILE_EOF|platform x86_64|metavar|DOTALL' "$file" || true
done

echo "===== commits affecting ppc64le ONNX requirements in `#2519` checkout ====="
git log --oneline -G 'requirements-min\.txt|openblas|OPENBLAS' -- \
  jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu \
  jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu \
  runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu

Length of output: 196281


@jiridanek I reviewed the live threads and the current #2519 head.

Source-review comments: satisfactorily addressed

The previously raised functional and maintainability items are present in the current source:

  • Intentional --platform x86_64 lookups for Torch and Accelerate on ppc64le are documented.
  • PyArrow and Pillow branch values are quoted.
  • Both runtime Datascience Dockerfiles document the expanding PROFILE_EOF heredoc and the need to escape login-time variables.
  • tests/test_native_build_versions.py now constrains the resolver lookup to one line using [ \t]+, and escapes the package name.
  • The cross-architecture PyArrow equality requirement is removed; each architecture is checked independently.
  • CLI help uses metavar="ARG", avoiding the incorrect/crashing tuple metavar.
  • The marker-environment-name, assertion-message, and Semgrep &&/|| boundary findings are resolved.
  • The Allure metadata finding was correctly withdrawn: the repository convention scopes that metadata to tests/containers/, not these unit/static-script tests.

Thread status

Four user-created inline threads are still unresolved in GitHub’s UI, although their requested changes are in the source and the replies document them:

  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh — x86_64 lookup rationale
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh — quoted PyArrow/Pillow refs
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu — heredoc warning
  • tests/test_native_build_versions.py — resolver regex

These can be manually resolved for review hygiene; I consider their content addressed.

Konflux/OpenBLAS result

The ppc64le ONNX failure is not fixed on #2519 itself: its ONNX builder still installs requirements-min.txt without provisioning openblas-devel, so the reported NumPy-from-sdist BLAS failure remains reproducible in principle.

#2534 contains the intended openblas-devel fix across the four relevant builder Dockerfiles. However, it is currently conflicting, and the current tip has no successful ppc64le Konflux validation (the available ppc64le GitHub build is cancelled). Therefore, the remediation is reasonable but not yet proven by the necessary architecture build.

Conclusion: all review-comment feedback on #2519 is satisfactorily addressed or validly withdrawn. The remaining release gate is validating and merging/restacking #2534, then obtaining a current-tip ppc64le Konflux build.

@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: 4

🧹 Nitpick comments (1)
jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu (1)

148-154: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Strip local-version suffixes before constructing Git refs.

The resolver can return PEP 440 versions containing +..., but these values are used directly in apache-arrow-* branches and v* tags. Strip the local suffix before forming both refs; current pins may be plain releases, but otherwise valid lock entries would fail checkout.

Proposed fix
 PYARROW_VERSION=$(python3 /tmp/pylock_version.py /tmp/pylock.toml pyarrow --platform "$TARGETARCH")
+PYARROW_VERSION="${PYARROW_VERSION%%+*}"
 ARROW_BRANCH="apache-arrow-${PYARROW_VERSION}"

 ONNX_VERSION=$(python3 /tmp/pylock_version.py /tmp/pylock.toml onnx --platform ppc64le)
+ONNX_VERSION="${ONNX_VERSION%%+*}"
 ONNX_TAG="v${ONNX_VERSION}"

Also applies to: 226-231

🤖 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 `@jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu` around lines 148
- 154, Update the version values used to construct the Apache Arrow branch and
tag refs in the PyArrow and ONNX checkout flows, stripping any PEP 440
local-version suffix beginning with “+” first. Apply the same normalization in
both the visible PyArrow flow and the corresponding ONNX flow so refs use only
the base release version.
🤖 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 `@jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh`:
- Line 43: Update the LD_LIBRARY_PATH export in devel_env_setup.sh to safely
handle an unset variable under set -u by using an unset-safe expansion, while
preserving the existing library directories and any preexisting value.

In `@tests/test_native_build_versions.py`:
- Around line 26-34: Update the test function in
tests/test_native_build_versions.py to use subtests for each Dockerfile,
forbidden-pattern assertion, pylock_version.py presence check, and
package-resolution check. Keep the existing validation logic and messages, but
scope each check with descriptive subtest contexts so failures in one Dockerfile
or package do not prevent the remaining checks from running.

In `@tests/unit/scripts/test_pylock_version.py`:
- Line 62: Update the plain assertions in
tests/unit/scripts/test_pylock_version.py at lines 62, 82, 87-96, and 127-128 to
include concise descriptive messages: identify the CLI invocation with
unexpected output, the expected os_name marker result, each marker expression
that evaluated unexpectedly, and the package/platform with its invalid resolved
version.
- Around line 16-23: Extend _DOCKERFILE_PIN_CASES with TrustyAI entries for
pillow on ppc64le and accelerate on x86_64, using the existing
jupyter/trustyai/ubi9-python-3.12/pylock.toml path so both devel_env_setup.sh
resolver lookups are covered.

---

Nitpick comments:
In `@jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu`:
- Around line 148-154: Update the version values used to construct the Apache
Arrow branch and tag refs in the PyArrow and ONNX checkout flows, stripping any
PEP 440 local-version suffix beginning with “+” first. Apply the same
normalization in both the visible PyArrow flow and the corresponding ONNX flow
so refs use only the base release version.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f7951670-b672-48de-b628-650031c94e16

📥 Commits

Reviewing files that changed from the base of the PR and between 429c811 and 8834a43.

📒 Files selected for processing (13)
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py
  • semgrep.yaml
  • tests/conftest.py
  • tests/test_native_build_versions.py
  • tests/unit/scripts/test_pylock_version.py
  • tests/unit/test_semgrep_shell_unquoted.py
🚧 Files skipped from review as they are similar to previous changes (8)
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • semgrep.yaml
  • tests/conftest.py
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • scripts/pylock_version.py
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu

Comment thread jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh Outdated
Comment thread tests/test_native_build_versions.py Outdated
Comment thread tests/unit/scripts/test_pylock_version.py
Comment thread tests/unit/scripts/test_pylock_version.py Outdated
jiridanek and others added 4 commits July 22, 2026 09:07
Read pinned package versions from pylock.toml with marker-aware
platform filtering using only the Python stdlib (tomllib + ast).

Co-authored-by: Cursor <cursoragent@cursor.com>
Wire datascience Dockerfiles to pylock_version.py, switch ONNX 1.22
ppc64le builds to requirements-min.txt, and cover Dockerfile pin lookups.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use pylock_version.py for torch/pyarrow/pillow/accelerate pins and quote
shell expansions so Semgrep shell-unquoted-var checks stay clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
Require word boundaries for dangerous commands and stop argument spans
at |, ||, ;, &, and && so matches stay on one logical command.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jiridanek
jiridanek force-pushed the fix/rhoai-2.25-ws3-arch-matrix branch from 8834a43 to 36c7a55 Compare July 22, 2026 09:07

@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: 1

🧹 Nitpick comments (4)
tests/unit/scripts/test_pylock_version.py (1)

119-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Run marker validation as subtests.

One invalid marker stops validation of every remaining marker. Use the existing with_subtests helper so failures identify each marker independently.

Proposed change
+from typing import TYPE_CHECKING
+
 import pytest
 
+from tests.with_subtests import with_subtests
+
+if TYPE_CHECKING:
+    from pytest import Subtests
+
 ...
-def test_native_build_pylocks_have_parseable_markers(pylock_version, pylock: Path) -> None:
+def test_native_build_pylocks_have_parseable_markers(
+    pylock_version, pylock: Path, subtests: Subtests
+) -> None:
 ...
-    for marker in markers:
+    `@with_subtests`(subtests, markers, msg="marker")
+    def _(marker: str) -> None:
         pylock_version.evaluate_marker(marker, env)

As per coding guidelines, “Use subtests from pytest-subtests plugin for iterating over multiple items with per-item assertions.”

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

In `@tests/unit/scripts/test_pylock_version.py` around lines 119 - 120, Update the
marker iteration around pylock_version.evaluate_marker to wrap each marker
validation in the existing with_subtests helper, so every marker runs
independently and failures identify the specific marker without stopping
subsequent validation.

Source: Coding guidelines

tests/unit/test_subtests.py (3)

1-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Place the unit test under the mirrored source path.

This test targets tests/with_subtests.py, but is located at tests/unit/test_subtests.py, which does not follow the required mirrored source layout. Move it to the repository’s corresponding mirrored path and retain the source-aligned test name.

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

In `@tests/unit/test_subtests.py` around lines 1 - 7, Move the unit test for
with_subtests from tests/unit/test_subtests.py to the repository’s mirrored path
corresponding to tests/with_subtests.py, preserving the source-aligned
test_subtests.py filename and its existing test contents.

Source: Coding guidelines


19-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add descriptive assertion messages.

The single assertions omit messages required by the test guidelines. Include the mode and expected item list so failures identify whether callback execution or final collection failed.

Also applies to: 30-32

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

In `@tests/unit/test_subtests.py` around lines 19 - 21, Update the assertions in
the subtest checks, including the assertion near the final collection validation
and the corresponding assertion around the additional referenced lines, to
include descriptive failure messages containing the relevant mode and expected
item list. Preserve the existing assertion conditions while making failures
distinguish callback execution from final collection validation.

Source: Coding guidelines


13-32: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Cover the failure path, not only successful items.

These tests would pass even if quiet=True failed to create a subtest for an exception or stopped before later items. Add a regression test that fails one item and verifies subsequent items execute and the failure is attributed to that item.

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

In `@tests/unit/test_subtests.py` around lines 13 - 32, Add a regression test
alongside test_with_subtests_quiet_runs_all_items that makes one input raise or
fail, then verifies later inputs still execute and the resulting failure is
attributed to the failing item’s subtest. Exercise the quiet=True path through
with_subtests and preserve the existing successful-item coverage.
🤖 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 `@tests/with_subtests.py`:
- Around line 41-46: Update the exception handling around f(item) in the subtest
execution flow to explicitly catch pytest.fail.Exception while continuing to let
KeyboardInterrupt and SystemExit propagate. Ensure failing items are re-raised
inside subtests so later items still execute, and add a regression test covering
one failing item followed by passing items.

---

Nitpick comments:
In `@tests/unit/scripts/test_pylock_version.py`:
- Around line 119-120: Update the marker iteration around
pylock_version.evaluate_marker to wrap each marker validation in the existing
with_subtests helper, so every marker runs independently and failures identify
the specific marker without stopping subsequent validation.

In `@tests/unit/test_subtests.py`:
- Around line 1-7: Move the unit test for with_subtests from
tests/unit/test_subtests.py to the repository’s mirrored path corresponding to
tests/with_subtests.py, preserving the source-aligned test_subtests.py filename
and its existing test contents.
- Around line 19-21: Update the assertions in the subtest checks, including the
assertion near the final collection validation and the corresponding assertion
around the additional referenced lines, to include descriptive failure messages
containing the relevant mode and expected item list. Preserve the existing
assertion conditions while making failures distinguish callback execution from
final collection validation.
- Around line 13-32: Add a regression test alongside
test_with_subtests_quiet_runs_all_items that makes one input raise or fail, then
verifies later inputs still execute and the resulting failure is attributed to
the failing item’s subtest. Exercise the quiet=True path through with_subtests
and preserve the existing successful-item coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c872fcab-d255-4ae7-b748-f6f37cb2cb07

📥 Commits

Reviewing files that changed from the base of the PR and between 8834a43 and 36c7a55.

📒 Files selected for processing (16)
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • pytest.ini
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py
  • semgrep.yaml
  • tests/conftest.py
  • tests/test_native_build_versions.py
  • tests/unit/scripts/test_pylock_version.py
  • tests/unit/test_semgrep_shell_unquoted.py
  • tests/unit/test_subtests.py
  • tests/with_subtests.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • tests/conftest.py
  • semgrep.yaml
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • scripts/pylock_version.py

Comment thread tests/with_subtests.py
Introduce a decorator that runs a multi-statement body as one subtest
per item, with quiet mode that only opens a subtest context on failure.
Use it for native Dockerfile/pylock pin coverage and pin subtests
verbosity to 0 by default.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jiridanek
jiridanek force-pushed the fix/rhoai-2.25-ws3-arch-matrix branch from 36c7a55 to cba986d Compare July 22, 2026 09:18

@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: 2

🧹 Nitpick comments (1)
tests/unit/test_subtests.py (1)

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

Add descriptive messages to bare assertions.

The tests/**/*.py guidelines require descriptive messages for single assert statements. Add assertion messages throughout these tests so failures identify the failing item or captured output.

Suggested change
-        assert u < 3
+        assert u < 3, f"unexpected item: {u}"
...
-    assert seen == [0, 1, 2]
+    assert seen == [0, 1, 2], f"items seen: {seen}"
...
-                assert seen == [0, 1, 2]
+                assert seen == [0, 1, 2], f"items seen: {seen}"
...
-    assert "Failed: intentional quiet-mode fail" in out
+    assert "Failed: intentional quiet-mode fail" in out, out
-    assert "SUBFAILED(item=0)" in out
+    assert "SUBFAILED(item=0)" in out, out
-    assert "assert seen ==" not in out
+    assert "assert seen ==" not in out, out
-    assert "assert [0] ==" not in out
+    assert "assert [0] ==" not in out, out

As per coding guidelines, single assertions in tests/**/*.py must include descriptive messages.

Also applies to: 24-24, 33-33, 35-35, 55-55, 63-66

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

In `@tests/unit/test_subtests.py` at line 22, Add descriptive failure messages to
every bare assertion in tests/unit/test_subtests.py, including the assertions
around u, captured output, and the items referenced at the specified locations.
Ensure each message identifies the failing value or expected condition while
preserving the existing assertion logic.

Source: Coding guidelines

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

Inline comments:
In `@tests/unit/scripts/test_pylock_version.py`:
- Around line 119-120: Update the marker iteration in the test to use the
pytest-subtests fixture, wrapping each pylock_version.evaluate_marker(marker,
env) call in subtests.test(...) with the current marker identified, so every
marker is validated independently and later failures remain visible.

In `@tests/unit/test_subtests.py`:
- Line 7: Update the exception handler in with_subtests to use tuple syntax when
catching Exception and pytest.fail.Exception, replacing the invalid
comma-separated form. Preserve the existing handling behavior so the helper
imports and runs under Python 3.14.

---

Nitpick comments:
In `@tests/unit/test_subtests.py`:
- Line 22: Add descriptive failure messages to every bare assertion in
tests/unit/test_subtests.py, including the assertions around u, captured output,
and the items referenced at the specified locations. Ensure each message
identifies the failing value or expected condition while preserving the existing
assertion logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 08759ca3-5b85-4e80-9af7-620076a0eff7

📥 Commits

Reviewing files that changed from the base of the PR and between 8834a43 and cba986d.

📒 Files selected for processing (16)
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.cpu
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/trustyai/ubi9-python-3.12/devel_env_setup.sh
  • pytest.ini
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py
  • semgrep.yaml
  • tests/conftest.py
  • tests/test_native_build_versions.py
  • tests/unit/scripts/test_pylock_version.py
  • tests/unit/test_semgrep_shell_unquoted.py
  • tests/unit/test_subtests.py
  • tests/with_subtests.py
🚧 Files skipped from review as they are similar to previous changes (11)
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.cpu
  • pytest.ini
  • jupyter/trustyai/ubi9-python-3.12/Dockerfile.konflux.cpu
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.cpu
  • tests/with_subtests.py
  • tests/conftest.py
  • jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu
  • semgrep.yaml
  • runtimes/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu
  • scripts/pylock_version.py

Comment on lines +119 to +120
for marker in markers:
pylock_version.evaluate_marker(marker, env)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Run each marker validation as a subtest.

One invalid marker aborts the loop and hides later failures. Wrap each evaluation in subtests.test(...).

Suggested fix
-def test_native_build_pylocks_have_parseable_markers(pylock_version, pylock: Path) -> None:
+def test_native_build_pylocks_have_parseable_markers(pylock_version, pylock: Path, subtests) -> None:
 ...
     env = pylock_version.marker_env(python_minor="3.12", platform_machine="x86_64")
     for marker in markers:
-        pylock_version.evaluate_marker(marker, env)
+        with subtests.test(msg="marker", marker=marker):
+            pylock_version.evaluate_marker(marker, env)

As per coding guidelines, “Use subtests from pytest-subtests plugin for iterating over multiple items with per-item assertions.”

📝 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
for marker in markers:
pylock_version.evaluate_marker(marker, env)
def test_native_build_pylocks_have_parseable_markers(pylock_version, pylock: Path, subtests) -> None:
...
env = pylock_version.marker_env(python_minor="3.12", platform_machine="x86_64")
for marker in markers:
with subtests.test(msg="marker", marker=marker):
pylock_version.evaluate_marker(marker, env)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/scripts/test_pylock_version.py` around lines 119 - 120, Update the
marker iteration in the test to use the pytest-subtests fixture, wrapping each
pylock_version.evaluate_marker(marker, env) call in subtests.test(...) with the
current marker identified, so every marker is validated independently and later
failures remain visible.

Source: Coding guidelines

Comment thread tests/unit/test_subtests.py
@jiridanek
jiridanek merged commit 93db8d4 into rhoai-2.25 Jul 22, 2026
37 of 43 checks passed
@jiridanek
jiridanek deleted the fix/rhoai-2.25-ws3-arch-matrix branch July 22, 2026 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants