mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-08-06 10:25:22 +02:00
feat: add configuration to only push mirror selected branches (#7823)
Adds the ability to selectively choose which branches are pushed to a mirror. This change adds an additional text box on the repository settings for each push mirror. Existing behavior is preserved when the field is left blank. When the repository is being pushed, only branches matching the comma separated branch filter are pushed. Resolves forgejo/forgejo#7242 Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7823 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: Paul Campbell <pcampbell@kemitix.net> Co-committed-by: Paul Campbell <pcampbell@kemitix.net>
This commit is contained in:
parent
0b74ecebe0
commit
9dfdacf54f
16 changed files with 1089 additions and 10 deletions
|
@ -111,6 +111,7 @@ var migrations = []*Migration{
|
|||
NewMigration("Noop because of https://codeberg.org/forgejo/forgejo/issues/8373", NoopAddIndexToActionRunStopped),
|
||||
// v35 -> v36
|
||||
NewMigration("Fix wiki unit default permission", FixWikiUnitDefaultPermission),
|
||||
NewMigration("Add `branch_filter` to `push_mirror` table", AddPushMirrorBranchFilter),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current Forgejo database version.
|
||||
|
|
16
models/forgejo_migrations/v37.go
Normal file
16
models/forgejo_migrations/v37.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddPushMirrorBranchFilter(x *xorm.Engine) error {
|
||||
type PushMirror struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
BranchFilter string `xorm:"VARCHAR(255)"`
|
||||
}
|
||||
return x.Sync2(new(PushMirror))
|
||||
}
|
|
@ -32,6 +32,7 @@ type PushMirror struct {
|
|||
Repo *Repository `xorm:"-"`
|
||||
RemoteName string
|
||||
RemoteAddress string `xorm:"VARCHAR(2048)"`
|
||||
BranchFilter string `xorm:"VARCHAR(2048)"`
|
||||
|
||||
// A keypair formatted in OpenSSH format.
|
||||
PublicKey string `xorm:"VARCHAR(100)"`
|
||||
|
@ -122,6 +123,11 @@ func UpdatePushMirrorInterval(ctx context.Context, m *PushMirror) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func UpdatePushMirrorBranchFilter(ctx context.Context, m *PushMirror) error {
|
||||
_, err := db.GetEngine(ctx).ID(m.ID).Cols("branch_filter").Update(m)
|
||||
return err
|
||||
}
|
||||
|
||||
var DeletePushMirrors = deletePushMirrors
|
||||
|
||||
func deletePushMirrors(ctx context.Context, opts PushMirrorOptions) error {
|
||||
|
|
|
@ -75,3 +75,139 @@ func TestPushMirrorPrivatekey(t *testing.T) {
|
|||
assert.Empty(t, actualPrivateKey)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPushMirrorBranchFilter(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
t.Run("Create push mirror with branch filter", func(t *testing.T) {
|
||||
m := &repo_model.PushMirror{
|
||||
RepoID: 1,
|
||||
RemoteName: "test-branch-filter",
|
||||
BranchFilter: "main,develop",
|
||||
}
|
||||
unittest.AssertSuccessfulInsert(t, m)
|
||||
assert.NotZero(t, m.ID)
|
||||
assert.Equal(t, "main,develop", m.BranchFilter)
|
||||
})
|
||||
|
||||
t.Run("Create push mirror with empty branch filter", func(t *testing.T) {
|
||||
m := &repo_model.PushMirror{
|
||||
RepoID: 1,
|
||||
RemoteName: "test-empty-filter",
|
||||
BranchFilter: "",
|
||||
}
|
||||
unittest.AssertSuccessfulInsert(t, m)
|
||||
assert.NotZero(t, m.ID)
|
||||
assert.Empty(t, m.BranchFilter)
|
||||
})
|
||||
|
||||
t.Run("Create push mirror without branch filter", func(t *testing.T) {
|
||||
m := &repo_model.PushMirror{
|
||||
RepoID: 1,
|
||||
RemoteName: "test-no-filter",
|
||||
// BranchFilter: "",
|
||||
}
|
||||
unittest.AssertSuccessfulInsert(t, m)
|
||||
assert.NotZero(t, m.ID)
|
||||
assert.Empty(t, m.BranchFilter)
|
||||
})
|
||||
|
||||
t.Run("Update branch filter", func(t *testing.T) {
|
||||
m := &repo_model.PushMirror{
|
||||
RepoID: 1,
|
||||
RemoteName: "test-update",
|
||||
BranchFilter: "main",
|
||||
}
|
||||
unittest.AssertSuccessfulInsert(t, m)
|
||||
|
||||
m.BranchFilter = "main,develop"
|
||||
require.NoError(t, repo_model.UpdatePushMirrorBranchFilter(db.DefaultContext, m))
|
||||
|
||||
updated := unittest.AssertExistsAndLoadBean(t, &repo_model.PushMirror{ID: m.ID})
|
||||
assert.Equal(t, "main,develop", updated.BranchFilter)
|
||||
})
|
||||
|
||||
t.Run("Retrieve push mirror with branch filter", func(t *testing.T) {
|
||||
original := &repo_model.PushMirror{
|
||||
RepoID: 1,
|
||||
RemoteName: "test-retrieve",
|
||||
BranchFilter: "main,develop",
|
||||
}
|
||||
unittest.AssertSuccessfulInsert(t, original)
|
||||
|
||||
retrieved := unittest.AssertExistsAndLoadBean(t, &repo_model.PushMirror{ID: original.ID})
|
||||
assert.Equal(t, original.BranchFilter, retrieved.BranchFilter)
|
||||
assert.Equal(t, "main,develop", retrieved.BranchFilter)
|
||||
})
|
||||
|
||||
t.Run("GetPushMirrorsByRepoID includes branch filter", func(t *testing.T) {
|
||||
mirrors := []*repo_model.PushMirror{
|
||||
{
|
||||
RepoID: 2,
|
||||
RemoteName: "mirror-1",
|
||||
BranchFilter: "main",
|
||||
},
|
||||
{
|
||||
RepoID: 2,
|
||||
RemoteName: "mirror-2",
|
||||
BranchFilter: "develop,feature-*",
|
||||
},
|
||||
{
|
||||
RepoID: 2,
|
||||
RemoteName: "mirror-3",
|
||||
BranchFilter: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, mirror := range mirrors {
|
||||
unittest.AssertSuccessfulInsert(t, mirror)
|
||||
}
|
||||
|
||||
retrieved, count, err := repo_model.GetPushMirrorsByRepoID(db.DefaultContext, 2, db.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(3), count)
|
||||
assert.Len(t, retrieved, 3)
|
||||
|
||||
filterMap := make(map[string]string)
|
||||
for _, mirror := range retrieved {
|
||||
filterMap[mirror.RemoteName] = mirror.BranchFilter
|
||||
}
|
||||
|
||||
assert.Equal(t, "main", filterMap["mirror-1"])
|
||||
assert.Equal(t, "develop,feature-*", filterMap["mirror-2"])
|
||||
assert.Empty(t, filterMap["mirror-3"])
|
||||
})
|
||||
|
||||
t.Run("GetPushMirrorsSyncedOnCommit includes branch filter", func(t *testing.T) {
|
||||
mirrors := []*repo_model.PushMirror{
|
||||
{
|
||||
RepoID: 3,
|
||||
RemoteName: "sync-mirror-1",
|
||||
BranchFilter: "main,develop",
|
||||
SyncOnCommit: true,
|
||||
},
|
||||
{
|
||||
RepoID: 3,
|
||||
RemoteName: "sync-mirror-2",
|
||||
BranchFilter: "feature-*",
|
||||
SyncOnCommit: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, mirror := range mirrors {
|
||||
unittest.AssertSuccessfulInsert(t, mirror)
|
||||
}
|
||||
|
||||
retrieved, err := repo_model.GetPushMirrorsSyncedOnCommit(db.DefaultContext, 3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, retrieved, 2)
|
||||
|
||||
filterMap := make(map[string]string)
|
||||
for _, mirror := range retrieved {
|
||||
filterMap[mirror.RemoteName] = mirror.BranchFilter
|
||||
}
|
||||
|
||||
assert.Equal(t, "main,develop", filterMap["sync-mirror-1"])
|
||||
assert.Equal(t, "feature-*", filterMap["sync-mirror-2"])
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue