Repository navigation
Gracefully handle existing remote branch and/or pull request #239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d9c2500
88db07f
68ecf3b
1d540b7
4190247
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,8 @@ | |
| import { Args } from "@bp/service/args/args.types"; | ||
| import { Configs } from "@bp/service/configs/configs.types"; | ||
| import PullRequestConfigsParser from "@bp/service/configs/pullrequest/pr-configs-parser"; | ||
| import GitCLIService from "@bp/service/git/git-cli"; | ||
| import GitClient from "@bp/service/git/git-client"; | ||
| import GitCLIService, { NonFastForwardError } from "@bp/service/git/git-cli"; | ||
| import GitClient, { PullRequestExists } from "@bp/service/git/git-client"; | ||
| import GitClientFactory from "@bp/service/git/git-client-factory"; | ||
| import { BackportPullRequest, GitClientType } from "@bp/service/git/git.types"; | ||
| import LoggerService from "@bp/service/logger/logger-service"; | ||
|
|
@@ -14,7 +14,7 @@ | |
| interface Git { | ||
| gitClientType: GitClientType; | ||
| gitClientApi: Pick<GitClient, ("getLatestPullRequestComments" | "createPullRequest" | "createPullRequestComment")>; | ||
| gitCli: Pick<GitCLIService, ("clone" | "createLocalBranch" | "fetch" | "remoteBranchExists" | "cherryPick" | "addRemote" | "push" | "pointToSameCommit" )>; | ||
| gitCli: Pick<GitCLIService, ("clone" | "createLocalBranch" | "fetch" | "hasRemoteOriginalWork" | "hasLocalOriginalWork" | "cherryPick" | "addRemote" | "push" | "pointToSameCommit" )>; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -142,13 +142,6 @@ | |
| } | ||
|
|
||
| async executeBackport(configs: Configs, backportPR: BackportPullRequest, git: Git): Promise<void> { | ||
| const remote = backportPR.headRepo?.cloneUrl ?? backportPR.cloneUrl; | ||
| const branchExists = await git.gitCli.remoteBranchExists(remote, backportPR.head); | ||
| if (branchExists) { | ||
| this.logger.warn(`Backport branch ${backportPR.head} already exists on ${remote}, skipping`); | ||
| return; | ||
| } | ||
|
|
||
| const notifyError = !configs.dryRun && configs.errorNotification.enabled && configs.errorNotification.message.length > 0; | ||
|
|
||
| if (notifyError && await this.failureAlreadyReported(configs, backportPR, git)) { | ||
|
|
@@ -274,13 +267,46 @@ | |
| if (!configs.dryRun) { | ||
| // 10. push the new branch to origin | ||
| yield async () => { | ||
| try { | ||
| await git.gitCli.push(configs.folder, backportPR.head, target_remote); | ||
| } catch (err) { | ||
| if (!(err instanceof NonFastForwardError)) { | ||
| throw err; | ||
| } | ||
| logger.info("Non-fast-forward remote branch"); | ||
| // fetch the diverting remote | ||
| await git.gitCli.fetch(configs.folder, backportPR.head, target_remote); | ||
| if ( | ||
| 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); | ||
|
Comment on lines
+280
to
+290
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is the core of the logic:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried this with original work and it works pretty well: We could probably strip some error msg here as it might be confusing but the important bit is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept the initial error, to ease debugging for users well-versed into git. the The repeated message is not directly due to this PR, but happens in this.logger.error(`Something went wrong backporting to ${backportPR.base}: ${error}`);
if (notifyError) {
// ...
}
throw error; // will trigger another log, with "Failure occurred during one of the backports:"Shall I remove this? |
||
| } | ||
| } | ||
| }; | ||
|
|
||
| // 11. create pull request new branch -> target branch (using octokit) | ||
| yield async () => { | ||
| const prUrl = await git.gitClientApi.createPullRequest(backportPR); | ||
| logger.info(`Pull request created: ${prUrl}`); | ||
| try{ | ||
| const prUrl = await git.gitClientApi.createPullRequest(backportPR); | ||
| logger.info(`Pull request created: ${prUrl}`); | ||
| } catch (err) { | ||
| if (!(err instanceof PullRequestExists)) { | ||
| throw err; | ||
| } | ||
| if (err.url){ | ||
| logger.info(`Pull request updated: ${err.url}`); | ||
| } else { | ||
| logger.info("The existing pull request has been updated"); | ||
| } | ||
| } | ||
| }; | ||
| } else { | ||
| yield async () => { | ||
|
|
@@ -309,9 +335,12 @@ | |
| async fetch(_cwd: string, branch: string, remote = "origin"): Promise<void> { | ||
| s += `git fetch ${remote} ${branch}`; | ||
| }, | ||
| async remoteBranchExists(_remote: string, _branch: string): Promise<boolean> { | ||
| async hasRemoteOriginalWork(_cwd: string, _branch: string, _remote = "origin"): Promise<boolean> { | ||
| return false; | ||
| }, | ||
| async hasLocalOriginalWork(_cwd: string, _branch: string, _remote = "origin"): Promise<boolean> { | ||
| return true; | ||
| }, | ||
| async cherryPick(_cwd: string, sha: string, strategy = "recursive", strategyOption = "theirs", cherryPickOptions: string | undefined, emptyCommit = "stop"): Promise<void> { | ||
| s += `git cherry-pick -m 1 --strategy=${strategy} --strategy-option=${strategyOption} --empty=${emptyCommit} `; | ||
| if (cherryPickOptions !== undefined) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.