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"
@@ -158,6 +163,14 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
158163 }
159164 }
160165
166+ // handle pull request merging, a pull request action should push at least 1 commit
167+ if opts .PushTrigger == repo_module .PushTriggerPRMergeToBase {
168+ handlePullRequestMerging (ctx , opts , ownerName , repoName , updates )
169+ if ctx .Written () {
170+ return
171+ }
172+ }
173+
161174 isPrivate := opts .GitPushOptions .Bool (private .GitPushOptionRepoPrivate )
162175 isTemplate := opts .GitPushOptions .Bool (private .GitPushOptionRepoTemplate )
163176 // Handle Push Options
@@ -172,7 +185,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
172185 wasEmpty = repo .IsEmpty
173186 }
174187
175- pusher , err := user_model . GetUserByID (ctx , opts .UserID )
188+ pusher , err := loadContextCacheUser (ctx , opts .UserID )
176189 if err != nil {
177190 log .Error ("Failed to Update: %s/%s Error: %v" , ownerName , repoName , err )
178191 ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {
@@ -307,3 +320,52 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
307320 RepoWasEmpty : wasEmpty ,
308321 })
309322}
323+
324+ func loadContextCacheUser (ctx context.Context , id int64 ) (* user_model.User , error ) {
325+ return cache .GetWithContextCache (ctx , "hook_post_receive_user" , id , func () (* user_model.User , error ) {
326+ return user_model .GetUserByID (ctx , id )
327+ })
328+ }
329+
330+ // handlePullRequestMerging handle pull request merging, a pull request action should push at least 1 commit
331+ func handlePullRequestMerging (ctx * gitea_context.PrivateContext , opts * private.HookOptions , ownerName , repoName string , updates []* repo_module.PushUpdateOptions ) {
332+ if len (updates ) == 0 {
333+ ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {
334+ Err : fmt .Sprintf ("Pushing a merged PR (pr:%d) no commits pushed " , opts .PullRequestID ),
335+ })
336+ return
337+ }
338+
339+ pr , err := issues_model .GetPullRequestByID (ctx , opts .PullRequestID )
340+ if err != nil {
341+ log .Error ("GetPullRequestByID[%d]: %v" , opts .PullRequestID , err )
342+ ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {Err : "GetPullRequestByID failed" })
343+ return
344+ }
345+
346+ pusher , err := loadContextCacheUser (ctx , opts .UserID )
347+ if err != nil {
348+ log .Error ("Failed to Update: %s/%s Error: %v" , ownerName , repoName , err )
349+ ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {Err : "Load pusher user failed" })
350+ return
351+ }
352+
353+ pr .MergedCommitID = updates [len (updates )- 1 ].NewCommitID
354+ pr .MergedUnix = timeutil .TimeStampNow ()
355+ pr .Merger = pusher
356+ pr .MergerID = pusher .ID
357+ err = db .WithTx (ctx , func (ctx context.Context ) error {
358+ // Removing an auto merge pull and ignore if not exist
359+ if err := pull_model .DeleteScheduledAutoMerge (ctx , pr .ID ); err != nil && ! db .IsErrNotExist (err ) {
360+ return fmt .Errorf ("DeleteScheduledAutoMerge[%d]: %v" , opts .PullRequestID , err )
361+ }
362+ if _ , err := pr .SetMerged (ctx ); err != nil {
363+ return fmt .Errorf ("SetMerged failed: %s/%s Error: %v" , ownerName , repoName , err )
364+ }
365+ return nil
366+ })
367+ if err != nil {
368+ log .Error ("Failed to update PR to merged: %v" , err )
369+ ctx .JSON (http .StatusInternalServerError , private.HookPostReceiveResult {Err : "Failed to update PR to merged" })
370+ }
371+ }
0 commit comments