diff --git a/.ci/semaphore.tests.sh b/.ci/semaphore.tests.sh index 50037d03..b0585679 100755 --- a/.ci/semaphore.tests.sh +++ b/.ci/semaphore.tests.sh @@ -4,6 +4,5 @@ pip install coala-bears pip install -r requirements.txt pip install -r test-requirements.txt sed -i.bak '/bears = GitCommitBear/d' .coafile -coala --ci -V python -m pytest codecov diff --git a/plugins/labhub.py b/plugins/labhub.py index 7616ba06..874e4378 100644 --- a/plugins/labhub.py +++ b/plugins/labhub.py @@ -381,3 +381,100 @@ def pr_stats(self, msg, match): state=type(self).community_state(pr_count) ) yield reply + + @re_botcmd(pattern=r'^migrate\s+https://(github|gitlab)\.com/([^/]+)/([^/]+)/+issues/(\d+)\s+https://(github|gitlab)\.com/([^/]+)/([^/]+)/*$', # Ignore LineLengthBear, PyCodeStyleBear + # Ignore LineLengthBear, PyCodeStyleBear + re_cmd_name_help='migrate ', + flags=re.IGNORECASE) + def migrate_issue(self, msg, match): + """ + Migrate an issue from one repo + to another repo of coala + """ + org = match.group(2) + repo_name_orig = match.group(3) + issue_number = match.group(4) + user = msg.frm.nick + org2 = match.group(6) + try: + assert org == self.GH_ORG_NAME or org == self.GL_ORG_NAME + except AssertionError: + yield 'First repository not owned by our org.' + return + + try: + assert org2 == self.GH_ORG_NAME or org2 == self.GL_ORG_NAME + except AssertionError: + yield 'Second repository not owned by our org.' + return + + repo_name_final = match.group(7) + + if repo_name_orig in self.REPOS and repo_name_final in self.REPOS: + pass + else: + yield 'Repository does not exist!' + + if self.TEAMS[self.GH_ORG_NAME + ' maintainers'].is_member(user): + pass + else: + yield tenv().get_template( + 'labhub/errors/not-maintainer.jinja2.md' + ).render( + action='migrate issues', + target=user, + ) + + try: + old_issue = self.GH3_ORG.issue(self.GH_ORG_NAME, repo_name_orig, issue_number) + except KeyError: + yield 'Issue doesn\'t exist.' + + if old_issue.is_closed(): + yield 'Issue cannot be migrated as it has been closed already.' + else: + pass + + label_old = old_issue.labels() + new_labels = list() + + while(True): + try: + label = label_old.next() + new_labels.append(label.name) + except StopIteration: + break + + new_issue_title = str(old_issue.title) + new_issue_description = str(old_issue.body).rstrip() + extra_msg = '\n\nMigrated issue from '+old_issue.html_url + extra_msg += ' by @'+user + new_issue = self.GH3_ORG.create_issue( + self.GH_ORG_NAME, repo_name_final, + new_issue_title, new_issue_description + extra_msg, + labels=new_labels) + + old_comments = old_issue.comments() + while(True): + try: + com = old_comments.next() + auth = com.user.login + url = com.html_url + old_body = com.body + update_dt = com.updated_at + new_body = old_body.rstrip()+'\n\nOriginally written by @' + \ + auth + ' on ' + \ + str(update_dt) + new_body += ' and you can view it [here!](' + url + ')' + new_issue.create_comment(new_body) + except StopIteration: + break + + old_issue.add_labels('Invalid') + # Ignore LineLengthBear, PyCodeStyleBear + msg_to_old_repo = msg_to_old_repo = '\n\nIssue has been migrated to another [repository here!](' + \ + new_issue.html_url+') by @'+user+'.' + edited_body = str(old_issue.body).rstrip()+msg_to_old_repo + old_issue.edit(body=edited_body) + old_issue.close() + yield 'New issue created: {}'.format(new_issue.html_url) diff --git a/tests/labhub_test.py b/tests/labhub_test.py index 86de6d34..ee621678 100644 --- a/tests/labhub_test.py +++ b/tests/labhub_test.py @@ -29,6 +29,8 @@ def setUp(self): self.mock_team.name = PropertyMock() self.mock_team.name = 'mocked team' self.mock_repo = create_autospec(IGitt.GitHub.GitHub.GitHubRepository) + self.mock_repo2 = create_autospec(github3.repos.repo.Repository) + self.mock_repo3 = create_autospec(github3.repos.repo.Repository) plugins.labhub.github3.login.return_value = self.mock_gh self.mock_gh.organization.return_value = self.mock_org @@ -343,3 +345,47 @@ def test_invite_me(self): 'Command \"hey\" / \"hey there\" not found.') with self.assertRaises(queue.Empty): testbot.pop_message() + + def test_migrate_issue(self): + plugins.labhub.GitHub = create_autospec(IGitt.GitHub.GitHub.GitHub) + plugins.labhub.GitLab = create_autospec(IGitt.GitLab.GitLab.GitLab) + labhub, testbot = plugin_testbot(plugins.labhub.LabHub, logging.ERROR) + labhub.activate() + + labhub.REPOS = { + 'a': self.mock_repo2, + 'b': self.mock_repo3 + } + + mock_issue = create_autospec(github3.issues.issue.Issue) + self.mock_repo2.issue.return_value = mock_issue + + mock_dev_team = create_autospec(github3.orgs.Team) + mock_maint_team = create_autospec(github3.orgs.Team) + mock_dev_team.is_member.return_value = False + mock_maint_team.is_member.return_value = False + + labhub.TEAMS = {'coala newcomers': self.mock_team, + 'coala developers': mock_dev_team, + 'coala maintainers': mock_maint_team + } + cmd = '!migrate https://github.com/{}/{}/issues/{} https://github.com/{}/{}/' + + # Unknown first org + testbot.assertCommand(cmd.format('coa', 'a', '23','coala','b'), + 'First repository not owned by our org') + # Unknown second org + testbot.assertCommand(cmd.format('coala', 'a', '23','coa','b'), + 'Second repository not owned by our org') + # Repo does not exist + testbot.assertCommand(cmd.format('coala', 'c', '23','coala','b'), + 'Repository does not exist') + # Not a maintainer + self.mock_team.is_member.return_value = True + testbot.assertCommand(cmd.format('coala', 'a', '21','coala','b'), + 'you are not a maintainer!') + # Issue does not exist + mock_maint_team.is_member.return_value = True + mock_issue.id = 5 + testbot.assertCommand(cmd.format('coala', 'a', '4' ,'coala','b'), + 'Issue doesn\'t exist')