From 006f06441645d864fc27ca30352367b3afafc5bb Mon Sep 17 00:00:00 2001
From: Gusted <postmaster@gusted.xyz>
Date: Mon, 22 Jan 2024 19:11:24 +0100
Subject: [PATCH] [CI] Fix false positive in database migration

- This also means that if one of the test fails, it will actually
propagate to make and subsequently fail the test.
- Remove the 'delete duplicates issue users' code, I checked this
against my local development database (which contains quite bizarre
cases, even some that Forgejo does not like), my local instance database
and against Codeberg production and they all yielded no results to this
query, so I'm removing it thus resolving the error that the delete code
was not compatible with Mysql.
- Sync all tables that are requires by the migration in the test.
- Resolves #2206

(cherry picked from commit 8e02be7e89a76ccbc3f8a58577be0fcc34e1469e)
---
 Makefile                                      | 18 ++++----
 .../issue_user.yml                            |  7 ---
 models/migrations/v1_22/v283.go               | 17 -------
 models/migrations/v1_22/v286_test.go          | 46 ++++++++++++++++++-
 4 files changed, 54 insertions(+), 34 deletions(-)

diff --git a/Makefile b/Makefile
index 531de4c612..8de6ed0525 100644
--- a/Makefile
+++ b/Makefile
@@ -134,6 +134,8 @@ GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/optio
 GO_SOURCES += $(GENERATED_GO_DEST)
 GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
 
+MIGRATION_PACKAGES := $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
+
 ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
 	GO_SOURCES += $(BINDATA_DEST)
 	GENERATED_GO_DEST += $(BINDATA_DEST)
@@ -684,8 +686,8 @@ migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
 
 .PHONY: migrations.individual.mysql.test
 migrations.individual.mysql.test: $(GO_SOURCES)
-	for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
-		GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
+	for pkg in $(MIGRATION_PACKAGES); do \
+		GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
 	done
 
 .PHONY: migrations.individual.sqlite.test\#%
@@ -694,8 +696,8 @@ migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
 
 .PHONY: migrations.individual.pgsql.test
 migrations.individual.pgsql.test: $(GO_SOURCES)
-	for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
-		GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
+	for pkg in $(MIGRATION_PACKAGES); do \
+		GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1;\
 	done
 
 .PHONY: migrations.individual.pgsql.test\#%
@@ -705,8 +707,8 @@ migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
 
 .PHONY: migrations.individual.mssql.test
 migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql
-	for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
-		GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg -test.failfast; \
+	for pkg in $(MIGRATION_PACKAGES); do \
+		GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' -test.failfast $$pkg || exit 1; \
 	done
 
 .PHONY: migrations.individual.mssql.test\#%
@@ -715,8 +717,8 @@ migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql
 
 .PHONY: migrations.individual.sqlite.test
 migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
-	for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
-		GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
+	for pkg in $(MIGRATION_PACKAGES); do \
+		GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
 	done
 
 .PHONY: migrations.individual.sqlite.test\#%
diff --git a/models/migrations/fixtures/Test_AddCombinedIndexToIssueUser/issue_user.yml b/models/migrations/fixtures/Test_AddCombinedIndexToIssueUser/issue_user.yml
index 7bbb6f2f30..b9995ac250 100644
--- a/models/migrations/fixtures/Test_AddCombinedIndexToIssueUser/issue_user.yml
+++ b/models/migrations/fixtures/Test_AddCombinedIndexToIssueUser/issue_user.yml
@@ -11,10 +11,3 @@
   issue_id: 1
   is_read: true
   is_mentioned: false
-
--
-  id: 3
-  uid: 2
-  issue_id: 1 # duplicated with id 2
-  is_read: false
-  is_mentioned: true
diff --git a/models/migrations/v1_22/v283.go b/models/migrations/v1_22/v283.go
index b2b94845d9..97b22f72a0 100644
--- a/models/migrations/v1_22/v283.go
+++ b/models/migrations/v1_22/v283.go
@@ -8,23 +8,6 @@ import (
 )
 
 func AddCombinedIndexToIssueUser(x *xorm.Engine) error {
-	type OldIssueUser struct {
-		IssueID int64
-		UID     int64
-		Cnt     int64
-	}
-
-	var duplicatedIssueUsers []OldIssueUser
-	if err := x.SQL("select * from (select issue_id, uid, count(1) as cnt from issue_user group by issue_id, uid) a where a.cnt > 1").
-		Find(&duplicatedIssueUsers); err != nil {
-		return err
-	}
-	for _, issueUser := range duplicatedIssueUsers {
-		if _, err := x.Exec("delete from issue_user where id in (SELECT id FROM issue_user WHERE issue_id = ? and uid = ? limit ?)", issueUser.IssueID, issueUser.UID, issueUser.Cnt-1); err != nil {
-			return err
-		}
-	}
-
 	type IssueUser struct {
 		UID     int64 `xorm:"INDEX unique(uid_to_issue)"` // User ID.
 		IssueID int64 `xorm:"INDEX unique(uid_to_issue)"`
diff --git a/models/migrations/v1_22/v286_test.go b/models/migrations/v1_22/v286_test.go
index e36a18a116..6493bfba2f 100644
--- a/models/migrations/v1_22/v286_test.go
+++ b/models/migrations/v1_22/v286_test.go
@@ -14,11 +14,53 @@ import (
 
 func PrepareOldRepository(t *testing.T) (*xorm.Engine, func()) {
 	type Repository struct { // old struct
-		ID int64 `xorm:"pk autoincr"`
+		ID               int64  `xorm:"pk autoincr"`
+		ObjectFormatName string `xorm:"VARCHAR(6) NOT NULL DEFAULT 'sha1'"`
+	}
+
+	type CommitStatus struct { // old struct
+		ID          int64  `xorm:"pk autoincr"`
+		ContextHash string `xorm:"char(40)"`
+	}
+
+	type Comment struct { // old struct
+		ID        int64  `xorm:"pk autoincr"`
+		CommitSHA string `xorm:"VARCHAR(40)"`
+	}
+
+	type PullRequest struct { // old struct
+		ID             int64  `xorm:"pk autoincr"`
+		MergeBase      string `xorm:"VARCHAR(40)"`
+		MergedCommitID string `xorm:"VARCHAR(40)"`
+	}
+
+	type Review struct { // old struct
+		ID       int64  `xorm:"pk autoincr"`
+		CommitID string `xorm:"VARCHAR(40)"`
+	}
+
+	type ReviewState struct { // old struct
+		ID        int64  `xorm:"pk autoincr"`
+		CommitSHA string `xorm:"VARCHAR(40)"`
+	}
+
+	type RepoArchiver struct { // old struct
+		ID       int64  `xorm:"pk autoincr"`
+		CommitID string `xorm:"VARCHAR(40)"`
+	}
+
+	type Release struct { // old struct
+		ID   int64  `xorm:"pk autoincr"`
+		Sha1 string `xorm:"VARCHAR(40)"`
+	}
+
+	type RepoIndexerStatus struct { // old struct
+		ID        int64  `xorm:"pk autoincr"`
+		CommitSha string `xorm:"VARCHAR(40)"`
 	}
 
 	// Prepare and load the testing database
-	return base.PrepareTestEnv(t, 0, new(Repository))
+	return base.PrepareTestEnv(t, 0, new(Repository), new(CommitStatus), new(Comment), new(PullRequest), new(Review), new(ReviewState), new(RepoArchiver), new(Release), new(RepoIndexerStatus))
 }
 
 func Test_RepositoryFormat(t *testing.T) {