mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-21 16:40:52 +00:00
Add package registry cleanup rules (#21658)
Fixes #20514 Fixes #20766 Fixes #20631 This PR adds Cleanup Rules for the package registry. This allows to delete unneeded packages automatically. Cleanup rules can be set up from the user or org settings. Please have a look at the documentation because I'm not a native english speaker. Rule Form  Rule List  Rule Preview  Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
parent
d3f850cc0e
commit
32db62515f
27 changed files with 1243 additions and 36 deletions
|
@ -203,22 +203,171 @@ func TestPackageQuota(t *testing.T) {
|
|||
func TestPackageCleanup(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
duration, _ := time.ParseDuration("-1h")
|
||||
|
||||
pbs, err := packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0))
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, pbs)
|
||||
t.Run("Common", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion)
|
||||
assert.NoError(t, err)
|
||||
pbs, err := packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, duration)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, pbs)
|
||||
|
||||
err = packages_service.Cleanup(nil, time.Duration(0))
|
||||
assert.NoError(t, err)
|
||||
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion)
|
||||
assert.NoError(t, err)
|
||||
|
||||
pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0))
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, pbs)
|
||||
err = packages_service.Cleanup(db.DefaultContext, duration)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion)
|
||||
assert.ErrorIs(t, err, packages_model.ErrPackageNotExist)
|
||||
pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, duration)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, pbs)
|
||||
|
||||
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion)
|
||||
assert.ErrorIs(t, err, packages_model.ErrPackageNotExist)
|
||||
})
|
||||
|
||||
t.Run("CleanupRules", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
type version struct {
|
||||
Version string
|
||||
ShouldExist bool
|
||||
Created int64
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
Name string
|
||||
Versions []version
|
||||
Rule *packages_model.PackageCleanupRule
|
||||
}{
|
||||
{
|
||||
Name: "Disabled",
|
||||
Versions: []version{
|
||||
{Version: "keep", ShouldExist: true},
|
||||
},
|
||||
Rule: &packages_model.PackageCleanupRule{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "KeepCount",
|
||||
Versions: []version{
|
||||
{Version: "keep", ShouldExist: true},
|
||||
{Version: "v1.0", ShouldExist: true},
|
||||
{Version: "test-3", ShouldExist: false, Created: 1},
|
||||
{Version: "test-4", ShouldExist: false, Created: 1},
|
||||
},
|
||||
Rule: &packages_model.PackageCleanupRule{
|
||||
Enabled: true,
|
||||
KeepCount: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "KeepPattern",
|
||||
Versions: []version{
|
||||
{Version: "keep", ShouldExist: true},
|
||||
{Version: "v1.0", ShouldExist: false},
|
||||
},
|
||||
Rule: &packages_model.PackageCleanupRule{
|
||||
Enabled: true,
|
||||
KeepPattern: "k.+p",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "RemoveDays",
|
||||
Versions: []version{
|
||||
{Version: "keep", ShouldExist: true},
|
||||
{Version: "v1.0", ShouldExist: false, Created: 1},
|
||||
},
|
||||
Rule: &packages_model.PackageCleanupRule{
|
||||
Enabled: true,
|
||||
RemoveDays: 60,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "RemovePattern",
|
||||
Versions: []version{
|
||||
{Version: "test", ShouldExist: true},
|
||||
{Version: "test-3", ShouldExist: false},
|
||||
{Version: "test-4", ShouldExist: false},
|
||||
},
|
||||
Rule: &packages_model.PackageCleanupRule{
|
||||
Enabled: true,
|
||||
RemovePattern: `t[e]+st-\d+`,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MatchFullName",
|
||||
Versions: []version{
|
||||
{Version: "keep", ShouldExist: true},
|
||||
{Version: "test", ShouldExist: false},
|
||||
},
|
||||
Rule: &packages_model.PackageCleanupRule{
|
||||
Enabled: true,
|
||||
RemovePattern: `package/test|different/keep`,
|
||||
MatchFullName: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Mixed",
|
||||
Versions: []version{
|
||||
{Version: "keep", ShouldExist: true, Created: time.Now().Add(time.Duration(10000)).Unix()},
|
||||
{Version: "dummy", ShouldExist: true, Created: 1},
|
||||
{Version: "test-3", ShouldExist: true},
|
||||
{Version: "test-4", ShouldExist: false, Created: 1},
|
||||
},
|
||||
Rule: &packages_model.PackageCleanupRule{
|
||||
Enabled: true,
|
||||
KeepCount: 1,
|
||||
KeepPattern: `dummy`,
|
||||
RemoveDays: 7,
|
||||
RemovePattern: `t[e]+st-\d+`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
for _, v := range c.Versions {
|
||||
url := fmt.Sprintf("/api/packages/%s/generic/package/%s/file.bin", user.Name, v.Version)
|
||||
req := NewRequestWithBody(t, "PUT", url, bytes.NewReader([]byte{1}))
|
||||
AddBasicAuthHeader(req, user.Name)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
if v.Created != 0 {
|
||||
pv, err := packages_model.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeGeneric, "package", v.Version)
|
||||
assert.NoError(t, err)
|
||||
_, err = db.GetEngine(db.DefaultContext).Exec("UPDATE package_version SET created_unix = ? WHERE id = ?", v.Created, pv.ID)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
c.Rule.OwnerID = user.ID
|
||||
c.Rule.Type = packages_model.TypeGeneric
|
||||
|
||||
pcr, err := packages_model.InsertCleanupRule(db.DefaultContext, c.Rule)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = packages_service.Cleanup(db.DefaultContext, duration)
|
||||
assert.NoError(t, err)
|
||||
|
||||
for _, v := range c.Versions {
|
||||
pv, err := packages_model.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeGeneric, "package", v.Version)
|
||||
if v.ShouldExist {
|
||||
assert.NoError(t, err)
|
||||
err = packages_service.DeletePackageVersionAndReferences(db.DefaultContext, pv)
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.ErrorIs(t, err, packages_model.ErrPackageNotExist)
|
||||
}
|
||||
}
|
||||
|
||||
assert.NoError(t, packages_model.DeleteCleanupRuleByID(db.DefaultContext, pcr.ID))
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue