Skip to content

Archive the must-gather collected#605

Merged
dbasunag merged 2 commits intoopendatahub-io:mainfrom
dbasunag:mgather
Sep 12, 2025
Merged

Archive the must-gather collected#605
dbasunag merged 2 commits intoopendatahub-io:mainfrom
dbasunag:mgather

Conversation

@dbasunag
Copy link
Copy Markdown
Collaborator

@dbasunag dbasunag commented Sep 10, 2025

Description

How Has This Been Tested?

Merge criteria:

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

Summary by CodeRabbit

  • New Features

    • Must-gather collections are automatically zipped and moved to the target directory.
    • Archive files use standardized names mg-{test_start_time}, defaulting to mg-0 when unavailable.
    • Temporary collection folders are removed after archiving.
  • Refactor

    • Simplified must-gather image resolution; architecture selection removed.
    • If no image is found, collection is skipped with clearer logging.
  • Documentation

    • Added “Must gather” usage and ARCHIVE_MUST_GATHER instructions.

@dbasunag dbasunag requested a review from a team as a code owner September 10, 2025 21:18
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 10, 2025

📝 Walkthrough

Walkthrough

The must-gather collection was refactored: image resolution now reads relatedImages from the installed CSV; collection output is archived into a ZIP and moved to the target directory. The API changed to accept base_file_name and remove architecture. Several infra helper functions were removed and the test hook now passes base_file_name.

Changes

Cohort / File(s) Summary
Test hook update
conftest.py
Calls collect_rhoai_must_gather with new keyword base_file_name=f"mg-{test_start_time}" (defaults to mg-0 if test_start_time unavailable); other args unchanged.
Infra helpers removal
utilities/infra.py
Removed public helpers: get_rhods_csv_version, get_openshift_pull_secret, generate_openshift_pull_secret_file, get_oc_image_info; removed related imports (base64, tempfile, JSONDecodeError). Remaining utilities (e.g., get_machine_platform) unchanged.
Must-gather refactor and API changes
utilities/must_gather_collector.py
Replaced image resolution with get_rhods_operator_installed_csv/relatedImages lookup for odh-must-gather; removed architecture and pull-secret logic. Updated signatures: get_must_gather_image_info() -> str and collect_rhoai_must_gather(base_file_name, target_dir, since, save_collection_output=True) -> None. Collection now archives the output to a ZIP named from base_file_name, moves the ZIP to target_dir, and cleans up original files; logs updated accordingly.
Documentation
docs/GETTING_STARTED.md
Added "Must gather" usage section describing --collect-must-gather, default archiving behavior, and ARCHIVE_MUST_GATHER env var; added two bullets on benefits of local oc binary.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Archive the must-gather collected" points at the PR’s primary change — the must-gather collection is now archived and moved to the target directory — so it correctly reflects the main behavior change rather than unrelated edits. It is short and focused, though the wording is slightly awkward grammatically. Overall it communicates the intent clearly enough for a reviewer scanning history.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

❤️ Share

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

@github-actions
Copy link
Copy Markdown

The following are automatically added/executed:

  • PR size label.
  • Run pre-commit
  • Run tox
  • Add PR author as the PR assignee
  • Build image based on the PR

Available user actions:

  • To mark a PR as WIP, add /wip in a comment. To remove it from the PR comment /wip cancel to the PR.
  • To block merging of a PR, add /hold in a comment. To un-block merging of PR comment /hold cancel.
  • To mark a PR as approved, add /lgtm in a comment. To remove, add /lgtm cancel.
    lgtm label removed on each new commit push.
  • To mark PR as verified comment /verified to the PR, to un-verify comment /verified cancel to the PR.
    verified label removed on each new commit push.
  • To Cherry-pick a merged PR /cherry-pick <target_branch_name> to the PR. If <target_branch_name> is valid,
    and the current PR is merged, a cherry-picked PR would be created and linked to the current PR.
  • To build and push image to quay, add /build-push-pr-image in a comment. This would create an image with tag
    pr-<pr_number> to quay repository. This image tag, however would be deleted on PR merge or close action.
Supported labels

{'/build-push-pr-image', '/lgtm', '/wip', '/cherry-pick', '/hold', '/verified'}

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
conftest.py (1)

450-456: Make archive name collision-proof and ensure target dir exists.

If DB lookup fails, multiple failures across tests could all use mg-0. Also, rely on oc to create dest dir is brittle. Pre-create the directory and make the archive name unique.

-            collect_rhoai_must_gather(
-                base_file_name=f"mg-{test_start_time}",
-                since=calculate_must_gather_timer(test_start_time=test_start_time),
-                target_dir=os.path.join(get_must_gather_collector_dir(), "pytest_exception_interact"),
-            )
+            target_dir = os.path.join(get_must_gather_collector_dir(), "pytest_exception_interact")
+            os.makedirs(target_dir, exist_ok=True)
+            base_file_name = f"mg-{test_start_time}-{shortuuid.uuid()[:8]}"
+            collect_rhoai_must_gather(
+                base_file_name=base_file_name,
+                since=calculate_must_gather_timer(test_start_time=test_start_time),
+                target_dir=target_dir,
+            )
utilities/must_gather_collector.py (3)

152-156: Sync docstring with new API (removed architecture, no return value).

Current docstring mentions architecture and a string return that no longer exist.

 def collect_rhoai_must_gather(
     base_file_name: str,
     target_dir: str,
     since: int,
     save_collection_output: bool = True,
 ) -> None:
@@
-    Args:
-        base_file_name: (str): Base file name for must-gather compressed file
+    Args:
+        base_file_name (str): Base file name (without extension) for the archive
         target_dir (str): Directory to store the must-gather output
         since (int): Time in seconds to collect logs from
         save_collection_output (bool, optional): Whether to save must-gather command output. Defaults to True.
-        architecture (str, optional): Target architecture for must-gather image. Defaults to "linux/amd64".
-
-    Returns:
-        str: Path to the must-gather output directory, or empty string if collection is skipped
+    Returns:
+        None

Also applies to: 161-169


188-188: Clarify error message.

Minor grammar and clarity tweak.

-        LOGGER.error("No must-gather image is found from the csv. Must-gather collection would be skipped.")
+        LOGGER.error("No must-gather image found in the installed CSV; skipping must-gather collection.")

110-113: Quote component_name to avoid shell injection if ever user-sourced.

Low risk today, but quoting is cheap and safer.

-    if component_name:
-        must_gather_command += f" -- 'export COMPONENT={component_name}; /usr/bin/gather' "
+    if component_name:
+        must_gather_command += f" -- 'export COMPONENT={shlex.quote(component_name)}; /usr/bin/gather' "
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91fc08c and 5f7d91e.

📒 Files selected for processing (3)
  • conftest.py (1 hunks)
  • utilities/infra.py (0 hunks)
  • utilities/must_gather_collector.py (3 hunks)
💤 Files with no reviewable changes (1)
  • utilities/infra.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-13T17:27:26.289Z
Learnt from: dbasunag
PR: opendatahub-io/opendatahub-tests#240
File: conftest.py:328-335
Timestamp: 2025-05-13T17:27:26.289Z
Learning: In the opendatahub-tests codebase, py_config["must_gather_collector"]["must_gather_base_directory"] is never empty as it's set during pytest_sessionstart() by combining get_base_dir() with BASE_DIRECTORY_NAME="must-gather-collected", making it safe to use in directory operations.

Applied to files:

  • conftest.py
  • utilities/must_gather_collector.py
📚 Learning: 2025-05-13T17:27:26.289Z
Learnt from: dbasunag
PR: opendatahub-io/opendatahub-tests#240
File: conftest.py:328-335
Timestamp: 2025-05-13T17:27:26.289Z
Learning: In the opendatahub-tests codebase, py_config["must_gather_collector"]["must_gather_base_directory"] is never empty as it's set during pytest_sessionstart() by combining get_base_dir() with BASE_DIRECTORY_NAME, making it safe to use in directory operations.

Applied to files:

  • conftest.py
  • utilities/must_gather_collector.py
🧬 Code graph analysis (1)
utilities/must_gather_collector.py (1)
utilities/infra.py (1)
  • get_rhods_operator_installed_csv (1016-1022)

sheltoncyril
sheltoncyril previously approved these changes Sep 10, 2025
Copy link
Copy Markdown
Contributor

@sheltoncyril sheltoncyril left a comment

Choose a reason for hiding this comment

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

/lgtm

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
utilities/must_gather_collector.py (2)

136-148: Harden CSV parsing and fix misleading/typo log.

Avoid AttributeError when relatedImages is missing; log when CSV is absent; fix “RHAOI” → “RHOAI”; safely read image keys.

 def get_must_gather_image_info() -> str:
-    csv_object = get_rhods_operator_installed_csv()
-    if not csv_object:
-        return ""
-    must_gather_image = [
-        image["image"] for image in csv_object.instance.spec.relatedImages if "odh-must-gather" in image["image"]
-    ]
-    if not must_gather_image:
-        LOGGER.warning(
-            "No RHAOI CSV found. Potentially ODH cluster and must-gather collection is not relevant for this cluster"
-        )
-        return ""
-    return must_gather_image[0]
+    csv_object = get_rhods_operator_installed_csv()
+    if not csv_object:
+        LOGGER.warning("No installed RHOAI/ODH CSV found; skipping must-gather image resolution.")
+        return ""
+    try:
+        related_images = getattr(csv_object.instance.spec, "relatedImages", []) or []
+    except Exception:
+        related_images = []
+    images = [img.get("image", "") for img in related_images if "odh-must-gather" in img.get("image", "")]
+    if not images:
+        LOGGER.warning("No odh-must-gather image found in installed CSV relatedImages; skipping collection.")
+        return ""
+    return images[0]

169-186: Write archive directly into target_dir; make toggle case-insensitive; use root_dir to avoid path issues.

Pre-create target_dir, emit archive in-place, remove extra copy/unlink, and accept common truthy values.

-    must_gather_image = get_must_gather_image_info()
+    must_gather_image = get_must_gather_image_info()
     if must_gather_image:
-        output = run_must_gather(image_url=must_gather_image, target_dir=target_dir, since=f"{since}s")
+        os.makedirs(target_dir, exist_ok=True)
+        output = run_must_gather(image_url=must_gather_image, target_dir=target_dir, since=f"{since}s")
         if save_collection_output:
             with open(os.path.join(target_dir, "output.log"), "w") as _file:
                 _file.write(output)
-        # get must gather directory to archive
-        path = get_must_gather_output_dir(must_gather_path=target_dir)
-        if os.getenv("ARCHIVE_MUST_GATHER", "true") == "true":
-            # archive the folder and get the zip file's name
-            file_name = shutil.make_archive(base_name=base_file_name, format="zip", base_dir=path)
-            # remove the folder that was archived
-            shutil.rmtree(path=path, ignore_errors=True)
-            # copy back the archived file to the same path
-            dest_file = os.path.join(target_dir, file_name)
-            shutil.copy(src=file_name, dst=dest_file)
-            LOGGER.info(f"{dest_file} is collected successfully")
-            os.unlink(file_name)
+        path = get_must_gather_output_dir(must_gather_path=target_dir)
+        archive_enabled = os.getenv("ARCHIVE_MUST_GATHER", "true").strip().lower() in {"1", "true", "yes", "y"}
+        if archive_enabled:
+            archive_base = os.path.join(target_dir, base_file_name)
+            archive_path = shutil.make_archive(base_name=archive_base, format="zip", root_dir=path)
+            shutil.rmtree(path=path, ignore_errors=True)
+            LOGGER.info(f"{archive_path} is collected successfully")
🧹 Nitpick comments (3)
docs/GETTING_STARTED.md (1)

44-58: Clarify toggle semantics and hyphenate “must-gather”.

  • Make env-var behavior explicit (case-insensitive truthy/falsey) to match intended UX.
  • Use consistent “must-gather” spelling.
-## Must gather
+## Must-gather
@@
-By default, the collected must-gather would be archived. To skip archiving, please set environment variable
-ARCHIVE_MUST_GATHER to any value other than "true". e.g.
+By default, the collected must-gather is archived. To skip archiving, set the
+ARCHIVE_MUST_GATHER environment variable to a falsey value (e.g., "false", "0", "no"; case-insensitive). For example:
@@
-export ARCHIVE_MUST_GATHER="false"
+export ARCHIVE_MUST_GATHER=false
conftest.py (1)

