44package private
55
66import (
7+ "context"
78 "fmt"
89 "net/http"
910
11+ "code.gitea.io/gitea/models/db"
1012 git_model "code.gitea.io/gitea/models/git"
1113 issues_model "code.gitea.io/gitea/models/issues"
1214 access_model "code.gitea.io/gitea/models/perm/access"
15+ pull_model "code.gitea.io/gitea/models/pull"
1316 repo_model "code.gitea.io/gitea/models/repo"
1417 user_model "code.gitea.io/gitea/models/user"
18+ "code.gitea.io/gitea/modules/cache"
1519 "code.gitea.io/gitea/modules/git"
1620 "code.gitea.io/gitea/modules/gitrepo"
1721 "code.gitea.io/gitea/modules/log"
1822 "code.gitea.io/gitea/modules/private"
1923 repo_module "code.gitea.io/gitea/modules/repository"
2024 "code.gitea.io/gitea/modules/setting"
25+ timeutil "code.gitea.io/gitea/modules/timeutil"
2126 "code.gitea.io/gitea/modules/util"
2227 "code.gitea.io/gitea/modules/web"
2328 gitea_context "code.gitea.io/gitea/services/context"
@@ -160,6 +165,14 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
160165 }
161166 }
162167
168+ // handle pull request merging, a pull request action should push at least 1 commit
169+ if opts .PushTrigger == repo_module .PushTriggerPRMergeToBase {
170+ handlePullRequestMerging (ctx , opts , ownerName , repoName , updates )
171+ if ctx .Written () {
172+ return
173+ }
174+ }
175+
163176 isPrivate := opts .GitPushOptions .Bool (private .GitPushOptionRepoPrivate )
164177 isTemplate := opts .GitPushOptions .Bool (private .GitPushOptionRepoTemplate )
165178 // Handle Push Options
@@ -174,7 +187,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
174187 wasEmpty = repo .IsEmpty
175188 }
176189
177- pusher , err := user_model . GetUserByID (ctx , opts .UserID )
190+ pusher , err := loadContextCacheUser (ctx , opts .UserID )
178191 if err != nil {
179192 log .Error ("Failed to Update: %s/%s Error: %v" , ownerName , repoName , err )
180193 ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {
@@ -309,3 +322,52 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
309322 RepoWasEmpty : wasEmpty ,
310323 })
311324}
325+
326+ func loadContextCacheUser (ctx context.Context , id int64 ) (* user_model.User , error ) {
327+ return cache .GetWithContextCache (ctx , "hook_post_receive_user" , id , func () (* user_model.User , error ) {
328+ return user_model .GetUserByID (ctx , id )
329+ })
330+ }
331+
332+ // handlePullRequestMerging handle pull request merging, a pull request action should push at least 1 commit
333+ func handlePullRequestMerging (ctx * gitea_context.PrivateContext , opts * private.HookOptions , ownerName , repoName string , updates []* repo_module.PushUpdateOptions ) {
334+ if len (updates ) == 0 {
335+ ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {
336+ Err : fmt .Sprintf ("Pushing a merged PR (pr:%d) no commits pushed " , opts .PullRequestID ),
337+ })
338+ return
339+ }
340+
341+ pr , err := issues_model .GetPullRequestByID (ctx , opts .PullRequestID )
342+ if err != nil {
343+ log .Error ("GetPullRequestByID[%d]: %v" , opts .PullRequestID , err )
344+ ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {Err : "GetPullRequestByID failed" })
345+ return
346+ }
347+
348+ pusher , err := loadContextCacheUser (ctx , opts .UserID )
349+ if err != nil {
350+ log .Error ("Failed to Update: %s/%s Error: %v" , ownerName , repoName , err )
351+ ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {Err : "Load pusher user failed" })
352+ return
353+ }
354+
355+ pr .MergedCommitID = updates [len (updates )- 1 ].NewCommitID
356+ pr .MergedUnix = timeutil .TimeStampNow ()
357+ pr .Merger = pusher
358+ pr .MergerID = pusher .ID
359+ err = db .WithTx (ctx , func (ctx context.Context ) error {
360+ // Removing an auto merge pull and ignore if not exist
361+ if err := pull_model .DeleteScheduledAutoMerge (ctx , pr .ID ); err != nil && ! db .IsErrNotExist (err ) {
362+ return fmt .Errorf ("DeleteScheduledAutoMerge[%d]: %v" , opts .PullRequestID , err )
363+ }
364+ if _ , err := pr .SetMerged (ctx ); err != nil {
365+ return fmt .Errorf ("SetMerged failed: %s/%s Error: %v" , ownerName , repoName , err )
366+ }
367+ return nil
368+ })
369+ if err != nil {
370+ log .Error ("Failed to update PR to merged: %v" , err )
371+ ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {Err : "Failed to update PR to merged" })
372+ }
373+ }
0 commit comments