From e68b9d00a6e05b3a941f63ffb696f91e554ac5ec Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 18 Oct 2024 20:33:49 +0200 Subject: Adding upstream version 9.0.3. Signed-off-by: Daniel Baumann --- services/actions/cleanup.go | 128 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 services/actions/cleanup.go (limited to 'services/actions/cleanup.go') diff --git a/services/actions/cleanup.go b/services/actions/cleanup.go new file mode 100644 index 0000000..34fa268 --- /dev/null +++ b/services/actions/cleanup.go @@ -0,0 +1,128 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package actions + +import ( + "context" + "errors" + "fmt" + "os" + "time" + + actions_model "code.gitea.io/gitea/models/actions" + actions_module "code.gitea.io/gitea/modules/actions" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/storage" + "code.gitea.io/gitea/modules/timeutil" +) + +// Cleanup removes expired actions logs, data and artifacts +func Cleanup(ctx context.Context) error { + // clean up expired artifacts + if err := CleanupArtifacts(ctx); err != nil { + return fmt.Errorf("cleanup artifacts: %w", err) + } + + // clean up old logs + if err := CleanupLogs(ctx); err != nil { + return fmt.Errorf("cleanup logs: %w", err) + } + + return nil +} + +// CleanupArtifacts removes expired add need-deleted artifacts and set records expired status +func CleanupArtifacts(taskCtx context.Context) error { + if err := cleanExpiredArtifacts(taskCtx); err != nil { + return err + } + return cleanNeedDeleteArtifacts(taskCtx) +} + +func cleanExpiredArtifacts(taskCtx context.Context) error { + artifacts, err := actions_model.ListNeedExpiredArtifacts(taskCtx) + if err != nil { + return err + } + log.Info("Found %d expired artifacts", len(artifacts)) + for _, artifact := range artifacts { + if err := actions_model.SetArtifactExpired(taskCtx, artifact.ID); err != nil { + log.Error("Cannot set artifact %d expired: %v", artifact.ID, err) + continue + } + if err := storage.ActionsArtifacts.Delete(artifact.StoragePath); err != nil { + log.Error("Cannot delete artifact %d: %v", artifact.ID, err) + continue + } + log.Info("Artifact %d set expired", artifact.ID) + } + return nil +} + +// deleteArtifactBatchSize is the batch size of deleting artifacts +const deleteArtifactBatchSize = 100 + +func cleanNeedDeleteArtifacts(taskCtx context.Context) error { + for { + artifacts, err := actions_model.ListPendingDeleteArtifacts(taskCtx, deleteArtifactBatchSize) + if err != nil { + return err + } + log.Info("Found %d artifacts pending deletion", len(artifacts)) + for _, artifact := range artifacts { + if err := actions_model.SetArtifactDeleted(taskCtx, artifact.ID); err != nil { + log.Error("Cannot set artifact %d deleted: %v", artifact.ID, err) + continue + } + if err := storage.ActionsArtifacts.Delete(artifact.StoragePath); err != nil { + log.Error("Cannot delete artifact %d: %v", artifact.ID, err) + continue + } + log.Info("Artifact %d set deleted", artifact.ID) + } + if len(artifacts) < deleteArtifactBatchSize { + log.Debug("No more artifacts pending deletion") + break + } + } + return nil +} + +const deleteLogBatchSize = 100 + +// CleanupLogs removes logs which are older than the configured retention time +func CleanupLogs(ctx context.Context) error { + olderThan := timeutil.TimeStampNow().AddDuration(-time.Duration(setting.Actions.LogRetentionDays) * 24 * time.Hour) + + count := 0 + for { + tasks, err := actions_model.FindOldTasksToExpire(ctx, olderThan, deleteLogBatchSize) + if err != nil { + return fmt.Errorf("find old tasks: %w", err) + } + for _, task := range tasks { + if err := actions_module.RemoveLogs(ctx, task.LogInStorage, task.LogFilename); err != nil && !errors.Is(err, os.ErrNotExist) { + log.Error("Failed to remove log %s (in storage %v) of task %v: %v", task.LogFilename, task.LogInStorage, task.ID, err) + // do not return error here, continue to next task + continue + } + task.LogIndexes = nil // clear log indexes since it's a heavy field + task.LogExpired = true + if err := actions_model.UpdateTask(ctx, task, "log_indexes", "log_expired"); err != nil { + log.Error("Failed to update task %v: %v", task.ID, err) + // do not return error here, continue to next task + continue + } + count++ + log.Trace("Removed log %s of task %v", task.LogFilename, task.ID) + } + if len(tasks) < deleteLogBatchSize { + break + } + } + + log.Info("Removed %d logs", count) + return nil +} -- cgit v1.2.3