Repository: fedora-infra/bodhi

Issue:
multiple bug numbers rejected as "not a number"
Creating a new update for  conntrack-tools-1.4.2-8.el7 
Traceback (most recent call last):
  File "/bin/bodhi", line 532, in <module>
    main()
  File "/bin/bodhi", line 225, in main
    data = bodhi.save(**update_args)
  File "/usr/lib/python2.7/site-packages/fedora/client/bodhi.py", line 107, in wrapper
    raise BodhiClientException(problems)
fedora.client.bodhi.BodhiClientException: "1253755 1253757 1255578" is not a number
Could not generate update request: Command 'bodhi --new --release epel7 --file bodhi.template conntrack-tools-1.4.2-8.el7 --username pwouters' returned non-zero exit status 1

I tried using comma's and spaces. This is using fedpkg-.5.5 and bodhi-client-0.9.12.2-1



Discussion:
Can you please provide the contents of the `bodhi.template` file?

Nevermind, I'm able to reproduce this issue in staging. It only happens with multiple bug numbers.


Resolving patch:
diff --git a/bodhi/schemas.py b/bodhi/schemas.py
--- a/bodhi/schemas.py
+++ b/bodhi/schemas.py
@@ -53,7 +53,7 @@ class CSRFProtectedSchema(colander.MappingSchema):
 
 
 class Bugs(colander.SequenceSchema):
-    bug = colander.SchemaNode(colander.Integer(), missing=None)
+    bug = colander.SchemaNode(colander.String(), missing=None)
 
 
 class Builds(colander.SequenceSchema):
diff --git a/bodhi/services/updates.py b/bodhi/services/updates.py
--- a/bodhi/services/updates.py
+++ b/bodhi/services/updates.py
@@ -36,6 +36,7 @@
     validate_username,
     validate_update_id,
     validate_requirements,
+    validate_bugs,
 )
 
 
@@ -126,19 +127,19 @@ def set_request(request):
 @updates.get(schema=bodhi.schemas.ListUpdateSchema,
              accept=('application/json', 'text/json'), renderer='json',
              validators=(validate_release, validate_releases,
-                         validate_enums, validate_username))
+                         validate_enums, validate_username, validate_bugs))
 @updates.get(schema=bodhi.schemas.ListUpdateSchema,
              accept=('application/javascript'), renderer='jsonp',
              validators=(validate_release, validate_releases,
-                         validate_enums, validate_username))
+                         validate_enums, validate_username, validate_bugs))
 @updates.get(schema=bodhi.schemas.ListUpdateSchema,
              accept=('application/atom+xml'), renderer='rss',
              validators=(validate_release, validate_releases,
-                         validate_enums, validate_username))
+                         validate_enums, validate_username, validate_bugs))
 @updates.get(schema=bodhi.schemas.ListUpdateSchema,
              accept=('text/html'), renderer='updates.html',
              validators=(validate_release, validate_releases,
-                         validate_enums, validate_username))
+                         validate_enums, validate_username, validate_bugs))
 def query_updates(request):
     db = request.db
     data = request.validated
@@ -277,6 +278,7 @@ def query_updates(request):
                   validate_acls,
                   validate_enums,
                   validate_requirements,
+                  validate_bugs,
               ))
 def new_update(request):
     """ Save an update.
diff --git a/bodhi/validators.py b/bodhi/validators.py
--- a/bodhi/validators.py
+++ b/bodhi/validators.py
@@ -489,6 +489,16 @@ def validate_releases(request):
         request.validated["releases"] = validated_releases
 
 
+def validate_bugs(request):
+    bugs = request.validated.get('bugs')
+    if bugs:
+        try:
+            request.validated['bugs'] = map(int, bugs)
+        except ValueError:
+            request.errors.add("querystring", "bugs",
+                               "Invalid bug ID specified: {}".format(bugs))
+
+
 def validate_username(request):
     """Make sure this user exists"""
     username = request.validated.get("user")


Test patch:
diff --git a/bodhi/tests/functional/test_updates.py b/bodhi/tests/functional/test_updates.py
--- a/bodhi/tests/functional/test_updates.py
+++ b/bodhi/tests/functional/test_updates.py
@@ -529,9 +529,9 @@ def test_list_updates_by_invalid_bug(self):
         res = self.app.get('/updates/', {"bugs": "cockroaches"}, status=400)
         body = res.json_body
         self.assertEquals(len(body.get('updates', [])), 0)
-        self.assertEquals(res.json_body['errors'][0]['name'], 'bugs.0')
+        self.assertEquals(res.json_body['errors'][0]['name'], 'bugs')
         self.assertEquals(res.json_body['errors'][0]['description'],
-                          '"cockroaches" is not a number')
+                "Invalid bug ID specified: [u'cockroaches']")
 
     def test_list_updates_by_unexisting_bug(self):
         res = self.app.get('/updates/', {"bugs": "19850110"})
@@ -1168,6 +1168,39 @@ def test_new_update(self, publish, *args):
         publish.assert_called_once_with(
             topic='update.request.testing', msg=mock.ANY)
 
+    @mock.patch(**mock_valid_requirements)
+    @mock.patch('bodhi.notifications.publish')
+    def test_new_update_with_multiple_bugs(self, publish, *args):
+        update = self.get_update('bodhi-2.0.0-2.fc17')
+        update['bugs'] = ['1234', '5678']
+        r = self.app.post_json('/updates/', update)
+        up = r.json_body
+        self.assertEquals(len(up['bugs']), 2)
+        self.assertEquals(up['bugs'][0]['bug_id'], 1234)
+        self.assertEquals(up['bugs'][1]['bug_id'], 5678)
+
+    @mock.patch(**mock_valid_requirements)
+    @mock.patch('bodhi.notifications.publish')
+    def test_new_update_with_multiple_bugs_as_str(self, publish, *args):
+        update = self.get_update('bodhi-2.0.0-2.fc17')
+        update['bugs'] = '1234, 5678'
+        r = self.app.post_json('/updates/', update)
+        up = r.json_body
+        self.assertEquals(len(up['bugs']), 2)
+        self.assertEquals(up['bugs'][0]['bug_id'], 1234)
+        self.assertEquals(up['bugs'][1]['bug_id'], 5678)
+
+    @mock.patch(**mock_valid_requirements)
+    @mock.patch('bodhi.notifications.publish')
+    def test_new_update_with_invalid_bugs_as_str(self, publish, *args):
+        update = self.get_update('bodhi-2.0.0-2.fc17')
+        update['bugs'] = '1234, blargh'
+        r = self.app.post_json('/updates/', update, status=400)
+        up = r.json_body
+        self.assertEquals(up['status'], 'error')
+        self.assertEquals(up['errors'][0]['description'],
+                          "Invalid bug ID specified: [u'1234', u'blargh']")
+
     @mock.patch(**mock_valid_requirements)
     @mock.patch('bodhi.notifications.publish')
     def test_edit_update(self, publish, *args):