gitea_hat/services/pull/check.go

206 lines
6.1 KiB
Go

package pull
import (
"context"
"fmt"
"strconv"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
webhook_model "code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting"
webhook_module "code.gitea.io/gitea/modules/webhook"
"code.gitea.io/gitea/services/gitdiff"
hat_issues_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/issues"
hat_pull_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/pull"
hat_webhook_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/webhook"
)
var hatPrPatchCheckerQueue *queue.WorkerPoolQueue[string]
func AddToTaskQueue(pr *issues_model.PullRequest, action string) {
if action == "opened" || action == "synchronized" {
err := hatPrPatchCheckerQueue.Push(strconv.FormatInt(pr.ID, 10))
if err != nil && err != queue.ErrAlreadyInQueue {
log.Error("Error adding prID %d to the test pull requests queue: %v", pr.ID, err)
}
} else {
log.Error("action type is not found rule.")
}
}
// InitializePullRequests checks and tests untested patches of pull requests.
func InitializePullRequests(ctx context.Context) {
prs, err := hat_issues_model.GetPullRequestIDsByIssueUpdatedUnix()
if err != nil {
log.Error("Find Checking PRs: %v", err)
return
}
for _, prID := range prs {
select {
case <-ctx.Done():
return
default:
if err := hatPrPatchCheckerQueue.Push(strconv.FormatInt(prID, 10)); err != nil {
log.Error("Error adding prID: %s to the pull requests patch hat checking queue %v", prID, err)
}
}
}
}
func InitializeCheckHook(ctx context.Context) {
w := webhook_model.Webhook{
RepoID: 0,
OwnerID: 0,
IsSystemWebhook: true,
URL: fmt.Sprintf("%sapi/hat/create_pr_version", setting.AppURL),
HTTPMethod: "POST",
}
_, err := hat_webhook_model.GetWebhook(&hat_webhook_model.Webhook{
Webhook: w,
})
if err != nil {
log.Error("Find System Hook: %v", err)
if webhook_model.IsErrWebhookNotExist(err) {
w.HookEvent = &webhook_module.HookEvent{
ChooseEvents: true,
HookEvents: webhook_module.HookEvents{
PullRequestSync: true,
PullRequest: true,
},
BranchFilter: "*",
}
w.ContentType = webhook_model.ContentTypeJSON
w.IsActive = true
w.Type = "gitea"
err = w.UpdateEvent()
if err != nil {
log.Error("Update System Hook Event: %v", err)
}
err = webhook_model.CreateWebhook(ctx, &w)
if err != nil {
log.Error("Create System Hook: %v", err)
}
}
}
return
}
func handler(data ...string) []string {
for _, datum := range data {
id, _ := strconv.ParseInt(datum, 10, 64)
ctx, _, _ := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("Create PR[%d] Version from checking queue", id))
pr, err := issues_model.GetPullRequestByID(ctx, id)
if err != nil {
log.Error("GetPullRequestByID[%s]: %v", datum, err)
continue
} else if pr.HasMerged {
continue
}
err = pr.LoadIssue(ctx)
if err != nil {
log.Error("pullrequest load issue error: %v", err)
continue
}
err = pr.LoadBaseRepo(ctx)
if err != nil {
log.Error("pullrequest load base repo error: %v", err)
continue
}
err = pr.LoadHeadRepo(ctx)
if err != nil {
log.Error("pullrequest load head repo error: %v", err)
continue
}
baseGitRepo, err := git.OpenRepository(db.DefaultContext, pr.BaseRepo.RepoPath())
if err != nil {
log.Error("git.OpenRepository err:%v", err)
continue
}
defer baseGitRepo.Close()
commit, err := baseGitRepo.GetCommit(pr.GetGitRefName())
if err != nil {
log.Error("GetCommit err:%v", err)
continue
}
hpr := &hat_issues_model.PullRequest{PullRequest: *pr}
err = hpr.LoadLatestPullRequestVersion(db.DefaultContext)
if err != nil && !issues_model.IsErrPullRequestNotExist(err) {
log.Error("pullrequest load version error: %v", err)
continue
}
if hpr.LatestPullRequestVersion == nil {
betweenCommitsCount, err := baseGitRepo.CommitsCountBetween(pr.MergeBase, commit.ID.String())
if err != nil {
log.Error("CommitsBeforeUntil err: %v", err)
continue
}
diffs, err := gitdiff.GetDiff(baseGitRepo, &gitdiff.DiffOptions{
BeforeCommitID: pr.MergeBase,
AfterCommitID: commit.ID.String(),
})
if err != nil {
log.Error("GetDiff err: %v", err)
continue
}
err = hat_pull_model.NewPullRequestVersion(db.DefaultContext, pr.HeadRepo, pr, diffs.TotalAddition, int(betweenCommitsCount), diffs.TotalDeletion, diffs.NumFiles, commit.ID.String(), pr.MergeBase, pr.MergeBase)
if err != nil {
log.Error("models.NewPullRequestVersion err: %v", err)
continue
}
} else {
if commit.ID.String() == hpr.LatestPullRequestVersion.HeadCommitID {
log.Error("This pull version is saved.")
continue
}
betweenCommitsCount, err := baseGitRepo.CommitsCountBetween(hpr.LatestPullRequestVersion.HeadCommitID, commit.ID.String())
if err != nil {
log.Error("CommitsBeforeUntil err: %v", err)
continue
}
diffs, err := gitdiff.GetDiff(baseGitRepo, &gitdiff.DiffOptions{
BeforeCommitID: hpr.LatestPullRequestVersion.HeadCommitID,
AfterCommitID: commit.ID.String(),
})
if err != nil {
log.Error("GetDiff err: %v", err)
continue
}
err = hat_pull_model.NewPullRequestVersion(db.DefaultContext, pr.HeadRepo, pr, diffs.TotalAddition, int(betweenCommitsCount), diffs.TotalDeletion, diffs.NumFiles, commit.ID.String(), pr.MergeBase, hpr.LatestPullRequestVersion.HeadCommitID)
if err != nil {
log.Error("models.NewPullRequestVersion err: %v", err)
continue
}
}
}
return nil
}
func Init() error {
hatPrPatchCheckerQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "hat_pr_patch_checker", handler)
if hatPrPatchCheckerQueue == nil {
return fmt.Errorf("Unable to create hat_pr_patch_checker Queue")
}
go graceful.GetManager().RunWithCancel(hatPrPatchCheckerQueue)
go graceful.GetManager().RunWithShutdownContext(InitializePullRequests)
go graceful.GetManager().RunWithShutdownContext(InitializeCheckHook)
return nil
}