Repository navigation
Gracefully handle existing remote branch and/or pull request - #239
oliverpool wants to merge 5 commits into
Conversation
This reverts commit c59a6f7.
the content will have been updated by the force-push
fdbbe5f to
e94d039
Compare
|
Thanks again @oliverpool , I really appreciate the effort you're putting in improving this tool ❤️ Overall the idea looks good but I'd like to take some time to ensure it is working as expected.
This is the tricky part: I haven't checked the code yet, but I just want to make sure we don't run the risk of doing a force push to a branch we shouldn't, since that could be irreversible.
This is very good improvement, +100 🚀 |
oliverpool
left a comment
There was a problem hiding this comment.
@lampajr thanks for the kind words!
To ease your review, here are the key additions of this PR.
Let me know what you think, once you have got time to review them!
| const output = await simpleGit().raw(["ls-remote", "--heads", this.remoteWithAuth(remote), branch]); | ||
| return output.trim().length > 0; | ||
| async _isUpstreamMissingWork(cwd: string, upstream: string, head: string): Promise<boolean> { | ||
| const stdout = await this.git(cwd).raw(["cherry", upstream, head]); |
There was a problem hiding this comment.
| @@ -187,7 +227,15 @@ export default class GitCLIService { | |||
| if (force) { | |||
| options.push("--force-with-lease"); | |||
There was a problem hiding this comment.
Note that I was able to keep the force-with-lease (since we fetch the upstream branch, to check for original work)
| await git.gitCli.hasRemoteOriginalWork(configs.folder, backportPR.head, target_remote) | ||
| ) { | ||
| logger.info("Remote branch contains original work, aborting"); | ||
| // throw original error: we cannot push in non-fast-forwarding way | ||
| throw err.cause; | ||
| } | ||
| if ( | ||
| await git.gitCli.hasLocalOriginalWork(configs.folder, backportPR.head, target_remote) | ||
| ) { | ||
| logger.info("Force-pushing rebased branch"); | ||
| await git.gitCli.push(configs.folder, backportPR.head, target_remote, true); |
There was a problem hiding this comment.
Here is the core of the logic:
- fetch the remote branch
- if it contains original work, abort
- otherwise if we have original work (ie rebase), force-push-with-lease
There was a problem hiding this comment.
I tried this with original work and it works pretty well:
[INFO ] [prod] Remote branch contains original work, aborting
[ERROR] [prod] Something went wrong backporting to prod: Error: To https://github.com/lampajr/backporting-example.git
! refs/heads/bp-prod-6353aff:refs/heads/bp-prod-6353aff [rejected] (non-fast-forward)
Done
Pushing to https://github.com/lampajr/backporting-example.git
error: failed to push some refs to 'https://github.com/lampajr/backporting-example.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
[ERROR] Error: Failure occurred during one of the backports: [Error: To https://github.com/lampajr/backporting-example.git
! refs/heads/bp-prod-6353aff:refs/heads/bp-prod-6353aff [rejected] (non-fast-forward)
Done
Pushing to https://github.com/lampajr/backporting-example.git
error: failed to push some refs to 'https://github.com/lampajr/backporting-example.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
]
[INFO ] Process failed
We could probably strip some error msg here as it might be confusing but the important bit is [INFO ] [prod] Remote branch contains original work, aborting - can be improved later.
There was a problem hiding this comment.
This is a bit hacky: return an empty URL if a pull request already exists for this base+head.
Ideally we should return the URL of the existing PR, but Forgejo does not expose this in a structured way (yet). I haven't tested github.
There was a problem hiding this comment.
As a temporary solution might, even though I don't think it is working as expected with github:
POST /repos/lampajr/backporting-example/pulls - 422 with id 9BB4:1EB9F9:EF86DE:1631085:6ADBBFF9 in 750ms
[ERROR] [prod] Something went wrong backporting to prod: HttpError: Validation Failed: {"resource":"PullRequest","code":"custom","message":"A pull request already exists for lampajr:bp-prod-6353aff."} - https://docs.github.com/rest/pulls/pulls#create-a-pull-request
[ERROR] Error: Failure occurred during one of the backports: [HttpError: Validation Failed: {"resource":"PullRequest","code":"custom","message":"A pull request already exists for lampajr:bp-prod-6353aff."} - https://docs.github.com/rest/pulls/pulls#create-a-pull-request]
[INFO ] Process failed
The process still fails in case of existing PR
lampajr
left a comment
There was a problem hiding this comment.
Hey @oliverpool , I tested this out a little bit and it looks good to me!
There is only one small issue that I'd like to cover before merging, looks like Forgejo returns different http code compared to github in case of existing PR - 409 (forgejo) vs 422 (github). Do you see any problem in implementing this as well?

fixes #234
Description
This changes the behavior introduced in #231 (aborting early if the branch exists on the remote) by @BtbN (tagging you to get your feedback :)
Instead of early-aborting if the same branch exists on the remote, this PR performs the cherry-pick and the compares the local and remote:
Afterwards the PR creation is always attempted: if a 409 reply is received (a PR already exists), log the message and succeed (only for github/forgejo).
This would be valuable for Forgejo on codeberg, where sometimes the branch creation succeeds, but the PR creation fails: currently the branch is left there forever (needs a manual PR opening).
With this fix, a re-run of the job would update the branch and retry PR creation (nicer than a manual PR opening).
How Has This Been Tested?
Unit tests have been added at the git-cli level, as well as at the runner level.
I performed a manual test on a local forgejo instance:
mainandltsbranchesmaingit-backporting: backport PR is opened (unchanged)ltsgit-backporting: the existing branch will be rebased (force push) - PR will be detected as presentgit-backporting: the existing branch will be left unchanged and a new PR createdgit-backporting: failure with messageRemote branch contains original work, abortingBest reviewed commit-by-commit.
Checklist
Merge criteria: