snapshot of https://github.com/go-gitea/gitea.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
cache-seeder / prune (push) Has been skipped
cache-seeder / frontend (push) Failing after 3s
cache-seeder / python (push) Failing after 3s
cache-seeder / gobuild (push) Failing after 4s
cache-seeder / lint (bindata, lint-backend) (push) Failing after 3s
giteabot backport / giteabot (push) Has been skipped
giteabot / giteabot (push) Has been skipped
cache-prune / prune (push) Has been skipped
release-nightly-snapcraft / build-and-publish (ubuntu-24.04) (push) Has been cancelled
release-nightly-snapcraft / build-and-publish (ubuntu-24.04-arm) (push) Has been cancelled
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
cron-renovate / cron-renovate (push) Has been skipped

This commit is contained in:
upstream-mirror
2026-09-15 21:41:59 +05:00
commit 52ae0c5802
6280 changed files with 624193 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"testing"
"gitea.dev/modelmigration/migrationtest"
)
func TestMain(m *testing.M) {
migrationtest.MainTest(m)
}

View File

@@ -0,0 +1,24 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"xorm.io/xorm"
)
func AddMaxParallelToActionRunJob(_ context.Context, x base.EngineMigration) error {
type ActionRunJob struct {
MaxParallel int `xorm:"NOT NULL DEFAULT 0"`
}
_, err := x.SyncWithOptions(xorm.SyncOptions{
IgnoreConstrains: true,
IgnoreDropIndices: true,
}, new(ActionRunJob))
return err
}

View File

@@ -0,0 +1,37 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"testing"
"gitea.dev/modelmigration/migrationtest"
"github.com/stretchr/testify/require"
)
func TestAddMaxParallelToActionRunJob(t *testing.T) {
type ActionRunJob struct {
ID int64 `xorm:"pk autoincr"`
Name string `xorm:"VARCHAR(255)"`
}
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(ActionRunJob))
defer deferable()
if x == nil || t.Failed() {
return
}
_, err := x.Insert(&ActionRunJob{Name: "job-a"})
require.NoError(t, err)
require.NoError(t, AddMaxParallelToActionRunJob(t.Context(), x))
// pre-existing rows must default to unlimited
var maxParallel int
has, err := x.SQL("SELECT max_parallel FROM action_run_job WHERE id = ?", 1).Get(&maxParallel)
require.NoError(t, err)
require.True(t, has)
require.Equal(t, 0, maxParallel)
}

View File

@@ -0,0 +1,27 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"xorm.io/xorm"
)
// AddDeferredMatrixColumnsToActionRunJob adds the columns backing deferred (dynamic) matrix expansion
func AddDeferredMatrixColumnsToActionRunJob(_ context.Context, x base.EngineMigration) error {
type ActionRunJob struct {
// IsMatrixDeferred marks jobs whose matrix depends on other jobs' outputs and is therefore expanded only once those jobs finish;
IsMatrixDeferred bool `xorm:"NOT NULL DEFAULT FALSE"`
// DeferredMatrixPayload preserves the raw, unevaluated payload across expansion so a rerun can re-derive the matrix
DeferredMatrixPayload []byte `xorm:"LONGBLOB"`
}
_, err := x.SyncWithOptions(xorm.SyncOptions{
IgnoreDropIndices: true,
IgnoreConstrains: true,
}, new(ActionRunJob))
return err
}

View File

@@ -0,0 +1,25 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"xorm.io/xorm"
)
// AddBlockOnCodeownerReviews adds block on codeowner reviews branch protection
func AddBlockOnCodeownerReviews(_ context.Context, x base.EngineMigration) error {
type ProtectedBranch struct {
BlockOnCodeownerReviews bool `xorm:"NOT NULL DEFAULT false"`
}
_, err := x.SyncWithOptions(xorm.SyncOptions{
IgnoreConstrains: true,
IgnoreDropIndices: true,
}, new(ProtectedBranch))
return err
}

View File

@@ -0,0 +1,52 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"xorm.io/xorm"
"xorm.io/xorm/schemas"
)
func AddLicensePathToRepoLicense(ctx context.Context, x base.EngineMigration) error {
// Drop the old 2-column UNIQUE(s) index on (repo_id, license) and, on
// re-runs, the index created under the new name.
// xorm Sync cannot reliably update an index when its column set changes.
indexes, err := x.Dialect().GetIndexes(x.DB(), ctx, "repo_license")
if err != nil {
return err
}
for _, idx := range indexes {
if idx.Name == "s" || idx.Name == "path" {
if _, err := x.Exec(x.Dialect().DropIndexSQL("repo_license", idx)); err != nil {
return err
}
}
}
// Add license_path column. The DEFAULT backfills existing rows: all repos
// created before this migration used the single LICENSE file convention.
type RepoLicense struct {
LicensePath string `xorm:"VARCHAR(255) NOT NULL DEFAULT 'LICENSE'"`
}
if _, err := x.SyncWithOptions(xorm.SyncOptions{
IgnoreDropIndices: true,
IgnoreConstrains: true,
}, new(RepoLicense)); err != nil {
return err
}
// Create new 3-column UNIQUE(path) index on (repo_id, license, license_path);
// xorm prefixes the name to UQE_repo_license_path.
newIndex := schemas.NewIndex("path", schemas.UniqueType)
newIndex.AddColumn("repo_id", "license", "license_path")
if _, err := x.Exec(x.Dialect().CreateIndexSQL("repo_license", newIndex)); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,80 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"testing"
"gitea.dev/modelmigration/migrationtest"
"gitea.dev/modules/timeutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"xorm.io/xorm/schemas"
)
// repoLicenseBeforeV345 mirrors the pre-migration repo_license table: no
// license_path column and a 2-column UNIQUE(s) index on (repo_id, license).
type repoLicenseBeforeV345 struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"UNIQUE(s) NOT NULL"`
CommitID string
License string `xorm:"VARCHAR(255) UNIQUE(s) NOT NULL"`
CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
}
func (repoLicenseBeforeV345) TableName() string { return "repo_license" }
func Test_AddLicensePathToRepoLicense(t *testing.T) {
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(repoLicenseBeforeV345))
defer deferable()
_, err := x.Insert(&repoLicenseBeforeV345{RepoID: 1, CommitID: "c1", License: "MIT"})
require.NoError(t, err)
_, err = x.Insert(&repoLicenseBeforeV345{RepoID: 1, CommitID: "c1", License: "Apache-2.0"})
require.NoError(t, err)
_, err = x.Insert(&repoLicenseBeforeV345{RepoID: 2, CommitID: "c2", License: "MIT"})
require.NoError(t, err)
indexes, err := x.Dialect().GetIndexes(x.DB(), context.Background(), "repo_license")
require.NoError(t, err)
oldIdx, ok := indexes["s"] // GetIndexes strips the UQE_repo_license_ prefix
require.True(t, ok, "old 2-column unique s index should exist before migration")
assert.Equal(t, schemas.UniqueType, oldIdx.Type)
assert.Equal(t, []string{"repo_id", "license"}, oldIdx.Cols)
require.NoError(t, AddLicensePathToRepoLicense(t.Context(), x))
require.NoError(t, AddLicensePathToRepoLicense(t.Context(), x)) // idempotent
indexes, err = x.Dialect().GetIndexes(x.DB(), context.Background(), "repo_license")
require.NoError(t, err)
assert.NotContains(t, indexes, "s", "old 2-column unique s index should be gone after migration")
newIdx, ok := indexes["path"] // GetIndexes strips the UQE_repo_license_ prefix
require.True(t, ok, "new index must be named path (UQE_repo_license_path)")
assert.Equal(t, schemas.UniqueType, newIdx.Type)
assert.Equal(t, []string{"repo_id", "license", "license_path"}, newIdx.Cols)
// pre-existing rows must default to the LICENSE path
type licenseRow struct {
RepoID int64
License string
LicensePath string
}
var rows []licenseRow
require.NoError(t, x.SQL("SELECT repo_id, license, license_path FROM repo_license ORDER BY id").Find(&rows))
require.Len(t, rows, 3)
for _, r := range rows {
assert.Equal(t, "LICENSE", r.LicensePath)
}
// the new index is unique per (repo_id, license, license_path): the exact
// duplicate must be rejected, while a second path for the same license
// in the same repo is allowed
_, err = x.Exec("INSERT INTO repo_license (repo_id, commit_id, license, license_path) VALUES (1, 'c1', 'MIT', 'LICENSE')")
require.Error(t, err)
_, err = x.Exec("INSERT INTO repo_license (repo_id, commit_id, license, license_path) VALUES (1, 'c1', 'MIT', 'LICENSES/MIT.txt')")
require.NoError(t, err)
}

View File

@@ -0,0 +1,25 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"xorm.io/xorm"
)
func AddWatchOptions(_ context.Context, x base.EngineMigration) error {
type Watch struct {
IncludePullRequests bool `xorm:"NOT NULL DEFAULT true"`
IncludeIssues bool `xorm:"NOT NULL DEFAULT true"`
IncludeReleases bool `xorm:"NOT NULL DEFAULT true"`
}
_, err := x.SyncWithOptions(xorm.SyncOptions{
IgnoreConstrains: true,
IgnoreIndices: true,
}, new(Watch))
return err
}

View File

@@ -0,0 +1,24 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
)
func RecreateEmailHashTable(_ context.Context, x base.EngineMigration) error {
// the rows are unreachable MD5 hashes and their UNIQUE email index would reject the SHA256 replacements
if err := x.DropTables("email_hash"); err != nil {
return err
}
type EmailHash struct {
Hash string `xorm:"pk varchar(64)"`
Email string `xorm:"UNIQUE(email_hashtype) NOT NULL"`
HashType string `xorm:"UNIQUE(email_hashtype) NOT NULL varchar(16)"`
}
return x.Sync(new(EmailHash))
}

View File

@@ -0,0 +1,38 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"strings"
"testing"
"gitea.dev/modelmigration/migrationtest"
"github.com/stretchr/testify/require"
)
func TestRecreateEmailHashTable(t *testing.T) {
type EmailHash struct {
Hash string `xorm:"pk varchar(32)"`
Email string `xorm:"UNIQUE NOT NULL"`
}
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(EmailHash))
defer deferable()
if x == nil || t.Failed() {
return
}
_, err := x.Insert(&EmailHash{Hash: strings.Repeat("a", 32), Email: "gitea@example.com"})
require.NoError(t, err)
require.NoError(t, RecreateEmailHashTable(t.Context(), x))
count, err := x.Count(new(EmailHash))
require.NoError(t, err)
require.EqualValues(t, 0, count, "the unreachable MD5 rows must be gone")
_, err = x.Exec("INSERT INTO email_hash (hash, email, hash_type) VALUES (?, ?, ?)", strings.Repeat("b", 64), "gitea@example.com", "sha256")
require.NoError(t, err, "the new schema must hold a SHA256 hash")
}

View File

@@ -0,0 +1,29 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"gitea.dev/modules/setting"
"xorm.io/xorm/schemas"
)
func ExpandActionScheduleContent(ctx context.Context, x base.EngineMigration) error {
if !setting.Database.Type.IsMySQL() {
return nil
}
return base.ModifyColumn(ctx, x, "action_schedule", &schemas.Column{
Name: "content",
SQLType: schemas.SQLType{
Name: "LONGBLOB",
},
Length: 0,
Nullable: true,
DefaultIsEmpty: true,
})
}

View File

@@ -0,0 +1,47 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"bytes"
"testing"
"gitea.dev/modelmigration/migrationtest"
"gitea.dev/modules/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestExpandActionScheduleContent(t *testing.T) {
if !setting.Database.Type.IsMySQL() {
t.Skip("Only MySQL limits BLOB columns to 65,535 bytes")
}
type ActionSchedule struct {
ID int64 `xorm:"pk autoincr"`
Content []byte `xorm:"BLOB"`
}
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(ActionSchedule))
defer deferable()
if x == nil || t.Failed() {
return
}
require.NoError(t, ExpandActionScheduleContent(t.Context(), x))
tables := migrationtest.LoadTableSchemasMap(t, x)
assert.Equal(t, "LONGBLOB", tables["action_schedule"].GetColumn("content").SQLType.Name)
content := bytes.Repeat([]byte("x"), 65_536)
_, err := x.Insert(&ActionSchedule{Content: content})
require.NoError(t, err)
var stored ActionSchedule
has, err := x.Get(&stored)
require.NoError(t, err)
require.True(t, has)
assert.Equal(t, content, stored.Content)
}

View File

@@ -0,0 +1,28 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"xorm.io/xorm"
)
func AddPublishedUnixToRelease(_ context.Context, x base.EngineMigration) error {
type Release struct {
PublishedUnix int64 `xorm:"NOT NULL DEFAULT 0"`
}
if _, err := x.SyncWithOptions(xorm.SyncOptions{
IgnoreConstrains: true,
IgnoreDropIndices: true,
}, new(Release)); err != nil {
return err
}
// existing rows have no recorded publication time, so fall back to their creation time
_, err := x.Exec("UPDATE `release` SET published_unix = created_unix WHERE published_unix = 0 AND is_draft = ?", false)
return err
}

View File

@@ -0,0 +1,41 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"testing"
"gitea.dev/modelmigration/migrationtest"
"github.com/stretchr/testify/require"
)
func TestAddPublishedUnixToRelease(t *testing.T) {
type Release struct {
ID int64 `xorm:"pk autoincr"`
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
IsTag bool `xorm:"NOT NULL DEFAULT false"`
CreatedUnix int64 `xorm:"INDEX"`
}
x, deferable := migrationtest.PrepareTestEnv(t, 0, new(Release))
defer deferable()
if x == nil || t.Failed() {
return
}
_, err := x.Insert(
&Release{CreatedUnix: 1000000},
&Release{IsDraft: true, CreatedUnix: 2000000},
&Release{IsTag: true, CreatedUnix: 3000000},
)
require.NoError(t, err)
require.NoError(t, AddPublishedUnixToRelease(t.Context(), x))
var got []struct{ PublishedUnix int64 }
require.NoError(t, x.Table("release").OrderBy("id").Find(&got))
require.Equal(t, []int64{1000000, 0, 3000000}, []int64{got[0].PublishedUnix, got[1].PublishedUnix, got[2].PublishedUnix},
"everything but drafts is backfilled")
}

View File

@@ -0,0 +1,23 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"xorm.io/xorm"
)
func AddRecipientAccessGrantedToRepoTransfer(_ context.Context, x base.EngineMigration) error {
type RepoTransfer struct {
RecipientAccessGranted bool `xorm:"NOT NULL DEFAULT false"`
}
_, err := x.SyncWithOptions(xorm.SyncOptions{
IgnoreConstrains: true,
IgnoreDropIndices: true,
}, new(RepoTransfer))
return err
}

View File

@@ -0,0 +1,38 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"xorm.io/xorm"
)
func AddTokenToDeployKey(ctx context.Context, x base.EngineMigration) error {
// Drop the old UNIQUE(s) index on (key_id, repo_id). Every token row carries key
// id 0, so the pair can no longer be unique. AddDeployKey still checks it in code.
indexes, err := x.Dialect().GetIndexes(x.DB(), ctx, "deploy_key")
if err != nil {
return err
}
if idx, ok := indexes["s"]; ok {
if _, err := x.Exec(x.Dialect().DropIndexSQL("deploy_key", idx)); err != nil {
return err
}
}
type DeployKey struct {
KeyID int64 `xorm:"INDEX"`
RepoID int64 `xorm:"INDEX"`
KeyType int `xorm:"NOT NULL DEFAULT 1"` // every existing row is an SSH key
TokenHash string `xorm:"INDEX"`
}
_, err = x.SyncWithOptions(xorm.SyncOptions{
IgnoreConstrains: true,
IgnoreDropIndices: true, // the bean only describes the new columns
}, new(DeployKey))
return err
}

View File

@@ -0,0 +1,37 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"gitea.dev/modelmigration/base"
"gitea.dev/modules/timeutil"
)
type AuditEvent struct {
ID int64 `xorm:"pk autoincr"`
Action string `xorm:"INDEX NOT NULL"`
ActorID int64 `xorm:"INDEX NOT NULL"`
ActorName string
ActorCredential string
ImpersonatorID int64 `xorm:"INDEX"`
ImpersonatorName string
ScopeID int64 `xorm:"INDEX(scope) NOT NULL"`
ScopeType string `xorm:"INDEX INDEX(scope) NOT NULL"`
ScopeName string
Origin string `xorm:"INDEX NOT NULL"`
Message string
Metadata string `xorm:"LONGTEXT JSON"`
IPAddress string
TimestampUnix timeutil.TimeStamp `xorm:"INDEX NOT NULL"`
}
func (*AuditEvent) TableName() string {
return "audit_event"
}
func AddAuditEventTable(_ context.Context, x base.EngineMigration) error {
return x.Sync(new(AuditEvent))
}

View File

@@ -0,0 +1,48 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v28
import (
"context"
"slices"
"testing"
"gitea.dev/modelmigration/migrationtest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"xorm.io/xorm/schemas"
)
func TestAddAuditEventTable(t *testing.T) {
x, deferable := migrationtest.PrepareTestEnv(t, 0)
defer deferable()
if x == nil || t.Failed() {
return
}
require.NoError(t, AddAuditEventTable(t.Context(), x))
indexes, err := x.Dialect().GetIndexes(x.DB(), context.Background(), "audit_event")
require.NoError(t, err)
for _, columns := range [][]string{
{"action"},
{"actor_id"},
{"scope_id", "scope_type"},
{"scope_type"},
{"origin"},
{"timestamp_unix"},
} {
assert.True(t, hasAuditIndexWithColumns(indexes, columns), "missing index on %v", columns)
}
}
func hasAuditIndexWithColumns(indexes map[string]*schemas.Index, columns []string) bool {
for _, index := range indexes {
if slices.Equal(index.Cols, columns) {
return true
}
}
return false
}