@@ -22,6 +22,7 @@ import (
22
22
"code.gitea.io/gitea/modules/log"
23
23
"code.gitea.io/gitea/modules/process"
24
24
"code.gitea.io/gitea/modules/queue"
25
+ notify_service "code.gitea.io/gitea/services/notify"
25
26
pull_service "code.gitea.io/gitea/services/pull"
26
27
)
27
28
@@ -30,6 +31,8 @@ var prAutoMergeQueue *queue.WorkerPoolQueue[string]
30
31
31
32
// Init runs the task queue to that handles auto merges
32
33
func Init () error {
34
+ notify_service .RegisterNotifier (NewNotifier ())
35
+
33
36
prAutoMergeQueue = queue .CreateUniqueQueue (graceful .GetManager ().ShutdownContext (), "pr_auto_merge" , handler )
34
37
if prAutoMergeQueue == nil {
35
38
return fmt .Errorf ("unable to create pr_auto_merge queue" )
@@ -47,7 +50,7 @@ func handler(items ...string) []string {
47
50
log .Error ("could not parse data from pr_auto_merge queue (%v): %v" , s , err )
48
51
continue
49
52
}
50
- handlePull (id , sha )
53
+ handlePullRequestAutoMerge (id , sha )
51
54
}
52
55
return nil
53
56
}
@@ -62,16 +65,6 @@ func addToQueue(pr *issues_model.PullRequest, sha string) {
62
65
// ScheduleAutoMerge if schedule is false and no error, pull can be merged directly
63
66
func ScheduleAutoMerge (ctx context.Context , doer * user_model.User , pull * issues_model.PullRequest , style repo_model.MergeStyle , message string ) (scheduled bool , err error ) {
64
67
err = db .WithTx (ctx , func (ctx context.Context ) error {
65
- lastCommitStatus , err := pull_service .GetPullRequestCommitStatusState (ctx , pull )
66
- if err != nil {
67
- return err
68
- }
69
-
70
- // we don't need to schedule
71
- if lastCommitStatus .IsSuccess () {
72
- return nil
73
- }
74
-
75
68
if err := pull_model .ScheduleAutoMerge (ctx , doer , pull .ID , style , message ); err != nil {
76
69
return err
77
70
}
@@ -95,8 +88,8 @@ func RemoveScheduledAutoMerge(ctx context.Context, doer *user_model.User, pull *
95
88
})
96
89
}
97
90
98
- // MergeScheduledPullRequest merges a previously scheduled pull request when all checks succeeded
99
- func MergeScheduledPullRequest (ctx context.Context , sha string , repo * repo_model.Repository ) error {
91
+ // StartPullRequestAutoMergeCheckBySHA start an automerge check task for repository and SHA
92
+ func StartPullRequestAutoMergeCheckBySHA (ctx context.Context , sha string , repo * repo_model.Repository ) error {
100
93
pulls , err := getPullRequestsByHeadSHA (ctx , sha , repo , func (pr * issues_model.PullRequest ) bool {
101
94
return ! pr .HasMerged && pr .CanAutoMerge ()
102
95
})
@@ -111,6 +104,33 @@ func MergeScheduledPullRequest(ctx context.Context, sha string, repo *repo_model
111
104
return nil
112
105
}
113
106
107
+ // StartPullRequestAutoMergeCheck start an automerge check task for a pull request
108
+ func StartPullRequestAutoMergeCheck (ctx context.Context , pull * issues_model.PullRequest ) {
109
+ if pull == nil || pull .HasMerged || ! pull .CanAutoMerge () {
110
+ return
111
+ }
112
+
113
+ if err := pull .LoadBaseRepo (ctx ); err != nil {
114
+ log .Error ("LoadBaseRepo: %v" , err )
115
+ return
116
+ }
117
+
118
+ gitRepo , err := gitrepo .OpenRepository (ctx , pull .BaseRepo )
119
+ if err != nil {
120
+ log .Error ("OpenRepository: %v" , err )
121
+ return
122
+ }
123
+ defer gitRepo .Close ()
124
+
125
+ commitID , err := gitRepo .GetRefCommitID (pull .GetGitRefName ())
126
+ if err != nil {
127
+ log .Error ("GetRefCommitID: %v" , err )
128
+ return
129
+ }
130
+
131
+ addToQueue (pull , commitID )
132
+ }
133
+
114
134
func getPullRequestsByHeadSHA (ctx context.Context , sha string , repo * repo_model.Repository , filter func (* issues_model.PullRequest ) bool ) (map [int64 ]* issues_model.PullRequest , error ) {
115
135
gitRepo , err := gitrepo .OpenRepository (ctx , repo )
116
136
if err != nil {
@@ -161,7 +181,8 @@ func getPullRequestsByHeadSHA(ctx context.Context, sha string, repo *repo_model.
161
181
return pulls , nil
162
182
}
163
183
164
- func handlePull (pullID int64 , sha string ) {
184
+ // handlePullRequestAutoMerge merge the pull request if all checks are successful
185
+ func handlePullRequestAutoMerge (pullID int64 , sha string ) {
165
186
ctx , _ , finished := process .GetManager ().AddContext (graceful .GetManager ().HammerContext (),
166
187
fmt .Sprintf ("Handle AutoMerge of PR[%d] with sha[%s]" , pullID , sha ))
167
188
defer finished ()
@@ -182,24 +203,50 @@ func handlePull(pullID int64, sha string) {
182
203
return
183
204
}
184
205
206
+ if err = pr .LoadBaseRepo (ctx ); err != nil {
207
+ log .Error ("%-v LoadBaseRepo: %v" , pr , err )
208
+ return
209
+ }
210
+
211
+ // check the sha is the same as pull request head commit id
212
+ baseGitRepo , err := gitrepo .OpenRepository (ctx , pr .BaseRepo )
213
+ if err != nil {
214
+ log .Error ("OpenRepository: %v" , err )
215
+ return
216
+ }
217
+ defer baseGitRepo .Close ()
218
+
219
+ headCommitID , err := baseGitRepo .GetRefCommitID (pr .GetGitRefName ())
220
+ if err != nil {
221
+ log .Error ("GetRefCommitID: %v" , err )
222
+ return
223
+ }
224
+ if headCommitID != sha {
225
+ log .Warn ("Head commit id of auto merge %-v does not match sha [%s]" , pr , sha )
226
+ return
227
+ }
228
+
185
229
// Get all checks for this pr
186
230
// We get the latest sha commit hash again to handle the case where the check of a previous push
187
231
// did not succeed or was not finished yet.
188
-
189
232
if err = pr .LoadHeadRepo (ctx ); err != nil {
190
233
log .Error ("%-v LoadHeadRepo: %v" , pr , err )
191
234
return
192
235
}
193
236
194
- headGitRepo , err := gitrepo .OpenRepository (ctx , pr .HeadRepo )
195
- if err != nil {
196
- log .Error ("OpenRepository %-v: %v" , pr .HeadRepo , err )
197
- return
237
+ var headGitRepo * git.Repository
238
+ if pr .BaseRepoID == pr .HeadRepoID {
239
+ headGitRepo = baseGitRepo
240
+ } else {
241
+ headGitRepo , err = gitrepo .OpenRepository (ctx , pr .HeadRepo )
242
+ if err != nil {
243
+ log .Error ("OpenRepository %-v: %v" , pr .HeadRepo , err )
244
+ return
245
+ }
246
+ defer headGitRepo .Close ()
198
247
}
199
- defer headGitRepo .Close ()
200
248
201
249
headBranchExist := headGitRepo .IsBranchExist (pr .HeadBranch )
202
-
203
250
if pr .HeadRepo == nil || ! headBranchExist {
204
251
log .Warn ("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]" , pr , pr .HeadRepoID , pr .HeadBranch )
205
252
return
@@ -238,23 +285,6 @@ func handlePull(pullID int64, sha string) {
238
285
return
239
286
}
240
287
241
- var baseGitRepo * git.Repository
242
- if pr .BaseRepoID == pr .HeadRepoID {
243
- baseGitRepo = headGitRepo
244
- } else {
245
- if err = pr .LoadBaseRepo (ctx ); err != nil {
246
- log .Error ("%-v LoadBaseRepo: %v" , pr , err )
247
- return
248
- }
249
-
250
- baseGitRepo , err = gitrepo .OpenRepository (ctx , pr .BaseRepo )
251
- if err != nil {
252
- log .Error ("OpenRepository %-v: %v" , pr .BaseRepo , err )
253
- return
254
- }
255
- defer baseGitRepo .Close ()
256
- }
257
-
258
288
if err := pull_service .Merge (ctx , pr , doer , baseGitRepo , scheduledPRM .MergeStyle , "" , scheduledPRM .Message , true ); err != nil {
259
289
log .Error ("pull_service.Merge: %v" , err )
260
290
return
0 commit comments