Repository: fedora-infra/bodhi

Issue:
Investigate effects of CLI `updates edit --addbuilds` against side-tags updates
There has been a report on infrastructure's matrix chat about an update that somehow had lost its `from_tag` attribute.
I suspect that's because the user tried to edit the update from CLI with `updates edit --addbuilds`. At a first look to the code this may cause the update to get broken, but we need to investigate.
We also need to better document how to refresh the build list of a side-tag update (I didn't find anything in the docs about that). 


Discussion:

Resolving patch:
diff --git a/bodhi-client/bodhi/client/cli.py b/bodhi-client/bodhi/client/cli.py
--- a/bodhi-client/bodhi/client/cli.py
+++ b/bodhi-client/bodhi/client/cli.py
@@ -557,13 +557,19 @@ def edit(url: str, id_provider: str, client_id: str, debug: bool, **kwargs):
                 sys.exit(1)
             if kwargs['addbuilds'] or kwargs['removebuilds']:
                 click.echo(
-                    "ERROR: The --from-tag option can't be used together with"
-                    " --addbuilds or --removebuilds.", err=True
+                    "ERROR: You have to use the web interface to update"
+                    " builds in a side-tag update.", err=True
                 )
                 sys.exit(1)
             kwargs['from_tag'] = former_update['from_tag']
             del kwargs['builds']
         else:
+            if former_update.get('from_tag', None):
+                click.echo(
+                    "ERROR: This update was created from a side-tag."
+                    " Please add --from_tag and try again.", err=True
+                )
+                sys.exit(1)
             kwargs.pop('from_tag')
             if kwargs['addbuilds']:
                 for build in kwargs['addbuilds'].split(','):


Test patch:
diff --git a/bodhi-client/tests/test_cli.py b/bodhi-client/tests/test_cli.py
--- a/bodhi-client/tests/test_cli.py
+++ b/bodhi-client/tests/test_cli.py
@@ -1812,8 +1812,8 @@ def test_from_tag_addbuilds(self, mocked_client_class, mocker):
                        '--url', 'http://localhost:6543'])
 
         assert result.exit_code == 1
-        assert result.output == ("ERROR: The --from-tag option can't be used together with"
-                                 " --addbuilds or --removebuilds.\n")
+        assert result.output == ("ERROR: You have to use the web interface to update"
+                                 " builds in a side-tag update.\n")
         mocked_client_class.query.assert_called_with(updateid='FEDORA-2017-c95b33872d')
 
     def test_from_tag_removebuilds(self, mocked_client_class, mocker):
@@ -1833,8 +1833,29 @@ def test_from_tag_removebuilds(self, mocked_client_class, mocker):
                        '--url', 'http://localhost:6543'])
 
         assert result.exit_code == 1
-        assert result.output == ("ERROR: The --from-tag option can't be used together with"
-                                 " --addbuilds or --removebuilds.\n")
+        assert result.output == ("ERROR: You have to use the web interface to update"
+                                 " builds in a side-tag update.\n")
+        mocked_client_class.query.assert_called_with(updateid='FEDORA-2017-c95b33872d')
+
+    def test_from_tag_missing_flag(self, mocked_client_class, mocker):
+        """
+        Assert --from-tag is required when editing a side-tag update.
+        """
+        data = client_test_data.EXAMPLE_QUERY_MUNCH.copy()
+        data.updates[0]['from_tag'] = 'fake_tag'
+        mocked_client_class.query = mocker.Mock(return_value=data)
+
+        runner = testing.CliRunner()
+
+        result = runner.invoke(
+            cli.edit, ['FEDORA-2017-c95b33872d',
+                       '--addbuilds', 'tar-1.29-4.fc25,nedit-5.7-1.fc25',
+                       '--notes', 'Updated package.',
+                       '--url', 'http://localhost:6543'])
+
+        assert result.exit_code == 1
+        assert result.output == ("ERROR: This update was created from a side-tag."
+                                 " Please add --from_tag and try again.\n")
         mocked_client_class.query.assert_called_with(updateid='FEDORA-2017-c95b33872d')
 
     def test_notes_and_notes_file(self, mocked_client_class):
diff --git a/devel/ci/integration/tests/test_bodhi_tasks.py b/devel/ci/integration/tests/test_bodhi_tasks.py
--- a/devel/ci/integration/tests/test_bodhi_tasks.py
+++ b/devel/ci/integration/tests/test_bodhi_tasks.py
@@ -93,6 +93,7 @@ def find_update():
             "AND r.id_prefix = 'FEDORA' "
             "AND u.locked = FALSE AND u.status IN ('pending', 'testing') "
             "AND u.type != 'security' "
+            "AND u.from_tag IS NULL "
             "AND us.name NOT LIKE '%packagerbot%' "
             "ORDER BY u.date_submitted DESC LIMIT 1"
         )