452-455: Make archive name collision-proof when test_start_time is 0 or reused.

Add a short unique suffix (and include phase) to avoid overwriting across retries/multiple failures.

-                base_file_name=f"mg-{test_start_time}",
+                base_file_name=f"mg-{test_start_time}-{report.when}-{shortuuid.uuid()[:6]}",
utilities/must_gather_collector.py (1)

166-168: Docstring return type is stale (function returns None).

Update Returns section to avoid confusion.

-    Returns:
-        str: Path to the must-gather output directory, or empty string if collection is skipped
+    Returns:
+        None
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f7d91e and 0f59377.

📒 Files selected for processing (4)
  • conftest.py (1 hunks)
  • docs/GETTING_STARTED.md (1 hunks)
  • utilities/infra.py (0 hunks)
  • utilities/must_gather_collector.py (2 hunks)
💤 Files with no reviewable changes (1)
  • utilities/infra.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-13T17:27:26.289Z
Learnt from: dbasunag
PR: opendatahub-io/opendatahub-tests#240
File: conftest.py:328-335
Timestamp: 2025-05-13T17:27:26.289Z
Learning: In the opendatahub-tests codebase, py_config["must_gather_collector"]["must_gather_base_directory"] is never empty as it's set during pytest_sessionstart() by combining get_base_dir() with BASE_DIRECTORY_NAME="must-gather-collected", making it safe to use in directory operations.

Applied to files:

  • conftest.py
  • utilities/must_gather_collector.py
📚 Learning: 2025-05-13T17:27:26.289Z
Learnt from: dbasunag
PR: opendatahub-io/opendatahub-tests#240
File: conftest.py:328-335
Timestamp: 2025-05-13T17:27:26.289Z
Learning: In the opendatahub-tests codebase, py_config["must_gather_collector"]["must_gather_base_directory"] is never empty as it's set during pytest_sessionstart() by combining get_base_dir() with BASE_DIRECTORY_NAME, making it safe to use in directory operations.

Applied to files:

  • conftest.py
  • utilities/must_gather_collector.py
🧬 Code graph analysis (1)
utilities/must_gather_collector.py (1)
utilities/infra.py (1)
  • get_rhods_operator_installed_csv (1016-1022)

@dbasunag
Copy link
Copy Markdown
Collaborator Author

/build-push-pr-image

@github-actions
Copy link
Copy Markdown

Status of building tag pr-605: success.
Status of pushing tag pr-605 to image registry: success.

Copy link
Copy Markdown
Contributor

@kpunwatk kpunwatk left a comment

Choose a reason for hiding this comment

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

/lgtm

Copy link
Copy Markdown
Contributor

@sheltoncyril sheltoncyril left a comment

Choose a reason for hiding this comment

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

/lgtm

Copy link
Copy Markdown
Contributor

@fege fege left a comment

Choose a reason for hiding this comment

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

/lgtm

@dbasunag dbasunag merged commit 5f9b797 into opendatahub-io:main Sep 12, 2025
12 checks passed
@dbasunag dbasunag deleted the mgather branch September 12, 2025 13:23
@github-actions
Copy link
Copy Markdown

Status of building tag latest: success.
Status of pushing tag latest to image registry: success.

@dbasunag
Copy link
Copy Markdown
Collaborator Author

/cherry-pcik 2.24

@dbasunag
Copy link
Copy Markdown
Collaborator Author

/cherry-pick 2.24

rhods-ci-bot pushed a commit that referenced this pull request Sep 12, 2025
@rhods-ci-bot
Copy link
Copy Markdown
Contributor

Cherry pick action created PR #607 successfully 🎉!
See: https://github.com/opendatahub-io/opendatahub-tests/actions/runs/17682709582

dbasunag added a commit that referenced this pull request Sep 12, 2025
Co-authored-by: Debarati Basu-Nag <dbasunag@redhat.com>
mwaykole pushed a commit to mwaykole/opendatahub-tests that referenced this pull request Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants