Skip to content

Hive-3130: bundle-gen rewrite + port to shell#2916

Open
suhanime wants to merge 4 commits into
openshift:masterfrom
suhanime:HIVE-3130
Open

Hive-3130: bundle-gen rewrite + port to shell#2916
suhanime wants to merge 4 commits into
openshift:masterfrom
suhanime:HIVE-3130

Conversation

@suhanime

@suhanime suhanime commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Refactor

    • Replaced the prior Python bundle automation with a new shell-based bundle generator and improved CLI behavior.
  • Chores

    • Removed legacy Python tooling and trimmed related developer dependencies.
    • Updated CSV template comments to reference the new bundle generator.
  • Bug Fixes

    • Improved help/usage handling, standardized logging to stderr, and made branch/version selection more robust.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jun 1, 2026
@openshift-ci-robot

openshift-ci-robot commented Jun 1, 2026

Copy link
Copy Markdown

@suhanime: This pull request references Hive-3130 which is a valid jira issue.

Details

In response to this:

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 openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7c8ee286-d9e4-4b8e-8ec6-9a9dc33ba4d1

📥 Commits

Reviewing files that changed from the base of the PR and between eb49be8 and 4152150.

📒 Files selected for processing (2)
  • hack/bundle-gen.sh
  • hack/version2.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • hack/bundle-gen.sh

📝 Walkthrough

Walkthrough

Replaces the Python bundle generator with a Bash script implementing CLI parsing, image validation/build, semver and previous-version discovery, bundle and CSV generation (with operatorhub extras), automated PR creation; removes Python helpers and updates small helper scripts and CSV template comments.

Changes

Bundle Generation Migration

Layer / File(s) Summary
CLI, bootstrap, parsing and entrypoint
hack/bundle-gen.sh
Script bootstrap, strict mode, constants/defaults, usage, require_arg, parse_args, cleanup() with EXIT trap and invocation guard.
Image validation and ensure_image
hack/bundle-gen.sh
validate_image queries Quay API for quay.io tags (unless skipped); ensure_image short-circuits on --dry-run or builds/pushes via make+podman; check_deps present.
Semver helper and previous-version lookup
hack/bundle-gen.sh
semver_gt compares versions; get_previous_version(channel) scans community-operators-prod bundles and selects highest matching channel version.
Bundle and CSV generation (+ extras)
hack/bundle-gen.sh, config/templates/hive-csv-template.yaml
generate_bundle creates bundle dir, copies CRDs, renders CSV from template with owned-CRDs, deployment image, and createdAt; add_operatorhub_extras sets spec.replaces and conditionally writes release-config.yaml; CSV template comments updated to reference bundle-gen.sh.
PR creation and main orchestration
hack/bundle-gen.sh
open_pr reuses/clones forks, manages update-hive-<version> branch, copies bundle, commits/pushes (unless --dry-run), and runs gh pr create; main orchestrates full flow and --dummy-bundle mode.

Supporting Script Improvements

Layer / File(s) Summary
Help flag and version helper updates
hack/app-sre/generate-saas-template.sh, hack/version2.sh
generate-saas-template.sh now matches -h/--help first and exits 0 after usage; version2.sh log() writes to stderr, branch-name deduplication via associative arrays, and derives BRANCH_NAME when HEAD differs.

Sequence Diagram(s)

sequenceDiagram
  participant Local as hack/bundle-gen.sh
  participant Quay as Quay API
  participant HiveRepo as Hive repo
  participant Community as community-operators-prod
  participant Fork as Fork repo
  participant GH as gh CLI

  Local->>Quay: validate image tag (validate_image)
  Local->>HiveRepo: clone target Hive repo & checkout commit
  Local->>Community: scan bundles to get previous version (get_previous_version)
  Local->>Fork: push update-hive-<version> branch with bundle (open_pr)
  Local->>GH: create PR via gh pr create (open_pr)
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I hopped from Python to a bashy glen,
Templates now whisper "sh" again,
I check the tags, fetch branches wide,
Pack bundles up and push with pride,
A tiny hop — CI sings, "then blend!"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: rewriting and porting bundle-gen from Python to shell script.
Docstring Coverage ✅ Passed Docstring coverage is 88.24% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot requested review from 2uasimojo and jstuever June 1, 2026 19:10
@openshift-ci

openshift-ci Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: suhanime

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

The pull request process is described here

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

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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 1, 2026

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

🤖 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 `@hack/bundle-gen.sh`:
- Around line 400-404: The script uses git -C "$repo_path" checkout -b
"$branch_name" which fails if the branch already exists; change this to git -C
"$repo_path" checkout -B "$branch_name" so the branch is force-created/updated
(allowing re-runs that correspond with the later --force push), referencing the
existing variables branch_name, repo_path, and semver_ver when locating the line
to modify.
- Around line 298-311: The loop currently iterates over every regular file in
crds_dir which allows non-YAML files to be processed by yq; change the find
invocation used to feed crd_file to only match YAML files (for example replace
find "$crds_dir" -maxdepth 1 -type f with find "$crds_dir" -maxdepth 1 -type f
\( -iname '*.yaml' -o -iname '*.yml' \) | sort) or add a guard before processing
each crd_file that skips files not ending in .yaml/.yml; update the use sites of
crd_file/kind/version_name/etc. accordingly so only YAML CRDs are copied and
passed to yq.
- Around line 162-166: The curl call that assigns the local variable resp can
hang; modify the command in the resp assignment inside the conditional (the
block using "if ! resp=$(curl -sf "$url"); then") to include a timeout flag
(e.g. --max-time <seconds> or --connect-timeout <seconds>) so the command fails
fast on unresponsive endpoints (for example use --max-time 30); keep the -s and
-f flags and preserve the existing error/exit handling.
🪄 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: 6a868823-77d5-47a8-81cb-4907b313c111

📥 Commits

Reviewing files that changed from the base of the PR and between db81e46 and 409e014.

📒 Files selected for processing (7)
  • config/templates/hive-csv-template.yaml
  • hack/app-sre/generate-saas-template.sh
  • hack/bundle-gen.py
  • hack/bundle-gen.sh
  • hack/github.py
  • hack/requirements.txt
  • hack/version2.sh
💤 Files with no reviewable changes (3)
  • hack/requirements.txt
  • hack/github.py
  • hack/bundle-gen.py

Comment thread hack/bundle-gen.sh
Comment thread hack/bundle-gen.sh Outdated
Comment thread hack/bundle-gen.sh Outdated

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

🧹 Nitpick comments (2)
hack/bundle-gen.sh (2)

302-310: 💤 Low value

Consider handling missing CRD descriptions gracefully.

If a CRD lacks .spec.versions[0].schema.openAPIV3Schema.description, yq returns the literal string "null", which would appear verbatim in the CSV's owned CRDs list.

♻️ Optional: default to empty string for missing description
-        description=$(yq '.spec.versions[0].schema.openAPIV3Schema.description' "$crd_file")
+        description=$(yq '.spec.versions[0].schema.openAPIV3Schema.description // ""' "$crd_file")
🤖 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 `@hack/bundle-gen.sh` around lines 302 - 310, The script currently assigns
description=$(yq '.spec.versions[0].schema.openAPIV3Schema.description'
"$crd_file") which can yield the literal "null"; update the logic around the
description variable (and the subsequent yq invocation that uses DESCRIPTION) to
normalize missing descriptions to an empty string. Concretely, after computing
description (or by adjusting the yq query), ensure if description is "null" or
empty it is replaced with "" before exporting DESCRIPTION and running the final
yq -i command that appends the CSV entry (refer to the variables description,
DESCRIPTION and the yq append invocation). This will prevent the literal "null"
from appearing in the owned CRDs list.

118-123: 💤 Low value

Consider validating that value-options receive an actual value.

If a user accidentally passes --github-user --verbose (missing the username), GITHUB_USER gets set to --verbose, causing a confusing failure later in open_pr. Similarly, passing --github-user at the end of the command line would hit an unbound variable error with an unclear message.

