def test_transplant_to_mozreview(self): local_repo_path = tempfile.mkdtemp() mozreview_repo_path = tempfile.mkdtemp() shutil.copy(os.path.join(HERE, 'test-data', 'initial.patch'), local_repo_path) try: cmds = [['hg', 'init'], ['hg', 'import', 'initial.patch'], ['hg', 'phase', '--public', '-r', '.'], ['hg', 'bookmark', 'upstream']] for cmd in cmds: # Use check_output to suppress the output from hg import subprocess.check_output(cmd, stderr=subprocess.STDOUT, cwd=local_repo_path) with open(os.path.join(local_repo_path, '.hg', 'hgrc'), 'w') as f: f.write('[extensions]\npurge =\n') f.write('[paths]\nmozreview-push = ') f.write(mozreview_repo_path) f.write('\n') f.write('upstream = .\n') cmds = [['hg', 'init']] for cmd in cmds: # Use check_output to suppress the output from hg import subprocess.check_output(cmd, stderr=subprocess.STDOUT, cwd=mozreview_repo_path) with open(os.path.join(mozreview_repo_path, '.hg', 'hgrc'), 'w') as f: f.write('[phases]\npublish = False\n') def get_repo_path(tree): return local_repo_path transplant.get_repo_path = get_repo_path class RetrieveCommits(): def __init__(self): self.files = [['rename-file.patch'], ['added-blah.patch']] self.current = 0 def __call__(self, gh, user, repo, pullrequest, path): if self.current > len(self.files): return [] else: files = self.files[self.current] self.current += 1 for f in files: shutil.copy(os.path.join(HERE, 'test-data', f), local_repo_path) return files gh = mock.Mock() github.retrieve_commits = RetrieveCommits() # land a patch with a rename landed, result = transplant.transplant_to_mozreview(gh, 'mozilla', 'cthulhu', 'repo', 0, 0, 'cookie', 0) # We expect this to not be landed as we're not pushing to a repo # with the mozreview extension, but we should not see an error in # the result. self.assertEqual(landed, False) self.assertEqual(result, '') # ensure patches are applied independently - this should fail if # we still see the rename above. cmds = [['hg', 'strip', '--no-backup', '-r', 'draft()']] for cmd in cmds: subprocess.check_call(cmd, stderr=subprocess.STDOUT, cwd=mozreview_repo_path) landed, result = transplant.transplant_to_mozreview(gh, 'mozilla', 'cthulhu', 'repo', 0, 0, 'cookie', 0) self.assertEqual(landed, False) self.assertEqual(result, '') self.assertTrue(os.path.isfile(os.path.join(local_repo_path, 'hello'))) # simple test of rexp to extract review id output = 'review url: http://localhost:55557/r/1 (pending)' m = re.search(transplant.REVIEW_REXP, output) self.assertIsNotNone(m) self.assertEqual(m.groups()[0], 'http://localhost:55557/r/1') finally: shutil.rmtree(local_repo_path) shutil.rmtree(mozreview_repo_path)
def handle_pending_mozreview_pullrequests(logger, dbconn): gh = github.connect() if not gh: return bzurl = config.get('bugzilla')['url'] cursor = dbconn.cursor() query = """ select id,ghuser,repo,pullrequest,destination,bzuserid,bzcookie,bugid, pingback_url from MozreviewPullRequest where landed is null """ cursor.execute(query) finished_revisions = [] mozreview_updates = [] for row in cursor.fetchall(): (transplant_id, ghuser, repo, pullrequest, destination, bzuserid, bzcookie, bugid, pingback_url) = row logger.info('attempting to import pullrequest: %s' % transplant_id) # see if we can extract the bug from the commit message if bugid is None: title, body = github.retrieve_issue(gh, ghuser, repo, pullrequest) bugs = parse_bugs(title) if bugs: bugid = bugs[0] logger.info('using bug %s from issue title' % bugid) finished_revisions.append([bugid, None, None, transplant_id]) # still no luck, attempt to autofile a bug on the user's behalf if bugid is None: logger.info('attempting to autofile bug for: %s' % transplant_id) b = bugsy.Bugsy(userid=bzuserid, cookie=bzcookie, bugzilla_url=bzurl) if not b: logger.info('could not connect to bugzilla instance at %s for ' 'pullrequest id %s' % (bzurl, transplant_id)) error = 'could not connect to bugzilla. bad credentials?' else: bug = bugsy.Bug() # Summary is required, the rest have defaults or are optional bug.summary = title if config.testing(): bug.product = 'TestProduct' bug.component = 'TestComponent' else: # TODO: determine a better product & component than the # defaults provided by Bugsy pass pr_url = github.url_for_pullrequest(ghuser,repo, pullrequest) bug.add_comment('%s\n\nImported from: %s' % (body, pr_url)) try: b.put(bug) bugid = bug.id logger.info('created bug: %s ' % bugid) finished_revisions.append([bugid, None, None, transplant_id]) except bugsy.BugsyException as e: logger.info('transplant failed: could not create new bug: %s ' % e.msg) finished_revisions.append([None, False, e.msg, transplant_id]) # set up data to be posted back to mozreview data = { 'request_id': transplant_id, 'bugid': None, 'landed': False, 'error_msg': 'could not create new bug: ' + e.msg, 'result': '' } mozreview_updates.append([transplant_id, pingback_url, json.dumps(data)]) landed, result = transplant.transplant_to_mozreview(gh, destination, ghuser, repo, pullrequest, bzuserid, bzcookie, bugid) if landed: logger.info(('transplanted from' ' https://github.com/%s/%s/pull/%s' ' to destination: %s new revision: %s') % (ghuser, repo, pullrequest, destination, result)) else: logger.info(('transplant failed' ' https://github.com/%s/%s/pull/%s' ' destination: %s error: %s') % (ghuser, repo, pullrequest, destination, result)) finished_revisions.append([bugid, landed, result, transplant_id]) # set up data to be posted back to mozreview data = { 'request_id': transplant_id, 'bugid': bugid, 'landed': landed, 'error_msg': '', 'result': '' } if landed: data['result'] = result else: data['error_msg'] = result mozreview_updates.append([transplant_id, pingback_url, json.dumps(data)]) if finished_revisions: query = """ update MozreviewPullRequest set bugid=%s,landed=%s,result=%s where id=%s """ cursor.executemany(query, finished_revisions) dbconn.commit() if mozreview_updates: query = """ insert into MozreviewUpdate(request_id,pingback_url,data) values(%s,%s,%s) """ cursor.executemany(query, mozreview_updates) dbconn.commit()