From 5a8f821de0d2c9ecf0023ec2049ce59215c4fc7c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2020 15:41:13 +0100 Subject: [PATCH] [FIX] forwardport: recover from failure to create forward port PR Currently if the creation of a forward-port pull request fails: * the branches are left un-cleaned * preceding PRs are left open * the PR whose creation failed may or may not have actually failed, and may or may not still be open We need to delete the forward port branches anyway, and IIRC that *should* automatically close the PR. Sadly making it so github predictably / reliably blows up when trying to create a PR via the API is difficult so this is essentially untestable. Closes #296 --- forwardport/models/project.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/forwardport/models/project.py b/forwardport/models/project.py index 0d1bda32..58417ce2 100644 --- a/forwardport/models/project.py +++ b/forwardport/models/project.py @@ -515,6 +515,8 @@ class PullRequests(models.Model): working_copy.push('target', new_branch) + gh = requests.Session() + gh.headers['Authorization'] = 'token %s' % proj.fp_github_token has_conflicts = any(conflicts.values()) # problemo: this should forward port a batch at a time, if porting # one of the PRs in the batch fails is huge problem, though this loop @@ -541,20 +543,25 @@ class PullRequests(models.Model): if not body: body = None - r = requests.post( - 'https://api.github.com/repos/{}/pulls'.format(pr.repository.name), json={ - 'title': title, - 'body': body, - 'head': '%s:%s' % (owner, new_branch), - 'base': target.name, - #'draft': has_conflicts, draft mode is not supported on private repos so remove it (again) - }, headers={ - 'Accept': 'application/vnd.github.shadow-cat-preview+json', - 'Authorization': 'token %s' % pr.repository.project_id.fp_github_token, - } - ) - assert 200 <= r.status_code < 300, r.json() - r = r.json() + r = gh.post('https://api.github.com/repos/{}/pulls'.format(pr.repository.name), json={ + 'base': target.name, 'head': '%s:%s' % (owner, new_branch), + 'title': title, 'body': body, + }) + results = r.json() + if not (200 <= r.status_code < 300): + _logger.warning("Failed to create forward-port PR for %s, deleting branches", pr.display_name) + # delete all the branches this should automatically close the + # PRs if we've created any. Using the API here is probably + # simpler than going through the working copies + for repo in self.mapped('repository'): + r = gh.delete('https://api.github.com/repos/{}/git/refs/heads/{}'.format(repo.fp_remote_target, new_branch)) + if r.ok: + _logger.info("Deleting %s:%s=success", repo.fp_remote_target, new_branch) + else: + _logger.warning("Deleting %s:%s=%s", repo.fp_remote_target, new_branch, r.json()) + raise RuntimeError("Forwardport failure: %s (%s)" % (pr.display_name, results)) + + r = results self.env.cr.commit() new_pr = self.search([