♻️ Optional: add a helper to validate required arguments
+require_arg() {
+    if [[ -z "${2:-}" || "$2" == --* ]]; then
+        echo "Error: $1 requires a value" >&2
+        exit 1
+    fi
+}
+
 parse_args() {
     while [[ $# -gt 0 ]]; do
         case "$1" in
             --verbose)               VERBOSE=true ;;
             --dry-run)               DRY_RUN=true ;;
             --hold)                  HOLD=true ;;
             --skip-release-config)   SKIP_RELEASE_CONFIG=true ;;
             --skip-image-validation) SKIP_IMAGE_VALIDATION=true ;;
-            --github-user)           GITHUB_USER="$2";        shift ;;
-            --hive-repo)             HIVE_REPO="$2";          shift ;;
-            --image-repo)            IMAGE_REPO="$2";         shift ;;
-            --image-tag-override)    IMAGE_TAG_OVERRIDE="$2"; shift ;;
-            --commit)                COMMIT_ISH="$2";         shift ;;
-            --dummy-bundle)          DUMMY_BUNDLE="$2";       shift ;;
+            --github-user)           require_arg "$1" "${2:-}"; GITHUB_USER="$2";        shift ;;
+            --hive-repo)             require_arg "$1" "${2:-}"; HIVE_REPO="$2";          shift ;;
+            --image-repo)            require_arg "$1" "${2:-}"; IMAGE_REPO="$2";         shift ;;
+            --image-tag-override)    require_arg "$1" "${2:-}"; IMAGE_TAG_OVERRIDE="$2"; shift ;;
+            --commit)                require_arg "$1" "${2:-}"; COMMIT_ISH="$2";         shift ;;
+            --dummy-bundle)          require_arg "$1" "${2:-}"; DUMMY_BUNDLE="$2";       shift ;;
             -h|--help)               usage; exit 0 ;;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hack/bundle-gen.sh` around lines 118 - 123, When parsing flags in
hack/bundle-gen.sh ensure value-options (e.g., --github-user, --hive-repo,
--image-repo, --image-tag-override, --commit, --dummy-bundle) verify the next
token is a real value (not another flag or empty) before assigning to
GITHUB_USER, HIVE_REPO, IMAGE_REPO, IMAGE_TAG_OVERRIDE, COMMIT_ISH, or
DUMMY_BUNDLE; add a small helper like require_value_or_exit that checks $2
exists and does not start with "-" and call it from each case branch (or inline
the check) to print a clear error and exit, so missing values don't propagate
into open_pr or cause unbound-variable failures.
🤖 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.

Nitpick comments:
In `@hack/bundle-gen.sh`:
- Around line 302-310: The script currently assigns description=$(yq
'.spec.versions[0].schema.openAPIV3Schema.description' "$crd_file") which can
yield the literal "null"; update the logic around the description variable (and
the subsequent yq invocation that uses DESCRIPTION) to normalize missing
descriptions to an empty string. Concretely, after computing description (or by
adjusting the yq query), ensure if description is "null" or empty it is replaced
with "" before exporting DESCRIPTION and running the final yq -i command that
appends the CSV entry (refer to the variables description, DESCRIPTION and the
yq append invocation). This will prevent the literal "null" from appearing in
the owned CRDs list.
- Around line 118-123: When parsing flags in hack/bundle-gen.sh ensure
value-options (e.g., --github-user, --hive-repo, --image-repo,
--image-tag-override, --commit, --dummy-bundle) verify the next token is a real
value (not another flag or empty) before assigning to GITHUB_USER, HIVE_REPO,
IMAGE_REPO, IMAGE_TAG_OVERRIDE, COMMIT_ISH, or DUMMY_BUNDLE; add a small helper
like require_value_or_exit that checks $2 exists and does not start with "-" and
call it from each case branch (or inline the check) to print a clear error and
exit, so missing values don't propagate into open_pr or cause unbound-variable
failures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b0a66c34-d5de-472a-ae7e-e332d87373db

📥 Commits

Reviewing files that changed from the base of the PR and between 409e014 and 8a082cb.

📒 Files selected for processing (7)
  • config/templates/hive-csv-template.yaml
  • hack/app-sre/generate-saas-template.sh
  • hack/bundle-gen.py
  • hack/bundle-gen.sh
  • hack/github.py
  • hack/requirements.txt
  • hack/version2.sh
💤 Files with no reviewable changes (3)
  • hack/requirements.txt
  • hack/bundle-gen.py
  • hack/github.py
✅ Files skipped from review due to trivial changes (1)
  • config/templates/hive-csv-template.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • hack/version2.sh
  • hack/app-sre/generate-saas-template.sh

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

🧹 Nitpick comments (1)
hack/bundle-gen.sh (1)

474-474: 💤 Low value

Defensive: use -- before positional arguments in git checkout.

While COMMIT is controlled by version_init and typically a SHA, adding -- prevents accidental flag interpretation if the value ever starts with -.

Proposed fix
-    git checkout "$COMMIT"
+    git checkout -- "$COMMIT"
🤖 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 `@hack/bundle-gen.sh` at line 474, The git checkout invocation using COMMIT is
vulnerable if COMMIT begins with a dash; update the checkout call in the script
so the positional argument is separated from flags by adding the explicit
separator: invoke git checkout with the `--` separator before "$COMMIT" (i.e.,
change the git checkout "$COMMIT" usage to use `git checkout -- "$COMMIT"`),
ensuring the COMMIT variable is still quoted to preserve whitespace.
🤖 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.

Nitpick comments:
In `@hack/bundle-gen.sh`:
- Line 474: The git checkout invocation using COMMIT is vulnerable if COMMIT
begins with a dash; update the checkout call in the script so the positional
argument is separated from flags by adding the explicit separator: invoke git
checkout with the `--` separator before "$COMMIT" (i.e., change the git checkout
"$COMMIT" usage to use `git checkout -- "$COMMIT"`), ensuring the COMMIT
variable is still quoted to preserve whitespace.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 65a4c0ce-2499-4d24-b2a1-c424a31af06a

📥 Commits

Reviewing files that changed from the base of the PR and between 8a082cb and c06c464.

📒 Files selected for processing (7)
  • config/templates/hive-csv-template.yaml
  • hack/app-sre/generate-saas-template.sh
  • hack/bundle-gen.py
  • hack/bundle-gen.sh
  • hack/github.py
  • hack/requirements.txt
  • hack/version2.sh
💤 Files with no reviewable changes (3)
  • hack/requirements.txt
  • hack/github.py
  • hack/bundle-gen.py
✅ Files skipped from review due to trivial changes (1)
  • config/templates/hive-csv-template.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • hack/app-sre/generate-saas-template.sh
  • hack/version2.sh

@suhanime

suhanime commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

/hold

@openshift-ci openshift-ci Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jun 3, 2026
suhanime added 2 commits June 3, 2026 19:17
Rewrites the OperatorHub bundle generation and publishing script from
Python to bash, eliminating all Python dependencies (GitPython, PyYAML,
semver, requests) in favour of standard tools already present in the
environment: git, yq (v4), jq, gh CLI.

Key changes:
- bundle-gen.sh replaces bundle-gen.py with identical CLI surface and
  behaviour. Usage: same flags, same $GITHUB_TOKEN env var.
- github.py and requirements.txt are removed; the new script uses
  `gh pr create` instead of the custom GitHub REST client.
- version2.sh is sourced directly instead of the now-deleted version2.py.
- Adds early dependency check (check_deps) that fails immediately with a
  clear error if yq, jq, git, or gh are not on PATH — preventing
  cascading silent failures mid-run.
- Fixes a latent Python bug: --dummy-bundle without --skip-release-config
  caused a TypeError (str + None) crash. The shell version separates
  generate_bundle from add_operatorhub_extras so this cannot occur.
- Fixes createdAt annotation: Python used local time mislabeled as UTC
  (datetime.now() with a literal Z suffix); shell uses date -u correctly.
- Fixes version2.sh log() routing: in library mode log messages wrote to
  stdout, corrupting command substitutions like branch_commit=$(find_branch).
  All log levels now always write to stderr.
- Temp-dir cleanup is guaranteed via EXIT trap rather than only on clean exit.
- --verbose now works (set -x); was dead code in the Python version.
- Dead code removed: generate_package() (never called) and
  SUBPROCESS_REDIRECT (set but never passed to any subprocess call).

Assisted-by: Claude Sonnet 4.6
…ate.sh

Follow-up to CodeRabbit's suggestion on openshift#2865. The help detection
loop matched any argument containing the substring "-h" (e.g. a file
path like /some/hive-template.yaml would trigger help mode and exit).
Fix by:
- Checking for -h / --help before the argument-count validation, so
  help works even when the wrong number of args is supplied.
- Using exact string matching instead of glob *-h*.
- Exiting with status 0 on help (was erroneously exiting 1).

Assisted-by: Claude Sonnet 4.6

@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 `@hack/version2.sh`:
- Around line 202-207: The mapfile -t pipelines for the arrays here, ancestors
and descendants are turning empty arrays into a single empty-string entry
because printf '%s\n' emits a blank line; update the three mapfile invocations
(the ones that read into here, ancestors, descendants) to filter out blank lines
before mapfile (e.g., pipe the printf output through a command that deletes
empty lines such as sed '/^$/d') or alternatively wrap each mapfile call in a
short guard that only runs when the source array has elements; ensure the change
preserves the existing set -u-safe empty-array expansion idiom and only affects
those three mapfile pipelines.
🪄 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: f5ede1ca-3b50-4205-9597-38dcfeadc2de

📥 Commits

Reviewing files that changed from the base of the PR and between 2be7faf and c25417b.

📒 Files selected for processing (7)
  • config/templates/hive-csv-template.yaml
  • hack/app-sre/generate-saas-template.sh
  • hack/bundle-gen.py
  • hack/bundle-gen.sh
  • hack/github.py
  • hack/requirements.txt
  • hack/version2.sh
💤 Files with no reviewable changes (3)
  • hack/requirements.txt
  • hack/github.py
  • hack/bundle-gen.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • config/templates/hive-csv-template.yaml
  • hack/app-sre/generate-saas-template.sh
  • hack/bundle-gen.sh

Comment thread hack/version2.sh Outdated

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

🤖 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 `@hack/bundle-gen.sh`:
- Around line 500-503: The script copies the new bundle into an existing
directory which causes nested output on reruns; before calling cp -r for the
generated bundle (in the block using generate_bundle, BUNDLE_DIR, ver_semver and
dest), ensure the previous output is removed or replaced by deleting the
existing destination directory (e.g., check for existence of dest and rm -rf it)
or use a copy command that replaces the target rather than nesting; update the
logic around dest to remove/replace the existing
hive-operator-bundle-v${ver_semver} before copying.
- Around line 449-458: The check_deps function currently omits curl so
validate_image() can later fail; add "curl" to the list of commands checked in
check_deps (the for cmd in ... loop) and include it in the error/help output so
the script fails fast when curl is missing; locate check_deps and update both
the for-loop's command list and the printed dependency lines to mention curl.
- Around line 509-515: The script currently only rejects equal versions
(ver_semver == prev_version) which allows generating bundles with a lower
version; update the guard in hack/bundle-gen.sh to perform a proper semver
comparison and fail unless ver_semver is strictly greater than prev_version
(i.e., treat ver_semver <= prev_version as an error). Locate the block around
ver_semver/prev_version and the calls to generate_bundle and
add_operatorhub_extras and replace the equality check with a semantic-version
comparison (for example using sort -V, version sort, or a small semver compare
function) so the script exits with an error if ver_semver is less-than or
equal-to prev_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: c17393d9-b1a3-4d66-a3f0-92456c845faf

📥 Commits

Reviewing files that changed from the base of the PR and between 2be7faf and 99c9dd4.

📒 Files selected for processing (7)
  • config/templates/hive-csv-template.yaml
  • hack/app-sre/generate-saas-template.sh
  • hack/bundle-gen.py
  • hack/bundle-gen.sh
  • hack/github.py
  • hack/requirements.txt
  • hack/version2.sh
💤 Files with no reviewable changes (3)
  • hack/requirements.txt
  • hack/github.py
  • hack/bundle-gen.py
✅ Files skipped from review due to trivial changes (1)
  • config/templates/hive-csv-template.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • hack/version2.sh
  • hack/app-sre/generate-saas-template.sh

Comment thread hack/bundle-gen.sh
Comment thread hack/bundle-gen.sh
Comment thread hack/bundle-gen.sh

@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 `@hack/bundle-gen.sh`:
- Around line 483-487: The call to version_init currently passes an empty second
arg when COMMIT_ISH is unset, causing version_init to treat it as HEAD; change
the call so the second argument is COMMIT_ISH if provided, otherwise explicitly
pass the requested branch value (the same value passed as the first
arg/DUMMY_BUNDLE) so version_init resolves the branch tip instead of using
whatever the repo has checked out; update the invocation that uses DUMMY_BUNDLE
and COMMIT_ISH accordingly so the subsequent checkout logic operates on the
intended branch tip.
🪄 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: 9d6b3f1a-a766-47d1-8bd3-42a94a64c1a1

📥 Commits

Reviewing files that changed from the base of the PR and between 99c9dd4 and eb49be8.

📒 Files selected for processing (2)
  • hack/bundle-gen.sh
  • hack/version2.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • hack/version2.sh

Comment thread hack/bundle-gen.sh
Comment on lines +483 to +487
# version2.sh sets globals: COMMIT, BRANCH_NAME, PREFIX, COMMIT_COUNT
# In OperatorHub mode the branch is always master; --dummy-bundle overrides
# this with an explicit branch (e.g. mce-2.1). Passing the branch explicitly
# avoids ambiguous auto-detection when the repo has many branches.
version_init "${DUMMY_BUNDLE:-master}" "${COMMIT_ISH:-}"

@coderabbitai coderabbitai Bot Jun 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make the no---commit path resolve the requested branch tip.

version_init() treats an empty second argument as HEAD (hack/version2.sh:244-255), so this still builds from whatever the clone has checked out. That breaks the documented defaults for both --dummy-bundle <branch> and --hive-repo pointing at a local repo whose HEAD is not master: Line 494 checks out the wrong commit, and the generated semver follows it.

Proposed fix
-    version_init "${DUMMY_BUNDLE:-master}" "${COMMIT_ISH:-}"
+    local target_branch="${DUMMY_BUNDLE:-master}"
+    version_init "$target_branch" "${COMMIT_ISH:-$target_branch}"
🤖 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 `@hack/bundle-gen.sh` around lines 483 - 487, The call to version_init
currently passes an empty second arg when COMMIT_ISH is unset, causing
version_init to treat it as HEAD; change the call so the second argument is
COMMIT_ISH if provided, otherwise explicitly pass the requested branch value
(the same value passed as the first arg/DUMMY_BUNDLE) so version_init resolves
the branch tip instead of using whatever the repo has checked out; update the
invocation that uses DUMMY_BUNDLE and COMMIT_ISH accordingly so the subsequent
checkout logic operates on the intended branch tip.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This would break the local clone usage, which is usually how the users execute bundle-gen currently. While the lack of commit if dummy-bundle option is used (with a non-master branch) might result in error, it will still come up with a useful failure message.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@suhanime, that's a fair point — for local clones, HEAD is exactly what the user wants to build from, and overriding it with the branch name as a fallback would break that common workflow. I'll defer to your judgment here.


✏️ Learnings added
Learnt from: suhanime
Repo: openshift/hive PR: 2916
File: hack/bundle-gen.sh:483-487
Timestamp: 2026-06-05T06:42:02.632Z
Learning: In `hack/bundle-gen.sh` (openshift/hive), the call `version_init "${DUMMY_BUNDLE:-master}" "${COMMIT_ISH:-}"` intentionally passes an empty second argument when `--commit` is not specified. This is by design: the primary use case is pointing `--hive-repo` at a local directory, where `HEAD` is the intended commit to build from. Passing the branch name as a fallback for the second arg would break local clone usage. Do not suggest changing this to `version_init "$target_branch" "${COMMIT_ISH:-$target_branch}"`.

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.


🧠 Learnings used
Learnt from: suhanime
Repo: openshift/hive PR: 2901
File: apis/vendor/github.com/openshift/api/config/v1/types_authentication.go:290-307
Timestamp: 2026-05-14T04:23:24.966Z
Learning: In the openshift/hive repository, vendor files (both at the repository root vendor/ directory and under apis/vendor/) must never be modified directly. Issues in vendored code should be addressed by bumping the dependency version in go.mod (or apis/go.mod) to pull in a version that contains the upstream fix. Do not raise review comments suggesting edits to vendored files.

@suhanime

suhanime commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

/hold cancel

@openshift-ci openshift-ci Bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jun 5, 2026
Comment thread hack/version2.sh Outdated
Comment on lines +202 to +207
# Deduplicate by logical branch name: the same branch appearing under multiple
# remotes (e.g. refs/heads/master and refs/remotes/origin/master both resolve
# to "master") should be counted once.
mapfile -t here < <(printf '%s\n' "${here[@]+"${here[@]}"}" | sort -u | grep -v '^$')
mapfile -t ancestors < <(printf '%s\n' "${ancestors[@]+"${ancestors[@]}"}" | sort -u | grep -v '^$')
mapfile -t descendants < <(printf '%s\n' "${descendants[@]+"${descendants[@]}"}" | sort -u | grep -v '^$')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I can't parse this. If all we're trying to do is deduplicate, can we just make here, ancestors, and descendants associative arrays?

@coderabbitai Can you break down this goofy syntax for me? I get the sort and grep. I get that mapfile is consuming a "file" with newlines and putting the contents into an array such that each line (minus the newline character) is one array entry. The bit in the middle is a mystery though. Talk me through from the first < to the last ".

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@2uasimojo Sure! Here's the breakdown of "${here[@]+"${here[@]}"}":


The core: ${parameter+word}

This is bash's use-alternative parameter expansion. The rule:

  • If parameter is unset or null, substitute nothing.
  • If parameter is set and non-null, substitute word.

Applying it to arrays: ${here[@]+...}

When the [@] subscript is used with the + operator on an empty array, bash treats it as "unset/null", so the whole thing expands to nothing. When the array has elements, it expands to word.

The reason this idiom exists at all is set -u (nounref), which is active here via set -euo pipefail. Without protection, ${here[@]} on an empty array causes a fatal "unbound variable" error in some bash versions.


The full expression: "${here[@]+"${here[@]}"}"

Breaking it apart:

Part Meaning
Outer "..." Outer double-quotes wrapping the whole expansion
${here[@]+ Check: does here have any elements?
"${here[@]}" The word: expand all array elements as separate arguments
}" Close the ${...} and the outer quote

Result:

  • here is empty → expands to nothing → printf '%s\n' gets no args → no output
  • here is non-empty → expands to "${here[@]}"printf '%s\n' "elem1" "elem2" ... → one element per line

Then sort -u deduplicates the lines, and grep -v '^$' strips any blank lines, and mapfile -t here reads the result back into the array.


Your associative array suggestion

Yes, that would be cleaner and more idiomatic. Instead of local -a here=(), you'd use:

declare -A here=()
declare -A ancestors=()
declare -A descendants=()

Then replace here+=("$refname") with here["$refname"]=1, and similarly for the others. Deduplication is free since a key can only appear once. Later, ${#here[@]} still gives the count, and "${!here[@]}" gives the keys (branch names). The awkward mapfile/printf/sort block goes away entirely.

The only wrinkle: the downstream code uses ${here[0]}, ${here[1]}, etc. (indexed access). Associative arrays don't guarantee order and don't support numeric indexing, so you'd need to convert to an indexed array first when reading out, e.g. mapfile -t here_arr < <(printf '%s\n' "${!here[@]}") before doing ${here_arr[0]}. Whether that's a net improvement in readability is debatable.

(¬_¬") 🐇

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The "downstream code" is only consuming the contents if there's exactly one entry; so something like

    if [[ ${#here[@]} -eq 1 ]]; then
        log "debug" "Found unique branch ${here[0]} at commit $(shortsha)"
        echo "${!here[@]}"   # <== prints "all keys", but there's only one.
        return 0
    fi

...would work fine, no?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@2uasimojo Yes, exactly right — ${!here[@]} when count is 1 gives the single key (the branch name), so the echo works perfectly.

The ${here[0]} in the debug log line also needs updating though, and ${descendants[*]} would print all 1s (the values) instead of branch names. Here's what the full downstream change would look like:

if [[ ${`#here`[@]} -eq 1 ]]; then
    log "debug" "Found unique branch ${!here[@]} at commit $(shortsha)"
    echo "${!here[@]}"
    return 0
fi

if [[ ${`#here`[@]} -gt 1 ]]; then
    log "fatal" "Found ${`#here`[@]} branches at commit $(shortsha)! Please specify a branch name explicitly."
fi

if [[ ${`#descendants`[@]} -eq 1 ]]; then
    log "debug" "Found branch ${!descendants[@]} descended from commit $(shortsha)"
    echo "${!descendants[@]}"
    return 0
fi

log "debug" "descendants: ${!descendants[*]}"

if [[ ${`#ancestors`[@]} -eq 1 ]]; then
    log "debug" "Found branch ${!ancestors[@]} which is an ancestor of commit $(shortsha)"
    echo "${!ancestors[@]}"
    return 0
fi

And the array declarations + population:

local -A here=()
local -A ancestors=()
local -A descendants=()

# ...
here["$refname"]=1
# or
ancestors["$refname"]=1
# or
descendants["$refname"]=1

That eliminates the mapfile/printf/sort block entirely. Net improvement in readability, I'd say.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, definitely. @suhanime wdyt?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

suhanime added 2 commits June 7, 2026 11:49
Bug: when bundle-gen was invoked with --commit pointing to a commit that
differs from the cloned repo's HEAD, version_init in version2.sh skipped
branch auto-detection entirely, leaving BRANCH_NAME empty. This caused
the version prefix to fall back to UNKNOWN_BRANCH_PREFIX ("0.0") instead
of the correct "1.2" for master, producing invalid bundle versions that
violate semver ordering against existing bundles.

This was introduced in f1bc37a when version2.py was ported to
version2.sh. The port missed the fallback to _branch_from_commit() that
the Python version called when the active branch HEAD did not match the
requested commit.

Fix in version2.sh:
- When the active branch HEAD does not match COMMIT, fall through to
  branch_from_commit to discover the correct branch.
- Deduplicate the here/ancestors/descendants arrays in branch_from_commit
  by logical branch name before uniqueness checks, so that the same branch
  appearing under multiple remotes (e.g. refs/heads/master and
  refs/remotes/origin/master) is counted once rather than causing a
  spurious "Found N branches" fatal error.

Fix in bundle-gen.sh:
- Explicitly pass "master" as the branch argument to version_init in
  OperatorHub mode (with --dummy-bundle overriding this when targeting a
  specific non-master branch such as mce-2.1). The version2.sh
  auto-detection is not reliable when the local repo has many branches
  that are all descendants of the requested commit.

Versioning guards added to OperatorHub mode to catch distinct failure
cases before they can reach the community-operator repos:
- Prefix check: verifies that the computed version prefix ($PREFIX)
  matches MASTER_BRANCH_PREFIX before cloning community-operators-prod.
  Fails fast if branch detection fell back to the unknown prefix.
- Existence check: rejects the bundle if the computed version is identical
  to the current upstream head with a clear "already exists" error.
- Ordering check: rejects the bundle if the computed version is lower than
  the current upstream head, which can happen if a valid-looking prefix
  was produced but the commit count has already been superseded.

The three checks are kept separate because they indicate distinct root
causes and warrant distinct, actionable error messages.

Assisted-by: Claude Sonnet 4.6
- hack/bundle-gen.sh: replace `git checkout upstream/main` and
  `git checkout -B` with `git switch --detach` and `git switch -C`
  for unambiguous branch vs pathspec semantics.

- hack/bundle-gen.sh: rm -rf the dummy-bundle output directory before
  cp -r so reruns for the same version replace it cleanly instead of
  nesting the new bundle inside the existing directory.

- hack/version2.sh: pipe mapfile deduplication through `grep -v '^$'`
  to prevent empty arrays from producing a spurious empty-string entry
  when printf emits a blank line on zero-element input.

Assisted-by: Claude Sonnet 4.6
@openshift-ci

openshift-ci Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

@suhanime: 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/security 4152150 link true /test security

Full PR test history. Your PR dashboard.

Details

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

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants