]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
script/backport-resolve-issue: handle tracker URLs better
authorNathan Cutler <ncutler@suse.com>
Wed, 28 Aug 2019 09:21:17 +0000 (11:21 +0200)
committerNathan Cutler <ncutler@suse.com>
Wed, 28 Aug 2019 11:41:01 +0000 (13:41 +0200)
Before this commit, backport-resolve-issue would blindly grab the first tracker
URL it saw in the GitHub PR description. With this commit, it examines all the
tracker URLs it sees in the PR description and uses the first one that
corresponds to an issue in the Redmine Backport tracker.

Signed-off-by: Nathan Cutler <ncutler@suse.com>
src/script/backport-resolve-issue

index 15d7b1184f3d7de6ddff16381f1bbc79d871713b..86ce07f180f75b044cfb15908c299a6c995294b7 100755 (executable)
@@ -296,7 +296,11 @@ class Backport:
         #
         # GitHub PR ID from merge commit string
         p = re.compile('\\d+')
-        self.github_pr_id = p.search(merge_commit_description).group()
+        try:
+            self.github_pr_id = p.search(merge_commit_description).group()
+        except AttributeError:
+            assert False, \
+                "Failed to extract GitHub PR ID from merge commit string ->{}<-".format(merge_commit_string)
         logging.debug("GitHub PR ID from merge commit string: {}".format(self.github_pr_id))
         self.populate_github_url()
         #
@@ -318,38 +322,24 @@ class Backport:
         if not no_browser:
             if browser_running():
                 os.system("{} {}".format(browser_cmd, self.github_url))
-        print('''================================================================
-{}
-merge commit {} ({})
-{}
-```
+        pr_title_trunc = self.github_pr_title
+        if len(pr_title_trunc) > 60:
+            pr_title_trunc = pr_title_trunc[0:50] + "|TRUNCATED"
+        print('''\n\n=================================================================
+GitHub PR URL:    {}
+GitHub PR title:  {}
+Merge commit:     {} ({})
+Merged:           {}
+Ceph version:     base {}, target {}'''.format(self.github_url, pr_title_trunc, self.merge_commit_sha1, self.merge_commit_gd, self.github_pr_merged, self.base_version, self.target_version))
+        if no_browser or not browser_running():
+            print('''----------------------- PR DESCRIPTION --------------------------
 {}
-```
-Merged: {}
-Ceph version: base {}, target {}
-================================================================'''.format(self.github_url, self.merge_commit_sha1, self.merge_commit_gd, self.github_pr_title, self.github_pr_desc, self.github_pr_merged, self.base_version, self.target_version))
+-----------------------------------------------------------------'''.format(self.github_pr_desc)) 
         assert self.github_pr_merged, "GitHub PR {} has not been merged!".format(self.github_pr_id)
         #
-        # extract tracker URL from description
-        p = re.compile('http.*://tracker.ceph.com/issues/\\d+')
-        try:
-            tracker_url = p.search(self.github_pr_desc).group()
-        except AttributeError:
-            assert False, \
-                "GitHub PR description does not contain a Tracker URL!"
-        p = re.compile('\\d+')
-        self.tracker_id = p.search(tracker_url).group()
-        assert self.tracker_id, \
-            "Failed to extract tracker ID from tracker URL {}".format(tracker_url)
-        self.populate_tracker_url()
-        logging.info("PR {} links to tracker {}"
-                     .format(self.github_url, self.tracker_url))
-        #
-        # we have a Tracker URL, but is it really a backport tracker?
-        backport_tracker_id = tracker2tracker_id['Backport']
-        self.redmine_issue = redmine.issue.get(self.tracker_id)
-        assert self.redmine_issue.tracker.id == backport_tracker_id, \
-            "Tracker {} is a {} (expected ->Backport<-)".format(self.tracker_url, self.redmine_issue.tracker)
+        # obtain backport tracker from GitHub PR description
+        self.extract_backport_tracker_from_github_pr_desc()
+        print('''Backport tracker: {}'''.format(self.tracker_url))
         #
         # does the Backport Tracker description link back to the GitHub PR?
         p = re.compile('http.*://github.com/ceph/ceph/pull/\\d+')
@@ -367,6 +357,8 @@ Ceph version: base {}, target {}
                           .format(self.github_url_from_tracker, github_id_from_tracker))
             assert github_id_from_tracker == self.github_pr_id, \
                 "GitHub PR ID {} does not match GitHub ID from tracker {}".format(self.github_pr_id, github_id_from_tracker)
+        print("=================================================================")
+        if self.github_url_from_tracker:
             logging.info("Tracker {} links to PR {}".format(self.tracker_url, self.github_url))
         else:
             logging.info("Tracker {} does not link to PR {} - will update".
@@ -440,6 +432,48 @@ Ceph version: base {}, target {}
                 return field['value']
         return None
     
+    def print_end_of_divider(self):
+        print("=================================================================")
+
+    def extract_backport_tracker_from_github_pr_desc(self):
+        global redmine_endpoint
+        p = re.compile('http.*://tracker.ceph.com/issues/\\d+')
+        matching_strings = p.findall(self.github_pr_desc)
+        if not matching_strings: 
+            self.print_end_of_divider()
+            assert False, \
+                "GitHub PR description does not contain a Tracker URL"
+        self.tracker_id = None
+        self.tracker_url = None
+        backport_trackers_found = 0
+        for tracker_url in matching_strings:
+            p = re.compile('\\d+')
+            tracker_id = p.search(tracker_url).group()
+            if not tracker_id:
+                self.print_end_of_divider()
+                assert tracker_id, \
+                    "Failed to extract tracker ID from tracker URL {}".format(tracker_url)
+            tracker_url = "{}/issues/{}".format(redmine_endpoint, tracker_id)
+            #
+            # we have a Tracker URL, but is it really a backport tracker?
+            backport_tracker_id = tracker2tracker_id['Backport']
+            redmine_issue = redmine.issue.get(tracker_id)
+            if redmine_issue.tracker.id == backport_tracker_id:
+                backport_trackers_found += 1
+                if backport_trackers_found == 1:
+                    self.redmine_issue = redmine_issue
+                    self.tracker_id = tracker_id
+                    self.tracker_url = tracker_url
+        if not self.tracker_id:
+            self.print_end_of_divider()
+            assert False, \
+                "No backport tracker found in PR description at {}".format(self.github_url)
+        if backport_trackers_found > 1:
+            logging.warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
+            logging.warning("PR description contains multiple ({}) backport tracker URLs - using only the first one"
+                            .format(backport_trackers_found))
+            logging.warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
+
     def get_tracker_target_version(self):
         if self.redmine_issue.fixed_version:
             logging.debug("Target version: ID {}, name {}"
@@ -537,10 +571,8 @@ if __name__ == '__main__':
     #
     # loop over the merge commits
     for merge in merges_raw_list:
-        print("\nMerges remaining to process: {}".format(merges_remaining))
         backport = None
         sha1 = merge.split(' ')[0]
-        print("Merge {}".format(merge))
         possible_to_resolve = True
         try:
             backport = Backport(repo, merge_commit_string=merge)
@@ -559,8 +591,11 @@ if __name__ == '__main__':
                 prompt = "[a] Abort, [i] Ignore, [u] Update tracker (default 'u') --> "
                 default_input_val = "u"
             else:
-                prompt = "[a] Abort, [i] Ignore --> "
-                default_input_val = "i"
+                if merges_remaining > 1:
+                    prompt = "[a] Abort, [i] Ignore --> "
+                    default_input_val = "i"
+                else:
+                    break
         input_val = input(prompt)
         if input_val == '':
             input_val = default_input_val
@@ -581,3 +616,4 @@ if __name__ == '__main__':
             else:
                 tag_sha1(repo, sha1)
         merges_remaining -= 1
+        print("Merges remaining to process: {}".format(merges_remaining))