gitea_hat/services/pull/check.go

207 lines
6.0 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/queue"
"code.gitea.io/gitea/modules/setting"
"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.UniqueQueue
func AddToTaskQueue(pr *issues_model.PullRequest, action string) {
if action == "opened" || action == "synchronized" {
err := hatPrPatchCheckerQueue.PushFunc(strconv.FormatInt(pr.ID, 10), func() error {
return nil
})
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.PushFunc(strconv.FormatInt(prID, 10), func() error {
log.Trace("Adding PR ID: %d to the pull requests patch hat checking queue", prID)
return nil
}); 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,
OrgID: 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_model.HookEvent{
ChooseEvents: true,
HookEvents: webhook_model.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 handle(data ...queue.Data) []queue.Data {
for _, datum := range data {
id, _ := strconv.ParseInt(datum.(string), 10, 64)
pr, err := issues_model.GetPullRequestByID(db.DefaultContext, id)
if err != nil {
log.Error("GetPullRequestByID[%s]: %v", datum, err)
continue
} else if pr.HasMerged {
continue
}
err = pr.LoadIssue()
if err != nil {
log.Error("pullrequest load issue error: %v", err)
continue
}
err = pr.LoadBaseRepo()
if err != nil {
log.Error("pullrequest load base repo error: %v", err)
continue
}
err = pr.LoadHeadRepo()
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("hat_pr_patch_checker", handle, "")
if hatPrPatchCheckerQueue == nil {
return fmt.Errorf("Unable to create hat_pr_patch_checker Queue")
}
go graceful.GetManager().RunWithShutdownFns(hatPrPatchCheckerQueue.Run)
go graceful.GetManager().RunWithShutdownContext(InitializePullRequests)
go graceful.GetManager().RunWithShutdownContext(InitializeCheckHook)
return nil
}