Allow package cleanup from admin page (#25307)
Until now expired package data gets deleted daily by a cronjob. The admin page shows the size of all packages and the size of unreferenced data. The users (#25035, #20631) expect the deletion of this data if they run the cronjob from the admin page but the job only deletes data older than 24h. This PR adds a new button which deletes all expired data. ![grafik](https://github.com/go-gitea/gitea/assets/1666336/b3e35d73-9496-4fa7-a20c-e5d30b1f6850) --------- Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
parent
c2b6897e35
commit
0c6ae61229
|
@ -2833,6 +2833,7 @@ repos.lfs_size = LFS Size
|
||||||
packages.package_manage_panel = Package Management
|
packages.package_manage_panel = Package Management
|
||||||
packages.total_size = Total Size: %s
|
packages.total_size = Total Size: %s
|
||||||
packages.unreferenced_size = Unreferenced Size: %s
|
packages.unreferenced_size = Unreferenced Size: %s
|
||||||
|
packages.cleanup = Clean up expired data
|
||||||
packages.owner = Owner
|
packages.owner = Owner
|
||||||
packages.creator = Creator
|
packages.creator = Creator
|
||||||
packages.name = Name
|
packages.name = Name
|
||||||
|
|
|
@ -6,6 +6,7 @@ package admin
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
packages_model "code.gitea.io/gitea/models/packages"
|
packages_model "code.gitea.io/gitea/models/packages"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
packages_service "code.gitea.io/gitea/services/packages"
|
packages_service "code.gitea.io/gitea/services/packages"
|
||||||
|
packages_cleanup_service "code.gitea.io/gitea/services/packages/cleanup"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -99,3 +101,13 @@ func DeletePackageVersion(ctx *context.Context) {
|
||||||
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
|
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
|
||||||
ctx.JSONRedirect(setting.AppSubURL + "/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type")))
|
ctx.JSONRedirect(setting.AppSubURL + "/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CleanupExpiredData(ctx *context.Context) {
|
||||||
|
if err := packages_cleanup_service.CleanupExpiredData(ctx, time.Duration(0)); err != nil {
|
||||||
|
ctx.ServerError("CleanupExpiredData", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Flash.Success(ctx.Tr("packages.cleanup.success"))
|
||||||
|
ctx.Redirect(setting.AppSubURL + "/admin/packages")
|
||||||
|
}
|
||||||
|
|
|
@ -597,6 +597,7 @@ func registerRoutes(m *web.Route) {
|
||||||
m.Group("/packages", func() {
|
m.Group("/packages", func() {
|
||||||
m.Get("", admin.Packages)
|
m.Get("", admin.Packages)
|
||||||
m.Post("/delete", admin.DeletePackageVersion)
|
m.Post("/delete", admin.DeletePackageVersion)
|
||||||
|
m.Post("/cleanup", admin.CleanupExpiredData)
|
||||||
}, packagesEnabled)
|
}, packagesEnabled)
|
||||||
|
|
||||||
m.Group("/hooks", func() {
|
m.Group("/hooks", func() {
|
||||||
|
|
|
@ -152,7 +152,7 @@ func registerCleanupPackages() {
|
||||||
OlderThan: 24 * time.Hour,
|
OlderThan: 24 * time.Hour,
|
||||||
}, func(ctx context.Context, _ *user_model.User, config Config) error {
|
}, func(ctx context.Context, _ *user_model.User, config Config) error {
|
||||||
realConfig := config.(*OlderThanConfig)
|
realConfig := config.(*OlderThanConfig)
|
||||||
return packages_cleanup_service.Cleanup(ctx, realConfig.OlderThan)
|
return packages_cleanup_service.CleanupTask(ctx, realConfig.OlderThan)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,17 @@ import (
|
||||||
debian_service "code.gitea.io/gitea/services/packages/debian"
|
debian_service "code.gitea.io/gitea/services/packages/debian"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cleanup removes expired package data
|
// Task method to execute cleanup rules and cleanup expired package data
|
||||||
func Cleanup(taskCtx context.Context, olderThan time.Duration) error {
|
func CleanupTask(ctx context.Context, olderThan time.Duration) error {
|
||||||
ctx, committer, err := db.TxContext(taskCtx)
|
if err := ExecuteCleanupRules(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return CleanupExpiredData(ctx, olderThan)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExecuteCleanupRules(outerCtx context.Context) error {
|
||||||
|
ctx, committer, err := db.TxContext(outerCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -30,7 +38,7 @@ func Cleanup(taskCtx context.Context, olderThan time.Duration) error {
|
||||||
|
|
||||||
err = packages_model.IterateEnabledCleanupRules(ctx, func(ctx context.Context, pcr *packages_model.PackageCleanupRule) error {
|
err = packages_model.IterateEnabledCleanupRules(ctx, func(ctx context.Context, pcr *packages_model.PackageCleanupRule) error {
|
||||||
select {
|
select {
|
||||||
case <-taskCtx.Done():
|
case <-outerCtx.Done():
|
||||||
return db.ErrCancelledf("While processing package cleanup rules")
|
return db.ErrCancelledf("While processing package cleanup rules")
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -122,6 +130,16 @@ func Cleanup(taskCtx context.Context, olderThan time.Duration) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return committer.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CleanupExpiredData(outerCtx context.Context, olderThan time.Duration) error {
|
||||||
|
ctx, committer, err := db.TxContext(outerCtx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
if err := container_service.Cleanup(ctx, olderThan); err != nil {
|
if err := container_service.Cleanup(ctx, olderThan); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,12 @@
|
||||||
{{.locale.Tr "admin.packages.package_manage_panel"}} ({{.locale.Tr "admin.total" .TotalCount}},
|
{{.locale.Tr "admin.packages.package_manage_panel"}} ({{.locale.Tr "admin.total" .TotalCount}},
|
||||||
{{.locale.Tr "admin.packages.total_size" (FileSize .TotalBlobSize)}},
|
{{.locale.Tr "admin.packages.total_size" (FileSize .TotalBlobSize)}},
|
||||||
{{.locale.Tr "admin.packages.unreferenced_size" (FileSize .TotalUnreferencedBlobSize)}})
|
{{.locale.Tr "admin.packages.unreferenced_size" (FileSize .TotalUnreferencedBlobSize)}})
|
||||||
|
<div class="ui right">
|
||||||
|
<form method="post" action="/admin/packages/cleanup">
|
||||||
|
{{.CsrfTokenHtml}}
|
||||||
|
<button class="ui primary tiny button">{{.locale.Tr "admin.packages.cleanup"}}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
<form class="ui form ignore-dirty">
|
<form class="ui form ignore-dirty">
|
||||||
|
|
|
@ -475,7 +475,7 @@ func TestPackageCleanup(t *testing.T) {
|
||||||
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, "cleanup-test", container_model.UploadVersion)
|
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, "cleanup-test", container_model.UploadVersion)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = packages_cleanup_service.Cleanup(db.DefaultContext, duration)
|
err = packages_cleanup_service.CleanupTask(db.DefaultContext, duration)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, duration)
|
pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, duration)
|
||||||
|
@ -610,7 +610,7 @@ func TestPackageCleanup(t *testing.T) {
|
||||||
pcr, err := packages_model.InsertCleanupRule(db.DefaultContext, c.Rule)
|
pcr, err := packages_model.InsertCleanupRule(db.DefaultContext, c.Rule)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = packages_cleanup_service.Cleanup(db.DefaultContext, duration)
|
err = packages_cleanup_service.CleanupTask(db.DefaultContext, duration)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
for _, v := range c.Versions {
|
for _, v := range c.Versions {
|
||||||
|
|
Loading…
Reference in New Issue