From ba1fbe7c0c47cd0ae31cd2e1fd26d77e2485bd78 Mon Sep 17 00:00:00 2001
From: "James E. Blair" <jeblair@redhat.com>
Date: Mon, 16 Sep 2019 14:11:52 -0700
Subject: [PATCH] Use robot_comments in Gerrit

When leaving file or line comments, leave them as robot comments
to enable more sophisticated processing/filtering.

Change-Id: Ib9e326d8a87639b06c1bc8b7f85425d98da9c003
---
 tests/base.py                          | 10 ++++-
 zuul/driver/gerrit/gerritconnection.py | 55 +++++++++++++++++++++-----
 2 files changed, 54 insertions(+), 11 deletions(-)

diff --git a/tests/base.py b/tests/base.py
index e93501d0c2..7958e1976a 100644
--- a/tests/base.py
+++ b/tests/base.py
@@ -658,6 +658,7 @@ class GerritWebServer(object):
             change_re = re.compile(r'/a/changes/(.*)\?o=.*')
             related_re = re.compile(r'/a/changes/(.*)/revisions/(.*)/related')
             change_search_re = re.compile(r'/a/changes/\?n=500.*&q=(.*)')
+            version_re = re.compile(r'/a/config/server/version')
 
             def do_POST(self):
                 path = self.path
@@ -699,6 +700,9 @@ class GerritWebServer(object):
                 m = self.list_checkers_re.match(path)
                 if m:
                     return self.list_checkers()
+                m = self.version_re.match(path)
+                if m:
+                    return self.version()
                 self.send_response(500)
                 self.end_headers()
 
@@ -719,7 +723,7 @@ class GerritWebServer(object):
 
                 message = data['message']
                 action = data.get('labels', {})
-                comments = data.get('comments', {})
+                comments = data.get('robot_comments', data.get('comments', {}))
                 tag = data.get('tag', None)
                 fake_gerrit._test_handle_review(
                     int(change.data['number']), message, action, comments,
@@ -812,6 +816,10 @@ class GerritWebServer(object):
                 self.send_data(results)
                 self.end_headers()
 
+            def version(self):
+                self.send_data('3.0.0-some-stuff')
+                self.end_headers()
+
             def send_data(self, data):
                 data = json.dumps(data).encode('utf-8')
                 data = b")]}'\n" + data
diff --git a/zuul/driver/gerrit/gerritconnection.py b/zuul/driver/gerrit/gerritconnection.py
index 3af893f7a4..8a64bad7cd 100644
--- a/zuul/driver/gerrit/gerritconnection.py
+++ b/zuul/driver/gerrit/gerritconnection.py
@@ -13,31 +13,33 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
+import copy
 import datetime
+import itertools
 import json
+import logging
+import paramiko
+import pprint
+import queue
 import re
 import re2
+import requests
 import select
+import shlex
 import threading
 import time
 import urllib
-import paramiko
-import logging
-import pprint
-import shlex
-import queue
 import urllib.parse
-import requests
 
 from typing import Dict, List
 from uuid import uuid4
 
+from zuul import version as zuul_version
 from zuul.connection import BaseConnection
+from zuul.driver.gerrit.auth import FormAuth
+from zuul.driver.gerrit.gerritmodel import GerritChange, GerritTriggerEvent
 from zuul.lib.logutil import get_annotated_logger
 from zuul.model import Ref, Tag, Branch, Project
-from zuul.driver.gerrit.gerritmodel import GerritChange, GerritTriggerEvent
-from zuul.driver.gerrit.auth import FormAuth
-from zuul import version as zuul_version
 
 # HTTP timeout in seconds
 TIMEOUT = 30
@@ -454,6 +456,7 @@ class GerritConnection(BaseConnection):
         self.client = None
         self.watched_checkers = []
         self.project_checker_map = {}
+        self.version = (0, 0, 0)
 
         self.baseurl = self.connection_config.get(
             'baseurl', 'https://%s' % self.server).rstrip('/')
@@ -1017,7 +1020,19 @@ class GerritConnection(BaseConnection):
             if labels:
                 data['labels'] = labels
             if file_comments:
-                data['comments'] = file_comments
+                if self.version >= (2, 15, 0):
+                    file_comments = copy.deepcopy(file_comments)
+                    url = item.formatStatusUrl()
+                    for comments in itertools.chain(file_comments.values()):
+                        for comment in comments:
+                            comment['robot_id'] = 'zuul'
+                            comment['robot_run_id'] = \
+                                item.current_build_set.uuid
+                            if url:
+                                comment['url'] = url
+                    data['robot_comments'] = file_comments
+                else:
+                    data['comments'] = file_comments
         data['tag'] = 'autogenerated:zuul:%s' % (item.pipeline.name)
         changeid = "%s~%s~%s" % (
             urllib.parse.quote(str(change.project), safe=''),
@@ -1293,8 +1308,28 @@ class GerritConnection(BaseConnection):
             project=project.getSafeAttributes(),
             sha=sha)
 
+    def _getRemoteVersion(self):
+        version = self.get('config/server/version')
+        base = version.split('-')[0]
+        parts = base.split('.')
+        major = minor = micro = 0
+        if len(parts) > 0:
+            major = int(parts[0])
+        if len(parts) > 1:
+            minor = int(parts[1])
+        if len(parts) > 2:
+            micro = int(parts[2])
+        self.version = (major, minor, micro)
+        self.log.info("Remote version is: %s (parsed as %s)" %
+                      (version, self.version))
+
     def onLoad(self):
         self.log.debug("Starting Gerrit Connection/Watchers")
+        try:
+            self._getRemoteVersion()
+        except Exception:
+            self.log.exception("Unable to determine remote Gerrit version")
+
         if self.enable_stream_events:
             self._start_watcher_thread()
         self._start_poller_thread()