Skip to content

RHAIENG-2853: Hermetic build for ROCm TensorFlow Jupyter image#3336

Merged
ysok merged 1 commit intoopendatahub-io:mainfrom
ysok-opendatahub-io:odh-RHAIENG-2853-jupyter-rocm-tensorflow
Apr 16, 2026
Merged

RHAIENG-2853: Hermetic build for ROCm TensorFlow Jupyter image#3336
ysok merged 1 commit intoopendatahub-io:mainfrom
ysok-opendatahub-io:odh-RHAIENG-2853-jupyter-rocm-tensorflow

Conversation

@ysok
Copy link
Copy Markdown
Contributor

@ysok ysok commented Apr 10, 2026

RHAIENG-2853: Hermetic build for ROCm TensorFlow Jupyter image

Description

Make the ROCm TensorFlow Jupyter notebook image build hermetically (prefetched mongocli, RPMs, and Python wheels via Cachi2), wire Tekton to run with hermetic prefetch, align requirements.rocm.txt with the lockfile index, and add the usual prefetch-input symlink so local prefetch scripts work.

How Has This Been Tested?

Self checklist (all need to be checked):

  • Ensure that you have run make test (gmake on macOS) before asking for review
  • Changes to everything except Dockerfile.konflux files should be done in odh/notebooks and automatically synced to rhds/notebooks. For Konflux-specific changes, modify Dockerfile.konflux files directly in rhds/notebooks as these require special attention in the downstream repository and flow to the upcoming RHOAI release.

Merge criteria:

  • The commits are squashed in a cohesive manner and have meaningful messages.
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has manually tested the changes and verified that the changes work

Summary by CodeRabbit

  • New Features

    • Hermetic prefetching of gomod, RPM, pip and generic artifacts for reproducible/offline image builds.
    • Requirements-generation mode that auto-selects index behavior based on project context.
  • Chores

    • Increased CPU/memory allocations for prefetch and build steps to improve reliability and speed.
    • Docker image builds now consume prefetched pip/RPM artifacts; added Python tooling dependencies (uv, micropipenv[toml]) for hermetic installs.
    • Requirements converter enhanced to handle direct‑URL locks and include sdist hashes; CLI uses embedded default index when no index is provided.

@openshift-ci openshift-ci Bot requested review from dibryant and jiridanek April 10, 2026 01:55
@github-actions
Copy link
Copy Markdown
Contributor

@ysok — This PR is from a fork.
The build-rhoai CI job was skipped because subscription
builds (RHEL, AIPCC) need secrets unavailable to forks.
ODH builds and code quality checks still ran.

Recommended: Push your branch to the main repo for full CI:

git remote add upstream https://github.com/opendatahub-io/notebooks.git
git push upstream HEAD:ysok/your-branch-name

Then open a new PR from that branch.

No push access? A maintainer will cherry-pick and test your changes.

See CONTRIBUTING.md for details.

@github-actions github-actions Bot added the review-requested GitHub Bot creates notification on #pr-review-ai-ide-team slack channel label Apr 10, 2026
@openshift-ci openshift-ci Bot added size/xxl and removed size/xxl labels Apr 10, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

