create "shared" package to workaround import loop issues
This commit is contained in:
parent
d96cef1ac4
commit
bb857855e5
3 changed files with 128 additions and 101 deletions
|
@ -7,8 +7,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
|
@ -24,20 +22,18 @@ import (
|
||||||
"code.gitea.io/gitea/modules/queue"
|
"code.gitea.io/gitea/modules/queue"
|
||||||
notify_service "code.gitea.io/gitea/services/notify"
|
notify_service "code.gitea.io/gitea/services/notify"
|
||||||
pull_service "code.gitea.io/gitea/services/pull"
|
pull_service "code.gitea.io/gitea/services/pull"
|
||||||
|
shared_automerge "code.gitea.io/gitea/services/shared/automerge"
|
||||||
)
|
)
|
||||||
|
|
||||||
// prAutoMergeQueue represents a queue to handle update pull request tests
|
|
||||||
var prAutoMergeQueue *queue.WorkerPoolQueue[string]
|
|
||||||
|
|
||||||
// Init runs the task queue to that handles auto merges
|
// Init runs the task queue to that handles auto merges
|
||||||
func Init() error {
|
func Init() error {
|
||||||
notify_service.RegisterNotifier(NewNotifier())
|
notify_service.RegisterNotifier(NewNotifier())
|
||||||
|
|
||||||
prAutoMergeQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "pr_auto_merge", handler)
|
shared_automerge.PRAutoMergeQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "pr_auto_merge", handler)
|
||||||
if prAutoMergeQueue == nil {
|
if shared_automerge.PRAutoMergeQueue == nil {
|
||||||
return fmt.Errorf("unable to create pr_auto_merge queue")
|
return fmt.Errorf("unable to create pr_auto_merge queue")
|
||||||
}
|
}
|
||||||
go graceful.GetManager().RunWithCancel(prAutoMergeQueue)
|
go graceful.GetManager().RunWithCancel(shared_automerge.PRAutoMergeQueue)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,13 +51,6 @@ func handler(items ...string) []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScheduleAutoMerge if schedule is false and no error, pull can be merged directly
|
// ScheduleAutoMerge if schedule is false and no error, pull can be merged directly
|
||||||
func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pull *issues_model.PullRequest, style repo_model.MergeStyle, message string) (scheduled bool, err error) {
|
func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pull *issues_model.PullRequest, style repo_model.MergeStyle, message string) (scheduled bool, err error) {
|
||||||
err = db.WithTx(ctx, func(ctx context.Context) error {
|
err = db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
|
@ -90,94 +79,12 @@ func RemoveScheduledAutoMerge(ctx context.Context, doer *user_model.User, pull *
|
||||||
|
|
||||||
// StartPRCheckAndAutoMergeBySHA start an automerge check and auto merge task for all pull requests of repository and SHA
|
// 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 {
|
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 shared_automerge.StartPRCheckAndAutoMergeBySHA(ctx, sha, repo)
|
||||||
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
|
// StartPRCheckAndAutoMerge start an automerge check and auto merge task for a pull request
|
||||||
func StartPRCheckAndAutoMerge(ctx context.Context, pull *issues_model.PullRequest) {
|
func StartPRCheckAndAutoMerge(ctx context.Context, pull *issues_model.PullRequest) {
|
||||||
if pull == nil || pull.HasMerged || !pull.CanAutoMerge() {
|
shared_automerge.StartPRCheckAndAutoMerge(ctx, pull)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlePullRequestAutoMerge merge the pull request if all checks are successful
|
// handlePullRequestAutoMerge merge the pull request if all checks are successful
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/services/automerge"
|
shared_automerge "code.gitea.io/gitea/services/shared/automerge"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getCacheKey(repoID int64, brancheName string) string {
|
func getCacheKey(repoID int64, brancheName string) string {
|
||||||
|
@ -117,7 +117,7 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.State.IsSuccess() {
|
if status.State.IsSuccess() {
|
||||||
if err := automerge.StartPRCheckAndAutoMergeBySHA(ctx, sha, repo); err != nil {
|
if err := shared_automerge.StartPRCheckAndAutoMergeBySHA(ctx, sha, repo); err != nil {
|
||||||
return fmt.Errorf("MergeScheduledPullRequest[repo_id: %d, user_id: %d, sha: %s]: %w", repo.ID, creator.ID, sha, err)
|
return fmt.Errorf("MergeScheduledPullRequest[repo_id: %d, user_id: %d, sha: %s]: %w", repo.ID, creator.ID, sha, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
120
services/shared/automerge/automerge.go
Normal file
120
services/shared/automerge/automerge.go
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
// 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
|
||||||
|
}
|
Loading…
Reference in a new issue