diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /services/actions/notifier.go | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to '')
-rw-r--r-- | services/actions/notifier.go | 777 |
1 files changed, 777 insertions, 0 deletions
diff --git a/services/actions/notifier.go b/services/actions/notifier.go new file mode 100644 index 0000000..2dd8115 --- /dev/null +++ b/services/actions/notifier.go @@ -0,0 +1,777 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package actions + +import ( + "context" + + issues_model "code.gitea.io/gitea/models/issues" + packages_model "code.gitea.io/gitea/models/packages" + perm_model "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" + "code.gitea.io/gitea/services/convert" + notify_service "code.gitea.io/gitea/services/notify" +) + +type actionsNotifier struct { + notify_service.NullNotifier +} + +var _ notify_service.Notifier = &actionsNotifier{} + +// NewNotifier create a new actionsNotifier notifier +func NewNotifier() notify_service.Notifier { + return &actionsNotifier{} +} + +// NewIssue notifies issue created event +func (n *actionsNotifier) NewIssue(ctx context.Context, issue *issues_model.Issue, _ []*user_model.User) { + ctx = withMethod(ctx, "NewIssue") + if err := issue.LoadRepo(ctx); err != nil { + log.Error("issue.LoadRepo: %v", err) + return + } + if err := issue.LoadPoster(ctx); err != nil { + log.Error("issue.LoadPoster: %v", err) + return + } + permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster) + + newNotifyInputFromIssue(issue, webhook_module.HookEventIssues).WithPayload(&api.IssuePayload{ + Action: api.HookIssueOpened, + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, issue.Poster, issue), + Repository: convert.ToRepo(ctx, issue.Repo, permission), + Sender: convert.ToUser(ctx, issue.Poster, nil), + }).Notify(withMethod(ctx, "NewIssue")) +} + +func (n *actionsNotifier) IssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, _ string) { + ctx = withMethod(ctx, "IssueChangeTitle") + + n.issueChange(ctx, doer, issue) +} + +// IssueChangeContent notifies change content of issue +func (n *actionsNotifier) IssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, _ string) { + ctx = withMethod(ctx, "IssueChangeContent") + + n.issueChange(ctx, doer, issue) +} + +func (n *actionsNotifier) issueChange(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { + var err error + if err = issue.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) + return + } + + permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster) + if issue.IsPull { + if err = issue.LoadPullRequest(ctx); err != nil { + log.Error("loadPullRequest: %v", err) + return + } + newNotifyInputFromIssue(issue, webhook_module.HookEventPullRequest). + WithDoer(doer). + WithPayload(&api.PullRequestPayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}), + Sender: convert.ToUser(ctx, doer, nil), + }). + WithPullRequest(issue.PullRequest). + Notify(ctx) + return + } + newNotifyInputFromIssue(issue, webhook_module.HookEventIssues). + WithDoer(doer). + WithPayload(&api.IssuePayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, doer, issue), + Repository: convert.ToRepo(ctx, issue.Repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + }). + Notify(ctx) +} + +// IssueChangeStatus notifies close or reopen issue to notifiers +func (n *actionsNotifier) IssueChangeStatus(ctx context.Context, doer *user_model.User, commitID string, issue *issues_model.Issue, _ *issues_model.Comment, isClosed bool) { + ctx = withMethod(ctx, "IssueChangeStatus") + permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster) + if issue.IsPull { + if err := issue.LoadPullRequest(ctx); err != nil { + log.Error("LoadPullRequest: %v", err) + return + } + // Merge pull request calls issue.changeStatus so we need to handle separately. + apiPullRequest := &api.PullRequestPayload{ + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + CommitID: commitID, + } + if isClosed { + apiPullRequest.Action = api.HookIssueClosed + } else { + apiPullRequest.Action = api.HookIssueReOpened + } + newNotifyInputFromIssue(issue, webhook_module.HookEventPullRequest). + WithDoer(doer). + WithPayload(apiPullRequest). + WithPullRequest(issue.PullRequest). + Notify(ctx) + return + } + apiIssue := &api.IssuePayload{ + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, doer, issue), + Repository: convert.ToRepo(ctx, issue.Repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + } + if isClosed { + apiIssue.Action = api.HookIssueClosed + } else { + apiIssue.Action = api.HookIssueReOpened + } + newNotifyInputFromIssue(issue, webhook_module.HookEventIssues). + WithDoer(doer). + WithPayload(apiIssue). + Notify(ctx) +} + +// IssueChangeAssignee notifies assigned or unassigned to notifiers +func (n *actionsNotifier) IssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { + ctx = withMethod(ctx, "IssueChangeAssignee") + + var action api.HookIssueAction + if removed { + action = api.HookIssueUnassigned + } else { + action = api.HookIssueAssigned + } + + hookEvent := webhook_module.HookEventIssueAssign + if issue.IsPull { + hookEvent = webhook_module.HookEventPullRequestAssign + } + + notifyIssueChange(ctx, doer, issue, hookEvent, action, nil) +} + +// IssueChangeMilestone notifies assignee to notifiers +func (n *actionsNotifier) IssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { + ctx = withMethod(ctx, "IssueChangeMilestone") + + var action api.HookIssueAction + if issue.MilestoneID > 0 { + action = api.HookIssueMilestoned + } else { + action = api.HookIssueDemilestoned + } + + hookEvent := webhook_module.HookEventIssueMilestone + if issue.IsPull { + hookEvent = webhook_module.HookEventPullRequestMilestone + } + + notifyIssueChange(ctx, doer, issue, hookEvent, action, nil) +} + +func (n *actionsNotifier) IssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, + addedLabels, removedLabels []*issues_model.Label, +) { + ctx = withMethod(ctx, "IssueChangeLabels") + + hookEvent := webhook_module.HookEventIssueLabel + if issue.IsPull { + hookEvent = webhook_module.HookEventPullRequestLabel + } + + for _, added := range addedLabels { + notifyIssueChange(ctx, doer, issue, hookEvent, api.HookIssueLabelUpdated, added) + } + for _, removed := range removedLabels { + notifyIssueChange(ctx, doer, issue, hookEvent, api.HookIssueLabelCleared, removed) + } +} + +func notifyIssueChange(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, event webhook_module.HookEventType, action api.HookIssueAction, label *issues_model.Label) { + var err error + if err = issue.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) + return + } + + if err = issue.LoadPoster(ctx); err != nil { + log.Error("LoadPoster: %v", err) + return + } + + var apiLabel *api.Label + if action == api.HookIssueLabelUpdated || action == api.HookIssueLabelCleared { + apiLabel = convert.ToLabel(label, issue.Repo, nil) + } + + if issue.IsPull { + if err = issue.LoadPullRequest(ctx); err != nil { + log.Error("loadPullRequest: %v", err) + return + } + newNotifyInputFromIssue(issue, event). + WithDoer(doer). + WithPayload(&api.PullRequestPayload{ + Action: action, + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}), + Sender: convert.ToUser(ctx, doer, nil), + Label: apiLabel, + }). + WithPullRequest(issue.PullRequest). + Notify(ctx) + return + } + permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster) + newNotifyInputFromIssue(issue, event). + WithDoer(doer). + WithPayload(&api.IssuePayload{ + Action: action, + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, doer, issue), + Repository: convert.ToRepo(ctx, issue.Repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + Label: apiLabel, + }). + Notify(ctx) +} + +// CreateIssueComment notifies comment on an issue to notifiers +func (n *actionsNotifier) CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, + issue *issues_model.Issue, comment *issues_model.Comment, _ []*user_model.User, +) { + ctx = withMethod(ctx, "CreateIssueComment") + + if issue.IsPull { + notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventPullRequestComment, api.HookIssueCommentCreated) + return + } + notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventIssueComment, api.HookIssueCommentCreated) +} + +func (n *actionsNotifier) UpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { + ctx = withMethod(ctx, "UpdateComment") + + if err := c.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + if c.Issue.IsPull { + notifyIssueCommentChange(ctx, doer, c, oldContent, webhook_module.HookEventPullRequestComment, api.HookIssueCommentEdited) + return + } + notifyIssueCommentChange(ctx, doer, c, oldContent, webhook_module.HookEventIssueComment, api.HookIssueCommentEdited) +} + +func (n *actionsNotifier) DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) { + ctx = withMethod(ctx, "DeleteComment") + + if err := comment.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + if comment.Issue.IsPull { + notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventPullRequestComment, api.HookIssueCommentDeleted) + return + } + notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventIssueComment, api.HookIssueCommentDeleted) +} + +func notifyIssueCommentChange(ctx context.Context, doer *user_model.User, comment *issues_model.Comment, oldContent string, event webhook_module.HookEventType, action api.HookIssueCommentAction) { + if err := comment.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + if err := comment.Issue.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + permission, _ := access_model.GetUserRepoPermission(ctx, comment.Issue.Repo, doer) + + payload := &api.IssueCommentPayload{ + Action: action, + Issue: convert.ToAPIIssue(ctx, doer, comment.Issue), + Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment), + Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + IsPull: comment.Issue.IsPull, + } + + if action == api.HookIssueCommentEdited { + payload.Changes = &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + } + } + + if comment.Issue.IsPull { + if err := comment.Issue.LoadPullRequest(ctx); err != nil { + log.Error("LoadPullRequest: %v", err) + return + } + newNotifyInputFromIssue(comment.Issue, event). + WithDoer(doer). + WithPayload(payload). + WithPullRequest(comment.Issue.PullRequest). + Notify(ctx) + return + } + + newNotifyInputFromIssue(comment.Issue, event). + WithDoer(doer). + WithPayload(payload). + Notify(ctx) +} + +func (n *actionsNotifier) NewPullRequest(ctx context.Context, pull *issues_model.PullRequest, _ []*user_model.User) { + ctx = withMethod(ctx, "NewPullRequest") + + if err := pull.LoadIssue(ctx); err != nil { + log.Error("pull.LoadIssue: %v", err) + return + } + if err := pull.Issue.LoadRepo(ctx); err != nil { + log.Error("pull.Issue.LoadRepo: %v", err) + return + } + if err := pull.Issue.LoadPoster(ctx); err != nil { + log.Error("pull.Issue.LoadPoster: %v", err) + return + } + + permission, _ := access_model.GetUserRepoPermission(ctx, pull.Issue.Repo, pull.Issue.Poster) + + newNotifyInputFromIssue(pull.Issue, webhook_module.HookEventPullRequest). + WithPayload(&api.PullRequestPayload{ + Action: api.HookIssueOpened, + Index: pull.Issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, pull, nil), + Repository: convert.ToRepo(ctx, pull.Issue.Repo, permission), + Sender: convert.ToUser(ctx, pull.Issue.Poster, nil), + }). + WithPullRequest(pull). + Notify(ctx) +} + +func (n *actionsNotifier) CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { + ctx = withMethod(ctx, "CreateRepository") + + newNotifyInput(repo, doer, webhook_module.HookEventRepository).WithPayload(&api.RepositoryPayload{ + Action: api.HookRepoCreated, + Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}), + Organization: convert.ToUser(ctx, u, nil), + Sender: convert.ToUser(ctx, doer, nil), + }).Notify(ctx) +} + +func (n *actionsNotifier) ForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { + ctx = withMethod(ctx, "ForkRepository") + + oldPermission, _ := access_model.GetUserRepoPermission(ctx, oldRepo, doer) + permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer) + + // forked webhook + newNotifyInput(oldRepo, doer, webhook_module.HookEventFork).WithPayload(&api.ForkPayload{ + Forkee: convert.ToRepo(ctx, oldRepo, oldPermission), + Repo: convert.ToRepo(ctx, repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + }).Notify(ctx) + + u := repo.MustOwner(ctx) + + // Add to hook queue for created repo after session commit. + if u.IsOrganization() { + newNotifyInput(repo, doer, webhook_module.HookEventRepository). + WithRef(git.RefNameFromBranch(oldRepo.DefaultBranch).String()). + WithPayload(&api.RepositoryPayload{ + Action: api.HookRepoCreated, + Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}), + Organization: convert.ToUser(ctx, u, nil), + Sender: convert.ToUser(ctx, doer, nil), + }).Notify(ctx) + } +} + +func (n *actionsNotifier) PullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, _ *issues_model.Comment, _ []*user_model.User) { + ctx = withMethod(ctx, "PullRequestReview") + + var reviewHookType webhook_module.HookEventType + + switch review.Type { + case issues_model.ReviewTypeApprove: + reviewHookType = webhook_module.HookEventPullRequestReviewApproved + case issues_model.ReviewTypeComment: + reviewHookType = webhook_module.HookEventPullRequestReviewComment + case issues_model.ReviewTypeReject: + reviewHookType = webhook_module.HookEventPullRequestReviewRejected + default: + // unsupported review webhook type here + log.Error("Unsupported review webhook type") + return + } + + if err := pr.LoadIssue(ctx); err != nil { + log.Error("pr.LoadIssue: %v", err) + return + } + + permission, err := access_model.GetUserRepoPermission(ctx, review.Issue.Repo, review.Issue.Poster) + if err != nil { + log.Error("models.GetUserRepoPermission: %v", err) + return + } + + newNotifyInput(review.Issue.Repo, review.Reviewer, reviewHookType). + WithRef(review.CommitID). + WithPayload(&api.PullRequestPayload{ + Action: api.HookIssueReviewed, + Index: review.Issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), + Repository: convert.ToRepo(ctx, review.Issue.Repo, permission), + Sender: convert.ToUser(ctx, review.Reviewer, nil), + Review: &api.ReviewPayload{ + Type: string(reviewHookType), + Content: review.Content, + }, + }).Notify(ctx) +} + +func (n *actionsNotifier) PullRequestReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { + if !issue.IsPull { + log.Warn("PullRequestReviewRequest: issue is not a pull request: %v", issue.ID) + return + } + + ctx = withMethod(ctx, "PullRequestReviewRequest") + + permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer) + if err := issue.LoadPullRequest(ctx); err != nil { + log.Error("LoadPullRequest failed: %v", err) + return + } + var action api.HookIssueAction + if isRequest { + action = api.HookIssueReviewRequested + } else { + action = api.HookIssueReviewRequestRemoved + } + newNotifyInputFromIssue(issue, webhook_module.HookEventPullRequestReviewRequest). + WithDoer(doer). + WithPayload(&api.PullRequestPayload{ + Action: action, + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + RequestedReviewer: convert.ToUser(ctx, reviewer, nil), + Repository: convert.ToRepo(ctx, issue.Repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + }). + WithPullRequest(issue.PullRequest). + Notify(ctx) +} + +func (*actionsNotifier) MergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + ctx = withMethod(ctx, "MergePullRequest") + + // Reload pull request information. + if err := pr.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + if err := pr.Issue.LoadRepo(ctx); err != nil { + log.Error("pr.Issue.LoadRepo: %v", err) + return + } + + permission, err := access_model.GetUserRepoPermission(ctx, pr.Issue.Repo, doer) + if err != nil { + log.Error("models.GetUserRepoPermission: %v", err) + return + } + + // Merge pull request calls issue.changeStatus so we need to handle separately. + apiPullRequest := &api.PullRequestPayload{ + Index: pr.Issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), + Repository: convert.ToRepo(ctx, pr.Issue.Repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + Action: api.HookIssueClosed, + } + + newNotifyInput(pr.Issue.Repo, doer, webhook_module.HookEventPullRequest). + WithRef(pr.MergedCommitID). + WithPayload(apiPullRequest). + WithPullRequest(pr). + Notify(ctx) +} + +func (n *actionsNotifier) PushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { + if git.IsEmptyCommitID(opts.NewCommitID, nil) { + log.Trace("new commitID is empty") + return + } + + ctx = withMethod(ctx, "PushCommits") + + apiPusher := convert.ToUser(ctx, pusher, nil) + apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) + if err != nil { + log.Error("commits.ToAPIPayloadCommits failed: %v", err) + return + } + + newNotifyInput(repo, pusher, webhook_module.HookEventPush). + WithRef(opts.RefFullName.String()). + WithPayload(&api.PushPayload{ + Ref: opts.RefFullName.String(), + Before: opts.OldCommitID, + After: opts.NewCommitID, + CompareURL: setting.AppURL + commits.CompareURL, + Commits: apiCommits, + HeadCommit: apiHeadCommit, + Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}), + Pusher: apiPusher, + Sender: apiPusher, + }). + Notify(ctx) +} + +func (n *actionsNotifier) CreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName, refID string) { + ctx = withMethod(ctx, "CreateRef") + + apiPusher := convert.ToUser(ctx, pusher, nil) + apiRepo := convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}) + + newNotifyInput(repo, pusher, webhook_module.HookEventCreate). + WithRef(refFullName.String()). + WithPayload(&api.CreatePayload{ + Ref: refFullName.String(), + Sha: refID, + RefType: refFullName.RefType(), + Repo: apiRepo, + Sender: apiPusher, + }). + Notify(ctx) +} + +func (n *actionsNotifier) DeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName) { + ctx = withMethod(ctx, "DeleteRef") + + apiPusher := convert.ToUser(ctx, pusher, nil) + apiRepo := convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}) + + newNotifyInput(repo, pusher, webhook_module.HookEventDelete). + WithPayload(&api.DeletePayload{ + Ref: refFullName.String(), + RefType: refFullName.RefType(), + PusherType: api.PusherTypeUser, + Repo: apiRepo, + Sender: apiPusher, + }). + Notify(ctx) +} + +func (n *actionsNotifier) SyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { + ctx = withMethod(ctx, "SyncPushCommits") + + apiPusher := convert.ToUser(ctx, pusher, nil) + apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) + if err != nil { + log.Error("commits.ToAPIPayloadCommits failed: %v", err) + return + } + + newNotifyInput(repo, pusher, webhook_module.HookEventPush). + WithRef(opts.RefFullName.String()). + WithPayload(&api.PushPayload{ + Ref: opts.RefFullName.String(), + Before: opts.OldCommitID, + After: opts.NewCommitID, + CompareURL: setting.AppURL + commits.CompareURL, + Commits: apiCommits, + TotalCommits: commits.Len, + HeadCommit: apiHeadCommit, + Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}), + Pusher: apiPusher, + Sender: apiPusher, + }). + Notify(ctx) +} + +func (n *actionsNotifier) SyncCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName, refID string) { + ctx = withMethod(ctx, "SyncCreateRef") + n.CreateRef(ctx, pusher, repo, refFullName, refID) +} + +func (n *actionsNotifier) SyncDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName) { + ctx = withMethod(ctx, "SyncDeleteRef") + n.DeleteRef(ctx, pusher, repo, refFullName) +} + +func (n *actionsNotifier) NewRelease(ctx context.Context, rel *repo_model.Release) { + ctx = withMethod(ctx, "NewRelease") + notifyRelease(ctx, rel.Publisher, rel, api.HookReleasePublished) +} + +func (n *actionsNotifier) UpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { + ctx = withMethod(ctx, "UpdateRelease") + notifyRelease(ctx, doer, rel, api.HookReleaseUpdated) +} + +func (n *actionsNotifier) DeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { + if rel.IsTag { + // has sent same action in `PushCommits`, so skip it. + return + } + ctx = withMethod(ctx, "DeleteRelease") + notifyRelease(ctx, doer, rel, api.HookReleaseDeleted) +} + +func (n *actionsNotifier) PackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { + ctx = withMethod(ctx, "PackageCreate") + notifyPackage(ctx, doer, pd, api.HookPackageCreated) +} + +func (n *actionsNotifier) PackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { + ctx = withMethod(ctx, "PackageDelete") + notifyPackage(ctx, doer, pd, api.HookPackageDeleted) +} + +func (n *actionsNotifier) AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + ctx = withMethod(ctx, "AutoMergePullRequest") + n.MergePullRequest(ctx, doer, pr) +} + +func (n *actionsNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + ctx = withMethod(ctx, "PullRequestSynchronized") + + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + if err := pr.Issue.LoadRepo(ctx); err != nil { + log.Error("pr.Issue.LoadRepo: %v", err) + return + } + + newNotifyInput(pr.Issue.Repo, doer, webhook_module.HookEventPullRequestSync). + WithPayload(&api.PullRequestPayload{ + Action: api.HookIssueSynchronized, + Index: pr.Issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), + Repository: convert.ToRepo(ctx, pr.Issue.Repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}), + Sender: convert.ToUser(ctx, doer, nil), + }). + WithPullRequest(pr). + Notify(ctx) +} + +func (n *actionsNotifier) PullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { + ctx = withMethod(ctx, "PullRequestChangeTargetBranch") + + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + if err := pr.Issue.LoadRepo(ctx); err != nil { + log.Error("pr.Issue.LoadRepo: %v", err) + return + } + + permission, _ := access_model.GetUserRepoPermission(ctx, pr.Issue.Repo, pr.Issue.Poster) + newNotifyInput(pr.Issue.Repo, doer, webhook_module.HookEventPullRequest). + WithPayload(&api.PullRequestPayload{ + Action: api.HookIssueEdited, + Index: pr.Issue.Index, + Changes: &api.ChangesPayload{ + Ref: &api.ChangesFromPayload{ + From: oldBranch, + }, + }, + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), + Repository: convert.ToRepo(ctx, pr.Issue.Repo, permission), + Sender: convert.ToUser(ctx, doer, nil), + }). + WithPullRequest(pr). + Notify(ctx) +} + +func (n *actionsNotifier) NewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { + ctx = withMethod(ctx, "NewWikiPage") + + newNotifyInput(repo, doer, webhook_module.HookEventWiki).WithPayload(&api.WikiPayload{ + Action: api.HookWikiCreated, + Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}), + Sender: convert.ToUser(ctx, doer, nil), + Page: page, + Comment: comment, + }).Notify(ctx) +} + +func (n *actionsNotifier) EditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { + ctx = withMethod(ctx, "EditWikiPage") + + newNotifyInput(repo, doer, webhook_module.HookEventWiki).WithPayload(&api.WikiPayload{ + Action: api.HookWikiEdited, + Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}), + Sender: convert.ToUser(ctx, doer, nil), + Page: page, + Comment: comment, + }).Notify(ctx) +} + +func (n *actionsNotifier) DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) { + ctx = withMethod(ctx, "DeleteWikiPage") + + newNotifyInput(repo, doer, webhook_module.HookEventWiki).WithPayload(&api.WikiPayload{ + Action: api.HookWikiDeleted, + Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}), + Sender: convert.ToUser(ctx, doer, nil), + Page: page, + }).Notify(ctx) +} + +// MigrateRepository is used to detect workflows after a repository has been migrated +func (n *actionsNotifier) MigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { + ctx = withMethod(ctx, "MigrateRepository") + + newNotifyInput(repo, doer, webhook_module.HookEventRepository).WithPayload(&api.RepositoryPayload{ + Action: api.HookRepoCreated, + Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}), + Organization: convert.ToUser(ctx, u, nil), + Sender: convert.ToUser(ctx, doer, nil), + }).Notify(ctx) +} |