PipelineRun YAMLs enable hermetic prefetching, change build-platform to a larger instance, add a prefetch-dependencies task with explicit compute requests/limits, and add step-level resource overrides for the image build step. Dockerfiles add ARGs (TARGETARCH, PYLOCK_FLAVOR), switch to Cachi2-prefetched gomod/pip/rpm inputs, import RPM GPG keys, change pip installs to use local wheel caches (--no-index) and disable pylock hash verification, and adjust mongocli build/copy behavior. Added a prefetch-input pointer file, added uv and micropipenv[toml] to pyproject, and extended pylock-to-requirements plus the lockfile generator to extract default index URLs and support public vs rh-index modes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Actionable Issues

  • Ensure RPM GPG verification fails the build on signature or key mismatch; do not allow fallback to unsigned packages. (CWE-347)
  • Restore cryptographic integrity for pip installs: re-enable hash verification or use signed artifacts; current --no-index --no-verify-hashes permits undetected tampering. (CWE-327, CWE-347)
  • Enforce provenance verification for Cachi2 prefetched caches (gomod, pip, RPMs): validate signatures/checksums before use and fail on mismatch to mitigate supply-chain injection. (CWE-612)
  • Hard-fail or require explicit operator confirmation when extract_default_index_from_pylock finds no clear index; strengthen regex/parsing and add unit tests for truncated/malformed files. (CWE-436)
  • When selecting public-index via PUBLIC_INDEX_PROJECTS, compare resolved realpaths and reject symlink/relative-path tricks to prevent path traversal or mode escalation. Add tests for symlinked/relative path cases. (CWE-59)
  • Whitelist allowed PYLOCK_FLAVOR and TARGETARCH values when passed from CI; reject unknown values to prevent selection of untrusted lockfiles or incompatible binaries. (CWE-426)
  • Validate and enforce CI-level resource quotas for the added high CPU/memory requests so oversized requests cannot starve other workloads; ensure admission control honors these overrides. (CWE-770)
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description includes a summary of changes and the JIRA reference, but the testing section and merge criteria checklist items are left unchecked/incomplete. Complete the self-checklist items (mark as checked if applicable) and provide specific testing instructions in the 'How Has This Been Tested?' section before merge.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title uses imperative mood ('Hermetic build') and includes the required JIRA ticket reference (RHAIENG-2853) in the correct format.
Branch Prefix Policy ✅ Passed PR title 'RHAIENG-2853: Hermetic build for ROCm TensorFlow Jupyter image' complies with main branch requirements and does not start with prohibited branch prefixes.

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


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

❤️ Share

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

@openshift-ci openshift-ci Bot added size/xxl and removed size/xxl labels Apr 10, 2026
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 3.59%. Comparing base (4f17bb6) to head (a245e57).

Additional details and impacted files

Impacted file tree graph

@@          Coverage Diff          @@
##            main   #3336   +/-   ##
=====================================
  Coverage   3.59%   3.59%           
=====================================
  Files         29      29           
  Lines       3310    3310           
  Branches     527     527           
=====================================
  Hits         119     119           
  Misses      3189    3189           
  Partials       2       2           
Flag Coverage Δ
python 3.59% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4f17bb6...a245e57. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm (1)

1-35: Hermetic mongocli build stage mirrors Konflux variant.

Configuration is consistent. Consider extracting shared stages to reduce duplication between Dockerfile.rocm and Dockerfile.konflux.rocm if divergence is not expected.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm` around lines 1 -
35, The mongocli-builder stage (FROM
registry.access.redhat.com/ubi9/go-toolset:1.25.8-1775491036 AS mongocli-builder
plus the COPY prefetch-input/mongocli, WORKDIR /tmp/mongocli-src and the
hermetic RUN block) is duplicated across Dockerfile.rocm and
Dockerfile.konflux.rocm; extract this shared build stage into a single reusable
artifact to avoid duplication—either move the mongocli builder stage into a
separate included Docker snippet or create a common base image (e.g., a shared
image built from the mongocli-builder stage) and replace the inline stage in
both Dockerfiles with `FROM <shared-mongocli-builder> AS mongocli-builder` (or
an `INCLUDE`/`COPY` of the shared stage), ensuring the hermetic env exports,
CGO/GOPROXY settings, and binary output path remain identical.
scripts/lockfile-generators/helpers/pylock-to-requirements.py (1)

42-54: Regex may over-match into adjacent content.

\S+ will greedily consume characters until whitespace, potentially capturing trailing punctuation or comment markers if the lockfile format varies. Consider using a more restrictive URL pattern or anchoring to expected delimiters.

-_DEFAULT_INDEX_RE = re.compile(r"--default-index=(https?://\S+)")
+_DEFAULT_INDEX_RE = re.compile(r"--default-index=['\"]?(https?://[^\s'\"]+)['\"]?")

This pattern explicitly handles optional quotes and stops at quote/whitespace boundaries.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/lockfile-generators/helpers/pylock-to-requirements.py` around lines
42 - 54, The regex _DEFAULT_INDEX_RE in extract_default_index_from_pylock is too
permissive (uses \S+); tighten it to explicitly capture an optional surrounding
quote and a URL that stops at whitespace or quote characters (e.g. match
optional quote, then https?:// followed by [^\s'"]+, then the matching quote)
and update the extraction to return the URL capture group (not the whole match)
with trailing quotes already excluded; modify _DEFAULT_INDEX_RE and the return
logic in extract_default_index_from_pylock to use that URL group.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm`:
- Around line 167-172: The pip install invocation in the Dockerfile (the UV_*
environment variables line invoking "uv pip install") is using the insecure flag
"--no-verify-hashes"; remove "--no-verify-hashes" from that command so pip
enforces the --hash checks produced by pylock-to-requirements.py, and if hash
verification then fails investigate and fix the Cachi2 wheel renaming/prefetch
process (or adjust --find-links layout) rather than disabling verification.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm`:
- Around line 168-174: The uv pip install invocation includes the dangerous
--no-verify-hashes flag which bypasses hash verification; update the
Dockerfile.rocm UV_NO_CACHE... uv pip install command to remove
--no-verify-hashes and enable pip's hash checking instead (e.g., ensure
requirements.txt contains per-package hashes and pass --require-hashes or simply
omit the bypass flag) so package integrity is verified during the hermetic
install; locate the UV_NO_CACHE=true UV_LINK_MODE=copy
UV_PREVIEW_FEATURES=pylock uv pip install line and change the flags accordingly.

