Skip to content

Add issue delete notifier #34592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8d799c2
use the correct context data for PR link template in issue card
badhezi Apr 15, 2025
f2a2acf
Merge branch 'main' into main
badhezi Apr 15, 2025
5cc1bda
Merge branch 'main' into main
GiteaBot Apr 16, 2025
54d37d1
Merge branch 'main' into main
GiteaBot Apr 16, 2025
ac25150
Merge branch 'go-gitea:main' into main
badhezi Apr 16, 2025
e11a339
Merge branch 'go-gitea:main' into main
badhezi Apr 20, 2025
104eecc
Merge branch 'go-gitea:main' into main
badhezi Apr 21, 2025
bcc4ade
Merge branch 'go-gitea:main' into main
badhezi Apr 22, 2025
a7aaa79
Merge branch 'go-gitea:main' into main
badhezi Apr 27, 2025
b46d314
Merge branch 'go-gitea:main' into main
badhezi Apr 28, 2025
4e2434b
Merge branch 'go-gitea:main' into main
badhezi Apr 29, 2025
7f72fe9
Merge branch 'go-gitea:main' into main
badhezi May 2, 2025
c6acfc1
Merge branch 'go-gitea:main' into main
badhezi May 11, 2025
016c2f3
Merge branch 'go-gitea:main' into main
badhezi May 12, 2025
a3c2953
Merge branch 'go-gitea:main' into main
badhezi May 13, 2025
4d7ea0d
Merge branch 'go-gitea:main' into main
badhezi May 20, 2025
bfa2d10
Merge branch 'go-gitea:main' into main
badhezi May 28, 2025
0d50b75
Merge branch 'go-gitea:main' into main
badhezi Jun 1, 2025
c511c71
add issue delete notifier
badhezi Jun 3, 2025
1e3d908
use doer permissions for issue delete webhook payload
badhezi Jun 3, 2025
650d326
add case for pull request deletion
badhezi Jun 3, 2025
2ba9a24
move const to relevant line
badhezi Jun 3, 2025
e729fc9
add test cases for issue delete and pull request delete webhooks
badhezi Jun 4, 2025
1ac0719
fix linting
badhezi Jun 4, 2025
8ed6da5
fix linting
badhezi Jun 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions modules/structs/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ const (
HookIssueReOpened HookIssueAction = "reopened"
// HookIssueEdited edited
HookIssueEdited HookIssueAction = "edited"
// HookIssueDeleted is an issue action for deleting an issue
HookIssueDeleted HookIssueAction = "deleted"
// HookIssueAssigned assigned
HookIssueAssigned HookIssueAction = "assigned"
// HookIssueUnassigned unassigned
Expand Down
4 changes: 2 additions & 2 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2371,7 +2371,7 @@ settings.event_repository = Repository
settings.event_repository_desc = Repository created or deleted.
settings.event_header_issue = Issue Events
settings.event_issues = Issues
settings.event_issues_desc = Issue opened, closed, reopened, or edited.
settings.event_issues_desc = Issue opened, closed, reopened, edited or deleted.
settings.event_issue_assign = Issue Assigned
settings.event_issue_assign_desc = Issue assigned or unassigned.
settings.event_issue_label = Issue Labeled
Expand All @@ -2382,7 +2382,7 @@ settings.event_issue_comment = Issue Comment
settings.event_issue_comment_desc = Issue comment created, edited, or deleted.
settings.event_header_pull_request = Pull Request Events
settings.event_pull_request = Pull Request
settings.event_pull_request_desc = Pull request opened, closed, reopened, or edited.
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited or deleted.
settings.event_pull_request_assign = Pull Request Assigned
settings.event_pull_request_assign_desc = Pull request assigned or unassigned.
settings.event_pull_request_label = Pull Request Labeled
Expand Down
37 changes: 37 additions & 0 deletions services/webhook/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,43 @@ func (m *webhookNotifier) NewIssue(ctx context.Context, issue *issues_model.Issu
}
}

func (m *webhookNotifier) DeleteIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) {
permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
if issue.IsPull {
if err := issue.LoadPullRequest(ctx); err != nil {
log.Error("LoadPullRequest: %v", err)
return
}
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
Action: api.HookIssueDeleted,
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
}); err != nil {
log.Error("PrepareWebhooks: %v", err)
}
} else {
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
}
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{
Action: api.HookIssueDeleted,
Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
}); err != nil {
log.Error("PrepareWebhooks: %v", err)
}
}
}

func (m *webhookNotifier) NewPullRequest(ctx context.Context, pull *issues_model.PullRequest, mentions []*user_model.User) {
if err := pull.LoadIssue(ctx); err != nil {
log.Error("pull.LoadIssue: %v", err)
Expand Down
7 changes: 7 additions & 0 deletions tests/integration/issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ func testNewIssue(t *testing.T, session *TestSession, user, repo, title, content
return issueURL
}

func testIssueDelete(t *testing.T, session *TestSession, issueURL string) {
req := NewRequestWithValues(t, "POST", path.Join(issueURL, "delete"), map[string]string{
"_csrf": GetUserCSRFToken(t, session),
})
session.MakeRequest(t, req, http.StatusSeeOther)
}

func testIssueAssign(t *testing.T, session *TestSession, repoLink string, issueID, assigneeID int64) {
req := NewRequestWithValues(t, "POST", fmt.Sprintf(repoLink+"/issues/assignee?issue_ids=%d", issueID), map[string]string{
"_csrf": GetUserCSRFToken(t, session),
Expand Down
72 changes: 72 additions & 0 deletions tests/integration/repo_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"path"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -450,6 +451,39 @@ func Test_WebhookIssue(t *testing.T) {
})
}

func Test_WebhookIssueDelete(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
var payloads []api.IssuePayload
var triggeredEvent string
provider := newMockWebhookProvider(func(r *http.Request) {
content, _ := io.ReadAll(r.Body)
var payload api.IssuePayload
err := json.Unmarshal(content, &payload)
assert.NoError(t, err)
payloads = append(payloads, payload)
triggeredEvent = "issue"
}, http.StatusOK)
defer provider.Close()

// 1. create a new webhook with special webhook for repo1
session := loginUser(t, "user2")
testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issues")
issueURL := testNewIssue(t, session, "user2", "repo1", "Title1", "Description1")

// 2. trigger the webhook
testIssueDelete(t, session, issueURL)

// 3. validate the webhook is triggered
assert.Equal(t, "issue", triggeredEvent)
require.Len(t, payloads, 2)
assert.EqualValues(t, "deleted", payloads[1].Action)
assert.Equal(t, "repo1", payloads[1].Issue.Repo.Name)
assert.Equal(t, "user2/repo1", payloads[1].Issue.Repo.FullName)
assert.Equal(t, "Title1", payloads[1].Issue.Title)
assert.Equal(t, "Description1", payloads[1].Issue.Body)
})
}

func Test_WebhookIssueAssign(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
var payloads []api.PullRequestPayload
Expand Down Expand Up @@ -596,6 +630,44 @@ func Test_WebhookPullRequest(t *testing.T) {
})
}

func Test_WebhookPullRequestDelete(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
var payloads []api.PullRequestPayload
var triggeredEvent string
provider := newMockWebhookProvider(func(r *http.Request) {
content, _ := io.ReadAll(r.Body)
var payload api.PullRequestPayload
err := json.Unmarshal(content, &payload)
assert.NoError(t, err)
payloads = append(payloads, payload)
triggeredEvent = "pull_request"
}, http.StatusOK)
defer provider.Close()

// 1. create a new webhook with special webhook for repo1
session := loginUser(t, "user2")
testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "pull_request")

testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated)

repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
issueURL := testCreatePullToDefaultBranch(t, session, repo1, repo1, "master2", "first pull request")

// 2. trigger the webhook
testIssueDelete(t, session, path.Join(repo1.Link(), "pulls", issueURL))

// 3. validate the webhook is triggered
assert.Equal(t, "pull_request", triggeredEvent)
require.Len(t, payloads, 2)
assert.EqualValues(t, "deleted", payloads[1].Action)
assert.Equal(t, "repo1", payloads[1].PullRequest.Base.Repository.Name)
assert.Equal(t, "user2/repo1", payloads[1].PullRequest.Base.Repository.FullName)
assert.Equal(t, 0, *payloads[1].PullRequest.Additions)
assert.Equal(t, 0, *payloads[1].PullRequest.ChangedFiles)
assert.Equal(t, 0, *payloads[1].PullRequest.Deletions)
})
}

func Test_WebhookPullRequestComment(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
var payloads []api.IssueCommentPayload
Expand Down