From da6d4a7db313854232dd9623b8c72aff4628c7b1 Mon Sep 17 00:00:00 2001 From: Edward Hervey <bilboed@bilboed.com> Date: Sun, 6 May 2018 13:36:40 +0100 Subject: [PATCH] Preserve author for issues, comments, attachments Use a 'sudo' token to act as the author when posting issues, comments, and attachments. --- bztogl/bztogl.py | 16 ++++-- bztogl/common.py | 4 +- test/test_bztogl.py | 133 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 test/test_bztogl.py diff --git a/bztogl/bztogl.py b/bztogl/bztogl.py index 3002a56..fd214bf 100644 --- a/bztogl/bztogl.py +++ b/bztogl/bztogl.py @@ -86,10 +86,12 @@ def processbug(bgo, target, user_cache, milestone_cache, bzbug): index[atid] = at return index - def gitlab_upload_file(target, filename, f): + def gitlab_upload_file(target, filename, f, sudo=None): url = "{}api/v3/projects/{}/uploads".format(target.gl_url, target.get_project().id) target.gl.session.headers = {"PRIVATE-TOKEN": target.token} + if sudo: + target.gl.session.headers['sudo'] = '{}'.format(sudo) ret = target.gl.session.post(url, files={ 'file': (urllib.parse.quote(filename), f) }) @@ -100,10 +102,11 @@ def processbug(bgo, target, user_cache, milestone_cache, bzbug): def migrate_attachment(comment, metadata): atid = comment['attachment_id'] + author = user_cache[comment['author']] filename = metadata[atid]['file_name'] print(" Attachment {} found, migrating".format(filename)) attfile = bgo.openattachment(atid) - ret = gitlab_upload_file(target, filename, attfile) + ret = gitlab_upload_file(target, filename, attfile, sudo=author.id) return template.render_attachment(atid, metadata[atid], ret) @@ -228,9 +231,14 @@ def processbug(bgo, target, user_cache, milestone_cache, bzbug): if bz_milestone and bz_milestone != '---': milestone = milestone_cache[bz_milestone] + if user_cache[bzbug.creator]: + sudo = user_cache[bzbug.creator].id + else: + sudo = None issue = target.create_issue(bzbug.id, bzbug.summary, description, labels, milestone, - str(bzbug.creation_time)) + str(bzbug.creation_time), + sudo=sudo) # Assign bug to actual account if exists assignee = user_cache[bzbug.assigned_to] @@ -263,7 +271,7 @@ def processbug(bgo, target, user_cache, milestone_cache, bzbug): issue.notes.create({ 'body': gitlab_comment, 'created_at': str(comment['creation_time']) - }) + }, sudo=author.id) # Do last, so that previous actions don't all send an email for cc_email in itertools.chain(bzbug.cc, [bzbug.creator]): diff --git a/bztogl/common.py b/bztogl/common.py index 623742e..098988f 100644 --- a/bztogl/common.py +++ b/bztogl/common.py @@ -32,7 +32,7 @@ class GitLab: return self.gl.projects.get(self.target_project) def create_issue(self, id, summary, description, labels, - milestone, creation_time): + milestone, creation_time, sudo=None): payload = { 'title': summary, 'description': description, @@ -43,7 +43,7 @@ class GitLab: if milestone: payload['milestone_id'] = milestone.id - return self.get_project().issues.create(payload) + return self.get_project().issues.create(payload, sudo=sudo) def get_all_users(self): if self.all_users is None: diff --git a/test/test_bztogl.py b/test/test_bztogl.py new file mode 100644 index 0000000..620d56e --- /dev/null +++ b/test/test_bztogl.py @@ -0,0 +1,133 @@ +import collections + +from bztogl import bztogl, users + + +def test_create_issue(): + bz = Bugzilla() + gl = Gitlab() + milestone_cache = collections.defaultdict(lambda: None) + bug = Bug(12345, bz) + + # XXX: Create a mock usercache, maybe mock target too ... ? + issue = bztogl.create_issue(target, None, milestone_cache, bug) + assert issue is not None + + +def test_update_content(): + bz = Bugzilla() + gl = Gitlab() + user_cache = collections.defaultdict(lambda: None) + user_cache['test@example.com'] = User() + + bug = Bug(12345, bz) + bug.assigned_to = 'test@example.com' + bug_dep = Bug(54321) + bug.depends_on = [ + bug_dep.bug_id + ] + + issue = Issue() + issue_dep = Issue() + issues = { + 12345: issue, + 54321: issue_dep, + } + + bztogl.update_content(bz, gl, user_cache, issues, issue, bug) + assert 'first comment' in issue.description + assert '#{}'.format(issue_dep.iid) in issue.description + + +def test_finalise_issue(): + bug = Bug(12345) + issue = Issue() + user_cache = collections.defaultdict(lambda: None) + + bztogl.finalise_issue(bug, issue, user_cache) + + +def test_close_bug(): + bz = Bugzilla() + bug = Bug(12345, bz) + issue = Issue() + + bztogl.close_bug(bug, issue) + + +class Bugzilla: + + def __init__(self): + self._proxy = object() + + def build_update(self, *args, **kwargs): + return None + + def update_bugs(self, *args, **kwargs): + pass + + +class Bug: + + next_id = 1 + + def __init__(self, id, bugzilla=None): + self.id = Bug.next_id + self.bug_id = id + self.bugzilla = bugzilla + self.summary = '' + self.creator = 'test@example.com' + self.creation_time = 12345 + self.assigned_to = None + self.cc = [] + self.status = 'NEW' + self.component = 'General' + self.version = None + self.target_milestone = None + self.keywords = [] + self.depends_on = [] + self.blocks = [] + self.see_also = [] + self.attachments = [] + + Bug.next_id += 1 + + def getcomments(self): + return [ + { + 'author': self.creator, + 'text': 'first comment' + } + ] + + +class Gitlab: + + def create_issue(self, *args, **kwargs): + issue = Issue() + issue.description = args[2] + return issue + + +class Issue: + + next_iid = 1 + + def __init__(self): + self.iid = Issue.next_iid + self.description = '' + self.web_url = '' + + Issue.next_iid += 1 + + def save(self, *args, **kwargs): + pass + + +class User: + + def __init__(self): + self.id = None + + def display_name(self): + return 'Test User' -- GitLab