From 84b684eba4b993a4a85f764032131c7a14995eb1 Mon Sep 17 00:00:00 2001 From: Sumit Paul Date: Wed, 30 Apr 2025 00:51:15 +0530 Subject: [PATCH] Add support for removed labels in issue and pull request notifications --- modules/structs/hook.go | 1 + services/actions/notifier.go | 68 ++++++++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/modules/structs/hook.go b/modules/structs/hook.go index 890a99c8fe..c74b20b72b 100644 --- a/modules/structs/hook.go +++ b/modules/structs/hook.go @@ -342,6 +342,7 @@ type PullRequestPayload struct { Action HookIssueAction `json:"action"` Index int64 `json:"number"` Changes *ChangesPayload `json:"changes,omitempty"` + RemovedLabels []*Label `json:"removed_labels"` PullRequest *PullRequest `json:"pull_request"` RequestedReviewer *User `json:"requested_reviewer"` Repository *Repository `json:"repository"` diff --git a/services/actions/notifier.go b/services/actions/notifier.go index 831cde3523..3582590c8c 100644 --- a/services/actions/notifier.go +++ b/services/actions/notifier.go @@ -26,6 +26,12 @@ type actionsNotifier struct { notify_service.NullNotifier } +type contextKey string + +const ( + removedLabelsKey contextKey = "GiteaRemovedLabels" +) + var _ notify_service.Notifier = &actionsNotifier{} // NewNotifier create a new actionsNotifier notifier @@ -189,7 +195,7 @@ func (n *actionsNotifier) IssueChangeMilestone(ctx context.Context, doer *user_m } func (n *actionsNotifier) IssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, - _, _ []*issues_model.Label, + addedLabels, removedLabels []*issues_model.Label, ) { ctx = withMethod(ctx, "IssueChangeLabels") @@ -198,6 +204,22 @@ func (n *actionsNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode hookEvent = webhook_module.HookEventPullRequestLabel } + // Track removedLabels for the webhook payload + var removedAPILabels []*api.Label + if len(removedLabels) > 0 { + if err := issue.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) + return + } + + removedAPILabels = make([]*api.Label, 0, len(removedLabels)) + for _, label := range removedLabels { + removedAPILabels = append(removedAPILabels, convert.ToLabel(label, issue.Repo, doer)) + } + + ctx = context.WithValue(ctx, removedLabelsKey, removedAPILabels) + } + notifyIssueChange(ctx, doer, issue, hookEvent, api.HookIssueLabelUpdated) } @@ -213,34 +235,50 @@ func notifyIssueChange(ctx context.Context, doer *user_model.User, issue *issues return } + // Get removed labels from context if present + var removedAPILabels []*api.Label + if removedLabelsValue := ctx.Value(removedLabelsKey); removedLabelsValue != nil { + if labels, ok := removedLabelsValue.([]*api.Label); ok { + removedAPILabels = labels + } + } + if issue.IsPull { if err = issue.LoadPullRequest(ctx); err != nil { log.Error("loadPullRequest: %v", err) return } + + payload := &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), + RemovedLabels: removedAPILabels, + } + 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), - }). + WithPayload(payload). WithPullRequest(issue.PullRequest). Notify(ctx) return } + permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster) + payload := &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), + RemovedLabels: removedAPILabels, + } + 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), - }). + WithPayload(payload). Notify(ctx) }