fix: classify git failures on stderr, restrict migration failure detail (#39010)

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2026-09-15 10:59:34 +02:00
committed by GitHub
parent 7b036e96c2
commit 812191c0f9
30 changed files with 136 additions and 137 deletions
+13 -37
View File
@@ -559,58 +559,34 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest,
// PushToBaseRepo pushes commits from branches of head repository to
// corresponding branches of base repository.
// FIXME: Only push branches that are actually updates?
func PushToBaseRepo(ctx context.Context, pr *issues_model.PullRequest) (err error) {
return pushToBaseRepoHelper(ctx, pr, "")
}
func pushToBaseRepoHelper(ctx context.Context, pr *issues_model.PullRequest, prefixHeadBranch string) (err error) {
func PushToBaseRepo(ctx context.Context, pr *issues_model.PullRequest) error {
log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitHeadRefName())
if err := pr.LoadHeadRepo(ctx); err != nil {
log.Error("Unable to load head repository for PR[%d] Error: %v", pr.ID, err)
return err
}
if err := pr.LoadBaseRepo(ctx); err != nil {
log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err)
return err
}
if err := pr.LoadIssue(ctx); err != nil {
return err
}
if err := pr.Issue.LoadPoster(ctx); err != nil {
return err
}
if err = pr.LoadIssue(ctx); err != nil {
return fmt.Errorf("unable to load issue %d for pr %d: %w", pr.IssueID, pr.ID, err)
}
if err = pr.Issue.LoadPoster(ctx); err != nil {
return fmt.Errorf("unable to load poster %d for pr %d: %w", pr.Issue.PosterID, pr.ID, err)
}
gitRefName := pr.GetGitHeadRefName()
baseRepoHeadRefName := pr.GetGitHeadRefName()
if err := git.PushManaged(ctx, pr.HeadRepo, pr.BaseRepo, git.PushOptions{
Branch: prefixHeadBranch + pr.HeadBranch + ":" + gitRefName,
Branch: git.BranchPrefix + pr.HeadBranch + ":" + baseRepoHeadRefName,
Force: true,
// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/...
Env: repo_module.InternalPushingEnvironment(pr.Issue.Poster, pr.BaseRepo),
}); err != nil {
if git.IsErrPushOutOfDate(err) {
// This should not happen as we're using force!
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, err)
return err
} else if rejectErr, ok := err.(*git.ErrPushRejected); ok {
log.Info("Unable to push PR head for %s#%d (%-v:%s) due to rejection:\nStdout: %s\nStderr: %s\nError: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, rejectErr.StdOut, rejectErr.StdErr, rejectErr.Err)
return err
} else if git.IsErrMoreThanOne(err) {
if prefixHeadBranch != "" {
log.Info("Can't push with %s%s", prefixHeadBranch, pr.HeadBranch)
return err
}
log.Info("Retrying to push with %s%s", git.BranchPrefix, pr.HeadBranch)
err = pushToBaseRepoHelper(ctx, pr, git.BranchPrefix)
return err
}
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to Error: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, err)
return fmt.Errorf("Push: %s:%s %s:%s %w", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), gitRefName, err)
// Since we use internal force-push, there should be no git error.
// If any error happens, it must be an internal error (e.g.: broken git hooks) but not user error.
return fmt.Errorf("unable to push from head branch %s:%s to base repo %s:%s, err: %w",
pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), baseRepoHeadRefName, err)
}
return nil
}