mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	Backport #31207 by @lunny Fix #31134 Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		@@ -26,7 +26,7 @@
 | 
			
		||||
  fork_id: 0
 | 
			
		||||
  is_template: false
 | 
			
		||||
  template_id: 0
 | 
			
		||||
  size: 7320
 | 
			
		||||
  size: 7597
 | 
			
		||||
  is_fsck_enabled: true
 | 
			
		||||
  close_issues_via_commit_in_any_branch: false
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -245,9 +245,21 @@ func handlePullRequestAutoMerge(pullID int64, sha string) {
 | 
			
		||||
		defer headGitRepo.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	headBranchExist := headGitRepo.IsBranchExist(pr.HeadBranch)
 | 
			
		||||
	if pr.HeadRepo == nil || !headBranchExist {
 | 
			
		||||
		log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
 | 
			
		||||
	switch pr.Flow {
 | 
			
		||||
	case issues_model.PullRequestFlowGithub:
 | 
			
		||||
		headBranchExist := headGitRepo.IsBranchExist(pr.HeadBranch)
 | 
			
		||||
		if pr.HeadRepo == nil || !headBranchExist {
 | 
			
		||||
			log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	case issues_model.PullRequestFlowAGit:
 | 
			
		||||
		headBranchExist := git.IsReferenceExist(ctx, baseGitRepo.Path, pr.GetGitRefName())
 | 
			
		||||
		if !headBranchExist {
 | 
			
		||||
			log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch(Agit): %s]", pr, pr.HeadRepoID, pr.HeadBranch)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		log.Error("wrong flow type %d", pr.Flow)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								tests/gitea-repositories-meta/user2/repo1.git/hooks/proc-receive
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										7
									
								
								tests/gitea-repositories-meta/user2/repo1.git/hooks/proc-receive
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
ORI_DIR=`pwd`
 | 
			
		||||
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
 | 
			
		||||
cd "$ORI_DIR"
 | 
			
		||||
for i in `ls "$SHELL_FOLDER/proc-receive.d"`; do
 | 
			
		||||
    sh "$SHELL_FOLDER/proc-receive.d/$i"
 | 
			
		||||
done
 | 
			
		||||
							
								
								
									
										2
									
								
								tests/gitea-repositories-meta/user2/repo1.git/hooks/proc-receive.d/gitea
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										2
									
								
								tests/gitea-repositories-meta/user2/repo1.git/hooks/proc-receive.d/gitea
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" proc-receive
 | 
			
		||||
@@ -31,6 +31,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	"code.gitea.io/gitea/modules/gitrepo"
 | 
			
		||||
	"code.gitea.io/gitea/modules/queue"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/modules/test"
 | 
			
		||||
	"code.gitea.io/gitea/modules/translation"
 | 
			
		||||
@@ -846,3 +847,132 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApproval(t *testing.T) {
 | 
			
		||||
		unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPullAutoMergeAfterCommitStatusSucceedAndApprovalForAgitFlow(t *testing.T) {
 | 
			
		||||
	onGiteaRun(t, func(t *testing.T, u *url.URL) {
 | 
			
		||||
		// create a pull request
 | 
			
		||||
		baseAPITestContext := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
 | 
			
		||||
 | 
			
		||||
		dstPath := t.TempDir()
 | 
			
		||||
 | 
			
		||||
		u.Path = baseAPITestContext.GitPath()
 | 
			
		||||
		u.User = url.UserPassword("user2", userPassword)
 | 
			
		||||
 | 
			
		||||
		t.Run("Clone", doGitClone(dstPath, u))
 | 
			
		||||
 | 
			
		||||
		err := os.WriteFile(path.Join(dstPath, "test_file"), []byte("## test content"), 0o666)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		err = git.AddChanges(dstPath, true)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		err = git.CommitChanges(dstPath, git.CommitChangesOptions{
 | 
			
		||||
			Committer: &git.Signature{
 | 
			
		||||
				Email: "user2@example.com",
 | 
			
		||||
				Name:  "user2",
 | 
			
		||||
				When:  time.Now(),
 | 
			
		||||
			},
 | 
			
		||||
			Author: &git.Signature{
 | 
			
		||||
				Email: "user2@example.com",
 | 
			
		||||
				Name:  "user2",
 | 
			
		||||
				When:  time.Now(),
 | 
			
		||||
			},
 | 
			
		||||
			Message: "Testing commit 1",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		stderrBuf := &bytes.Buffer{}
 | 
			
		||||
 | 
			
		||||
		err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").
 | 
			
		||||
			AddDynamicArguments(`topic=test/head2`).
 | 
			
		||||
			AddArguments("-o").
 | 
			
		||||
			AddDynamicArguments(`title="create a test pull request with agit"`).
 | 
			
		||||
			AddArguments("-o").
 | 
			
		||||
			AddDynamicArguments(`description="This PR is a test pull request which created with agit"`).
 | 
			
		||||
			Run(&git.RunOpts{Dir: dstPath, Stderr: stderrBuf})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		assert.Contains(t, stderrBuf.String(), setting.AppURL+"user2/repo1/pulls/6")
 | 
			
		||||
 | 
			
		||||
		baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"})
 | 
			
		||||
		pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
 | 
			
		||||
			Flow:       issues_model.PullRequestFlowAGit,
 | 
			
		||||
			BaseRepoID: baseRepo.ID,
 | 
			
		||||
			BaseBranch: "master",
 | 
			
		||||
			HeadRepoID: baseRepo.ID,
 | 
			
		||||
			HeadBranch: "user2/test/head2",
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		session := loginUser(t, "user1")
 | 
			
		||||
		// add protected branch for commit status
 | 
			
		||||
		csrf := GetCSRF(t, session, "/user2/repo1/settings/branches")
 | 
			
		||||
		// Change master branch to protected
 | 
			
		||||
		req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{
 | 
			
		||||
			"_csrf":                 csrf,
 | 
			
		||||
			"rule_name":             "master",
 | 
			
		||||
			"enable_push":           "true",
 | 
			
		||||
			"enable_status_check":   "true",
 | 
			
		||||
			"status_check_contexts": "gitea/actions",
 | 
			
		||||
			"required_approvals":    "1",
 | 
			
		||||
		})
 | 
			
		||||
		session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
 | 
			
		||||
		user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
 | 
			
		||||
		// first time insert automerge record, return true
 | 
			
		||||
		scheduled, err := automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.True(t, scheduled)
 | 
			
		||||
 | 
			
		||||
		// second time insert automerge record, return false because it does exist
 | 
			
		||||
		scheduled, err = automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
		assert.False(t, scheduled)
 | 
			
		||||
 | 
			
		||||
		// reload pr again
 | 
			
		||||
		pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
 | 
			
		||||
		assert.False(t, pr.HasMerged)
 | 
			
		||||
		assert.Empty(t, pr.MergedCommitID)
 | 
			
		||||
 | 
			
		||||
		// update commit status to success, then it should be merged automatically
 | 
			
		||||
		baseGitRepo, err := gitrepo.OpenRepository(db.DefaultContext, baseRepo)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		sha, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		masterCommitID, err := baseGitRepo.GetBranchCommitID("master")
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		baseGitRepo.Close()
 | 
			
		||||
		defer func() {
 | 
			
		||||
			testResetRepo(t, baseRepo.RepoPath(), "master", masterCommitID)
 | 
			
		||||
		}()
 | 
			
		||||
 | 
			
		||||
		err = commitstatus_service.CreateCommitStatus(db.DefaultContext, baseRepo, user1, sha, &git_model.CommitStatus{
 | 
			
		||||
			State:     api.CommitStatusSuccess,
 | 
			
		||||
			TargetURL: "https://gitea.com",
 | 
			
		||||
			Context:   "gitea/actions",
 | 
			
		||||
		})
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		time.Sleep(2 * time.Second)
 | 
			
		||||
 | 
			
		||||
		// reload pr again
 | 
			
		||||
		pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
 | 
			
		||||
		assert.False(t, pr.HasMerged)
 | 
			
		||||
		assert.Empty(t, pr.MergedCommitID)
 | 
			
		||||
 | 
			
		||||
		// approve the PR from non-author
 | 
			
		||||
		approveSession := loginUser(t, "user1")
 | 
			
		||||
		req = NewRequest(t, "GET", fmt.Sprintf("/user2/repo1/pulls/%d", pr.Index))
 | 
			
		||||
		resp := approveSession.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
		htmlDoc := NewHTMLParser(t, resp.Body)
 | 
			
		||||
		testSubmitReview(t, approveSession, htmlDoc.GetCSRF(), "user2", "repo1", strconv.Itoa(int(pr.Index)), sha, "approve", http.StatusOK)
 | 
			
		||||
 | 
			
		||||
		time.Sleep(2 * time.Second)
 | 
			
		||||
 | 
			
		||||
		// realod pr again
 | 
			
		||||
		pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
 | 
			
		||||
		assert.True(t, pr.HasMerged)
 | 
			
		||||
		assert.NotEmpty(t, pr.MergedCommitID)
 | 
			
		||||
 | 
			
		||||
		unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user