mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 14:31:02 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			120 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2021 Gitea. All rights reserved.
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| package automerge
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	issues_model "code.gitea.io/gitea/models/issues"
 | |
| 	repo_model "code.gitea.io/gitea/models/repo"
 | |
| 	"code.gitea.io/gitea/modules/git"
 | |
| 	"code.gitea.io/gitea/modules/gitrepo"
 | |
| 	"code.gitea.io/gitea/modules/log"
 | |
| 	"code.gitea.io/gitea/modules/queue"
 | |
| )
 | |
| 
 | |
| // PRAutoMergeQueue represents a queue to handle update pull request tests
 | |
| var PRAutoMergeQueue *queue.WorkerPoolQueue[string]
 | |
| 
 | |
| func addToQueue(pr *issues_model.PullRequest, sha string) {
 | |
| 	log.Trace("Adding pullID: %d to the pull requests patch checking queue with sha %s", pr.ID, sha)
 | |
| 	if err := PRAutoMergeQueue.Push(fmt.Sprintf("%d_%s", pr.ID, sha)); err != nil {
 | |
| 		log.Error("Error adding pullID: %d to the pull requests patch checking queue %v", pr.ID, err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // StartPRCheckAndAutoMergeBySHA start an automerge check and auto merge task for all pull requests of repository and SHA
 | |
| func StartPRCheckAndAutoMergeBySHA(ctx context.Context, sha string, repo *repo_model.Repository) error {
 | |
| 	pulls, err := getPullRequestsByHeadSHA(ctx, sha, repo, func(pr *issues_model.PullRequest) bool {
 | |
| 		return !pr.HasMerged && pr.CanAutoMerge()
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	for _, pr := range pulls {
 | |
| 		addToQueue(pr, sha)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // StartPRCheckAndAutoMerge start an automerge check and auto merge task for a pull request
 | |
| func StartPRCheckAndAutoMerge(ctx context.Context, pull *issues_model.PullRequest) {
 | |
| 	if pull == nil || pull.HasMerged || !pull.CanAutoMerge() {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if err := pull.LoadBaseRepo(ctx); err != nil {
 | |
| 		log.Error("LoadBaseRepo: %v", err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	gitRepo, err := gitrepo.OpenRepository(ctx, pull.BaseRepo)
 | |
| 	if err != nil {
 | |
| 		log.Error("OpenRepository: %v", err)
 | |
| 		return
 | |
| 	}
 | |
| 	defer gitRepo.Close()
 | |
| 	commitID, err := gitRepo.GetRefCommitID(pull.GetGitRefName())
 | |
| 	if err != nil {
 | |
| 		log.Error("GetRefCommitID: %v", err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	addToQueue(pull, commitID)
 | |
| }
 | |
| 
 | |
| func getPullRequestsByHeadSHA(ctx context.Context, sha string, repo *repo_model.Repository, filter func(*issues_model.PullRequest) bool) (map[int64]*issues_model.PullRequest, error) {
 | |
| 	gitRepo, err := gitrepo.OpenRepository(ctx, repo)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer gitRepo.Close()
 | |
| 
 | |
| 	refs, err := gitRepo.GetRefsBySha(sha, "")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	pulls := make(map[int64]*issues_model.PullRequest)
 | |
| 
 | |
| 	for _, ref := range refs {
 | |
| 		// Each pull branch starts with refs/pull/ we then go from there to find the index of the pr and then
 | |
| 		// use that to get the pr.
 | |
| 		if strings.HasPrefix(ref, git.PullPrefix) {
 | |
| 			parts := strings.Split(ref[len(git.PullPrefix):], "/")
 | |
| 
 | |
| 			// e.g. 'refs/pull/1/head' would be []string{"1", "head"}
 | |
| 			if len(parts) != 2 {
 | |
| 				log.Error("getPullRequestsByHeadSHA found broken pull ref [%s] on repo [%-v]", ref, repo)
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			prIndex, err := strconv.ParseInt(parts[0], 10, 64)
 | |
| 			if err != nil {
 | |
| 				log.Error("getPullRequestsByHeadSHA found broken pull ref [%s] on repo [%-v]", ref, repo)
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			p, err := issues_model.GetPullRequestByIndex(ctx, repo.ID, prIndex)
 | |
| 			if err != nil {
 | |
| 				// If there is no pull request for this branch, we don't try to merge it.
 | |
| 				if issues_model.IsErrPullRequestNotExist(err) {
 | |
| 					continue
 | |
| 				}
 | |
| 				return nil, err
 | |
| 			}
 | |
| 
 | |
| 			if filter(p) {
 | |
| 				pulls[p.ID] = p
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return pulls, nil
 | |
| }
 |