Skip to content

Conversation

ashwgit
Copy link
Contributor

@ashwgit ashwgit commented Sep 4, 2025

These modification changes the behavior the way _opm_registry_add function is being called inside opm_registry_add_fbc , by calling _opm_registry_add multiple times with chunks of bundles it prevents opm command execution error which happens when a large number of bundles is passed as arguments.

@chandwanitulsi @yashvardhannanavati @xDaile @JAVGan @lipoja PTAL

Summary by Sourcery

Prevent opm command execution errors by limiting the number of bundle arguments per call and processing bundles in configurable chunks

Enhancements:

  • Introduce iib_max_number_of_bundles_as_cmd_argument configuration parameter
  • Refactor opm_registry_add_fbc to invoke _opm_registry_add in multiple chunked calls based on the new configuration

Tests:

  • Update test_opm_registry_add_fbc to patch temp DB creation and assert multiple chunked _opm_registry_add invocations

Copy link

sourcery-ai bot commented Sep 4, 2025

Reviewer's Guide

Prevent opm “reached max number of arguments” errors by introducing a configurable bundle batch size and splitting registry additions into chunks in opm_registry_add_fbc.

File-Level Changes

Change Details Files
Expose max bundles chunk size as a configurable parameter
  • Add iib_max_number_of_bundles_as_cmd_argument to Config class
  • Set default value to 500
iib/workers/config.py
Split bundle additions into configurable chunks
  • Retrieve iib_max_number_of_bundles_as_cmd_argument via get_worker_config
  • Loop over bundles in slices of the configured size
  • Invoke _opm_registry_add iteratively for each chunk
iib/workers/tasks/opm_operations.py
Adapt tests to validate chunked _opm_registry_add calls
  • Mock iib_max_number_of_bundles_as_cmd_argument in test config setup
  • Patch _get_or_create_temp_index_db_file to return a stable path
  • Assert multiple _opm_registry_add calls match expected chunk boundaries
tests/test_workers/test_tasks/test_opm_operations.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

@ashwgit ashwgit force-pushed the modify_opm_registry_add_calls branch from 86bb0cb to 7607de9 Compare September 4, 2025 15:24
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 they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `iib/workers/tasks/opm_operations.py:826` </location>
<code_context>
         The format of the token must be in the format "user:password".
     :param str container_tool: the container tool to be used to operate on the index image
     """
+    conf = get_worker_config()
+
     index_db_file = _get_or_create_temp_index_db_file(
</code_context>

<issue_to_address>
Consider validating conf.iib_max_number_of_bundles_as_cmd_argument for non-positive values.

A positive value check will help avoid runtime errors from invalid loop ranges.
</issue_to_address>

### Comment 2
<location> `iib/workers/config.py:49` </location>
<code_context>
     iib_index_configs_gitlab_tokens_map: Optional[Dict[str, Dict[str, str]]] = None
     iib_log_level: str = 'INFO'
     iib_deprecate_bundles_limit = 200
+    iib_max_number_of_bundles_as_cmd_argument = 500
     iib_max_recursive_related_bundles = 15
     # list of index images to which we can add bundles without "com.redhat.openshift.versions" label
</code_context>

<issue_to_address>
Default value for iib_max_number_of_bundles_as_cmd_argument may need documentation or justification.

Consider adding a brief comment or reference explaining why 500 was chosen, particularly if it's based on system or tool constraints.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
    iib_deprecate_bundles_limit = 200
    iib_max_number_of_bundles_as_cmd_argument = 500
    iib_max_recursive_related_bundles = 15
=======
    iib_deprecate_bundles_limit = 200
    # Maximum number of bundles allowed as a command argument (500) is chosen to avoid exceeding shell argument length limits and to ensure compatibility with underlying system tools.
    iib_max_number_of_bundles_as_cmd_argument = 500
    iib_max_recursive_related_bundles = 15
>>>>>>> REPLACE

</suggested_fix>

### Comment 3
<location> `tests/test_workers/test_tasks/test_opm_operations.py:513` </location>
<code_context>
-        container_tool=container_tool,
-        graph_update_mode=graph_update_mode,
-    )
+    if bundles:
+        expected_calls = []
+        for i in range(0, len(bundles), max_bundles):
+            chunk = bundles[i : i + max_bundles]
+            expected_calls.append(
+                call(
+                    base_dir=tmpdir,
+                    index_db=index_db_file,
+                    bundles=chunk,
+                    overwrite_csv=overwrite_csv,
+                    container_tool=container_tool,
+                    graph_update_mode=graph_update_mode,
+                )
+            )
+        mock_ora.assert_has_calls(expected_calls)

     mock_om.assert_called_once_with(index_db=index_db_file, base_dir=tmpdir)
</code_context>

<issue_to_address>
Missing test for empty bundles list edge case.

Add a test with an empty 'bundles' list to confirm '_opm_registry_add' is not called and the function handles this case correctly.

Suggested implementation:

```python
    max_bundles = mock_config.return_value.iib_max_number_of_bundles_as_cmd_argument

    if bundles:
        expected_calls = []
        for i in range(0, len(bundles), max_bundles):
            chunk = bundles[i : i + max_bundles]
            expected_calls.append(
                call(
                    base_dir=tmpdir,
                    index_db=index_db_file,
                    bundles=chunk,
                    overwrite_csv=overwrite_csv,
                    container_tool=container_tool,
                    graph_update_mode=graph_update_mode,
                )
            )
        mock_ora.assert_has_calls(expected_calls)
    else:
        mock_ora.assert_not_called()

    mock_om.assert_called_once_with(index_db=index_db_file, base_dir=tmpdir)
    mock_ogd.assert_called_once_with(

```

If this logic is inside a test function, you should also add a dedicated test function for the empty bundles case, e.g. `def test_opm_operations_empty_bundles(...)`. In that function, set `bundles = []` and verify the mocks as above.
</issue_to_address>

### Comment 4
<location> `tests/test_workers/test_tasks/test_opm_operations.py:515` </location>
<code_context>
-    )
+    if bundles:
+        expected_calls = []
+        for i in range(0, len(bundles), max_bundles):
+            chunk = bundles[i : i + max_bundles]
+            expected_calls.append(
+                call(
+                    base_dir=tmpdir,
</code_context>

<issue_to_address>
Missing test for batch size greater than bundles length.

Add a test case where the number of bundles is less than the batch size to verify that batching does not occur and only one '_opm_registry_add' call is made.
</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.

The format of the token must be in the format "user:password".
:param str container_tool: the container tool to be used to operate on the index image
"""
conf = get_worker_config()
Copy link

Choose a reason for hiding this comment

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

suggestion (bug_risk): Consider validating conf.iib_max_number_of_bundles_as_cmd_argument for non-positive values.

A positive value check will help avoid runtime errors from invalid loop ranges.

Comment on lines +513 to +522
if bundles:
expected_calls = []
for i in range(0, len(bundles), max_bundles):
chunk = bundles[i : i + max_bundles]
expected_calls.append(
call(
base_dir=tmpdir,
index_db=index_db_file,
bundles=chunk,
overwrite_csv=overwrite_csv,
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Missing test for empty bundles list edge case.

Add a test with an empty 'bundles' list to confirm '_opm_registry_add' is not called and the function handles this case correctly.

Suggested implementation:

    max_bundles = mock_config.return_value.iib_max_number_of_bundles_as_cmd_argument

    if bundles:
        expected_calls = []
        for i in range(0, len(bundles), max_bundles):
            chunk = bundles[i : i + max_bundles]
            expected_calls.append(
                call(
                    base_dir=tmpdir,
                    index_db=index_db_file,
                    bundles=chunk,
                    overwrite_csv=overwrite_csv,
                    container_tool=container_tool,
                    graph_update_mode=graph_update_mode,
                )
            )
        mock_ora.assert_has_calls(expected_calls)
    else:
        mock_ora.assert_not_called()

    mock_om.assert_called_once_with(index_db=index_db_file, base_dir=tmpdir)
    mock_ogd.assert_called_once_with(

If this logic is inside a test function, you should also add a dedicated test function for the empty bundles case, e.g. def test_opm_operations_empty_bundles(...). In that function, set bundles = [] and verify the mocks as above.

Copy link
Contributor

Choose a reason for hiding this comment

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

This one as well please @ashwgit

Comment on lines +515 to +517
for i in range(0, len(bundles), max_bundles):
chunk = bundles[i : i + max_bundles]
expected_calls.append(
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Missing test for batch size greater than bundles length.

Add a test case where the number of bundles is less than the batch size to verify that batching does not occur and only one '_opm_registry_add' call is made.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice suggestion, ptal @ashwgit

container_tool=container_tool,
graph_update_mode=graph_update_mode,
)
for i in range(0, len(bundles), conf.iib_max_number_of_bundles_as_cmd_argument):
Copy link
Contributor

Choose a reason for hiding this comment

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

Taking advantage of the comment from sourcery-ai to avoid negative numbrers, you might even use abs for it:

Suggested change
for i in range(0, len(bundles), conf.iib_max_number_of_bundles_as_cmd_argument):
for i in range(0, len(bundles), abs(conf.iib_max_number_of_bundles_as_cmd_argument)):

Comment on lines +515 to +517
for i in range(0, len(bundles), max_bundles):
chunk = bundles[i : i + max_bundles]
expected_calls.append(
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice suggestion, ptal @ashwgit

Comment on lines +513 to +522
if bundles:
expected_calls = []
for i in range(0, len(bundles), max_bundles):
chunk = bundles[i : i + max_bundles]
expected_calls.append(
call(
base_dir=tmpdir,
index_db=index_db_file,
bundles=chunk,
overwrite_csv=overwrite_csv,
Copy link
Contributor

Choose a reason for hiding this comment

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

This one as well please @ashwgit

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.

2 participants