Skip to content

NO-ISSUE: Add inspect-catalog helper - #2942

Open
pacevedom wants to merge 4 commits into
openshift:mainfrom
pacevedom:inspect-catalog
Open

NO-ISSUE: Add inspect-catalog helper#2942
pacevedom wants to merge 4 commits into
openshift:mainfrom
pacevedom:inspect-catalog

Conversation

@pacevedom

@pacevedom pacevedom commented Jul 28, 2026

Copy link
Copy Markdown
Contributor
$ ./hack/inspect-catalog.sh --help
Usage: inspect-catalog.sh [OPTIONS] CATALOG_IMAGE

Extract and display all bundles from an OLM file-based catalog image.

Arguments:
  CATALOG_IMAGE    Catalog image reference (tag or digest)

Options:
  --json           Output as JSON array (includes commit IDs)
  --arch ARCH      Platform architecture (default: amd64)
  --package NAME   Filter to a specific package
  --version VER    Filter to a specific version (e.g., 4.19.3 or v4.19.3)
  --no-commits     Skip fetching commit IDs (faster)
  -h, --help       Show this help

Examples:
  inspect-catalog.sh quay.io/org/catalog@sha256:abc123...
  inspect-catalog.sh --json quay.io/org/catalog:latest
  inspect-catalog.sh --package lvms-operator --version 4.19.3 IMAGE

$ ./hack/inspect-catalog.sh quay.io/redhat-user-workloads/logical-volume-manag-tenant/lvm-operator-catalog@sha256:40e1f0e2fb764b6e166c0f1af1e68b0ecd9662d9c7737e7159d7c1f3443d011f
Resolving amd64 manifest...
Pulling image layers...
Extracting bundle information...
Fetching commit IDs for 28 images...
Done.

Package: lvms-operator

  Channel: stable-4.18
  ----------------------------------------------------------------------
  [bundle] lvms-operator.v4.18.0        3ebaca245644  commit:9a7ea209dbfb
    lvms-must-gather     fa96b89ffaa0  commit:987f74ada360
    lvms-operator        0c0153db16cb  commit:74db7522c618
    topolvm-csi          4c8ee1fa1ec1  commit:def13df88eab
  [bundle] lvms-operator.v4.18.1        647b839a19ef  commit:43ef276e7931
    lvms-must-gather     075eb4426082  commit:3b4c8cd9fbcd
    lvms-operator        8888d4544134  commit:c2f53303d014
    topolvm-csi          fa2575c4ff57  commit:bc8d1f802991
  [bundle] lvms-operator.v4.18.2        1e37fa696824  commit:d104f2dd1dde
    lvms-must-gather     57f26d3fd9c3  commit:e528d837e449
    lvms-operator        59740856359e  commit:dd529263c81f
    topolvm-csi          cb349df9ef3a  commit:4cc6524a4b81
  [bundle] lvms-operator.v4.18.3        43d5efde837d  commit:2009097c581c
    skips v4.18.0,v4.18.1,v4.18.2
    lvms-must-gather     5d0534e08790  commit:9b475e877af0
    lvms-operator        80f5e48600d9  commit:38a92258b91c
    topolvm-csi          b3b1c4836a82  commit:045802c3cf20

  Channel: stable-4.19
  ----------------------------------------------------------------------
  [bundle] lvms-operator.v4.19.0        6cec0bc33b40  commit:b102ce576e22
    lvms-must-gather     28e0e1feecc7  commit:ee82fa46314b
    lvms-operator        373371743d4c  commit:50c9aac27f7e
  [bundle] lvms-operator.v4.19.1        db9b7aa0d4fe  commit:5bc4a2ad56c7
    lvms-must-gather     1e455df18829  commit:98d5f8d5ac09
    lvms-operator        3701735419e2  commit:c2f3347b7f1a
  [bundle] lvms-operator.v4.19.2        077222b42d5a  commit:f78f77c60ad2
    lvms-must-gather     128106963d49  commit:5b96492f0c53
    lvms-operator        ef047e920236  commit:5b96492f0c53
  [bundle] lvms-operator.v4.19.3        5245275268dd  commit:------------
    replaces v4.18.3  skips v4.18.0,v4.18.1,v4.18.2,v4.19.0,v4.19.1,v4.19.2  range >=4.2.0 <4.19.3
    lvms-must-gather     a780573a1ea5  commit:bff279174d0a
    lvms-operator        e0ebe6eba711  commit:------------

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Added a command-line utility to inspect file-based catalogs bundled in container images.
    • Supports architecture selection plus package and version filtering, and outputs either normalized JSON or a human-readable report.
    • Extracts bundle package/image details, channel lists, and upgrade/replacement/skip relationships (including skip ranges).
    • Includes related images and selected package properties for the matched entries.

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

Copy link
Copy Markdown

@pacevedom: This pull request explicitly references no jira issue.

Details

In response to this:

$ ./hack/inspect-catalog.sh --help
Usage: inspect-catalog.sh [OPTIONS] CATALOG_IMAGE

Extract and display all bundles from an OLM file-based catalog image.

Arguments:
 CATALOG_IMAGE    Catalog image reference (tag or digest)

Options:
 --json           Output as JSON array
 --arch ARCH      Platform architecture (default: amd64)
 --package NAME   Filter to a specific package
 --version VER    Filter to a specific version (e.g., 4.19.3 or v4.19.3)
 --labels         Fetch image labels (vcs-ref, build-date) via skopeo inspect per bundle
 -h, --help       Show this help

Examples:
 inspect-catalog.sh quay.io/org/catalog@sha256:abc123...
 inspect-catalog.sh --json --labels quay.io/org/catalog:latest
 inspect-catalog.sh --package lvms-operator --version 4.19.3 quay.io/org/catalog@sha256:abc123...

$ ./hack/inspect-catalog.sh --version 4.19.3 --labels quay.io/redhat-user-workloads/logical-volume-manag-tenant/lvm-operator-catalog@sha256:7afafe437eb3084ac29cb82fc22c922fd5e14625944b23848483ef68c17b283e
Resolving amd64 manifest...
Pulling image layers...
Extracting bundle information...
Fetching labels for 1 bundle(s)...
 Inspecting sha256:b3d246dd8967cda961c3e011bc612885c31ceb153f270238841dc717f911bb07...
================================================================================
Package:  lvms-operator
Bundle:   lvms-operator.v4.19.3
Image:    registry.redhat.io/lvms4/lvms-operator-bundle@sha256:b3d246dd8967cda961c3e011bc612885c31ceb153f270238841dc717f911bb07
Channels: stable-4.19

 Channel stable-4.19:
   Replaces:  lvms-operator.v4.18.3
   Skips:     lvms-operator.v4.18.0, lvms-operator.v4.18.1, lvms-operator.v4.18.2, lvms-operator.v4.19.0, lvms-operator.v4.19.1
   SkipRange: >=4.2.0 <4.19.3

Related Images:
 registry.redhat.io/lvms4/lvms-operator-bundle@sha256:b3d246dd8967cda961c3e011bc612885c31ceb153f270238841dc717f911bb07
 [lvms-must-gather] registry.redhat.io/lvms4/lvms-must-gather-rhel9@sha256:a780573a1ea56aea51f40b4af11497ad6598048eb0d72b931ca084fb132f1801
 [lvms-operator] registry.redhat.io/lvms4/lvms-rhel9-operator@sha256:102ec1179e6b8913c452690af228df32c9ccb8433462f58dc7dc5a0fee2034a9

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.

@openshift-ci openshift-ci Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Jul 28, 2026
@openshift-ci
openshift-ci Bot requested review from jaypoulz and jerpeter1 July 28, 2026 09:20
@openshift-ci

openshift-ci Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: pacevedom

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 Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Walkthrough

Adds hack/inspect-catalog.sh, a CLI utility that resolves architecture-specific OLM catalog images, extracts catalog entries, filters bundle metadata, enriches image data with commit IDs, and emits JSON or formatted text.

Changes

Catalog inspection utility

Layer / File(s) Summary
Input and image resolution
hack/inspect-catalog.sh
Parses CLI options, checks required commands, creates temporary storage, resolves architecture-specific manifests, and extracts catalog.json files from image layers.
Bundle processing and enrichment
hack/inspect-catalog.sh
Builds channel and upgrade metadata, collects related images, applies package and version filters, and optionally fetches vcs-ref commit IDs in parallel.
Output rendering
hack/inspect-catalog.sh
Prints normalized JSON or grouped human-readable package, channel, bundle, and related-image data.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: jaypoulz, jerpeter1

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant inspect_catalog
  participant skopeo
  participant CatalogLayers
  participant jq
  Operator->>inspect_catalog: provide catalog image and filters
  inspect_catalog->>skopeo: inspect manifest and copy image
  skopeo-->>CatalogLayers: provide image layers
  CatalogLayers-->>inspect_catalog: provide catalog.json files
  inspect_catalog->>jq: build and filter bundle metadata
  inspect_catalog->>skopeo: fetch vcs-ref labels when enabled
  inspect_catalog-->>Operator: return JSON or formatted report
Loading
🚥 Pre-merge checks | ✅ 15
✅ Passed checks (15 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Stable And Deterministic Test Names ✅ Passed PR only modifies hack/inspect-catalog.sh (a bash script). No Go test files or Ginkgo test patterns (It, Describe, Context, When) are present. Check not applicable.
Test Structure And Quality ✅ Passed PR adds bash utility script only, not Ginkgo test code; check for test structure quality does not apply.
Microshift Test Compatibility ✅ Passed PR adds only hack/inspect-catalog.sh, a Bash utility script with no Ginkgo tests. Custom check applies only to new e2e tests, not utility scripts.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No Ginkgo e2e tests added; PR contains only a Bash utility script (hack/inspect-catalog.sh). Check not applicable.
Topology-Aware Scheduling Compatibility ✅ Passed The PR adds hack/inspect-catalog.sh, a Bash utility script for inspecting OLM catalog images. It contains no Kubernetes manifests, deployment code, operator definitions, or scheduling constraints...
Ote Binary Stdout Contract ✅ Passed PASS — The PR changes only hack/inspect-catalog.sh, a Bash helper. No OTE binary or process-level Go setup code is changed.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The PR changes only hack/inspect-catalog.sh; no changed Go or test files and no added Ginkgo It/Describe/Context/When declarations were found.
No-Weak-Crypto ✅ Passed The script contains no weak cryptographic algorithms, custom crypto implementations, or unsafe secret comparisons. It only uses standard tools (skopeo, jq, tar) to inspect OLM manifests.
Container-Privileges ✅ Passed The PR adds only a Bash shell script utility (hack/inspect-catalog.sh). It contains no container or Kubernetes manifests with privileged configurations.
No-Sensitive-Data-In-Logs ✅ Passed The script logs only public container image metadata (digests, registry URLs, package versions, channel names, commit IDs). No passwords, tokens, API keys, PII, session IDs, internal hostnames, or...
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the addition of the inspect-catalog helper.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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/inspect-catalog.sh`:
- Around line 1-2: Add lightweight functional coverage for the filtering and
parsing logic in hack/inspect-catalog.sh, exercising resolve_arch_digest and
build_output with fixture inputs that include host:port stripping and
version-regex cases. Integrate the bats or shell test with the repository’s
existing verification workflow and ensure all tests pass.
- Around line 92-95: Update the external-command handling in the catalog
inspection flow, especially the skopeo inspect invocation near raw and the
skopeo copy invocation, so failures retain and surface stderr before set -e
terminates the script. Preserve successful stdout parsing and ensure
authentication, network, or invalid-reference errors are emitted with useful
command context instead of being suppressed.
- Around line 87-109: Update the base-image derivation in resolve_arch_digest()
so tag removal preserves registry ports, stripping only the tag from the final
path segment of the image reference. Keep the existing digest output format
unchanged, ensuring references such as localhost:5000/catalog:v1 resolve to
localhost:5000/catalog@${digest}.
- Around line 162-166: Update the bundle version filter in the jq pipeline to
use test() for regex-style matching against .name, while preserving the exact
$bundle_version comparison and the existing suffix match.
🪄 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)

Review profile: CHILL

Plan: Pro Plus

Run ID: 2b201e08-60f3-498d-9021-d472e900fe3c

📥 Commits

Reviewing files that changed from the base of the PR and between 33143de and af8fc10.

📒 Files selected for processing (1)
  • hack/inspect-catalog.sh

Comment thread hack/inspect-catalog.sh
Comment on lines +1 to +2
#!/bin/bash
set -euo pipefail

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

No test coverage for the filtering/parsing logic.

Two of the bugs flagged above (host:port stripping, version-regex condition) are exactly the kind a small functional test would catch. As per coding guidelines, "Contributions should include tests as needed, and all tests must pass before submission." Consider a lightweight bats/shell test (or a make verify-integrated check) exercising resolve_arch_digest and build_output against fixture inputs.

🤖 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/inspect-catalog.sh` around lines 1 - 2, Add lightweight functional
coverage for the filtering and parsing logic in hack/inspect-catalog.sh,
exercising resolve_arch_digest and build_output with fixture inputs that include
host:port stripping and version-regex cases. Integrate the bats or shell test
with the repository’s existing verification workflow and ensure all tests pass.

Source: Coding guidelines

Comment thread hack/inspect-catalog.sh
Comment on lines +87 to +109
resolve_arch_digest() {
local image="$1"
local arch="$2"

local raw
raw=$(skopeo inspect --raw "docker://${image}" 2>/dev/null)

local media_type
media_type=$(echo "${raw}" | jq -r '.mediaType // .schemaVersion' 2>/dev/null)

case "${media_type}" in
*index*|*list*)
local digest
digest=$(echo "${raw}" | jq -r \
--arg arch "${arch}" \
'.manifests[] | select(.platform.architecture == $arch) | .digest' 2>/dev/null | head -1)
if [[ -z "${digest}" ]]; then
echo "Error: no manifest found for architecture ${arch}" >&2
exit 1
fi
local base
base=$(echo "${image}" | sed 's/@sha256:.*//; s/:.*$//')
echo "${base}@${digest}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Reproduce the bug: sed strips the registry port instead of the tag
echo "localhost:5000/catalog:v1" | sed 's/@sha256:.*//; s/:.*$//'
# Expected: localhost:5000/catalog  -- Actual: localhost

Repository: openshift/lvm-operator

Length of output: 170


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant script section and demonstrate the sed behavior for several image refs.
sed -n '80,115p' hack/inspect-catalog.sh

echo "--- sed port/tag handling ---"
for ref in \
  registry.example.com:5000/catalog:v1 \
  quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:abc \
  localhost:5000/catalog:v1 \
  catalog:v1 \
  localhost:5000/catalog \
  app:v1 \
  a/b/c:v2; do
  printf '%s -> %s\n' "$ref" "$(printf '%s' "$ref" | sed 's/@sha256:.*//; s/:.*$/')"
done

Repository: openshift/lvm-operator

Length of output: 1751


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "--- sed behavior using bash command substitution ---"
for ref in \
  registry.example.com:5000/catalog:v1 \
  registry.example.com:5000/catalog \
  quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:abc \
  localhost:5000/catalog:v1 \
  catalog:v1 \
  localhost:5000/catalog \
  app:v1 \
  a/b/c:v2; do
  printf '%s -> %s\n' "$ref" "$(printf '%s' "$ref" | sed 's/@sha256:.*//; s/:.*$/')"
done

Repository: openshift/lvm-operator

Length of output: 906


Handle registry ports when stripping image tags.

In resolve_arch_digest(), sed 's/:.*$//' strips everything after the first :, so localhost:5000/catalog:v1 becomes localhost instead of localhost:5000/catalog. Use the last path segment to remove only the tag, otherwise the resolved ${base}@${digest} reference fed to skopeo copy will be invalid for ported registries.

🤖 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/inspect-catalog.sh` around lines 87 - 109, Update the base-image
derivation in resolve_arch_digest() so tag removal preserves registry ports,
stripping only the tag from the final path segment of the image reference. Keep
the existing digest output format unchanged, ensuring references such as
localhost:5000/catalog:v1 resolve to localhost:5000/catalog@${digest}.

Comment thread hack/inspect-catalog.sh Outdated
Comment on lines +92 to +95
raw=$(skopeo inspect --raw "docker://${image}" 2>/dev/null)

local media_type
media_type=$(echo "${raw}" | jq -r '.mediaType // .schemaVersion' 2>/dev/null)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

External command failures are completely silent.

Line 92 discards skopeo inspect --raw stderr, and line 123 discards both stdout and stderr from skopeo copy. Combined with set -e, any failure (auth, network, bad ref) exits the script immediately with zero diagnostic output — a rough experience for a tool whose whole purpose is inspection/troubleshooting.

🩹 Proposed fix: surface errors before exiting
     local raw
-    raw=$(skopeo inspect --raw "docker://${image}" 2>/dev/null)
+    raw=$(skopeo inspect --raw "docker://${image}") || {
+        echo "Error: failed to inspect ${image}" >&2
+        exit 1
+    }
-skopeo copy "docker://${RESOLVED_IMAGE}" "dir://${IMGDIR}" >/dev/null 2>&1
+if ! skopeo copy "docker://${RESOLVED_IMAGE}" "dir://${IMGDIR}" >/dev/null; then
+    echo "Error: failed to pull image ${RESOLVED_IMAGE}" >&2
+    exit 1
+fi

Also applies to: 123-123

🤖 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/inspect-catalog.sh` around lines 92 - 95, Update the external-command
handling in the catalog inspection flow, especially the skopeo inspect
invocation near raw and the skopeo copy invocation, so failures retain and
surface stderr before set -e terminates the script. Preserve successful stdout
parsing and ensure authentication, network, or invalid-reference errors are
emitted with useful command context instead of being suppressed.

Comment thread hack/inspect-catalog.sh Outdated
Comment on lines +162 to +166
[.[] | select(.schema == "olm.bundle") |
select(if $pkg != "" then .package == $pkg else true end) |
((.properties // [])[] | select(.type == "olm.package") | .value.version) as $bundle_version |
select(if $ver != "" then ($bundle_version == $ver or .name == (".*v" + $ver) or (.name | endswith("v" + $ver))) else true end) |
. as $bundle |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm equality vs regex-test semantics in jq
echo '{"name":"lvms-operator.v4.19.3"}' | jq '.name == (".*v" + "4.19.3")'   # false
echo '{"name":"lvms-operator.v4.19.3"}' | jq '.name | test(".*v" + "4.19.3")' # true

Repository: openshift/lvm-operator

Length of output: 171


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '145,175p' hack/inspect-catalog.sh
printf '\njq matches in file:\n'
rg -n "\.name ==" hack/inspect-catalog.sh

Repository: openshift/lvm-operator

Length of output: 1681


Use a regex test for name-based version matches.

.name == ("v" + $ver) still compares against the literal string ".*v4.19.3", so regex-style matching never fires. Use test() instead if matching versions in bundle names is intended.

♻️ Proposed fix
-        select(if $ver != "" then ($bundle_version == $ver or .name == (".*v" + $ver) or (.name | endswith("v" + $ver))) else true end) |
+        select(if $ver != "" then ($bundle_version == $ver or (.name | test(".*v" + $ver)) or (.name | endswith("v" + $ver))) else true end) |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[.[] | select(.schema == "olm.bundle") |
select(if $pkg != "" then .package == $pkg else true end) |
((.properties // [])[] | select(.type == "olm.package") | .value.version) as $bundle_version |
select(if $ver != "" then ($bundle_version == $ver or .name == (".*v" + $ver) or (.name | endswith("v" + $ver))) else true end) |
. as $bundle |
[.[] | select(.schema == "olm.bundle") |
select(if $pkg != "" then .package == $pkg else true end) |
((.properties // [])[] | select(.type == "olm.package") | .value.version) as $bundle_version |
select(if $ver != "" then ($bundle_version == $ver or (.name | test(".*v" + $ver)) or (.name | endswith("v" + $ver))) else true end) |
. as $bundle |
🤖 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/inspect-catalog.sh` around lines 162 - 166, Update the bundle version
filter in the jq pipeline to use test() for regex-style matching against .name,
while preserving the exact $bundle_version comparison and the existing suffix
match.

@codecov-commenter

codecov-commenter commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 54.23%. Comparing base (0d60aea) to head (6b11404).
⚠️ Report is 70 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2942      +/-   ##
==========================================
- Coverage   54.72%   54.23%   -0.49%     
==========================================
  Files          54       53       -1     
  Lines        4225     4239      +14     
==========================================
- Hits         2312     2299      -13     
- Misses       1732     1758      +26     
- Partials      181      182       +1     

see 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@pacevedom

Copy link
Copy Markdown
Contributor Author

/retest

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/inspect-catalog.sh`:
- Around line 103-106: Update the manifest digest extraction pipeline in
hack/inspect-catalog.sh to convert an unmatched architecture result from JSON
null to an empty value, using first // empty or an equivalent null check before
the existing empty validation. Ensure the subsequent image-reference
construction cannot emit `@null` for tag images.
- Around line 308-320: The catalog rendering in inspect-catalog.sh is only using
the first channel and first upgrade entry for each bundle, so update the jq flow
around the group_by(.channels[0]) block to expand each bundle across all of its
channels instead of collapsing to .channels[0]. Then, within the per-channel
output, select the matching upgrade_info item by channel before calling
format_upgrade, so the bundle image and upgrade metadata stay aligned for every
channel.
🪄 Autofix

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)

Review profile: CHILL

Plan: Pro Plus

Run ID: 8196ab08-d2a8-4279-8369-a836556f3879

📥 Commits

Reviewing files that changed from the base of the PR and between 75e59f9 and 6b11404.

📒 Files selected for processing (1)
  • hack/inspect-catalog.sh

Comment thread hack/inspect-catalog.sh
Comment on lines +103 to +106
'[.manifests[] |
select(.platform.architecture == $arch) |
.digest] | first' \
2>/dev/null)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)hack/inspect-catalog\.sh$|(^|/)Makefile$|(^|/)README' || true

echo
echo "== inspect-catalog relevant lines =="
if [ -f hack/inspect-catalog.sh ]; then
  nl -ba hack/inspect-catalog.sh | sed -n '80,120p'
fi

echo
echo "== jq first behavior =="
jq -nr '[] | first' || true
jq -nr '[' | jq '. as {msg: .} | empty' || true
printf 'jq 2>/dev/null null:'; jq -nr '[] | first | tostring' 2>/dev/null || true

echo
echo "== search null check patterns =="
rg -n "first|manifest\.digest|jq -n|r|`@null`|null" hack/inspect-catalog.sh 2>/dev/null || true

Repository: openshift/lvm-operator

Length of output: 357


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== inspect-catalog relevant lines =="
if [ -f hack/inspect-catalog.sh ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' hack/inspect-catalog.sh | sed -n '80,120p'
fi

echo
echo "== jq first behavior =="
jq -nr '[] | first' || true
printf '%s\n' 'jq 2>/dev/null null:'
jq -nr '[] | first | tostring' 2>/dev/null || true

echo
echo "== search related patterns =="
grep -nE 'first|manifest\.digest|jq|`@null`|null|MISSING|architecture|digest' hack/inspect-catalog.sh || true

Repository: openshift/lvm-operator

Length of output: 3401


Reject an unmatched architecture before building the image reference.

When no manifest matches arch, first outputs JSON null, and the empty check at line 107 does not reject it. Add first // empty or reject null before line 107 to avoid emitting @null for a tag image.

🤖 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/inspect-catalog.sh` around lines 103 - 106, Update the manifest digest
extraction pipeline in hack/inspect-catalog.sh to convert an unmatched
architecture result from JSON null to an empty value, using first // empty or an
equivalent null check before the existing empty validation. Ensure the
subsequent image-reference construction cannot emit `@null` for tag images.

Comment thread hack/inspect-catalog.sh
Comment on lines +308 to +320
group_by(.package)[] |
.[0].package as $pkg |
"Package: \($pkg)",
(group_by(.channels[0])[] |
.[0].channels[0] as $chan |
"",
" Channel: \($chan)",
" \("-" * 70)",
(sort_by(.version |
split(".") | map(tonumber? // 0))[] |
.image as $bundle_img |
(.upgrade_info[0] |
format_upgrade) as $ug |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate file and relevant lines"
wc -l hack/inspect-catalog.sh || true
sed -n '280,340p' hack/inspect-catalog.sh

echo
echo "Search for format_upgrade definition and channel metadata usage"
rg -n "format_upgrade|upgrade_info|group_by|flatten|channels" hack/inspect-catalog.sh

Repository: openshift/lvm-operator

Length of output: 2018


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Inspect channel metadata construction"
sed -n '130,205p' hack/inspect-catalog.sh

echo
echo "Read full jq script without helper definitions"
sed -n '1,230p' hack/inspect-catalog.sh

echo
echo "Search for generate jq script"
rg -n "jq --null-input|jq -n|channel_entries|upgrade_info|channels:" .

Repository: openshift/lvm-operator

Length of output: 8965


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Run read-only jq probe against a synthetic multi-channel catalog"
python3 - <<'PY'
import json
catalog = {
    "schema": "olm.package", "name": "pkg", "defaultChannel": "default",
    "channels": [{"name": "alpha", "head": "bundle-v1.0.0"}, {"name": "beta", "head": "bundle-v1.0.0"}]
}
channels = {
    "schema": "olm.channel", "name": "alpha", "entries": [
        {"name": "bundle-v1.0.0", "replaces": "alpha-0.1.0"}
    ]
}
channels2 = {
    "schema": "olm.channel", "name": "beta", "entries": [
        {"name": "bundle-v1.0.0", "replaces": "beta-0.1.0"}
    ]
}
bundle = {
    "schema": "olm.bundle", "name": "bundle-v1.0.0", "package": "pkg",
    "image": "sha256:aaaa", "relatedImages": [],
    "properties": [{"type": "olm.package", "value": {"package": "pkg", "version": "1.0.0"}}]
}
print(json.dumps([catalog, channels, channels2, bundle], indent=2))
PY

jq -n --slurpfile all <(python3 - <<'PY'
import json
catalog = {
    "schema": "olm.package", "name": "pkg", "defaultChannel": "default",
    "channels": [{"name": "alpha", "head": "bundle-v1.0.0"}, {"name": "beta", "head": "bundle-v1.0.0"}]
}
channels = {
    "schema": "olm.channel", "name": "alpha", "entries": [
        {"name": "bundle-v1.0.0", "replaces": "alpha-0.1.0"}
    ]
}
channels2 = {
    "schema": "olm.channel", "name": "beta", "entries": [
        {"name": "bundle-v1.0.0", "replaces": "beta-0.1.0"}
    ]
}
bundle = {
    "schema": "olm.bundle", "name": "bundle-v1.0.0", "package": "pkg",
    "image": "sha256:aaaa", "relatedImages": [],
    "properties": [{"type": "olm.package", "value": {"package": "pkg", "version": "1.0.0"}}]
}
print(json.dumps([catalog, channels, channels2, bundle]))
PY
) '
def channel_entries:
    [.[] | select(.schema == "olm.channel") |
        . as $ch | .entries[]? |
        {channel: $ch.name, bundle: .name, replaces: .replaces,
         skips: (.skips // []), skipRange: .skipRange}];

def get_version:
    [(.properties // [])[] |
        select(.type == "olm.package") | .value.version
    ] | first // "";

def short_sha: .;
def short_commit: .;
def strip_prefix: sub("^v"; "") | sub("^"; "");

. as $all |
channel_entries as $channels |
[.[] | select(.schema == "olm.bundle") |
    get_version as $bv |
    . as $bundle |
    {
        package: .package,
        name: .name,
        version: $bv,
        image: .image,
        channels: ([($channels[] |
            select(.bundle == $bundle.name) | .channel)] | unique),
        upgrade_info: [($channels[] |
            select(.bundle == $bundle.name) |
            {channel: .channel, replaces: .replaces,
             skips: .skips, skipRange: .skipRange})],
        relatedImages: [(.relatedImages // [])[] |
            {name: .name, image: .image}]
    }
] | sort_by(.package, .name)
'

Repository: openshift/lvm-operator

Length of output: 1213


Render every channel for a multi-channel bundle.

The catalog query stores one channels array and one upgrade_info array per bundle, so grouping by .channels[0] only publishes the first channel. upgrade_info[0] can also show upgrade metadata for a different channel. Expand each bundle per channel and select the upgrade_info entry whose channel matches the current channel.

🤖 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/inspect-catalog.sh` around lines 308 - 320, The catalog rendering in
inspect-catalog.sh is only using the first channel and first upgrade entry for
each bundle, so update the jq flow around the group_by(.channels[0]) block to
expand each bundle across all of its channels instead of collapsing to
.channels[0]. Then, within the per-channel output, select the matching
upgrade_info item by channel before calling format_upgrade, so the bundle image
and upgrade metadata stay aligned for every channel.

@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

@pacevedom: all tests passed!

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. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants