Skip to content

feat: implement software reporting for containers #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

btraven00
Copy link
Collaborator

@btraven00 btraven00 commented Mar 14, 2025

We use a combination of container URI, tag and hash of the image used in the execution

Summary by CodeRabbit

  • New Features

    • Enhanced container image handling to ensure complete image identifiers by automatically appending default tags when necessary.
    • Improved software reporting with detailed image information, supporting multiple container runtimes.
  • Tests

    • Added new tests to validate the updated image reporting and container management functionality, including checks for software name and version format.

Copy link

coderabbitai bot commented Mar 14, 2025

📝 Walkthrough

Walkthrough

The changes add functionality for handling container images within the deployment plugin. A private method in the container environment class now parses an image URI and appends a default tag if necessary. The shell command decoration routine is updated to incorporate this information, and the software reporting method now returns a report containing the image URI and tag. In addition, separate manager classes for UDocker and Podman containers are introduced to perform image inspection via subprocess calls. A new test method is added to verify the correctness of the software report’s details.

Changes

File(s) Change Summary
src/snakemake_software_deployment_plugin_container/__init__.py - Added _get_image_uri_and_tag in ContainerEnv for parsing image URIs
- Modified decorate_shellcmd to use the new parsing method
- Updated report_software to return a report with image URI, tag, and image ID via inspection
- Introduced UDockerManager and PodmanManager classes with inspect_image methods handling subprocess calls and error checking
tests/test_plugin.py - Added test_report_software in TestUDockerContainer to validate the report software functionality by checking image name, version format, and tag prefix

Sequence Diagram(s)

sequenceDiagram
    participant Env as ContainerEnv
    participant Spec as Image Spec
    participant Shell as Shell Command
    participant Mgr as {PodmanManager / UDockerManager}
    participant Report as SoftwareReport

    Env->>Spec: _get_image_uri_and_tag()
    Spec-->>Env: Return image URI and tag
    Env->>Shell: decorate_shellcmd(cmd) using image info
    Shell-->>Env: Executes decorated command
    Env->>Mgr: Determine container type and call inspect_image(image_id)
    Mgr-->>Env: Return full image ID (if available)
    Env->>Report: Construct SoftwareReport with image URI, tag, & image ID
Loading

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Uses image tag (provided) and image hash (after inspection of the local
registry).
@btraven00 btraven00 force-pushed the feat/software-report branch from 206d83a to d3f1664 Compare March 14, 2025 18:30
Copy link

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🧹 Nitpick comments (3)
tests/test_plugin.py (2)

57-74: Consider verifying the return code of sp.run.

Currently, the call to sp.run does not check for errors or non-zero exit codes, which may mask potential issues with fetching the container image or running the command. Adding check=True or verifying result.returncode helps ensure that failures are captured.

-sp.run(decorated_cmd, shell=True, executable=self.shell_executable)
+result = sp.run(decorated_cmd, shell=True, executable=self.shell_executable)
+assert result.returncode == 0, f"Container run failed with exit code {result.returncode}"

110-126: Apply the same validation in Podman tests.

Similar to the UDocker container test, verifying the exit code here helps detect failures during container fetching or command execution.

-sp.run(decorated_cmd, shell=True, executable=self.shell_executable)
+result = sp.run(decorated_cmd, shell=True, executable=self.shell_executable)
+assert result.returncode == 0, f"Container run failed with exit code {result.returncode}"
src/snakemake_software_deployment_plugin_container/__init__.py (1)

198-199: Streamline conditional checks.

The nested condition for rootfs and diff_ids can be simplified to a single check for improved readability, as suggested by static analysis.

-if "rootfs" in inspect_data and "diff_ids" in inspect_data["rootfs"]:
-    if len(inspect_data["rootfs"]["diff_ids"]) > 0:
+if ("rootfs" in inspect_data
+    and "diff_ids" in inspect_data["rootfs"]
+    and len(inspect_data["rootfs"]["diff_ids"]) > 0):
🧰 Tools
🪛 Ruff (0.8.2)

198-199: Use a single if statement instead of nested if statements

(SIM102)

🛑 Comments failed to post (2)
src/snakemake_software_deployment_plugin_container/__init__.py (2)

85-92: ⚠️ Potential issue

Ensure support for custom registries containing multiple colons.

At present, _get_image_uri_and_tag raises errors for URIs that contain a port or additional segments (e.g., registry.company.org:5000/myimage:tag). This limitation restricts valid URIs to strictly one or two colon-delimited parts. Consider a more robust parsing strategy that handles custom registry formats:

-def _get_image_uri_and_tag(self) -> Iterable[str]:
-    parts = self.spec.image_uri.split(":")
-    if len(parts) > 2:
-        raise WorkflowError("Malformed image URI", self.spec.image_uri)
-    if len(parts) != 2:
-        parts += ["latest"]
-    return parts
+def _get_image_uri_and_tag(self) -> Iterable[str]:
+    # Example: handle optional port and tag by splitting on the rightmost colon
+    if ":" not in self.spec.image_uri:
+        return [self.spec.image_uri, "latest"]
+    repo_tag_split = self.spec.image_uri.rsplit(":", 1)
+    if len(repo_tag_split) == 1:
+        # no tag, default to 'latest'
+        return [repo_tag_split[0], "latest"]
+    return repo_tag_split

Also applies to: 118-118


159-179: ⚠️ Potential issue

Use both the repository name and tag when inspecting images.

The code currently inspects images using only the repository name (e.g., rep[0]). If an explicit tag is specified (e.g., alpine:3.17), inspection might fail without including it. Consider revising the call to pm.inspect_image to include both parts:

-uri, tag = self._get_image_uri_and_tag()
...
-full_image_id = pm.inspect_image(uri)
+repo, tag = self._get_image_uri_and_tag()
+full_image_id = pm.inspect_image(f"{repo}:{tag}")

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@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

🧹 Nitpick comments (2)
src/snakemake_software_deployment_plugin_container/__init__.py (2)

180-215: Well-structured UDockerManager class with comprehensive error handling.

The class properly handles image inspection and extraction of the hash identifier. The error handling covers multiple potential failure points.

Consider these improvements:

  1. Combine the nested if statements on lines 197-199 into a single condition:
-            if "rootfs" in inspect_data and "diff_ids" in inspect_data["rootfs"]:
-                if len(inspect_data["rootfs"]["diff_ids"]) > 0:
+            if "rootfs" in inspect_data and "diff_ids" in inspect_data["rootfs"] and len(inspect_data["rootfs"]["diff_ids"]) > 0:
  1. Consider using a logger instead of print statements for better error handling:
-            print(f"error: failed to extract hash for udocker image {image_id}: {e}")
+            import logging
+            logger = logging.getLogger(__name__)
+            logger.warning(f"Failed to extract hash for udocker image {image_id}: {e}")
🧰 Tools
🪛 Ruff (0.8.2)

197-198: Use a single if statement instead of nested if statements

(SIM102)


217-237: Well-implemented PodmanManager class for container inspection.

The class properly extracts the image ID for Podman containers and includes comprehensive error handling for different failure scenarios.

Consider using a logger instead of print statements for more consistent error handling:

-            print(f"error: failed to inspect image {image_id}: {e}")
+            import logging
+            logger = logging.getLogger(__name__)
+            logger.warning(f"Failed to inspect image {image_id}: {e}")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 206d83a and d3f1664.

📒 Files selected for processing (2)
  • src/snakemake_software_deployment_plugin_container/__init__.py (6 hunks)
  • tests/test_plugin.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.py`: Do not try to improve formatting. Do not suggest ...

**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

  • src/snakemake_software_deployment_plugin_container/__init__.py
  • tests/test_plugin.py
🪛 Ruff (0.8.2)
src/snakemake_software_deployment_plugin_container/__init__.py

197-198: Use a single if statement instead of nested if statements

(SIM102)

🔇 Additional comments (8)
tests/test_plugin.py (2)

57-73: Well-designed test for UDocker container software reporting.

The test effectively verifies the container's software reporting functionality by:

  1. Getting the environment and decorating a test command
  2. Running the command to ensure the image is fetched
  3. Validating that the reported software has the expected name and version format

The assertions correctly check that the container name is "alpine" and that the version follows the expected format of "tag/hash".


110-126: Well-implemented test for Podman container software reporting.

This test mirrors the UDocker test with appropriate comments explaining the purpose and expected format of the software report. The comments clarify that the version follows the format "tag/hash" (e.g., "latest/aded1e1a5b37").

Both tests ensure consistency in software reporting across different container backends.

src/snakemake_software_deployment_plugin_container/__init__.py (6)

5-7: Appropriate additions to imports.

The added imports (json and full subprocess) are necessary for the new functionality to parse container inspection results.


34-35: Good extraction of SOURCE_CACHE constant.

Defining this path as a constant improves maintainability by centralizing the definition of the source cache location.


84-90: Well-implemented image URI parsing with proper error handling.

The method correctly handles different URI formats and adds a default "latest" tag when none is specified. The error handling for malformed URIs is appropriate.


117-117: Improved shell command decoration using the new URI parsing method.

The code now uses the helper method to properly handle image URIs and tags.


119-120: Refactored cache path handling using the new constant.

This change improves consistency by using the centralized SOURCE_CACHE constant.


157-178: Well-implemented software reporting with container inspection.

The method properly:

  1. Extracts the image URI and tag
  2. Creates a SoftwareReport with container details
  3. Uses the appropriate container manager to inspect the image
  4. Enhances the version information with the image hash

The TODOs indicate potential future improvements for encapsulating backend-specific logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant