create "internal/shared" package to workaround import loop issues
This commit is contained in:
parent
0f99a0e3c0
commit
968a1a7029
3 changed files with 125 additions and 101 deletions
117
internal/shared/services/automerge/automerge.go
Normal file
117
internal/shared/services/automerge/automerge.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
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
|
||||
}
|
|
@ -7,9 +7,8 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
shared_automerge "code.gitea.io/gitea/internal/shared/services/automerge"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
|
@ -26,18 +25,15 @@ import (
|
|||
pull_service "code.gitea.io/gitea/services/pull"
|
||||
)
|
||||
|
||||
// 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
|
||||
func Init() error {
|
||||
notify_service.RegisterNotifier(NewNotifier())
|
||||
|
||||
prAutoMergeQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "pr_auto_merge", handler)
|
||||
if prAutoMergeQueue == nil {
|
||||
shared_automerge.PRAutoMergeQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "pr_auto_merge", handler)
|
||||
if shared_automerge.PRAutoMergeQueue == nil {
|
||||
return fmt.Errorf("unable to create pr_auto_merge queue")
|
||||
}
|
||||
go graceful.GetManager().RunWithCancel(prAutoMergeQueue)
|
||||
go graceful.GetManager().RunWithCancel(shared_automerge.PRAutoMergeQueue)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -55,13 +51,6 @@ func handler(items ...string) []string {
|
|||
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
|
||||
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 {
|
||||
|
@ -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
|
||||
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
|
||||
return shared_automerge.StartPRCheckAndAutoMergeBySHA(ctx, sha, repo)
|
||||
}
|
||||
|
||||
// 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
|
||||
shared_automerge.StartPRCheckAndAutoMerge(ctx, pull)
|
||||
}
|
||||
|
||||
// handlePullRequestAutoMerge merge the pull request if all checks are successful
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"fmt"
|
||||
"slices"
|
||||
|
||||
shared_automerge "code.gitea.io/gitea/internal/shared/services/automerge"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
|
@ -19,7 +20,6 @@ import (
|
|||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/services/automerge"
|
||||
)
|
||||
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue