Skip to content

Conversation

@JAVGan
Copy link
Contributor

@JAVGan JAVGan commented Aug 29, 2025

The RM request should cause the git_utils to remove the operators from the git repository and commit the changes, which was something that didn't happen in the previous versions.

This commit changes the git_utils module as by adding a new parameter to push_configs_to_git named rm_operators which should only receive a list of operators when a RM operation is handled.

It also updates the build module to send the RM operators list to push_configs_to_git by passing it over to the necessary functions.

Finally, it adds new unit-tests and improve some existing ones.

Signed-off-by: Jonathan Gangi jgangi@redhat.com

Assisted-by: Cursor/Gemini

Summary by Sourcery

Add support for handling RM requests by introducing a new rm_operators parameter to push_configs_to_git, implementing removal logic for operators during Git updates, and propagating this parameter through the build workflow. Update and extend unit tests to cover removal scenarios and introduce a RegexMatcher helper for verifying directory deletions.

New Features:

  • Add rm_operators parameter to push_configs_to_git to enable operator removal on RM requests
  • Propagate rm_operators through build tasks (_update_index_image_pull_spec, _overwrite_from_index, handle_rm_request) to push_configs_to_git

Enhancements:

  • Implement logic in git_utils to remove specified operator directories when rm_operators is provided
  • Introduce RegexMatcher utility in tests for regex-based call assertions

Tests:

  • Add comprehensive unit tests for push_configs_to_git removal scenarios (partial, full, none, and empty repo)
  • Update existing tests to include rm_operators parameter and verify commit_and_push behavior

@JAVGan JAVGan requested a review from nmars August 29, 2025 14:07
@sourcery-ai
Copy link

sourcery-ai bot commented Aug 29, 2025

Reviewer's Guide

This PR implements support for RM requests by introducing an rm_operators parameter in git_utils.push_configs_to_git, propagating it through the build pipeline, implementing operator directory removal in the repository, and adding/updating unit tests to cover various RM scenarios.

File-Level Changes

Change Details Files
Support removal of operator configs in git_utils when rm_operators is provided
  • Add rm_operators parameter to push_configs_to_git signature
  • Implement removal branch: iterate over rm_operators and call shutil.rmtree for each
  • Adjust logic to distinguish between RM and ADD operations
iib/workers/tasks/git_utils.py
Propagate rm_operators through build task functions
  • Add rm_operators parameter to _update_index_image_pull_spec, _overwrite_from_index, and handle_rm_request signatures
  • Pass rm_operators argument into push_configs_to_git calls
iib/workers/tasks/build.py
Add and update unit tests for rm_operators behavior
  • Introduce RegexMatcher helper for regex-based assertions on shutil.rmtree calls
  • Add tests covering removal scenarios: specific operators, all operators, none, and empty repository
  • Update existing push_configs_to_git tests with new mocks and assertions
tests/test_workers/test_tasks/test_git_utils.py
Update build module tests to include rm_operators parameter
  • Include rm_operators=None in test_update_index_image_pull_spec and test_overwrite_from_index calls
  • Adjust mock expectations to accommodate the new parameter
tests/test_workers/test_tasks/test_build.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Potential risk of removing unintended directories. (link)

General comments:

  • In push_configs_to_git, overloading rm_operators as a truthy flag to select removal vs. addition can be confusing—consider refactoring to an explicit operation mode (e.g., enum or separate add/remove parameters) to clarify the control flow.
  • Removal commits still use the generic commit message template without noting which operators were deleted—consider customizing the commit message when rm_operators is provided for clearer audit history.
  • The RegexMatcher and removal tests share a lot of boilerplate—consider DRYing them up with pytest parametrization or shared test helpers to reduce duplication.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In push_configs_to_git, overloading rm_operators as a truthy flag to select removal vs. addition can be confusing—consider refactoring to an explicit operation mode (e.g., enum or separate add/remove parameters) to clarify the control flow.
- Removal commits still use the generic commit message template without noting which operators were deleted—consider customizing the commit message when rm_operators is provided for clearer audit history.
- The RegexMatcher and removal tests share a lot of boilerplate—consider DRYing them up with pytest parametrization or shared test helpers to reduce duplication.

## Individual Comments

### Comment 1
<location> `iib/workers/tasks/git_utils.py:94` </location>
<code_context>
+                # Remove operators from the Git repo if an RM operation is requested
+                for operator_package in rm_operators:
+                    operator_dir = os.path.join(repo_configs_dir, operator_package)
+                    shutil.rmtree(operator_dir)
             else:
-                shutil.copytree(src_configs_path, repo_configs_dir)
</code_context>

<issue_to_address>
Potential risk of removing unintended directories.

Validate operator_package to prevent path traversal and ensure only intended directories are removed.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@JAVGan
Copy link
Contributor Author

JAVGan commented Aug 29, 2025

@nmars @yashvardhannanavati during yesterday's night I was thinking: If we do remove all images in the catalog that are not present in the image we might fall in a situation that we may remove unnecessary operators because we were blindly removing what we thought to be the correct ones.

Then an enlightenment came into my mind: why do we pass a boolean saying RM operation instead of directly passing the RM operators list? Wouldn't be simpler and safer to pass the RM operators list directly? Then I came to this, asked Cursor to help me with the tests, reviewed the tests and the rest is history.

There might be some adjustments required but I would love to hear your opinion in the matter

@JAVGan
Copy link
Contributor Author

JAVGan commented Aug 29, 2025

@sourcery-ai review

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • In push_configs_to_git, consider guarding shutil.rmtree with an exists check or ignore_errors=True (or wrap in try/except) to avoid failures when the operator directory is already gone.
  • The RegexMatcher helper in the tests is generic enough to be reused; think about extracting it into a shared test utilities module so other tests can import it instead of redefining it here.
  • The conditional logic that switches between rm_operators and operator_packages in push_configs_to_git is a bit hard to follow—consider splitting the add and remove workflows into separate functions or using an explicit flag to make the intent clearer.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In push_configs_to_git, consider guarding shutil.rmtree with an exists check or ignore_errors=True (or wrap in try/except) to avoid failures when the operator directory is already gone.
- The RegexMatcher helper in the tests is generic enough to be reused; think about extracting it into a shared test utilities module so other tests can import it instead of redefining it here.
- The conditional logic that switches between rm_operators and operator_packages in push_configs_to_git is a bit hard to follow—consider splitting the add and remove workflows into separate functions or using an explicit flag to make the intent clearer.

## Individual Comments

### Comment 1
<location> `iib/workers/tasks/git_utils.py:90` </location>
<code_context>
             )

-            if operator_packages:
+            if rm_operators:
+                # Remove operators from the Git repo if an RM operation is requested
+                for operator_package in set(rm_operators):
+                    if operator_package:  # We don't want to remove the whole /configs directory
+                        operator_dir = os.path.join(repo_configs_dir, operator_package)
+                        shutil.rmtree(operator_dir)
+            elif operator_packages:
+                # Add content to the Git repo if an ADD or any other operation is requested
</code_context>

<issue_to_address>
Consider handling missing operator directories gracefully during removal.

Catching FileNotFoundError when removing operator directories will prevent failures if the directory is missing, which may be expected in some cases.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
                        operator_dir = os.path.join(repo_configs_dir, operator_package)
                        shutil.rmtree(operator_dir)
=======
                        operator_dir = os.path.join(repo_configs_dir, operator_package)
                        try:
                            shutil.rmtree(operator_dir)
                        except FileNotFoundError:
                            # Directory does not exist, nothing to remove
                            pass
>>>>>>> REPLACE

</suggested_fix>

### Comment 2
<location> `iib/workers/tasks/git_utils.py:105` </location>
<code_context>
                     shutil.copytree(src_pkg_dir, dest_pkg_dir, dirs_exist_ok=True)
             else:
+                # Add all content to the Git repo for ADD or any other operation
                 shutil.copytree(src_configs_path, repo_configs_dir)

             # Print git status to the logs
</code_context>

<issue_to_address>
Consider using dirs_exist_ok=True for shutil.copytree to avoid errors if the destination exists.

If repo_configs_dir might already exist, setting dirs_exist_ok=True will prevent errors and improve robustness.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
                shutil.copytree(src_configs_path, repo_configs_dir)
=======
                shutil.copytree(src_configs_path, repo_configs_dir, dirs_exist_ok=True)
>>>>>>> REPLACE

</suggested_fix>

### Comment 3
<location> `tests/test_workers/test_tasks/test_build.py:469` </location>
<code_context>
             index_repo_map=url_repo_map,
+            rm_operators=None,
         )
         mock_pcg.assert_called_once_with(
             request_id=1,
             from_index=from_index,
             src_configs_path='/tmp/catalog_dir',
             index_repo_map=url_repo_map,
+            rm_operators=None,
         )
     else:
</code_context>

<issue_to_address>
Consider adding a test for non-None rm_operators in build tasks.

Current tests only cover rm_operators=None. Please add a test with a non-empty rm_operators list to ensure correct handling of removal requests.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        index_repo_map=url_repo_map,
        rm_operators=None,
    )

    # Verify catalog config handling
            from_index=from_index,
            src_configs_path='/tmp/catalog_dir',
            index_repo_map=url_repo_map,
            rm_operators=None,
        )
=======
        index_repo_map=url_repo_map,
        rm_operators=None,
    )

    # Test with non-empty rm_operators
    rm_operators_list = ["operator1", "operator2"]
    build_task(
        request_id=2,
        from_index=from_index,
        src_configs_path='/tmp/catalog_dir',
        index_repo_map=url_repo_map,
        rm_operators=rm_operators_list,
    )
    mock_pcg.assert_any_call(
        request_id=2,
        from_index=from_index,
        src_configs_path='/tmp/catalog_dir',
        index_repo_map=url_repo_map,
        rm_operators=rm_operators_list,
    )

    # Verify catalog config handling
            from_index=from_index,
            src_configs_path='/tmp/catalog_dir',
            index_repo_map=url_repo_map,
            rm_operators=None,
        )
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@JAVGan JAVGan force-pushed the fix-rm-git branch 3 times, most recently from a093a28 to e77a3ae Compare August 29, 2025 15:39
nmars
nmars previously approved these changes Aug 29, 2025
Copy link
Contributor

@nmars nmars left a comment

Choose a reason for hiding this comment

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

Looks good!

The `RM` request should cause the `git_utils` to remove the operators
from the `git` repository and commit the changes, which was something
that didn't happen in the previous versions.

This commit changes the `git_utils` module as by adding a new parameter
to `push_configs_to_git` named `rm_operators` which should only receive
a list of operators when a `RM` operation is handled.

It also updates the `build` module to send the `RM` operators list to
`push_configs_to_git` by passing it over to the necessary functions.

Finally, it adds new unit-tests and improve some existing ones.

Signed-off-by: Jonathan Gangi <jgangi@redhat.com>

Assisted-by: Cursor/Gemini
@JAVGan JAVGan merged commit b4523e3 into master Sep 2, 2025
2 checks passed
@JAVGan JAVGan deleted the fix-rm-git branch September 2, 2025 19:31
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.

3 participants