/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
1
# Copyright (C) 2018 Breezy Developers
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
0.434.1 by Jelmer Vernooij
Use absolute_import.
17
"""Support for GitHub."""
18
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
19
from __future__ import absolute_import
20
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
21
import os
22
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
23
from .propose import (
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
24
    Hoster,
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
25
    HosterLoginRequired,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
26
    MergeProposal,
0.432.2 by Jelmer Vernooij
Publish command sort of works.
27
    MergeProposalBuilder,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
28
    MergeProposalExists,
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
29
    PrerequisiteBranchUnsupported,
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
30
    UnsupportedHoster,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
31
    )
32
33
from ... import (
0.431.33 by Jelmer Vernooij
Fix URLs from gitlab.
34
    branch as _mod_branch,
0.432.3 by Jelmer Vernooij
Publish command works for github.
35
    controldir,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
36
    errors,
37
    hooks,
38
    urlutils,
0.432.3 by Jelmer Vernooij
Publish command works for github.
39
    version_string as breezy_version,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
40
    )
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
41
from ...config import AuthenticationConfig, GlobalStack, config_dir
0.431.32 by Jelmer Vernooij
Properly resolve git+ssh URLs.
42
from ...git.urls import git_url_to_bzr_url
0.432.3 by Jelmer Vernooij
Publish command works for github.
43
from ...i18n import gettext
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
44
from ...sixish import PY3
0.432.3 by Jelmer Vernooij
Publish command works for github.
45
from ...trace import note
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
46
from ...lazy_import import lazy_import
47
lazy_import(globals(), """
48
from github import Github
49
""")
50
51
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
52
def store_github_token(scheme, host, token):
53
    with open(os.path.join(config_dir(), 'github.conf'), 'w') as f:
54
        f.write(token)
55
56
57
def retrieve_github_token(scheme, host):
58
    path = os.path.join(config_dir(), 'github.conf')
59
    if not os.path.exists(path):
60
        return None
0.435.1 by Jelmer Vernooij
Fix reading github credentials.
61
    with open(path, 'r') as f:
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
62
        return f.read().strip()
63
64
0.431.44 by Jelmer Vernooij
Support get/set description.
65
def determine_title(description):
66
    return description.splitlines()[0]
67
68
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
69
class NotGitHubUrl(errors.BzrError):
70
71
    _fmt = "Not a GitHub URL: %(url)s"
72
73
    def __init__(self, url):
74
        errors.BzrError.__init__(self)
75
        self.url = url
76
77
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
78
class GitHubLoginRequired(HosterLoginRequired):
79
80
    _fmt = "Action requires GitHub login."
81
82
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
83
def connect_github():
7211.13.7 by Jelmer Vernooij
Fix formatting.
84
    """Connect to GitHub.
85
    """
86
    user_agent = "Breezy/%s" % breezy_version
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
87
88
    auth = AuthenticationConfig()
89
90
    credentials = auth.get_credentials('https', 'github.com')
91
    if credentials is not None:
0.432.3 by Jelmer Vernooij
Publish command works for github.
92
        return Github(credentials['user'], credentials['password'],
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
93
                      user_agent=user_agent)
94
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
95
    # TODO(jelmer): token = auth.get_token('https', 'github.com')
96
    token = retrieve_github_token('https', 'github.com')
97
    if token is not None:
0.431.61 by Jelmer Vernooij
Fix token login.
98
        return Github(token, user_agent=user_agent)
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
99
    else:
100
        note('Accessing GitHub anonymously. To log in, run \'brz gh-login\'.')
101
        return Github(user_agent=user_agent)
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
102
103
0.431.44 by Jelmer Vernooij
Support get/set description.
104
class GitHubMergeProposal(MergeProposal):
105
106
    def __init__(self, pr):
107
        self._pr = pr
108
109
    @property
110
    def url(self):
111
        return self._pr.html_url
112
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
113
    def _branch_from_part(self, part):
114
        return github_url_to_bzr_url(part.repo.html_url, part.ref)
115
116
    def get_source_branch_url(self):
117
        return self._branch_from_part(self._pr.head)
118
119
    def get_target_branch_url(self):
120
        return self._branch_from_part(self._pr.base)
121
0.431.44 by Jelmer Vernooij
Support get/set description.
122
    def get_description(self):
123
        return self._pr.body
124
125
    def set_description(self, description):
126
        self._pr.edit(body=description, title=determine_title(description))
127
0.431.46 by Jelmer Vernooij
Add MergeProposal.is_merged.
128
    def is_merged(self):
129
        return self._pr.merged
130
7260.2.1 by Jelmer Vernooij
Implement .close on merge proposals.
131
    def close(self):
132
        self._pr.edit(state='closed')
133
0.431.44 by Jelmer Vernooij
Support get/set description.
134
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
135
def parse_github_url(url):
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
136
    (scheme, user, password, host, port, path) = urlutils.parse_url(
137
        url)
138
    if host != 'github.com':
139
        raise NotGitHubUrl(url)
140
    (owner, repo_name) = path.strip('/').split('/')
0.432.12 by Jelmer Vernooij
Fix .git ends.
141
    if repo_name.endswith('.git'):
142
        repo_name = repo_name[:-4]
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
143
    return owner, repo_name
144
145
146
def parse_github_branch_url(branch):
147
    url = urlutils.split_segment_parameters(branch.user_url)[0]
148
    owner, repo_name = parse_github_url(url)
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
149
    return owner, repo_name, branch.name
150
151
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
152
def github_url_to_bzr_url(url, branch_name):
153
    if not PY3:
154
        branch_name = branch_name.encode('utf-8')
155
    return urlutils.join_segment_parameters(
7211.13.7 by Jelmer Vernooij
Fix formatting.
156
        git_url_to_bzr_url(url), {"branch": branch_name})
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
157
158
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
159
def convert_github_error(fn):
160
    def convert(self, *args, **kwargs):
161
        import github
162
        try:
163
            return fn(self, *args, **kwargs)
164
        except github.GithubException as e:
165
            if e.args[0] == 401:
166
                raise GitHubLoginRequired(self)
167
            raise
168
    return convert
169
170
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
171
class GitHub(Hoster):
172
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
173
    name = 'github'
174
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
175
    supports_merge_proposal_labels = True
176
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
177
    def __repr__(self):
178
        return "GitHub()"
179
7260.1.1 by Jelmer Vernooij
Add .base_url property to Hoster.
180
    @property
181
    def base_url(self):
182
        # TODO(jelmer): Can we get the default URL from the Python API package
183
        # somehow?
184
        return "https://github.com"
185
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
186
    def __init__(self):
187
        self.gh = connect_github()
188
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
189
    @convert_github_error
0.431.20 by Jelmer Vernooij
publish -> publish_derived.
190
    def publish_derived(self, local_branch, base_branch, name, project=None,
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
191
                        owner=None, revision_id=None, overwrite=False,
192
                        allow_lossy=True):
0.432.12 by Jelmer Vernooij
Fix .git ends.
193
        import github
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
194
        base_owner, base_project, base_branch_name = parse_github_branch_url(base_branch)
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
195
        base_repo = self.gh.get_repo('%s/%s' % (base_owner, base_project))
0.432.3 by Jelmer Vernooij
Publish command works for github.
196
        if owner is None:
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
197
            owner = self.gh.get_user().login
0.432.3 by Jelmer Vernooij
Publish command works for github.
198
        if project is None:
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
199
            project = base_repo.name
0.432.3 by Jelmer Vernooij
Publish command works for github.
200
        try:
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
201
            remote_repo = self.gh.get_repo('%s/%s' % (owner, project))
0.432.12 by Jelmer Vernooij
Fix .git ends.
202
            remote_repo.id
203
        except github.UnknownObjectException:
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
204
            base_repo = self.gh.get_repo('%s/%s' % (base_owner, base_project))
205
            if owner == self.gh.get_user().login:
206
                owner_obj = self.gh.get_user()
0.432.3 by Jelmer Vernooij
Publish command works for github.
207
            else:
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
208
                owner_obj = self.gh.get_organization(owner)
0.432.12 by Jelmer Vernooij
Fix .git ends.
209
            remote_repo = owner_obj.create_fork(base_repo)
0.432.3 by Jelmer Vernooij
Publish command works for github.
210
            note(gettext('Forking new repository %s from %s') %
7211.13.7 by Jelmer Vernooij
Fix formatting.
211
                 (remote_repo.html_url, base_repo.html_url))
0.432.3 by Jelmer Vernooij
Publish command works for github.
212
        else:
213
            note(gettext('Reusing existing repository %s') % remote_repo.html_url)
0.431.32 by Jelmer Vernooij
Properly resolve git+ssh URLs.
214
        remote_dir = controldir.ControlDir.open(git_url_to_bzr_url(remote_repo.ssh_url))
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
215
        try:
7211.13.7 by Jelmer Vernooij
Fix formatting.
216
            push_result = remote_dir.push_branch(
217
                local_branch, revision_id=revision_id, overwrite=overwrite,
218
                name=name)
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
219
        except errors.NoRoundtrippingSupport:
220
            if not allow_lossy:
221
                raise
7211.13.7 by Jelmer Vernooij
Fix formatting.
222
            push_result = remote_dir.push_branch(
223
                local_branch, revision_id=revision_id,
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
224
                overwrite=overwrite, name=name, lossy=True)
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
225
        return push_result.target_branch, github_url_to_bzr_url(
7211.13.7 by Jelmer Vernooij
Fix formatting.
226
            remote_repo.html_url, name)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
227
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
228
    @convert_github_error
0.431.28 by Jelmer Vernooij
Implement Hoster.get_push_url.
229
    def get_push_url(self, branch):
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
230
        owner, project, branch_name = parse_github_branch_url(branch)
0.431.28 by Jelmer Vernooij
Implement Hoster.get_push_url.
231
        repo = self.gh.get_repo('%s/%s' % (owner, project))
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
232
        return github_url_to_bzr_url(repo.ssh_url, branch_name)
0.431.28 by Jelmer Vernooij
Implement Hoster.get_push_url.
233
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
234
    @convert_github_error
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
235
    def get_derived_branch(self, base_branch, name, project=None, owner=None):
236
        import github
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
237
        base_owner, base_project, base_branch_name = parse_github_branch_url(base_branch)
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
238
        base_repo = self.gh.get_repo('%s/%s' % (base_owner, base_project))
239
        if owner is None:
240
            owner = self.gh.get_user().login
241
        if project is None:
242
            project = base_repo.name
243
        try:
244
            remote_repo = self.gh.get_repo('%s/%s' % (owner, project))
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
245
            full_url = github_url_to_bzr_url(remote_repo.ssh_url, name)
0.431.33 by Jelmer Vernooij
Fix URLs from gitlab.
246
            return _mod_branch.Branch.open(full_url)
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
247
        except github.UnknownObjectException:
248
            raise errors.NotBranchError('https://github.com/%s/%s' % (owner, project))
249
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
250
    @convert_github_error
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
251
    def get_proposer(self, source_branch, target_branch):
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
252
        return GitHubMergeProposalBuilder(self.gh, source_branch, target_branch)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
253
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
254
    @convert_github_error
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
255
    def iter_proposals(self, source_branch, target_branch, status='open'):
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
256
        (source_owner, source_repo_name, source_branch_name) = (
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
257
            parse_github_branch_url(source_branch))
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
258
        (target_owner, target_repo_name, target_branch_name) = (
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
259
            parse_github_branch_url(target_branch))
0.431.67 by Jelmer Vernooij
Support multiple merge proposals per branch.
260
        target_repo = self.gh.get_repo(
261
            "%s/%s" % (target_owner, target_repo_name))
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
262
        state = {
263
            'open': 'open',
264
            'merged': 'closed',
265
            'closed': 'closed',
266
            'all': 'all'}
267
        for pull in target_repo.get_pulls(
268
                head=target_branch_name,
269
                state=state[status]):
270
            if (status == 'closed' and pull.merged or
271
                    status == 'merged' and not pull.merged):
272
                continue
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
273
            if pull.head.ref != source_branch_name:
274
                continue
7268.4.1 by Jelmer Vernooij
Don't attempt to resolve None when repo has gone away.
275
            if pull.head.repo is None:
276
                # Repo has gone the way of the dodo
277
                continue
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
278
            if (pull.head.repo.owner.login != source_owner or
7211.13.7 by Jelmer Vernooij
Fix formatting.
279
                    pull.head.repo.name != source_repo_name):
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
280
                continue
0.431.67 by Jelmer Vernooij
Support multiple merge proposals per branch.
281
            yield GitHubMergeProposal(pull)
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
282
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
283
    def hosts(self, branch):
284
        try:
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
285
            parse_github_branch_url(branch)
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
286
        except NotGitHubUrl:
287
            return False
288
        else:
289
            return True
290
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
291
    @classmethod
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
292
    def probe_from_url(cls, url):
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
293
        try:
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
294
            parse_github_url(url)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
295
        except NotGitHubUrl:
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
296
            raise UnsupportedHoster(url)
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
297
        return cls()
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
298
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
299
    @classmethod
300
    def iter_instances(cls):
301
        yield cls()
302
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
303
    @convert_github_error
0.431.66 by Jelmer Vernooij
Add support for status argument.
304
    def iter_my_proposals(self, status='open'):
305
        query = ['is:pr']
306
        if status == 'open':
307
            query.append('is:open')
308
        elif status == 'closed':
309
            query.append('is:unmerged')
7268.2.1 by Jelmer Vernooij
Don't include open unmerged pull requests in 'closed'.
310
            # Also use "is:closed" otherwise unmerged open pull requests are
311
            # also included.
312
            query.append('is:closed')
0.431.66 by Jelmer Vernooij
Add support for status argument.
313
        elif status == 'merged':
314
            query.append('is:merged')
315
        query.append('author:%s' % self.gh.get_user().login)
316
        for issue in self.gh.search_issues(query=' '.join(query)):
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
317
            yield GitHubMergeProposal(issue.as_pull_request())
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
318
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
319
0.432.2 by Jelmer Vernooij
Publish command sort of works.
320
class GitHubMergeProposalBuilder(MergeProposalBuilder):
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
321
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
322
    def __init__(self, gh, source_branch, target_branch):
323
        self.gh = gh
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
324
        self.source_branch = source_branch
325
        self.target_branch = target_branch
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
326
        (self.target_owner, self.target_repo_name, self.target_branch_name) = (
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
327
            parse_github_branch_url(self.target_branch))
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
328
        (self.source_owner, self.source_repo_name, self.source_branch_name) = (
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
329
            parse_github_branch_url(self.source_branch))
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
330
331
    def get_infotext(self):
332
        """Determine the initial comment for the merge proposal."""
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
333
        info = []
334
        info.append("Merge %s into %s:%s\n" % (
335
            self.source_branch_name, self.target_owner,
336
            self.target_branch_name))
337
        info.append("Source: %s\n" % self.source_branch.user_url)
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
338
        info.append("Target: %s\n" % self.target_branch.user_url)
339
        return ''.join(info)
340
341
    def get_initial_body(self):
342
        """Get a body for the proposal for the user to modify.
343
344
        :return: a str or None.
345
        """
346
        return None
347
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
348
    def create_proposal(self, description, reviewers=None, labels=None,
349
                        prerequisite_branch=None):
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
350
        """Perform the submission."""
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
351
        if prerequisite_branch is not None:
352
            raise PrerequisiteBranchUnsupported(self)
0.432.10 by Jelmer Vernooij
More test fixes.
353
        import github
0.432.7 by Jelmer Vernooij
propose works \o/
354
        # TODO(jelmer): Probe for right repo name
0.432.12 by Jelmer Vernooij
Fix .git ends.
355
        if self.target_repo_name.endswith('.git'):
356
            self.target_repo_name = self.target_repo_name[:-4]
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
357
        target_repo = self.gh.get_repo("%s/%s" % (self.target_owner, self.target_repo_name))
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
358
        # TODO(jelmer): Allow setting title explicitly?
0.431.44 by Jelmer Vernooij
Support get/set description.
359
        title = determine_title(description)
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
360
        # TOOD(jelmer): Set maintainers_can_modify?
0.432.10 by Jelmer Vernooij
More test fixes.
361
        try:
362
            pull_request = target_repo.create_pull(
363
                title=title, body=description,
364
                head="%s:%s" % (self.source_owner, self.source_branch_name),
365
                base=self.target_branch_name)
366
        except github.GithubException as e:
367
            if e.status == 422:
368
                raise MergeProposalExists(self.source_branch.user_url)
369
            raise
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
370
        if reviewers:
371
            for reviewer in reviewers:
372
                pull_request.assignees.append(
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
373
                    self.gh.get_user(reviewer))
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
374
        if labels:
375
            for label in labels:
376
                pull_request.issue.labels.append(label)
0.431.44 by Jelmer Vernooij
Support get/set description.
377
        return GitHubMergeProposal(pull_request)