diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go
index e2874fae73..8d98ff0f9e 100644
--- a/modules/notification/webhook/webhook.go
+++ b/modules/notification/webhook/webhook.go
@@ -399,3 +399,50 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models
 		go webhook_module.HookQueue.Add(comment.Issue.Repo.ID)
 	}
 }
+
+func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue,
+	addedLabels []*models.Label, removedLabels []*models.Label) {
+	var err error
+
+	if err = issue.LoadRepo(); err != nil {
+		log.Error("LoadRepo: %v", err)
+		return
+	}
+
+	if err = issue.LoadPoster(); err != nil {
+		log.Error("LoadPoster: %v", err)
+		return
+	}
+
+	mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
+	if issue.IsPull {
+		if err = issue.LoadPullRequest(); err != nil {
+			log.Error("loadPullRequest: %v", err)
+			return
+		}
+		if err = issue.PullRequest.LoadIssue(); err != nil {
+			log.Error("LoadIssue: %v", err)
+			return
+		}
+		err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
+			Action:      api.HookIssueLabelUpdated,
+			Index:       issue.Index,
+			PullRequest: issue.PullRequest.APIFormat(),
+			Repository:  issue.Repo.APIFormat(models.AccessModeNone),
+			Sender:      doer.APIFormat(),
+		})
+	} else {
+		err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
+			Action:     api.HookIssueLabelUpdated,
+			Index:      issue.Index,
+			Issue:      issue.APIFormat(),
+			Repository: issue.Repo.APIFormat(mode),
+			Sender:     doer.APIFormat(),
+		})
+	}
+	if err != nil {
+		log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
+	} else {
+		go webhook_module.HookQueue.Add(issue.RepoID)
+	}
+}
diff --git a/services/issue/label.go b/services/issue/label.go
index bb36d58492..5e154df959 100644
--- a/services/issue/label.go
+++ b/services/issue/label.go
@@ -6,58 +6,9 @@ package issue
 
 import (
 	"code.gitea.io/gitea/models"
-	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/notification"
-	api "code.gitea.io/gitea/modules/structs"
-	"code.gitea.io/gitea/modules/webhook"
 )
 
-func sendLabelUpdatedWebhook(issue *models.Issue, doer *models.User) {
-	var err error
-
-	if err = issue.LoadRepo(); err != nil {
-		log.Error("LoadRepo: %v", err)
-		return
-	}
-
-	if err = issue.LoadPoster(); err != nil {
-		log.Error("LoadPoster: %v", err)
-		return
-	}
-
-	mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
-	if issue.IsPull {
-		if err = issue.LoadPullRequest(); err != nil {
-			log.Error("loadPullRequest: %v", err)
-			return
-		}
-		if err = issue.PullRequest.LoadIssue(); err != nil {
-			log.Error("LoadIssue: %v", err)
-			return
-		}
-		err = webhook.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
-			Action:      api.HookIssueLabelUpdated,
-			Index:       issue.Index,
-			PullRequest: issue.PullRequest.APIFormat(),
-			Repository:  issue.Repo.APIFormat(models.AccessModeNone),
-			Sender:      doer.APIFormat(),
-		})
-	} else {
-		err = webhook.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
-			Action:     api.HookIssueLabelUpdated,
-			Index:      issue.Index,
-			Issue:      issue.APIFormat(),
-			Repository: issue.Repo.APIFormat(mode),
-			Sender:     doer.APIFormat(),
-		})
-	}
-	if err != nil {
-		log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
-	} else {
-		go webhook.HookQueue.Add(issue.RepoID)
-	}
-}
-
 // ClearLabels clears all of an issue's labels
 func ClearLabels(issue *models.Issue, doer *models.User) (err error) {
 	if err = issue.ClearLabels(doer); err != nil {
@@ -75,7 +26,7 @@ func AddLabel(issue *models.Issue, doer *models.User, label *models.Label) error
 		return err
 	}
 
-	sendLabelUpdatedWebhook(issue, doer)
+	notification.NotifyIssueChangeLabels(doer, issue, []*models.Label{label}, nil)
 	return nil
 }
 
@@ -85,7 +36,7 @@ func AddLabels(issue *models.Issue, doer *models.User, labels []*models.Label) e
 		return err
 	}
 
-	sendLabelUpdatedWebhook(issue, doer)
+	notification.NotifyIssueChangeLabels(doer, issue, labels, nil)
 	return nil
 }
 
@@ -107,6 +58,6 @@ func RemoveLabel(issue *models.Issue, doer *models.User, label *models.Label) er
 		return err
 	}
 
-	sendLabelUpdatedWebhook(issue, doer)
+	notification.NotifyIssueChangeLabels(doer, issue, nil, []*models.Label{label})
 	return nil
 }