Skip to content

Conversation

@atheo89
Copy link
Member

@atheo89 atheo89 commented Nov 4, 2025

Related to: https://issues.redhat.com/browse/RHAIENG-1489
and partially to: https://issues.redhat.com/browse/RHAIENG-1649

Description

This PR introduces pylock_generator.sh, a Bash automation tool that generates
uv lock files (pylock.toml) for all supported notebook image flavors and runtimes.

Key features:

  • Supports targeted mode (specific directory) and automatic mode (repo-wide)
  • Detects available Dockerfiles (CPU, CUDA, ROCm) and locks accordingly
  • Uses official Red Hat index URLs for reproducible dependency resolution
  • Includes detailed progress and error reporting

How can be used

1. Run for in automatic mode (repo-wide)
bash scripts/pylock_generator.sh

2. Run for a specific image directory
bash scripts/pylock_generator.sh jupyter/minimal/ubi9-python-3.12

NOTE: If there is a missing package on pyproject.toml it will produces the following(for example):

  × No solution found when resolving dependencies:
  ╰─▶ Because kubeflow-training was not found in the package registry and datascience-notebook depends on kubeflow-training==1.9.3, we can conclude that your requirements are unsatisfiable.

so in this case you can comment out problematic package in the above case the kubeflow-training, and run it again, and probably it will print another missing package, and so on. So these missing packages should be reported to AIPCC team.

(PS: I didn't find a good solution to skip the missing packages and report a log error with the missing onces)

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

  • Chores
    • Enhanced Python dependency management automation for multiple hardware configurations (CPU, CUDA, and ROCm), ensuring consistent and reliable environments across different deployment scenarios.

@openshift-ci openshift-ci bot requested review from dibryant and jiridanek November 4, 2025 19:46
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 4, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

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

@github-actions github-actions bot added the review-requested GitHub Bot creates notification on #pr-review-ai-ide-team slack channel label Nov 4, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

A new Bash script is added to automate Python lock file generation. The script scans designated project directories for pyproject.toml files, identifies Python flavors via Dockerfile variants (CPU, CUDA, ROCm), and invokes uv pip compile with appropriate index URLs to generate corresponding lock files, including error handling and result aggregation.

Changes

Cohort / File(s) Change Summary
Lock File Generation Script
scripts/pylocks_generator.sh
New Bash script for automated Python lock file generation across multiple project directories (jupyter, runtimes, rstudio, codeserver). Detects Python flavors via Dockerfiles, executes uv pip compile with flavor-specific index URLs, and reports success/failure outcomes with guidance for failures.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Verify the logic for directory scanning and Dockerfile detection across the four target directories
  • Confirm uv pip compile invocation syntax and index URL correctness for each flavor (CPU, CUDA, ROCm)
  • Review error handling and cleanup procedures in the run_lock function
  • Check the final summary aggregation logic for correctness

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding an automated script for dependency lock generation.
Description check ✅ Passed The description covers key aspects (features, usage examples, testing notes) and marks all merge criteria as complete, though 'How Has This Been Tested' section lacks detailed test procedures.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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/l and removed size/l labels Nov 4, 2025
Copy link
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 (3)
scripts/pylocks_generator.sh (3)

7-9: Quote the $index variable for consistency and defensive coding.

While the unquoted expansion on line 97 works correctly (the URL has no spaces and expands as a single argument), it's inconsistent with other quoted variables in the command and less defensive. Quote it for consistency.

   $HAS_CPU && run_lock "cpu" "$CPU_INDEX"
   $HAS_CUDA && run_lock "cuda" "$CUDA_INDEX"
   $HAS_ROCM && run_lock "rocm" "$ROCM_INDEX"

Then in the run_lock function:

     uv pip compile pyproject.toml \
       --output-file "$output" \
       --format pylock.toml \
       --generate-hashes \
       --emit-index-url \
       --python-version="$PYTHON_VERSION" \
       --python-platform linux \
       --no-annotate \
-      $index
+      "$index"

Also applies to: 97-97


101-107: Consider capturing and logging uv pip compile stderr for better diagnostics.

When uv pip compile fails on line 98, the error output is not captured or logged. This makes it difficult for users to diagnose failures when they occur (e.g., missing dependencies, invalid Python version, malformed pyproject.toml).

Consider capturing stderr to help users debug:

    if [ $status -ne 0 ]; then
      warn "${flavor^^} lock failed in $TARGET_DIR"
      warn "Stderr output: $(uv pip compile ... 2>&1 || true)"
      rm -f "$output"
      DIR_SUCCESS=false
    else

Alternatively, document that users can re-run the command manually with full output for debugging.


24-25: Add validation for targeted directory input.

When a user provides a targeted directory via command-line argument (line 25), the script doesn't validate that the directory exists or contains pyproject.toml. This leads to opaque failures later (e.g., during cd or when uv pip compile can't find pyproject.toml).

Add validation after line 25:

if [ $# -gt 0 ]; then
  TARGET_DIRS=("$1")
  if [ ! -d "$1" ] || [ ! -f "$1/pyproject.toml" ]; then
    error "Target directory '$1' does not exist or does not contain pyproject.toml"
    exit 1
  fi

This provides immediate, actionable feedback to users.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 731c89f and 0061bce.

📒 Files selected for processing (1)
  • scripts/pylocks_generator.sh (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: code-static-analysis
🔇 Additional comments (1)
scripts/pylocks_generator.sh (1)

1-2: Solid error handling setup.

The shebang and set -euo pipefail establish safe defaults that will catch and exit on errors, undefined variables, and pipeline failures.

Comment on lines +49 to +99
for TARGET_DIR in "${TARGET_DIRS[@]}"; do
echo
echo "==================================================================="
info "Processing directory: $TARGET_DIR"
echo "==================================================================="

cd "$TARGET_DIR" || continue
mkdir -p uv.lock
PYTHON_VERSION="${PWD##*-}"

# Detect available Dockerfiles (flavors)
HAS_CPU=false
HAS_CUDA=false
HAS_ROCM=false
[ -f "Dockerfile.cpu" ] && HAS_CPU=true
[ -f "Dockerfile.cuda" ] && HAS_CUDA=true
[ -f "Dockerfile.rocm" ] && HAS_ROCM=true

if ! $HAS_CPU && ! $HAS_CUDA && ! $HAS_ROCM; then
warn "No Dockerfiles found in $TARGET_DIR (cpu/cuda/rocm). Skipping."
cd - >/dev/null
continue
fi

echo "📦 Python version: $PYTHON_VERSION"
echo "🧩 Detected flavors:"
$HAS_CPU && echo " • CPU"
$HAS_CUDA && echo " • CUDA"
$HAS_ROCM && echo " • ROCm"
echo

DIR_SUCCESS=true

run_lock() {
local flavor="$1"
local index="$2"
local output="uv.lock/pylock.${flavor}.toml"

echo "➡️ Generating ${flavor^^} lock file..."
set +e
uv pip compile pyproject.toml \
--output-file "$output" \
--format pylock.toml \
--generate-hashes \
--emit-index-url \
--python-version="$PYTHON_VERSION" \
--python-platform linux \
--no-annotate \
$index
local status=$?
set -e
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Add pre-flight check for uv command availability.

The script invokes uv pip compile (line 89) without verifying that the uv command is installed or in PATH. If uv is missing, the error will be cryptic and unhelpful to users.

Add a check near the beginning of the script (after line 41):

# Pre-flight check
if ! command -v uv &>/dev/null; then
  error "uv command not found. Please install uv: https://github.com/astral-sh/uv"
  exit 1
fi

Additionally, verify that the uv pip compile flags used in the script are supported:

  • --emit-index-url (line 93)
  • --format pylock.toml (line 92)

These flags are critical to correct behavior and should be tested or documented.


I need to gather information to verify the review comment. Let me examine the script and check the uv tool documentation.


---

🏁 Script executed:

```shell
#!/bin/bash
# Check if scripts/pylocks_generator.sh exists and show its content from the beginning
fd "pylocks_generator.sh" --type f --exec cat {} \;

Length of output: 3895


🌐 Web query:

uv pip compile --emit-index-url --format pylock.toml flags documentation

💡 Result:

Short answer — what those flags do and how to use them with uv:

  • --emit-index-url — include index URLs in the compiled output (uv by default omits index URLs). When passed, uv will emit all index URLs it knows about (including the default PyPI URL). [1][2]

  • --format pylock.toml — tell uv to write the lock in the PEP‑751 pylock.toml format instead of requirements.txt. uv supports exporting/compiling to pylock.toml and can later install/sync from it. [1]

  • Notes / usage:

    • uv pip compile prints output to stdout by default; use -o/--output-file to write to a file. Example: uv pip compile requirements.in -o pylock.toml --format pylock.toml --emit-index-url. [1]
    • uv’s --emit-index-url behavior differs from pip-tools: uv will include all index URLs when asked, including the default. [2]

Sources:
[1] uv — Locking / pip compile documentation.
[2] uv — Compatibility with pip (describes --emit-index-url differences).


Add pre-flight check for uv command availability.

The script invokes uv pip compile (line 89) without verifying that the uv command is installed or in PATH. If uv is missing, the error will be cryptic and unhelpful to users.

Add a check near the beginning of the script (after line 41):

# Pre-flight check
if ! command -v uv &>/dev/null; then
  error "uv command not found. Please install uv: https://github.com/astral-sh/uv"
  exit 1
fi

The flags --emit-index-url and --format pylock.toml are both valid uv commands supported for pip compile operations.

🤖 Prompt for AI Agents
In scripts/pylocks_generator.sh around lines 49 to 99 (add check after line 41),
the script invokes `uv` without verifying it exists; add a pre-flight check
immediately after line 41 that uses `command -v uv` to detect availability, and
if missing call the existing error/log helper with a clear message (e.g. "uv
command not found. Please install uv: https://github.com/astral-sh/uv") and exit
1; ensure the check returns non-zero on missing `uv` so the script fails fast
before reaching the `uv pip compile` invocation.


cd "$TARGET_DIR" || continue
mkdir -p uv.lock
PYTHON_VERSION="${PWD##*-}"
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add validation for Python version extraction from directory name.

The extraction PYTHON_VERSION="${PWD##*-}" assumes the directory follows a naming convention (e.g., ubi9-python-3.12). If a directory doesn't end with a version suffix or lacks a -, the extraction produces an invalid or empty result, leading to silent failures or cryptic errors from uv pip compile --python-version="".

Add a validation check after line 57:

PYTHON_VERSION="${PWD##*-}"

# Validate Python version extraction
if [[ ! "$PYTHON_VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
  warn "Could not extract valid Python version from directory name: $PWD"
  warn "Expected directory format: .../ubi9-python-X.Y"
  cd - >/dev/null
  continue
fi

This ensures only directories with valid version suffixes are processed.

🤖 Prompt for AI Agents
In scripts/pylocks_generator.sh around line 57, the code extracts PYTHON_VERSION
using PYTHON_VERSION="${PWD##*-}" but does not validate the result; add a
validation step immediately after that extraction to check the extracted value
matches a semantic version pattern like X.Y (e.g., using a regex
^[0-9]+\.[0-9]+$), and if it fails log/warn that the directory name could not
yield a valid Python version (include the PWD and expected format), then change
back to the previous directory and continue the loop to skip processing this
directory.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 4, 2025

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

Test name Commit Details Required Rerun command
ci/prow/images 0061bce link true /test images

Full PR test history. Your PR dashboard.

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

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant