From 65529bd334974d35f907c75420a9070197174ee8 Mon Sep 17 00:00:00 2001
From: Zettat123 <zettat123@gmail.com>
Date: Wed, 8 May 2024 22:45:15 +0800
Subject: [PATCH] Update issue indexer after merging a PR (#30715)

Fix #30684

(cherry picked from commit f09e68ec33262d5356779572a0b1c66e6e86590f)

Conflicts:
	tests/integration/pull_merge_test.go
	trivial context conflict
(cherry picked from commit 8f0f6bf89cdcd12cd4daa761aa259fdba7e32b50)

(cherry picked from commit df5513978a630355a28b6b42fcc63fe5d70652d8)
---
 services/indexer/notify.go           | 16 ++++++++
 tests/integration/pull_merge_test.go | 61 ++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+)

diff --git a/services/indexer/notify.go b/services/indexer/notify.go
index f1e21a2d40..e2cfe477d3 100644
--- a/services/indexer/notify.go
+++ b/services/indexer/notify.go
@@ -152,3 +152,19 @@ func (r *indexerNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode
 func (r *indexerNotifier) IssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) {
 	issue_indexer.UpdateIssueIndexer(ctx, issue.ID)
 }
+
+func (r *indexerNotifier) MergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
+	if err := pr.LoadIssue(ctx); err != nil {
+		log.Error("LoadIssue: %v", err)
+		return
+	}
+	issue_indexer.UpdateIssueIndexer(ctx, pr.Issue.ID)
+}
+
+func (r *indexerNotifier) AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
+	if err := pr.LoadIssue(ctx); err != nil {
+		log.Error("LoadIssue: %v", err)
+		return
+	}
+	issue_indexer.UpdateIssueIndexer(ctx, pr.Issue.ID)
+}
diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go
index 3bd4f57410..6dddb84bcd 100644
--- a/tests/integration/pull_merge_test.go
+++ b/tests/integration/pull_merge_test.go
@@ -27,6 +27,7 @@ import (
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/gitrepo"
 	"code.gitea.io/gitea/modules/hostmatcher"
+	"code.gitea.io/gitea/modules/queue"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/test"
@@ -600,3 +601,63 @@ func TestPullDontRetargetChildOnWrongRepo(t *testing.T) {
 		assert.EqualValues(t, "Closed", prStatus)
 	})
 }
+
+func TestPullMergeIndexerNotifier(t *testing.T) {
+	onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+		// create a pull request
+		session := loginUser(t, "user1")
+		testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+		testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+		createPullResp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "Indexer notifier test pull")
+
+		assert.NoError(t, queue.GetManager().FlushAll(context.Background(), 0))
+		time.Sleep(time.Second)
+
+		repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{
+			OwnerName: "user2",
+			Name:      "repo1",
+		})
+		issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{
+			RepoID:   repo1.ID,
+			Title:    "Indexer notifier test pull",
+			IsPull:   true,
+			IsClosed: false,
+		})
+
+		// build the request for searching issues
+		link, _ := url.Parse("/api/v1/repos/issues/search")
+		query := url.Values{}
+		query.Add("state", "closed")
+		query.Add("type", "pulls")
+		query.Add("q", "notifier")
+		link.RawQuery = query.Encode()
+
+		// search issues
+		searchIssuesResp := session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
+		var apiIssuesBefore []*api.Issue
+		DecodeJSON(t, searchIssuesResp, &apiIssuesBefore)
+		assert.Len(t, apiIssuesBefore, 0)
+
+		// merge the pull request
+		elem := strings.Split(test.RedirectURL(createPullResp), "/")
+		assert.EqualValues(t, "pulls", elem[3])
+		testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
+
+		// check if the issue is closed
+		issue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{
+			ID: issue.ID,
+		})
+		assert.True(t, issue.IsClosed)
+
+		assert.NoError(t, queue.GetManager().FlushAll(context.Background(), 0))
+		time.Sleep(time.Second)
+
+		// search issues again
+		searchIssuesResp = session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
+		var apiIssuesAfter []*api.Issue
+		DecodeJSON(t, searchIssuesResp, &apiIssuesAfter)
+		if assert.Len(t, apiIssuesAfter, 1) {
+			assert.Equal(t, issue.ID, apiIssuesAfter[0].ID)
+		}
+	})
+}