---

Nitpick comments:
In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm`:
- Around line 1-35: The mongocli-builder stage (FROM
registry.access.redhat.com/ubi9/go-toolset:1.25.8-1775491036 AS mongocli-builder
plus the COPY prefetch-input/mongocli, WORKDIR /tmp/mongocli-src and the
hermetic RUN block) is duplicated across Dockerfile.rocm and
Dockerfile.konflux.rocm; extract this shared build stage into a single reusable
artifact to avoid duplication—either move the mongocli builder stage into a
separate included Docker snippet or create a common base image (e.g., a shared
image built from the mongocli-builder stage) and replace the inline stage in
both Dockerfiles with `FROM <shared-mongocli-builder> AS mongocli-builder` (or
an `INCLUDE`/`COPY` of the shared stage), ensuring the hermetic env exports,
CGO/GOPROXY settings, and binary output path remain identical.

In `@scripts/lockfile-generators/helpers/pylock-to-requirements.py`:
- Around line 42-54: The regex _DEFAULT_INDEX_RE in
extract_default_index_from_pylock is too permissive (uses \S+); tighten it to
explicitly capture an optional surrounding quote and a URL that stops at
whitespace or quote characters (e.g. match optional quote, then https?://
followed by [^\s'"]+, then the matching quote) and update the extraction to
return the URL capture group (not the whole match) with trailing quotes already
excluded; modify _DEFAULT_INDEX_RE and the return logic in
extract_default_index_from_pylock to use that URL group.
🪄 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: Repository YAML (base), Central YAML (inherited), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 20be49e3-5c35-4ee9-9cfd-d955c0eaba0d

📥 Commits

Reviewing files that changed from the base of the PR and between 99e07e7 and 93564ae.

📒 Files selected for processing (9)
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-pull-request.yaml
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-push.yaml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm
  • jupyter/rocm/tensorflow/ubi9-python-3.12/prefetch-input
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pylock.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pyproject.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/requirements.rocm.txt
  • scripts/lockfile-generators/helpers/pylock-to-requirements.py
👮 Files not reviewed due to content moderation or server errors (1)
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pylock.toml

Comment thread jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm
Comment thread jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm
@ysok ysok force-pushed the odh-RHAIENG-2853-jupyter-rocm-tensorflow branch from 93564ae to aeb1041 Compare April 10, 2026 02:49
@openshift-ci openshift-ci Bot added size/xxl and removed size/xxl labels Apr 10, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm`:
- Line 126: The COPY instruction currently uses an explicit filename destination
("COPY --from=mongocli-builder /tmp/mongocli /opt/app-root/bin/mongocli");
update it to use the trailing-slash directory convention to match other
Dockerfiles (e.g., replace the destination with "/opt/app-root/bin/") so the
line becomes "COPY --from=mongocli-builder /tmp/mongocli /opt/app-root/bin/"
ensuring consistency with the datascience, pytorch, and rocm variants and
predictable behavior when copying the mongocli binary.
🪄 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: Repository YAML (base), Central YAML (inherited), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 1f40afed-d8b0-4a1c-8ea5-61e5622fcf94

📥 Commits

Reviewing files that changed from the base of the PR and between 93564ae and aeb1041.

📒 Files selected for processing (10)
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-pull-request.yaml
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-push.yaml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm
  • jupyter/rocm/tensorflow/ubi9-python-3.12/prefetch-input
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pylock.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pyproject.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/requirements.rocm.txt
  • scripts/lockfile-generators/create-requirements-lockfile.sh
  • scripts/lockfile-generators/helpers/pylock-to-requirements.py
✅ Files skipped from review due to trivial changes (1)
  • jupyter/rocm/tensorflow/ubi9-python-3.12/prefetch-input
🚧 Files skipped from review as they are similar to previous changes (3)
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pyproject.toml
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-pull-request.yaml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm
👮 Files not reviewed due to content moderation or server errors (1)
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pylock.toml

# Copy dynamically-linked mongocli built in earlier build stage
COPY --from=mongocli-builder /tmp/mongocli /opt/app-root/bin/
### END Copy mongocli from builder
COPY --from=mongocli-builder /tmp/mongocli /opt/app-root/bin/mongocli
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if other Dockerfiles use similar mongocli copy patterns
rg -n 'COPY.*mongocli' --type dockerfile

Repository: opendatahub-io/notebooks

Length of output: 102


🏁 Script executed:

#!/bin/bash
# Find the specific Dockerfile and view context around line 126
find . -name "Dockerfile.rocm" -o -name "*Dockerfile*" | grep -E "jupyter/rocm/tensorflow" | head -5

Repository: opendatahub-io/notebooks

Length of output: 193


🏁 Script executed:

#!/bin/bash
# Search for COPY patterns with mongocli in any Dockerfile-like files
find . -name "Dockerfile*" -o -name "dockerfile*" | xargs grep -l "mongocli" 2>/dev/null

Repository: opendatahub-io/notebooks

Length of output: 937


🏁 Script executed:

#!/bin/bash
# Search for similar COPY --from patterns with binary destinations
find . \( -name "Dockerfile*" -o -name "dockerfile*" \) | xargs grep -n "COPY --from.*bin/" 2>/dev/null | head -20

Repository: opendatahub-io/notebooks

Length of output: 2265


🏁 Script executed:

#!/bin/bash
# View the target Dockerfile around line 126
sed -n '120,135p' ./jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm | cat -n

Repository: opendatahub-io/notebooks

Length of output: 772


🏁 Script executed:

#!/bin/bash
# Compare all mongocli COPY patterns in detail
echo "=== Patterns with explicit filename (no trailing slash) ===" && \
grep -n "COPY --from=mongocli-builder.*bin/mongocli" ./jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm ./jupyter/pytorch+llmcompressor/ubi9-python-3.12/Dockerfile.cuda && \
echo "" && \
echo "=== Patterns with directory (trailing slash) ===" && \
grep -n "COPY --from=mongocli-builder.*bin/$" ./jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu ./jupyter/datascience/ubi9-python-3.12/Dockerfile.konflux.cpu

Repository: opendatahub-io/notebooks

Length of output: 697


Standardize mongocli destination syntax across Dockerfiles.

The COPY destination uses explicit filename /opt/app-root/bin/mongocli (no trailing slash), but other Dockerfiles in the codebase copy mongocli to /opt/app-root/bin/ (with trailing slash). Adopt one convention consistently—either explicit filename format or trailing slash directory convention—to avoid confusion and maintain predictability. The datascience Dockerfile uses the trailing slash approach; align rocm and pytorch+llmcompressor variants to match.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm` at line 126, The
COPY instruction currently uses an explicit filename destination ("COPY
--from=mongocli-builder /tmp/mongocli /opt/app-root/bin/mongocli"); update it to
use the trailing-slash directory convention to match other Dockerfiles (e.g.,
replace the destination with "/opt/app-root/bin/") so the line becomes "COPY
--from=mongocli-builder /tmp/mongocli /opt/app-root/bin/" ensuring consistency
with the datascience, pytorch, and rocm variants and predictable behavior when
copying the mongocli binary.

@ysok ysok force-pushed the odh-RHAIENG-2853-jupyter-rocm-tensorflow branch from aeb1041 to ae4b775 Compare April 10, 2026 03:15
@openshift-ci openshift-ci Bot added size/xxl and removed size/xxl labels Apr 10, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm (1)

143-163: ⚠️ Potential issue | 🟡 Minor

Add default value for PYLOCK_FLAVOR to prevent build failures from omitted argument.

If this ARG is omitted, line 162 resolves to requirements..txt and the build fails before dependency installation. All callers currently provide this through build-args/rocm.conf via the Makefile, but a safe default protects against direct builds or non-standard invocations.

Patch
-ARG PYLOCK_FLAVOR
+ARG PYLOCK_FLAVOR=rocm
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm` around lines 143 -
163, The Dockerfile defines ARG PYLOCK_FLAVOR but no default, causing COPY
${TENSORFLOW_SOURCE_CODE}/requirements.${PYLOCK_FLAVOR}.txt to expand to
requirements..txt when the build-arg is omitted; set a sensible default by
changing the ARG declaration (ARG PYLOCK_FLAVOR=rocm) so COPY references a valid
file (referencing ARG PYLOCK_FLAVOR and the COPY line) and prevent build
failures for direct/non-standard builds.
🧹 Nitpick comments (1)
scripts/lockfile-generators/helpers/pylock-to-requirements.py (1)

86-99: Minor defensive gap: hashes field type not validated.

If a malformed pylock has hashes as a non-dict (string, list, None), sdist.get("hashes", {}).items() raises AttributeError. Unlikely with uv-generated files, but inconsistent with the isinstance(sdist, dict) pattern applied to the parent.

Defensive check (optional)
         sdist = pkg.get("sdist")
-        if isinstance(sdist, dict):
-            for algo, digest in sdist.get("hashes", {}).items():
+        if isinstance(sdist, dict) and isinstance(sdist.get("hashes"), dict):
+            for algo, digest in sdist["hashes"].items():
                 hashes.append(f"--hash={algo}:{digest}")
         archive = pkg.get("archive")
-        if isinstance(archive, dict):
-            for algo, digest in archive.get("hashes", {}).items():
+        if isinstance(archive, dict) and isinstance(archive.get("hashes"), dict):
+            for algo, digest in archive["hashes"].items():
                 hashes.append(f"--hash={algo}:{digest}")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/lockfile-generators/helpers/pylock-to-requirements.py` around lines
86 - 99, The loops that assume a "hashes" mapping (for wheel entries, sdist and
archive) call .items() on whl.get("hashes", {}), sdist.get("hashes", {}), and
archive.get("hashes", {}) without verifying the returned value is a dict; update
those loops in the pylock-to-requirements logic so you first retrieve the hashes
value (e.g., h = whl.get("hashes")), check isinstance(h, dict) before iterating
h.items(), and do the same defensive isinstance(h, dict) check for
sdist.get("hashes") and archive.get("hashes") to skip non-dict/malformed values
instead of raising AttributeError.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm`:
- Around line 143-163: The Dockerfile defines ARG PYLOCK_FLAVOR but no default,
causing COPY ${TENSORFLOW_SOURCE_CODE}/requirements.${PYLOCK_FLAVOR}.txt to
expand to requirements..txt when the build-arg is omitted; set a sensible
default by changing the ARG declaration (ARG PYLOCK_FLAVOR=rocm) so COPY
references a valid file (referencing ARG PYLOCK_FLAVOR and the COPY line) and
prevent build failures for direct/non-standard builds.

---

Nitpick comments:
In `@scripts/lockfile-generators/helpers/pylock-to-requirements.py`:
- Around line 86-99: The loops that assume a "hashes" mapping (for wheel
entries, sdist and archive) call .items() on whl.get("hashes", {}),
sdist.get("hashes", {}), and archive.get("hashes", {}) without verifying the
returned value is a dict; update those loops in the pylock-to-requirements logic
so you first retrieve the hashes value (e.g., h = whl.get("hashes")), check
isinstance(h, dict) before iterating h.items(), and do the same defensive
isinstance(h, dict) check for sdist.get("hashes") and archive.get("hashes") to
skip non-dict/malformed values instead of raising AttributeError.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 49f97759-e996-4fc1-94b4-b4e94b6131ea

📥 Commits

Reviewing files that changed from the base of the PR and between aeb1041 and ae4b775.

📒 Files selected for processing (10)
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-pull-request.yaml
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-push.yaml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm
  • jupyter/rocm/tensorflow/ubi9-python-3.12/prefetch-input
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pylock.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pyproject.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/requirements.rocm.txt
  • scripts/lockfile-generators/create-requirements-lockfile.sh
  • scripts/lockfile-generators/helpers/pylock-to-requirements.py
✅ Files skipped from review due to trivial changes (2)
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pyproject.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/prefetch-input
🚧 Files skipped from review as they are similar to previous changes (2)
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-push.yaml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm
👮 Files not reviewed due to content moderation or server errors (1)
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pylock.toml

@ysok ysok force-pushed the odh-RHAIENG-2853-jupyter-rocm-tensorflow branch from ae4b775 to 6ce1152 Compare April 10, 2026 03:35
@openshift-ci openshift-ci Bot added size/xxl and removed size/xxl labels Apr 10, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm (2)

1-2: Unused ARG TARGETARCH declaration.

Same issue as Dockerfile.konflux.rocm - declared but not referenced.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm` around lines 1 - 2,
Remove the unused Docker build argument declaration ARG TARGETARCH from the
Dockerfile.rocm to match other files; locate the top-level ARG TARGETARCH line
in Dockerfile.rocm and delete it (or reference it only if you later add logic
that uses TARGETARCH), ensuring there are no remaining references to TARGETARCH
in this file.

79-87: Redundant GPG key imports across build stages.

Both rocm-base (lines 47-50) and rocm-jupyter-minimal (lines 79-83) import the same GPG keys. Since rocm-jupyter-minimal inherits from rocm-base, the keys are already imported. This adds ~3 extra layers.

Proposed fix - remove redundant imports in child stage
-# [HERMETIC] Import GPG keys for prefetched RPM verification.
-# CentOS key imported only if prefetched (present in Dockerfile.cpu; may be absent in Konflux).
-RUN rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official || true
-RUN rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-EPEL-9 || true
-RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
+# GPG keys already imported in rocm-base stage
+# EPEL-9 key needed only if EPEL packages are installed in this stage
+RUN rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-EPEL-9 || true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm` around lines 79 -
87, The rocm-jupyter-minimal stage duplicates GPG key imports already performed
in the rocm-base stage; remove the three redundant RUN rpm --import lines in the
rocm-jupyter-minimal stage (the ones importing RPM-GPG-KEY-CentOS-Official,
RPM-GPG-KEY-EPEL-9 and RPM-GPG-KEY-redhat-release) so the keys remain imported
only in rocm-base, leaving the subsequent COPY prefetch-input/... lines intact;
ensure no other child stages re-import those same keys.
jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm (2)

1-2: Unused ARG TARGETARCH declaration.

TARGETARCH is declared but not referenced anywhere in the Dockerfile. If it's intended for future use or multi-arch builds, add a comment. Otherwise, remove it to avoid confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm` around
lines 1 - 2, The Dockerfile declares ARG TARGETARCH but never uses it; either
remove the unused ARG TARGETARCH declaration or document its intended purpose
with an inline comment (e.g., for future multi-arch builds) so it's not
confusing—locate the ARG TARGETARCH line in the Dockerfile.konflux.rocm and
either delete that ARG or replace it with a short comment explaining why
TARGETARCH is kept for future use.

47-50: GPG key import failures silently ignored may mask prefetch issues.

Using || true on GPG key imports means a missing or corrupted key file won't fail the build. While the CentOS key may legitimately be absent, failing silently could allow RPM installations without proper signature verification.

Consider logging when keys are missing:

Proposed fix
-RUN rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official || true
+RUN rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official || echo "WARN: CentOS GPG key not found, skipping"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm` around
lines 47 - 50, The CentOS GPG import currently uses a silent ignore ("RUN rpm
--import /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official || true") which
can hide missing/corrupt keys; change this to explicitly check for the file
before importing and log a clear warning if it's absent, e.g. test for the
presence of /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official and only run
rpm --import if present, printing a descriptive message when it isn't, while
keeping the redhat import (rpm --import
/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release) as a regular import that fails on
error so unexpected issues are surfaced.
scripts/lockfile-generators/helpers/pylock-to-requirements.py (1)

50-57: Edge case: regex may capture trailing characters from multiline comments.

The regex _DEFAULT_INDEX_RE uses \S+ which will greedily match non-whitespace. If the pylock comment contains additional flags after the URL on the same line (e.g., --default-index=https://pypi.org/simple --some-other-flag), the URL would incorrectly include --some-other-flag.

Consider tightening the pattern or splitting on whitespace:

Proposed fix
-_DEFAULT_INDEX_RE = re.compile(r"--default-index=(https?://\S+)")
+_DEFAULT_INDEX_RE = re.compile(r"--default-index=(https?://[^\s'\"]+)")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/lockfile-generators/helpers/pylock-to-requirements.py` around lines
50 - 57, The regex in extract_default_index_from_pylock (using _DEFAULT_INDEX_RE
with \S+) can capture trailing flags on the same line; update the extraction to
only return the URL token by splitting the captured group on whitespace and
taking the first token (then strip surrounding quotes), or tighten
_DEFAULT_INDEX_RE to capture only URL characters (e.g., use a character class
like [^\s'"]+). Apply this change in extract_default_index_from_pylock so
m.group(1) is replaced with the cleaned first token before rstrip("'\"").
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm`:
- Around line 1-2: The Dockerfile declares ARG TARGETARCH but never uses it;
either remove the unused ARG TARGETARCH declaration or document its intended
purpose with an inline comment (e.g., for future multi-arch builds) so it's not
confusing—locate the ARG TARGETARCH line in the Dockerfile.konflux.rocm and
either delete that ARG or replace it with a short comment explaining why
TARGETARCH is kept for future use.
- Around line 47-50: The CentOS GPG import currently uses a silent ignore ("RUN
rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official || true")
which can hide missing/corrupt keys; change this to explicitly check for the
file before importing and log a clear warning if it's absent, e.g. test for the
presence of /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official and only run
rpm --import if present, printing a descriptive message when it isn't, while
keeping the redhat import (rpm --import
/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release) as a regular import that fails on
error so unexpected issues are surfaced.

In `@jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm`:
- Around line 1-2: Remove the unused Docker build argument declaration ARG
TARGETARCH from the Dockerfile.rocm to match other files; locate the top-level
ARG TARGETARCH line in Dockerfile.rocm and delete it (or reference it only if
you later add logic that uses TARGETARCH), ensuring there are no remaining
references to TARGETARCH in this file.
- Around line 79-87: The rocm-jupyter-minimal stage duplicates GPG key imports
already performed in the rocm-base stage; remove the three redundant RUN rpm
--import lines in the rocm-jupyter-minimal stage (the ones importing
RPM-GPG-KEY-CentOS-Official, RPM-GPG-KEY-EPEL-9 and RPM-GPG-KEY-redhat-release)
so the keys remain imported only in rocm-base, leaving the subsequent COPY
prefetch-input/... lines intact; ensure no other child stages re-import those
same keys.

In `@scripts/lockfile-generators/helpers/pylock-to-requirements.py`:
- Around line 50-57: The regex in extract_default_index_from_pylock (using
_DEFAULT_INDEX_RE with \S+) can capture trailing flags on the same line; update
the extraction to only return the URL token by splitting the captured group on
whitespace and taking the first token (then strip surrounding quotes), or
tighten _DEFAULT_INDEX_RE to capture only URL characters (e.g., use a character
class like [^\s'"]+). Apply this change in extract_default_index_from_pylock so
m.group(1) is replaced with the cleaned first token before rstrip("'\"").

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 540fe29f-2e0a-401e-a604-a9173f579bdb

📥 Commits

Reviewing files that changed from the base of the PR and between ae4b775 and 6ce1152.

📒 Files selected for processing (10)
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-pull-request.yaml
  • .tekton/odh-workbench-jupyter-tensorflow-rocm-py312-ubi9-odh-main-push.yaml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.konflux.rocm
  • jupyter/rocm/tensorflow/ubi9-python-3.12/Dockerfile.rocm
  • jupyter/rocm/tensorflow/ubi9-python-3.12/prefetch-input
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pylock.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pyproject.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/requirements.rocm.txt
  • scripts/lockfile-generators/create-requirements-lockfile.sh
  • scripts/lockfile-generators/helpers/pylock-to-requirements.py
✅ Files skipped from review due to trivial changes (2)
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pyproject.toml
  • jupyter/rocm/tensorflow/ubi9-python-3.12/prefetch-input
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/lockfile-generators/create-requirements-lockfile.sh
👮 Files not reviewed due to content moderation or server errors (1)
  • jupyter/rocm/tensorflow/ubi9-python-3.12/pylock.toml

@ysok ysok force-pushed the odh-RHAIENG-2853-jupyter-rocm-tensorflow branch from 208b0bb to 131cf21 Compare April 10, 2026 13:53
@ysok ysok force-pushed the odh-RHAIENG-2853-jupyter-rocm-tensorflow branch from 131cf21 to fd9a301 Compare April 13, 2026 15:23
@ysok ysok force-pushed the odh-RHAIENG-2853-jupyter-rocm-tensorflow branch from fd9a301 to 7ea48b3 Compare April 16, 2026 12:41
@ysok
Copy link
Copy Markdown
Contributor Author

ysok commented Apr 16, 2026

Konflux build is good, but need to rebase, then merge.

image

@ysok ysok force-pushed the odh-RHAIENG-2853-jupyter-rocm-tensorflow branch from 7ea48b3 to 6987178 Compare April 16, 2026 20:10
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 16, 2026

[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 atheo89 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

Hermetic ROCm TensorFlow Jupyter image: wire Tekton/Cachi2 prefetch for gomod (mongocli), RPM+generic (prefetch-input/odh), and pip (requirements.rocm.txt). Dockerfiles install Python packages from Cachi2-fetched wheels; pyproject.toml uses the public-index lock path. pylock-to-requirements gains stricter Hermeto output (hashes and direct wheel URLs).

COPY prefetch-input/... paths are relative to the repo-root build context (path-context .); no per-component prefetch-input symlink, because Konflux Hermeto rejects symlink segments in tracked prefetch paths.
@ysok ysok force-pushed the odh-RHAIENG-2853-jupyter-rocm-tensorflow branch from 6987178 to a245e57 Compare April 16, 2026 20:15
@openshift-ci openshift-ci Bot removed the lgtm label Apr 16, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 16, 2026

New changes are detected. LGTM label has been removed.

@openshift-ci openshift-ci Bot added size/xxl and removed size/xxl labels Apr 16, 2026
@ysok ysok merged commit b161125 into opendatahub-io:main Apr 16, 2026
16 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-requested GitHub Bot creates notification on #pr-review-ai-ide-team slack channel size/xxl

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants