Skip to content

USHIFT-7189: CI Doctor image health information#199

Merged
openshift-merge-bot[bot] merged 12 commits into
openshift-eng:mainfrom
ggiguash:ci-doctor-image-health
Jun 26, 2026
Merged

USHIFT-7189: CI Doctor image health information#199
openshift-merge-bot[bot] merged 12 commits into
openshift-eng:mainfrom
ggiguash:ci-doctor-image-health

Conversation

@ggiguash

@ggiguash ggiguash commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Sample Report

report-lvm-operator-ci-doctor.html

Image Health UI

LVMS

image

MicroShift

image

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Added an Image Health tab to the CI Doctor HTML report with per-release/per-repository container image version (z-stream), architectures, grade badges, and freshness timestamps.
    • Added a latest only checkbox to hide non-latest rows.
    • Extended the console Summary output with an Image Health section when image data is available.
  • UI Improvements
    • Switched table rendering in the new tab to reusable, sortable data-table styles.
  • Chores
    • Introduced shared container catalog tooling and reused it across plugins via symlinks.

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 22, 2026
@openshift-ci

openshift-ci Bot commented Jun 22, 2026

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci

openshift-ci Bot commented Jun 22, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ggiguash

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

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds rh-catalog.sh Bash API client for Red Hat Container Catalog queries, filter_images.py Python filter with release-aware tag matching and freshness grade computation from ISO date ranges, extends doctor.sh to orchestrate image metadata collection into cached JSON files, and implements generalized data-table styling in create-report.py with a new interactive Image Health tab showing per-release/per-repo image versions and freshness grades plus latest-only filtering.

Changes

Container Image Health Reporting

Layer / File(s) Summary
rh-catalog.sh — Red Hat Catalog API client with subcommands
plugins/shared/scripts/rh-catalog.sh, plugins/lvms-ci/scripts/rh-catalog.sh, plugins/microshift-ci/scripts/rh-catalog.sh
New Bash script with set -euo pipefail, fetch_api() implementing curl with --fail and 60-second timeout, and subcommands id (outputs ._id), tags (delegates to Python filter), streams (outputs .content_stream_tags), and images (pipes JSON to Python filter with optional --tag). lvms-ci and microshift-ci scripts are symlinks to the shared implementation.
filter_images.py — Tag matching and freshness grade computation
plugins/shared/scripts/filter_images.py, plugins/lvms-ci/scripts/filter_images.py, plugins/microshift-ci/scripts/filter_images.py
New Python filter module with tag_matches_release() using digit-boundary regex for version matching, _current_freshness_grade() selecting active grade by parsing ISO date ranges in UTC, filter_tags() aggregating and optionally filtering image tag names, and filter_images() projecting per-image records with _id, sorted unique tags, architecture, truncated digest, and freshness_grade. lvms-ci and microshift-ci scripts are symlinks to the shared implementation.
doctor.sh — Image metadata collection orchestration
plugins/shared/scripts/doctor.sh
_component_repos() helper maps COMPONENT names to space-separated catalog repository identifiers. cmd_finalize new phase creates ${WORKDIR}/images/, queries catalog IDs via rh-catalog.sh <repo> id, and fetches per-release image JSON via rh-catalog.sh <repo> images --tag <release>, writing empty ID and [] fallbacks on failure.
Report data-table styling and grade constants
plugins/shared/scripts/create-report.py
_GRADE_ORDER and _GRADE_CSS constants rank freshness grades and map to CSS badge classes. Replaces bugs-table-specific CSS with reusable .data-table styles including clickable sort headers and badge classes (grade-a through grade-f, grade-na). Adds filterLatestImages() JavaScript to toggle row visibility. Retargets table-sort initialization from .bugs-table to .data-table. Updates bugs table renderer to emit class="data-table".
Image Health tab rendering and report integration
plugins/shared/scripts/create-report.py
load_images_data() reads cached image JSON from workdir/images/; build_images_tab_data() filters by release, derives z-stream display tags, computes worst freshness grade across architectures per version, and merges per-architecture entries; render_images_section() generates per-release/per-repo tables with grade badges and data-latest attributes. generate_html() signature extended with images_tab_data parameter; template includes "Image Health" tab button and content container. main() calls load_images_data(), build_images_tab_data(), passes to generate_html(), and extends console Summary with Image Health section listing per-release repos and worst grades.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • pacevedom
🚥 Pre-merge checks | ✅ 9 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Ai-Attribution ⚠️ Warning Commit c0f68e9 subject "Address Claude code review" explicitly mentions AI tool usage, but lacks required Assisted-by or Generated-by trailers for Red Hat attribution. Add Assisted-by or Generated-by trailer to the commit message for proper Red Hat AI attribution (e.g., "Assisted-by: Claude noreply@anthropic.com").
✅ Passed checks (9 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'USHIFT-7189: CI Doctor image health information' directly and clearly describes the main change—adding Image Health information to the CI Doctor tool. The changeset implements a new Image Health tab with related functionality.
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.
No-Weak-Crypto ✅ Passed No weak cryptography (MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB), custom crypto implementations, or non-constant-time secret comparisons found in any modified files.
Container-Privileges ✅ Passed This PR contains only Bash and Python utility scripts for CI tooling (create-report.py, doctor.sh, rh-catalog.sh, filter_images.py), not container or Kubernetes manifests. No container privileges c...
No-Sensitive-Data-In-Logs ✅ Passed No sensitive data exposure found in logging. The only console output includes public Red Hat catalog IDs used in public URLs, no API credentials, tokens, or PII.
No-Hardcoded-Secrets ✅ Passed No hardcoded secrets found. All APIs use public endpoints without embedded credentials, no password/token/key variables contain string literals, and no base64 or suspicious credential patterns dete...
No-Injection-Vectors ✅ Passed No injection vectors found. Code uses safe patterns: HTML escaping via html.escape, re.escape for regex, proper variable quoting in bash, hardcoded repo mappings, and safe json.load—zero instances...

✏️ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
plugins/shared/scripts/create-report.py (1)

724-756: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Unused component parameter in function signature.

The component parameter is declared but never referenced in the function body. The docstring confirms repos are discovered from filenames rather than a component mapping.

🔧 Suggested fix
-def load_images_data(workdir, component, releases):
+def load_images_data(workdir, releases):

And update the call site at line 1708:

-    images_data = load_images_data(workdir, component, releases)
+    images_data = load_images_data(workdir, releases)
🤖 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 `@plugins/shared/scripts/create-report.py` around lines 724 - 756, The function
load_images_data has a component parameter in its signature that is never used
within the function body. Remove the component parameter from the
load_images_data function signature since the function discovers repositories
from filenames rather than a component mapping (as documented in the docstring).
Also update the call site at line 1708 to remove the component argument when
invoking load_images_data.
🤖 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 `@plugins/shared/scripts/doctor.sh`:
- Around line 27-33: The _component_repos function currently returns
space-delimited strings which rely on unquoted variable splitting for parsing.
Refactor this function to use bash arrays instead, where each repository is a
separate array element. Then update the code that uses the output from
_component_repos (around the area where repos are consumed) to properly handle
and iterate over the array using proper quoting patterns like "${array[@]}" to
avoid word splitting issues and ensure compliance with shell coding guidelines.

In `@plugins/shared/scripts/rh-catalog.sh`:
- Line 1: The shebang at the top of the rh-catalog.sh file currently uses
#!/bin/bash but according to the repository's CONTRIBUTING.md guidelines, it
must use #!/usr/bin/bash instead. Replace the shebang line with the correct path
to the bash interpreter as specified in the coding standards.
- Around line 25-37: The curl command in the fetch_api function lacks a timeout
parameter, allowing it to block indefinitely on stalled connections and
preventing the retry loop from advancing. Add a timeout option to the curl
command (such as --max-time or --connect-timeout) to ensure the request fails
after a reasonable duration if the connection stalls, allowing the loop to
proceed to the next retry attempt.

---

Nitpick comments:
In `@plugins/shared/scripts/create-report.py`:
- Around line 724-756: The function load_images_data has a component parameter
in its signature that is never used within the function body. Remove the
component parameter from the load_images_data function signature since the
function discovers repositories from filenames rather than a component mapping
(as documented in the docstring). Also update the call site at line 1708 to
remove the component argument when invoking load_images_data.
🪄 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: Enterprise

Run ID: b1282fa0-c094-4050-9dde-9e49b9bbcbe0

📥 Commits

Reviewing files that changed from the base of the PR and between b9b061f and fb7f32b.

📒 Files selected for processing (3)
  • plugins/shared/scripts/create-report.py
  • plugins/shared/scripts/doctor.sh
  • plugins/shared/scripts/rh-catalog.sh

Comment thread plugins/shared/scripts/doctor.sh
Comment thread plugins/shared/scripts/rh-catalog.sh
Comment thread plugins/shared/scripts/rh-catalog.sh
@coderabbitai coderabbitai Bot added the ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review label Jun 22, 2026
@ggiguash ggiguash force-pushed the ci-doctor-image-health branch from 905ddb7 to c0f68e9 Compare June 23, 2026 07:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 `@plugins/shared/scripts/filter_images.py`:
- Around line 42-48: The issue is that datetime.fromisoformat() on naive
timestamp strings (like "2024-06-01" or "2024-06-01T12:00:00") produces naive
datetimes, which cannot be compared with timezone-aware datetimes, causing the
comparison on line 47 to silently fail. Convert the parsed start_dt and end_dt
to timezone-aware datetimes before performing the comparison, handling various
input formats including date-only strings, naive ISO timestamps, and Z-notation.
Additionally, add test cases covering naive ISO string inputs, Z-notation
timestamps, and aware datetime comparisons to validate the parsing and
comparison logic works correctly per CONTRIBUTING.md requirements.
- Line 88: The sorting of tags on line 88 uses only `len` as the sort key, which
is unstable when multiple tags have the same length since set iteration order is
nondeterministic. This causes `tags[0]` used on line 96 to vary between runs.
Modify the `sorted(set(all_tags), key=len)` call to use a tuple key that sorts
by length first, then by the tag string itself alphabetically as a secondary
sort criterion to ensure deterministic ordering regardless of set iteration
order.
🪄 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: Enterprise

Run ID: 6901d722-21b3-4954-841a-8ed341ac691d

📥 Commits

Reviewing files that changed from the base of the PR and between 905ddb7 and c0f68e9.

📒 Files selected for processing (6)
  • plugins/lvms-ci/scripts/filter_images.py
  • plugins/microshift-ci/scripts/filter_images.py
  • plugins/shared/scripts/create-report.py
  • plugins/shared/scripts/doctor.sh
  • plugins/shared/scripts/filter_images.py
  • plugins/shared/scripts/rh-catalog.sh
✅ Files skipped from review due to trivial changes (1)
  • plugins/microshift-ci/scripts/filter_images.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/shared/scripts/doctor.sh
  • plugins/shared/scripts/create-report.py

Comment thread plugins/shared/scripts/filter_images.py Outdated
Comment thread plugins/shared/scripts/filter_images.py Outdated
@ggiguash ggiguash force-pushed the ci-doctor-image-health branch from c0f68e9 to db63ceb Compare June 23, 2026 11:44
@ggiguash ggiguash force-pushed the ci-doctor-image-health branch from b15db97 to a7f735d Compare June 26, 2026 08:29
@ggiguash ggiguash marked this pull request as ready for review June 26, 2026 09:05
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 26, 2026
@ggiguash ggiguash force-pushed the ci-doctor-image-health branch from bd862c3 to 53316d6 Compare June 26, 2026 09:06
@kasturinarra

kasturinarra commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Couple of generic review comments:

  • I would still prefer the report this way as it provides much more clarity than what is attached in the PR
image
  • I am not sure if we really need s390x and ppc64le for lvms because we do not really test them, having amd and arm is sufficient.

@kasturinarra

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jun 26, 2026
@openshift-merge-bot openshift-merge-bot Bot merged commit d06c004 into openshift-eng:main Jun 26, 2026
5 checks passed
@ggiguash ggiguash deleted the ci-doctor-image-health branch June 27, 2026 04:21
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. lgtm Indicates that a PR is ready to be merged. ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants