From 8a0c738d9b4d4fe739714ae7a7fcea2a71581285 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 1 Apr 2019 12:49:33 +0200 Subject: Fix gerrit bot closing issues that were manually re-opened MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of closing the issue again, post a comment. Change-Id: I76d3c531abbad2fa97912925af3630cf866bcf8c Fixes: QTQAINFRA-2847 Reviewed-by: Paul Wicking Reviewed-by: Jędrzej Nowacki --- scripts/jira/jira-bug-closer/jiracloser/closer.py | 23 ++++++++++++++++------ .../jira-bug-closer/tests/test_jira_close_issue.py | 12 ++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/scripts/jira/jira-bug-closer/jiracloser/closer.py b/scripts/jira/jira-bug-closer/jiracloser/closer.py index 0b564918..35959d39 100644 --- a/scripts/jira/jira-bug-closer/jiracloser/closer.py +++ b/scripts/jira/jira-bug-closer/jiracloser/closer.py @@ -179,7 +179,18 @@ class JiraCloser: changes.append('%s (%s/%s)' % (fix.sha1, fix.repository, fix.branch)) return {'customfield_10142': ' '.join(changes)} - def _close_issue(self, issue: jira.Issue, fields: Dict[str, Any]) -> None: + @staticmethod + def _is_reopened(issue: jira.Issue): + for change in issue.changelog.histories: + for item in change.items: + if item.toString == 'Open' and item.fromString == 'Closed': + return True + return False + + def _close_issue(self, issue: jira.Issue, fields: Dict[str, Any], ignore_reopened: bool) -> None: + if not ignore_reopened and JiraCloser._is_reopened(issue): + self.jira_client.add_comment(issue, 'A change related to this issue was integrated. This issue was re-opened before, the bot will not close this issue, please close it manually when applicable.') + return if issue.fields.status.name == 'In Progress': fields.update({'resolution': {'name': 'Done'}}) self.jira_client.transition_issue(issue.key, transition='Fixed', fields=fields) @@ -189,9 +200,9 @@ class JiraCloser: fields.update({'resolution': {'name': 'Done'}}) self.jira_client.transition_issue(issue.key, transition='Close', fields=fields) - def _update_issue(self, fix: FixedByTag, issue_key: str, fixes: bool) -> None: + def _update_issue(self, fix: FixedByTag, issue_key: str, fixes: bool, ignore_reopened: bool=False) -> None: try: - issue = self.jira_client.issue(issue_key) + issue = self.jira_client.issue(issue_key, expand='changelog') version_id = None if fixes: # get the fix version to update @@ -199,7 +210,7 @@ class JiraCloser: # get changes in the form of sha1 and repo + branch extra_fields.update(self._get_change_sha1_field(issue, fix)) # close the issue - self._close_issue(issue, extra_fields) + self._close_issue(issue, extra_fields, ignore_reopened=ignore_reopened) if self.config.add_comment_to_issues: comment = comment_template.substitute(sha1=fix.sha1, repository=fix.repository, branch=fix.branch, fix_version=fix.version or 'unknown version', version_id=version_id or 'unknown version', subject=fix.subject) @@ -214,11 +225,11 @@ class JiraCloser: else: raise e - def _update_issue_with_retry(self, fix: FixedByTag, issue_key: str, fixes: bool) -> None: + def _update_issue_with_retry(self, fix: FixedByTag, issue_key: str, fixes: bool, ignore_reopened: bool=False) -> None: for attempt in range(5): sleep(attempt) # wait for up to 4 seconds, try 5 times try: - self._update_issue(fix, issue_key, fixes) + self._update_issue(fix, issue_key, fixes, ignore_reopened) break except jira.exceptions.JIRAError as e: if e.status_code == 500: diff --git a/scripts/jira/jira-bug-closer/tests/test_jira_close_issue.py b/scripts/jira/jira-bug-closer/tests/test_jira_close_issue.py index e5c79eb8..dc9cbf93 100644 --- a/scripts/jira/jira-bug-closer/tests/test_jira_close_issue.py +++ b/scripts/jira/jira-bug-closer/tests/test_jira_close_issue.py @@ -55,7 +55,13 @@ def test_close_issue(): fix = FixedByTag(repository='foo/bar', branch='dev', version='5.13.0', sha1='bd0279c4173eb627d432d9a05411bbc725240d4e', task_numbers=[], fixes=['CON-5'], author='Some One', subject='Close a test issue') - j._update_issue_with_retry(fix, issue_key, True) + j._update_issue_with_retry(fix, issue_key, fixes=True) + + # This issue was re-opened, by default we will only post a comment but not re-open it again + issue = j.jira_client.issue(issue_key) + assert issue.fields.status.name == 'Open' + + j._update_issue_with_retry(fix, issue_key, fixes=True, ignore_reopened=True) issue = j.jira_client.issue(issue_key) assert issue.fields.status.name == 'Closed' @@ -72,7 +78,7 @@ def test_close_issue(): # Assign to bot and start work assert j.jira_client.assign_issue(issue.key, assignee='qtgerritbot') j.jira_client.transition_issue(issue_key, transition='Start Work') - j._update_issue_with_retry(fix, issue_key, True) + j._update_issue_with_retry(fix, issue_key, True, ignore_reopened=True) issue = j.jira_client.issue(issue_key) assert issue.fields.status.name == 'Closed' assert issue.fields.resolution.name == 'Done' @@ -94,7 +100,7 @@ def test_close_issue(): issue = j.jira_client.issue(issue_key) assert len(issue.fields.fixVersions) == 1 - j._update_issue_with_retry(fix, issue_key, True) + j._update_issue_with_retry(fix, issue_key, True, ignore_reopened=True) issue = j.jira_client.issue(issue_key) assert issue.fields.status.name == 'Closed' assert issue.fields.resolution.name == 'Done' -- cgit v1.2.3