Skip to content

Commit

Permalink
labhub.py: add migrate_issue plugin
Browse files Browse the repository at this point in the history
Includes a migrate issue plugin that migrates an issue
from one repo to another subject to conditions on the
command like only maintainers can perform migration,
issue must exist and issue must not be closed already.

The plugin copies the issue title, issue description but
appends the URL of the old issue and handle of the user
that migrated the issue, to the description of the new
issue. All comments are copied and written along with other
details like author, date/time and URL of the old comment.

Also includes tests to check functionality.

Closes coala#518
  • Loading branch information
aabhaas-vaish committed Apr 7, 2018
1 parent 583785c commit 31ecd7a
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 0 deletions.
97 changes: 97 additions & 0 deletions plugins/labhub.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.com/([^/]+)/([^/]+)/+issues/(\d+)\s+https://github.com/([^/]+)/([^/]+)/*$', # Ignore LineLengthBear, PyCodeStyleBear
# Ignore LineLengthBear, PyCodeStyleBear
re_cmd_name_help='migrate <complete-issue-URL-to-be-copied-from> <complete-repo-URL-to-be-copied-into>',
flags=re.IGNORECASE)
def migrate_issue(self, msg, match):
"""
Migrate an issue from one repo
to another repo of coala
"""
org = match.group(1)
repo_name_orig = match.group(2)
issue_number = match.group(3)
user = msg.frm.nick
org2 = match.group(4)
repo_name_final = match.group(5)

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

if (repo_name_orig in self.REPOS) and (repo_name_final in self.REPOS):
pass
else:
yield 'Repository does not exist!'
return

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,
)
return

try:
old_issue = self.REPOS[repo_name_orig].get_issue(int(issue_number))
old_labels = old_issue.labels

except RuntimeError:
yield 'Issue does not exist!'
return

if str(old_issue.state) == 'closed':
yield 'Issue cannot be migrated as it has been closed already.'
return
else:
pass

url1 = 'https://github.com/{}/{}/issues/{}'
new_issue_title = old_issue.title
new_issue_description = old_issue.description.rstrip()
extra_msg = '\n\nMigrated issue from '+url1.format(
org, repo_name_orig, issue_number) + \
' by @' + str(user)

new_issue = self.REPOS[repo_name_final].create_issue(
new_issue_title, new_issue_description+extra_msg)
new_issue.labels = old_labels

old_comm = old_issue.comments

for i in range(len(old_comm)):
author = old_comm[i].author
comm_text = old_comm[i].body.rstrip()
updated = old_comm[i].updated
comm_url = url1.format(org, repo_name_orig, issue_number) + \
'#issuecomment-' + str(old_comm[i].number)
new_body = comm_text + '\n\nOriginally written by @' + \
author + ' on ' + \
str(updated) + ' UTC' + \
' and you can view it [here!](' + comm_url + ')'
new_issue.add_comment(new_body)

url2 = 'https://github.com/{}/{}/issues/{}'.format(
org, repo_name_final, new_issue.number)

migrated_comm = 'Issue has been migrated to another [repository](' + \
url2 + ') by @' + str(user)
old_issue.add_comment(migrated_comm)
old_labels.add('Invalid')
old_issue.labels = old_labels
old_issue.close()

yield 'New issue created: {}'.format(url2)
return
88 changes: 88 additions & 0 deletions tests/labhub_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def setUp(self):

self.mock_org = create_autospec(github3.orgs.Organization)
self.mock_gh = create_autospec(github3.GitHub)

self.mock_team = create_autospec(github3.orgs.Team)
self.mock_team.name = PropertyMock()
self.mock_team.name = 'mocked team'
Expand Down Expand Up @@ -343,3 +344,90 @@ 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_repo,
'b': self.mock_repo
}

mock_maint_team = create_autospec(github3.orgs.Team)
mock_maint_team.is_member.return_value = False

labhub.TEAMS = {
'coala maintainers': mock_maint_team,
'coala developers': self.mock_team,
'coala newcomers': self.mock_team
}
cmd = '!migrate https://github.com/{}/{}/issues/{} https://github.com/{}/{}/'

# Not a maintainer
testbot.assertCommand(cmd.format('coala', 'a', '21','coala','b'),
'you are not a maintainer!')
# 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')
# No issue exists
mock_maint_team.is_member.return_value = True
self.mock_repo.get_issue = Mock(side_effect=RuntimeError)
testbot.assertCommand(cmd.format('coala', 'a', '21','coala','b'),
'Issue does not exist!')
# Issue closed
mock_maint_team.is_member.return_value = True
mock_iss = create_autospec(IGitt.GitHub.GitHub.GitHubIssue)
self.mock_repo.get_issue = Mock(return_value=mock_iss)
mock_iss.labels = PropertyMock()
mock_iss.state = PropertyMock()
mock_iss.state = 'closed'
testbot.assertCommand(cmd.format('coala', 'a', '21','coala','b'),
'has been closed already')
# Migrate issue
mock_maint_team.is_member.return_value = True
mock_iss = create_autospec(IGitt.GitHub.GitHub.GitHubIssue)
issue2 = create_autospec(IGitt.GitHub.GitHub.GitHubIssue)

self.mock_repo.get_issue = Mock(return_value=mock_iss)
label_prop = PropertyMock(return_value={'enhancement','bug'})
type(mock_iss).labels = label_prop
mock_iss.title = PropertyMock()
mock_iss.labels = 'Issue title'
mock_iss.description = PropertyMock()
mock_iss.description = 'Issue description'
mock_iss.state = PropertyMock()
mock_iss.state = 'open'

self.mock_repo.create_issue = Mock(return_value=issue2)
issue2.labels = PropertyMock()

mock_comment = create_autospec(IGitt.GitHub.GitHub.GitHubComment)
mock_comment2 = create_autospec(IGitt.GitHub.GitHub.GitHubComment)

mock_iss.comments = PropertyMock()
mock_iss.comments = list()
mock_iss.comments.append(mock_comment)
mock_comment.author = PropertyMock()
mock_comment.author = 'random-access7'
mock_comment.body = PropertyMock()
mock_comment.body = 'Comment bobdy'
mock_comment.number = PropertyMock()
mock_comment.number = 1743
mock_comment.updated = PropertyMock()
mock_comment.updated = '07/04/2018'

issue2.add_comment = Mock(return_value=mock_comment2)
mock_iss.add_comment = Mock(return_value=mock_comment2)
mock_iss.close = Mock(return_value=True)

testbot.assertCommand(cmd.format('coala', 'a', '21','coala','b'),
'issue created:')

0 comments on commit 31ecd7a

Please sign in to comment.