diff --git a/modules/notification/bots/bots.go b/modules/notification/bots/bots.go index 27f68b1330..0e9e4dcc81 100644 --- a/modules/notification/bots/bots.go +++ b/modules/notification/bots/bots.go @@ -29,6 +29,7 @@ import ( "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + bots_service "code.gitea.io/gitea/services/bots" "github.com/nektos/act/pkg/jobparser" ) @@ -44,11 +45,11 @@ func NewNotifier() base.Notifier { return &botsNotifier{} } -func notify(repo *repo_model.Repository, doer *user_model.User, ref string, evt webhook.HookEventType, payload api.Payloader) error { - return notifyWithPR(repo, doer, ref, evt, payload, nil) +func notify(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, ref string, evt webhook.HookEventType, payload api.Payloader) error { + return notifyWithPR(ctx, repo, doer, ref, evt, payload, nil) } -func notifyWithPR(repo *repo_model.Repository, doer *user_model.User, ref string, evt webhook.HookEventType, payload api.Payloader, pr *issues_model.PullRequest) error { +func notifyWithPR(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, ref string, evt webhook.HookEventType, payload api.Payloader, pr *issues_model.PullRequest) error { if unit.TypeBots.UnitGlobalDisabled() { return nil } @@ -109,7 +110,18 @@ func notifyWithPR(repo *repo_model.Repository, doer *user_model.User, ref string } if err := bots_model.InsertRun(&run, jobs); err != nil { log.Error("InsertRun: %v", err) + continue } + if jobs, _, err := bots_model.FindRunJobs(ctx, bots_model.FindRunJobOptions{RunID: run.ID}); err != nil { + log.Error("FindRunJobs: %v", err) + } else { + for _, job := range jobs { + if err := bots_service.CreateCommitStatus(ctx, job); err != nil { + log.Error("CreateCommitStatus: %v", err) + } + } + } + } return nil } @@ -126,7 +138,7 @@ func (a *botsNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.I } mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) - if err := notify(issue.Repo, issue.Poster, issue.Repo.DefaultBranch, + if err := notify(ctx, issue.Repo, issue.Poster, issue.Repo.DefaultBranch, webhook.HookEventIssues, &api.IssuePayload{ Action: api.HookIssueOpened, Index: issue.Index, @@ -159,7 +171,7 @@ func (a *botsNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_m } else { apiPullRequest.Action = api.HookIssueReOpened } - err = notify(issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventPullRequest, apiPullRequest) + err = notify(ctx, issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventPullRequest, apiPullRequest) } else { apiIssue := &api.IssuePayload{ Index: issue.Index, @@ -172,7 +184,7 @@ func (a *botsNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_m } else { apiIssue.Action = api.HookIssueReOpened } - err = notify(issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventIssues, apiIssue) + err = notify(ctx, issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventIssues, apiIssue) } if err != nil { log.Error("PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err) @@ -203,7 +215,7 @@ func (a *botsNotifier) NotifyIssueChangeLabels(ctx context.Context, doer *user_m log.Error("LoadIssue: %v", err) return } - err = notify(issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventPullRequestLabel, &api.PullRequestPayload{ + err = notify(ctx, issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventPullRequestLabel, &api.PullRequestPayload{ Action: api.HookIssueLabelUpdated, Index: issue.Index, PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), @@ -211,7 +223,7 @@ func (a *botsNotifier) NotifyIssueChangeLabels(ctx context.Context, doer *user_m Sender: convert.ToUser(doer, nil), }) } else { - err = notify(issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventIssueLabel, &api.IssuePayload{ + err = notify(ctx, issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventIssueLabel, &api.IssuePayload{ Action: api.HookIssueLabelUpdated, Index: issue.Index, Issue: convert.ToAPIIssue(ctx, issue), @@ -232,7 +244,7 @@ func (a *botsNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_ var err error if issue.IsPull { - err = notify(issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventPullRequestComment, &api.IssueCommentPayload{ + err = notify(ctx, issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventPullRequestComment, &api.IssueCommentPayload{ Action: api.HookIssueCommentCreated, Issue: convert.ToAPIIssue(ctx, issue), Comment: convert.ToComment(comment), @@ -241,7 +253,7 @@ func (a *botsNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_ IsPull: true, }) } else { - err = notify(issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventIssueComment, &api.IssueCommentPayload{ + err = notify(ctx, issue.Repo, doer, issue.Repo.DefaultBranch, webhook.HookEventIssueComment, &api.IssueCommentPayload{ Action: api.HookIssueCommentCreated, Issue: convert.ToAPIIssue(ctx, issue), Comment: convert.ToComment(comment), @@ -271,7 +283,7 @@ func (a *botsNotifier) NotifyNewPullRequest(ctx context.Context, pull *issues_mo } mode, _ := access_model.AccessLevel(ctx, pull.Issue.Poster, pull.Issue.Repo) - if err := notifyWithPR(pull.Issue.Repo, pull.Issue.Poster, pull.Issue.Repo.DefaultBranch, webhook.HookEventPullRequest, &api.PullRequestPayload{ + if err := notifyWithPR(ctx, pull.Issue.Repo, pull.Issue.Poster, pull.Issue.Repo.DefaultBranch, webhook.HookEventPullRequest, &api.PullRequestPayload{ Action: api.HookIssueOpened, Index: pull.Issue.Index, PullRequest: convert.ToAPIPullRequest(ctx, pull, nil), @@ -289,7 +301,7 @@ func (a *botsNotifier) NotifyTransferRepository(ctx context.Context, doer *user_ } func (a *botsNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { - if err := notify(repo, doer, repo.DefaultBranch, + if err := notify(ctx, repo, doer, repo.DefaultBranch, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoCreated, @@ -306,7 +318,7 @@ func (a *botsNotifier) NotifyForkRepository(ctx context.Context, doer *user_mode mode, _ := access_model.AccessLevel(ctx, doer, repo) // forked webhook - if err := notify(oldRepo, doer, oldRepo.DefaultBranch, webhook.HookEventFork, &api.ForkPayload{ + if err := notify(ctx, oldRepo, doer, oldRepo.DefaultBranch, webhook.HookEventFork, &api.ForkPayload{ Forkee: convert.ToRepo(oldRepo, oldMode), Repo: convert.ToRepo(repo, mode), Sender: convert.ToUser(doer, nil), @@ -318,7 +330,7 @@ func (a *botsNotifier) NotifyForkRepository(ctx context.Context, doer *user_mode // Add to hook queue for created repo after session commit. if u.IsOrganization() { - if err := notify(repo, doer, oldRepo.DefaultBranch, webhook.HookEventRepository, &api.RepositoryPayload{ + if err := notify(ctx, repo, doer, oldRepo.DefaultBranch, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Organization: convert.ToUser(u, nil), @@ -355,7 +367,7 @@ func (a *botsNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_m log.Error("models.AccessLevel: %v", err) return } - if err := notifyWithPR(review.Issue.Repo, review.Reviewer, review.CommitID, reviewHookType, &api.PullRequestPayload{ + if err := notifyWithPR(ctx, review.Issue.Repo, review.Reviewer, review.CommitID, reviewHookType, &api.PullRequestPayload{ Action: api.HookIssueReviewed, Index: review.Issue.Index, PullRequest: convert.ToAPIPullRequest(db.DefaultContext, pr, nil), @@ -402,7 +414,7 @@ func (*botsNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_mode Action: api.HookIssueClosed, } - err = notifyWithPR(pr.Issue.Repo, doer, pr.MergedCommitID, webhook.HookEventPullRequest, apiPullRequest, pr) + err = notifyWithPR(ctx, pr.Issue.Repo, doer, pr.MergedCommitID, webhook.HookEventPullRequest, apiPullRequest, pr) if err != nil { log.Error("PrepareWebhooks: %v", err) } @@ -416,7 +428,7 @@ func (a *botsNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model return } - if err := notify(repo, pusher, opts.RefFullName, webhook.HookEventPush, &api.PushPayload{ + if err := notify(ctx, repo, pusher, opts.RefFullName, webhook.HookEventPush, &api.PushPayload{ Ref: opts.RefFullName, Before: opts.OldCommitID, After: opts.NewCommitID, @@ -436,7 +448,7 @@ func (a *botsNotifier) NotifyCreateRef(ctx context.Context, pusher *user_model.U apiRepo := convert.ToRepo(repo, perm.AccessModeNone) refName := git.RefEndName(refFullName) - if err := notify(repo, pusher, refName, webhook.HookEventCreate, &api.CreatePayload{ + if err := notify(ctx, repo, pusher, refName, webhook.HookEventCreate, &api.CreatePayload{ Ref: refName, Sha: refID, RefType: refType, @@ -452,7 +464,7 @@ func (a *botsNotifier) NotifyDeleteRef(ctx context.Context, pusher *user_model.U apiRepo := convert.ToRepo(repo, perm.AccessModeNone) refName := git.RefEndName(refFullName) - if err := notify(repo, pusher, refName, webhook.HookEventDelete, &api.DeletePayload{ + if err := notify(ctx, repo, pusher, refName, webhook.HookEventDelete, &api.DeletePayload{ Ref: refName, RefType: refType, PusherType: api.PusherTypeUser, @@ -471,7 +483,7 @@ func (a *botsNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_m return } - if err := notify(repo, pusher, opts.RefFullName, webhook.HookEventPush, &api.PushPayload{ + if err := notify(ctx, repo, pusher, opts.RefFullName, webhook.HookEventPush, &api.PushPayload{ Ref: opts.RefFullName, Before: opts.OldCommitID, After: opts.NewCommitID, @@ -502,7 +514,7 @@ func sendReleaseNofiter(ctx context.Context, doer *user_model.User, rel *repo_mo } mode, _ := access_model.AccessLevel(ctx, doer, rel.Repo) - if err := notify(rel.Repo, doer, ref, webhook.HookEventRelease, &api.ReleasePayload{ + if err := notify(ctx, rel.Repo, doer, ref, webhook.HookEventRelease, &api.ReleasePayload{ Action: action, Release: convert.ToRelease(rel), Repository: convert.ToRepo(rel.Repo, mode), @@ -547,7 +559,7 @@ func notifyPackage(sender *user_model.User, pd *packages_model.PackageDescriptor return } - if err := notify(pd.Repository, sender, "", webhook.HookEventPackage, &api.PackagePayload{ + if err := notify(ctx, pd.Repository, sender, "", webhook.HookEventPackage, &api.PackagePayload{ Action: action, Package: apiPackage, Sender: convert.ToUser(sender, nil), diff --git a/routers/api/bots/runner/runner.go b/routers/api/bots/runner/runner.go index 3ffcbfd092..d0efd5a199 100644 --- a/routers/api/bots/runner/runner.go +++ b/routers/api/bots/runner/runner.go @@ -172,11 +172,8 @@ func (s *Service) UpdateTask( if err := task.LoadJob(ctx); err != nil { return nil, status.Errorf(codes.Internal, "load job: %v", err) } - if err := task.Job.LoadAttributes(ctx); err != nil { - return nil, status.Errorf(codes.Internal, "load run: %v", err) - } - if err := bots_service.CreateCommitStatus(ctx, task); err != nil { + if err := bots_service.CreateCommitStatus(ctx, task.Job); err != nil { log.Error("Update commit status failed: %v", err) // go on } diff --git a/routers/web/repo/bots/view.go b/routers/web/repo/bots/view.go index 58e7261421..0dead07981 100644 --- a/routers/web/repo/bots/view.go +++ b/routers/web/repo/bots/view.go @@ -16,6 +16,7 @@ import ( context_module "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/web" + bots_service "code.gitea.io/gitea/services/bots" runnerv1 "code.gitea.io/bots-proto-go/runner/v1" "xorm.io/builder" @@ -211,8 +212,10 @@ func Rerun(ctx *context_module.Context) { job.Stopped = 0 if err := db.WithTx(ctx, func(ctx context.Context) error { - _, err := bots_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, "task_id", "status", "started", "stopped") - return err + if _, err := bots_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, "task_id", "status", "started", "stopped"); err != nil { + return err + } + return bots_service.CreateCommitStatus(ctx, job) }); err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return @@ -250,6 +253,9 @@ func Cancel(ctx *context_module.Context) { if err := bots_model.StopTask(ctx, job.TaskID, bots_model.StatusCancelled); err != nil { return err } + if err := bots_service.CreateCommitStatus(ctx, job); err != nil { + return err + } } return nil }); err != nil { diff --git a/services/bots/bots.go b/services/bots/bots.go index ede2f1c9c3..d96e57830b 100644 --- a/services/bots/bots.go +++ b/services/bots/bots.go @@ -66,19 +66,17 @@ func DeleteResourceOfRepository(ctx context.Context, repo *repo_model.Repository return nil } -func CreateCommitStatus(ctx context.Context, task *bots_model.BotTask) error { - if err := task.LoadJob(ctx); err != nil { - return fmt.Errorf("load job: %w", err) - } - if err := task.Job.LoadAttributes(ctx); err != nil { +func CreateCommitStatus(ctx context.Context, job *bots_model.BotRunJob) error { + if err := job.LoadAttributes(ctx); err != nil { return fmt.Errorf("load run: %w", err) } - if task.Job.Run.Event != webhook.HookEventPush { + run := job.Run + if run.Event != webhook.HookEventPush { return nil } - payload, err := task.Job.Run.GetPushEventPayload() + payload, err := run.GetPushEventPayload() if err != nil { return fmt.Errorf("GetPushEventPayload: %w", err) } @@ -88,17 +86,17 @@ func CreateCommitStatus(ctx context.Context, task *bots_model.BotTask) error { return fmt.Errorf("GetUserByID: %w", err) } - repo := task.Job.Run.Repo + repo := run.Repo sha := payload.HeadCommit.ID - ctxname := task.Job.Name - state := toCommitStatus(task.Job.Status) + ctxname := job.Name + state := toCommitStatus(job.Status) if statuses, _, err := git_model.GetLatestCommitStatus(ctx, repo.ID, sha, db.ListOptions{}); err != nil { return fmt.Errorf("GetLatestCommitStatus: %w", err) } else { - for _, status := range statuses { - if status.Context == ctxname { - if status.State == state { + for _, v := range statuses { + if v.Context == ctxname { + if v.State == state { return nil } break @@ -112,7 +110,7 @@ func CreateCommitStatus(ctx context.Context, task *bots_model.BotTask) error { Creator: creator, CommitStatus: &git_model.CommitStatus{ SHA: sha, - TargetURL: task.Job.Run.HTMLURL(), + TargetURL: run.HTMLURL(), Description: "", Context: ctxname, CreatorID: payload.Pusher.ID, diff --git a/services/bots/clear_tasks.go b/services/bots/clear_tasks.go index 0664af0f6b..8225bbe709 100644 --- a/services/bots/clear_tasks.go +++ b/services/bots/clear_tasks.go @@ -33,7 +33,13 @@ func StopZombieTasks(ctx context.Context) error { for _, task := range tasks { if err := db.WithTx(ctx, func(ctx context.Context) error { - return bots_model.StopTask(ctx, task.ID, bots_model.StatusFailure) + if err := bots_model.StopTask(ctx, task.ID, bots_model.StatusFailure); err != nil { + return err + } + if err := task.LoadJob(ctx); err != nil { + return err + } + return CreateCommitStatus(ctx, task.Job) }); err != nil { log.Warn("stop zombie task %v: %v", task.ID, err) // go on @@ -55,7 +61,13 @@ func StopEndlessTasks(ctx context.Context) error { for _, task := range tasks { if err := db.WithTx(ctx, func(ctx context.Context) error { - return bots_model.StopTask(ctx, task.ID, bots_model.StatusFailure) + if err := bots_model.StopTask(ctx, task.ID, bots_model.StatusFailure); err != nil { + return err + } + if err := task.LoadJob(ctx); err != nil { + return err + } + return CreateCommitStatus(ctx, task.Job) }); err != nil { log.Warn("stop endless task %v: %v", task.ID, err) // go on @@ -80,8 +92,10 @@ func CancelAbandonedJobs(ctx context.Context) error { job.Status = bots_model.StatusCancelled job.Stopped = now if err := db.WithTx(ctx, func(ctx context.Context) error { - _, err := bots_model.UpdateRunJob(ctx, job, nil, "status", "stopped") - return err + if _, err := bots_model.UpdateRunJob(ctx, job, nil, "status", "stopped"); err != nil { + return err + } + return CreateCommitStatus(ctx, job) }); err != nil { log.Warn("cancel abandoned job %v: %v", job.ID, err) // go on