Skip to content

Commit a0d1630

Browse files
GiteaBotlunny
andauthored
Fix agit automerge (#31207) (#31881)
Backport #31207 by @lunny Fix #31134 Co-authored-by: Lunny Xiao <[email protected]>
1 parent 0affb5c commit a0d1630

File tree

5 files changed

+155
-4
lines changed

5 files changed

+155
-4
lines changed

models/fixtures/repository.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
fork_id: 0
2727
is_template: false
2828
template_id: 0
29-
size: 7320
29+
size: 7597
3030
is_fsck_enabled: true
3131
close_issues_via_commit_in_any_branch: false
3232

services/automerge/automerge.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,21 @@ func handlePullRequestAutoMerge(pullID int64, sha string) {
245245
defer headGitRepo.Close()
246246
}
247247

248-
headBranchExist := headGitRepo.IsBranchExist(pr.HeadBranch)
249-
if pr.HeadRepo == nil || !headBranchExist {
250-
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
248+
switch pr.Flow {
249+
case issues_model.PullRequestFlowGithub:
250+
headBranchExist := headGitRepo.IsBranchExist(pr.HeadBranch)
251+
if pr.HeadRepo == nil || !headBranchExist {
252+
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
253+
return
254+
}
255+
case issues_model.PullRequestFlowAGit:
256+
headBranchExist := git.IsReferenceExist(ctx, baseGitRepo.Path, pr.GetGitRefName())
257+
if !headBranchExist {
258+
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch(Agit): %s]", pr, pr.HeadRepoID, pr.HeadBranch)
259+
return
260+
}
261+
default:
262+
log.Error("wrong flow type %d", pr.Flow)
251263
return
252264
}
253265

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env bash
2+
ORI_DIR=`pwd`
3+
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
4+
cd "$ORI_DIR"
5+
for i in `ls "$SHELL_FOLDER/proc-receive.d"`; do
6+
sh "$SHELL_FOLDER/proc-receive.d/$i"
7+
done
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env bash
2+
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" proc-receive

tests/integration/pull_merge_test.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"code.gitea.io/gitea/modules/git"
3232
"code.gitea.io/gitea/modules/gitrepo"
3333
"code.gitea.io/gitea/modules/queue"
34+
"code.gitea.io/gitea/modules/setting"
3435
api "code.gitea.io/gitea/modules/structs"
3536
"code.gitea.io/gitea/modules/test"
3637
"code.gitea.io/gitea/modules/translation"
@@ -846,3 +847,132 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApproval(t *testing.T) {
846847
unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
847848
})
848849
}
850+
851+
func TestPullAutoMergeAfterCommitStatusSucceedAndApprovalForAgitFlow(t *testing.T) {
852+
onGiteaRun(t, func(t *testing.T, u *url.URL) {
853+
// create a pull request
854+
baseAPITestContext := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
855+
856+
dstPath := t.TempDir()
857+
858+
u.Path = baseAPITestContext.GitPath()
859+
u.User = url.UserPassword("user2", userPassword)
860+
861+
t.Run("Clone", doGitClone(dstPath, u))
862+
863+
err := os.WriteFile(path.Join(dstPath, "test_file"), []byte("## test content"), 0o666)
864+
assert.NoError(t, err)
865+
866+
err = git.AddChanges(dstPath, true)
867+
assert.NoError(t, err)
868+
869+
err = git.CommitChanges(dstPath, git.CommitChangesOptions{
870+
Committer: &git.Signature{
871+
872+
Name: "user2",
873+
When: time.Now(),
874+
},
875+
Author: &git.Signature{
876+
877+
Name: "user2",
878+
When: time.Now(),
879+
},
880+
Message: "Testing commit 1",
881+
})
882+
assert.NoError(t, err)
883+
884+
stderrBuf := &bytes.Buffer{}
885+
886+
err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").
887+
AddDynamicArguments(`topic=test/head2`).
888+
AddArguments("-o").
889+
AddDynamicArguments(`title="create a test pull request with agit"`).
890+
AddArguments("-o").
891+
AddDynamicArguments(`description="This PR is a test pull request which created with agit"`).
892+
Run(&git.RunOpts{Dir: dstPath, Stderr: stderrBuf})
893+
assert.NoError(t, err)
894+
895+
assert.Contains(t, stderrBuf.String(), setting.AppURL+"user2/repo1/pulls/6")
896+
897+
baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"})
898+
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
899+
Flow: issues_model.PullRequestFlowAGit,
900+
BaseRepoID: baseRepo.ID,
901+
BaseBranch: "master",
902+
HeadRepoID: baseRepo.ID,
903+
HeadBranch: "user2/test/head2",
904+
})
905+
906+
session := loginUser(t, "user1")
907+
// add protected branch for commit status
908+
csrf := GetCSRF(t, session, "/user2/repo1/settings/branches")
909+
// Change master branch to protected
910+
req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{
911+
"_csrf": csrf,
912+
"rule_name": "master",
913+
"enable_push": "true",
914+
"enable_status_check": "true",
915+
"status_check_contexts": "gitea/actions",
916+
"required_approvals": "1",
917+
})
918+
session.MakeRequest(t, req, http.StatusSeeOther)
919+
920+
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
921+
// first time insert automerge record, return true
922+
scheduled, err := automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
923+
assert.NoError(t, err)
924+
assert.True(t, scheduled)
925+
926+
// second time insert automerge record, return false because it does exist
927+
scheduled, err = automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
928+
assert.Error(t, err)
929+
assert.False(t, scheduled)
930+
931+
// reload pr again
932+
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
933+
assert.False(t, pr.HasMerged)
934+
assert.Empty(t, pr.MergedCommitID)
935+
936+
// update commit status to success, then it should be merged automatically
937+
baseGitRepo, err := gitrepo.OpenRepository(db.DefaultContext, baseRepo)
938+
assert.NoError(t, err)
939+
sha, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
940+
assert.NoError(t, err)
941+
masterCommitID, err := baseGitRepo.GetBranchCommitID("master")
942+
assert.NoError(t, err)
943+
baseGitRepo.Close()
944+
defer func() {
945+
testResetRepo(t, baseRepo.RepoPath(), "master", masterCommitID)
946+
}()
947+
948+
err = commitstatus_service.CreateCommitStatus(db.DefaultContext, baseRepo, user1, sha, &git_model.CommitStatus{
949+
State: api.CommitStatusSuccess,
950+
TargetURL: "https://gitea.com",
951+
Context: "gitea/actions",
952+
})
953+
assert.NoError(t, err)
954+
955+
time.Sleep(2 * time.Second)
956+
957+
// reload pr again
958+
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
959+
assert.False(t, pr.HasMerged)
960+
assert.Empty(t, pr.MergedCommitID)
961+
962+
// approve the PR from non-author
963+
approveSession := loginUser(t, "user1")
964+
req = NewRequest(t, "GET", fmt.Sprintf("/user2/repo1/pulls/%d", pr.Index))
965+
resp := approveSession.MakeRequest(t, req, http.StatusOK)
966+
htmlDoc := NewHTMLParser(t, resp.Body)
967+
testSubmitReview(t, approveSession, htmlDoc.GetCSRF(), "user2", "repo1", strconv.Itoa(int(pr.Index)), sha, "approve", http.StatusOK)
968+
969+
time.Sleep(2 * time.Second)
970+
971+
// realod pr again
972+
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
973+
assert.True(t, pr.HasMerged)
974+
assert.NotEmpty(t, pr.MergedCommitID)
975+
976+
unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
977+
})
978+
}

0 commit comments

Comments
 (0)