mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-29 02:04:15 +00:00
refactor: clean up git repo and model migration packages (#38564)
enable the golangci depguard lint rule: deny "models" and its sub packages in "modelmigration" package.
This commit is contained in:
@@ -11,19 +11,14 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/models/db" //nolint:depguard // allow to access db in migration
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/setting"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
||||
// Migrations should never use model structs directly, because the model structs can be different in different releases.
|
||||
// e.g. if one migration uses "User" model, it works in the early releases, then one day,
|
||||
// when the User model changes, the migration breaks because it will use the new (incorrect) User model,
|
||||
// it should only use the old User model. The same to "modules/structs".
|
||||
// However, many the existing migrations already abuses "modules/structs" (search "gitea.dev/models/" in the migrations).
|
||||
// TODO: need to fully decouple the migration package and models & structs package
|
||||
type (
|
||||
EngineMigration = db.EngineMigration
|
||||
Session = db.Session
|
||||
@@ -519,3 +514,7 @@ func ModifyColumn(x EngineMigration, tableName string, col *schemas.Column) erro
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Iterate[Bean any](ctx context.Context, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error {
|
||||
return db.Iterate(ctx, cond, f)
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package base
|
||||
|
||||
import (
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
func LocalCodeGitRepo(ownerName, repoName string) gitcmd.RepositoryFacade {
|
||||
return repo_model.CodeRepoByName(ownerName, repoName)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package base
|
||||
|
||||
import (
|
||||
"gitea.dev/models/db" //nolint:depguard // allow to access db in migration
|
||||
"gitea.dev/modules/git/gitrepo"
|
||||
)
|
||||
|
||||
// HINT: MIGRATION-STRUCT-FROZEN: the structs used in migrations should not be affected by the changes happen in the future,
|
||||
// because the details can be different in different releases.
|
||||
// e.g. if one migration uses "User" model, it works in the early releases,
|
||||
// then one day, when the User model changes, the existing migration will break because it will use the new (incorrect) User model,
|
||||
// it should only use the old User model.
|
||||
//
|
||||
// Related: "models", "modules/structs", git repo directory layout on the disk, etc.
|
||||
//
|
||||
// If changes happen, the old migrations need to use a snapshot struct/function (copy the code and freeze)
|
||||
|
||||
type ResourceIndex = db.ResourceIndex
|
||||
|
||||
func LocalCodeGitRepo(ownerName, repoName string) gitrepo.RepositoryFacade {
|
||||
return gitrepo.CodeRepoByName(ownerName, repoName)
|
||||
}
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/models/unittest"
|
||||
"gitea.dev/models/db" //nolint:depguard // allow to access db in migration tests
|
||||
"gitea.dev/models/unittest" //nolint:depguard // allow to access db in migration tests
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/testlogger"
|
||||
|
||||
@@ -5,7 +5,7 @@ package v1_17
|
||||
|
||||
import (
|
||||
"gitea.dev/modelmigration/base"
|
||||
packages_model "gitea.dev/models/packages"
|
||||
packages_model "gitea.dev/models/packages" //nolint:depguard // only consts are used
|
||||
container_module "gitea.dev/modules/packages/container"
|
||||
|
||||
"xorm.io/xorm/schemas"
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/issues"
|
||||
"gitea.dev/modules/timeutil"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
@@ -19,6 +19,15 @@ func UpdateOpenMilestoneCounts(x base.EngineMigration) error {
|
||||
return fmt.Errorf("error selecting open milestone IDs: %w", err)
|
||||
}
|
||||
|
||||
type Milestone struct {
|
||||
ID int64
|
||||
IsClosed bool
|
||||
NumIssues int
|
||||
NumClosedIssues int
|
||||
Completeness int
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
for _, id := range openMilestoneIDs {
|
||||
_, err := x.ID(id).
|
||||
Cols("num_issues", "num_closed_issues").
|
||||
@@ -31,7 +40,7 @@ func UpdateOpenMilestoneCounts(x base.EngineMigration) error {
|
||||
"is_closed": true,
|
||||
},
|
||||
)).
|
||||
Update(&issues.Milestone{})
|
||||
Update(&Milestone{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error updating issue counts in milestone %d: %w", id, err)
|
||||
}
|
||||
|
||||
@@ -7,16 +7,34 @@ import (
|
||||
"testing"
|
||||
|
||||
"gitea.dev/modelmigration/migrationtest"
|
||||
"gitea.dev/models/issues"
|
||||
"gitea.dev/modules/timeutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_UpdateOpenMilestoneCounts(t *testing.T) {
|
||||
type ExpectedMilestone issues.Milestone
|
||||
type Issue struct {
|
||||
ID int64
|
||||
RepoID int64
|
||||
Index int64
|
||||
MilestoneID int64
|
||||
IsClosed bool
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
type Milestone struct {
|
||||
ID int64
|
||||
IsClosed bool
|
||||
NumIssues int
|
||||
NumClosedIssues int
|
||||
Completeness int
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
type ExpectedMilestone Milestone
|
||||
|
||||
// Prepare and load the testing database
|
||||
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(issues.Milestone), new(ExpectedMilestone), new(issues.Issue))
|
||||
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(Milestone), new(ExpectedMilestone), new(Issue))
|
||||
defer deferable()
|
||||
if x == nil || t.Failed() {
|
||||
return
|
||||
@@ -32,7 +50,7 @@ func Test_UpdateOpenMilestoneCounts(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
got := []issues.Milestone{}
|
||||
got := []Milestone{}
|
||||
if err := x.Table("milestone").Asc("id").Find(&got); !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ package v1_19
|
||||
|
||||
import (
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/modules/timeutil"
|
||||
)
|
||||
|
||||
@@ -96,7 +95,7 @@ func AddActionsTables(x base.EngineMigration) error {
|
||||
NumClosedActionRuns int `xorm:"NOT NULL DEFAULT 0"`
|
||||
}
|
||||
|
||||
type ActionRunIndex db.ResourceIndex
|
||||
type ActionRunIndex base.ResourceIndex
|
||||
|
||||
type ActionTask struct {
|
||||
ID int64
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"errors"
|
||||
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/modules/timeutil"
|
||||
)
|
||||
|
||||
@@ -60,7 +59,7 @@ func AddBranchTable(x base.EngineMigration) error {
|
||||
}
|
||||
|
||||
branches := make([]Branch, 0, 100)
|
||||
if err := db.Iterate(context.Background(), nil, func(ctx context.Context, deletedBranch *DeletedBranch) error {
|
||||
if err := base.Iterate(context.Background(), nil, func(ctx context.Context, deletedBranch *DeletedBranch) error {
|
||||
branches = append(branches, Branch{
|
||||
RepoID: deletedBranch.RepoID,
|
||||
Name: deletedBranch.Name,
|
||||
|
||||
@@ -9,6 +9,24 @@ import (
|
||||
"gitea.dev/modules/timeutil"
|
||||
)
|
||||
|
||||
type ProjectBoardV293 struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Title string
|
||||
Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board
|
||||
Sorting int8 `xorm:"NOT NULL DEFAULT 0"`
|
||||
Color string `xorm:"VARCHAR(7)"`
|
||||
|
||||
ProjectID int64 `xorm:"INDEX NOT NULL"`
|
||||
CreatorID int64 `xorm:"NOT NULL"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
func (ProjectBoardV293) TableName() string {
|
||||
return "project_board"
|
||||
}
|
||||
|
||||
// CheckProjectColumnsConsistency ensures there is exactly one default board per project present
|
||||
func CheckProjectColumnsConsistency(x base.EngineMigration) error {
|
||||
sess := x.NewSession()
|
||||
@@ -25,20 +43,6 @@ func CheckProjectColumnsConsistency(x base.EngineMigration) error {
|
||||
BoardID int64
|
||||
}
|
||||
|
||||
type ProjectBoard struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Title string
|
||||
Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board
|
||||
Sorting int8 `xorm:"NOT NULL DEFAULT 0"`
|
||||
Color string `xorm:"VARCHAR(7)"`
|
||||
|
||||
ProjectID int64 `xorm:"INDEX NOT NULL"`
|
||||
CreatorID int64 `xorm:"NOT NULL"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
for {
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
@@ -56,7 +60,7 @@ func CheckProjectColumnsConsistency(x base.EngineMigration) error {
|
||||
}
|
||||
|
||||
for _, p := range projects {
|
||||
if _, err := sess.Insert(ProjectBoard{
|
||||
if _, err := sess.Insert(ProjectBoardV293{
|
||||
ProjectID: p.ID,
|
||||
Default: true,
|
||||
Title: "Uncategorized",
|
||||
|
||||
@@ -7,14 +7,30 @@ import (
|
||||
"testing"
|
||||
|
||||
"gitea.dev/modelmigration/migrationtest"
|
||||
"gitea.dev/models/project"
|
||||
"gitea.dev/modules/timeutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_CheckProjectColumnsConsistency(t *testing.T) {
|
||||
// Prepare and load the testing database
|
||||
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(project.Project), new(project.Column))
|
||||
type Project struct {
|
||||
ID int64
|
||||
Title string
|
||||
Description string
|
||||
OwnerID int64
|
||||
RepoID int64
|
||||
CreatorID int64
|
||||
IsClosed bool
|
||||
TemplateType uint8
|
||||
BoardType uint8
|
||||
Type uint8
|
||||
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
ClosedDateUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(Project), new(ProjectBoardV293))
|
||||
defer deferable()
|
||||
if x == nil || t.Failed() {
|
||||
return
|
||||
@@ -23,7 +39,7 @@ func Test_CheckProjectColumnsConsistency(t *testing.T) {
|
||||
assert.NoError(t, CheckProjectColumnsConsistency(x))
|
||||
|
||||
// check if default column was added
|
||||
var defaultColumn project.Column
|
||||
var defaultColumn ProjectBoardV293
|
||||
has, err := x.Where("project_id=? AND `default` = ?", 1, true).Get(&defaultColumn)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
@@ -31,13 +47,17 @@ func Test_CheckProjectColumnsConsistency(t *testing.T) {
|
||||
assert.True(t, defaultColumn.Default)
|
||||
|
||||
// check if multiple defaults, previous were removed and last will be kept
|
||||
expectDefaultColumn, err := project.GetColumn(t.Context(), 2)
|
||||
var expectDefaultColumn ProjectBoardV293
|
||||
has, err = x.ID(2).Get(&expectDefaultColumn)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.Equal(t, int64(2), expectDefaultColumn.ProjectID)
|
||||
assert.False(t, expectDefaultColumn.Default)
|
||||
|
||||
expectNonDefaultColumn, err := project.GetColumn(t.Context(), 3)
|
||||
var expectNonDefaultColumn ProjectBoardV293
|
||||
has, err = x.ID(3).Get(&expectNonDefaultColumn)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.Equal(t, int64(2), expectNonDefaultColumn.ProjectID)
|
||||
assert.True(t, expectNonDefaultColumn.Default)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ package v1_27
|
||||
|
||||
import (
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/db"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
@@ -25,7 +24,7 @@ func AddReusableWorkflowFieldsToActionRunJob(x base.EngineMigration) error {
|
||||
ReusableWorkflowContent []byte `xorm:"LONGBLOB"`
|
||||
}
|
||||
|
||||
type ActionRunAttemptJobIDIndex db.ResourceIndex
|
||||
type ActionRunAttemptJobIDIndex base.ResourceIndex
|
||||
|
||||
if _, err := x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, new(ActionRunJob)); err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user