diff --git a/models/actions/run.go b/models/actions/run.go index ab6e319b1cc85..8d4cef022899e 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -305,6 +305,39 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork return commiter.Commit() } +func DeleteTaskSteps(ctx context.Context, steps []*ActionTaskStep) error { + for _, step := range steps { + if err := db.DeleteBeans(ctx, step); err != nil { + return err + } + } + return nil +} + +func DeleteTask(ctx context.Context, actionTask *ActionTask) error { + return db.DeleteBeans(ctx, actionTask) +} + +func DeleteRunJob(ctx context.Context, job *ActionRunJob) error { + return db.DeleteBeans(ctx, job) +} + +func DeleteRun(ctx context.Context, run *ActionRun) error { + if run.Repo == nil { + repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID) + if err != nil { + return err + } + run.Repo = repo + } + + if err := db.DeleteBeans(ctx, run); err != nil { + return err + } + + return updateRepoRunsNumbers(ctx, run.Repo) +} + func GetRunByID(ctx context.Context, id int64) (*ActionRun, error) { var run ActionRun has, err := db.GetEngine(ctx).Where("id=?", id).Get(&run) diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index abb1f6b66b979..cc9d64cf5fcb0 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -405,6 +405,66 @@ func Cancel(ctx *context_module.Context) { ctx.JSON(http.StatusOK, struct{}{}) } +// Delete deletes a run and all its jobs. +func Delete(ctx *context_module.Context) { + runIndex := ctx.ParamsInt64("run") + + run, err := actions_model.GetRunByID(ctx, runIndex) + if err != nil { + ctx.Error(http.StatusNotFound, err.Error()) + return + } + + _, jobs := getRunJobs(ctx, runIndex, -1) + if ctx.Written() { + return + } + + // Initializes a transaction where it will: + // 1. Get all the tasks associate with each job as well as the task steps + // 2. Delete all the task steps, tasks, jobs and run itself. + if err := db.WithTx(ctx, func(ctx context.Context) error { + for _, job := range jobs { + + if job.TaskID == 0 { + return fmt.Errorf("job not associate with any task") + } + if job.Status == actions_model.StatusRunning { + return fmt.Errorf("job is running, can't delete") + } + + task, err := actions_model.GetTaskByID(ctx, job.TaskID) + if err != nil { + return fmt.Errorf("error while getting task: %v", err) + } + + taskSteps, err := actions_model.GetTaskStepsByTaskID(ctx, task.ID) + if err != nil { + return fmt.Errorf("error while getting task steps: %v", err) + } + + if err := actions_model.DeleteTaskSteps(ctx, taskSteps); err != nil { + return fmt.Errorf("error while deleting task steps: %v", err) + } + + if err := actions_model.DeleteTask(ctx, task); err != nil { + return fmt.Errorf("error while deleting task: %v", err) + } + + if err := actions_model.DeleteRunJob(ctx, job); err != nil { + return fmt.Errorf("error while deleting run job: %v", err) + } + } + if err := actions_model.DeleteRun(ctx, run); err != nil { + return fmt.Errorf("error while deleting run: %v", err) + } + return nil + }); err != nil { + ctx.Error(http.StatusInternalServerError, err.Error()) + return + } +} + func Approve(ctx *context_module.Context) { runIndex := ctx.ParamsInt64("run") diff --git a/routers/web/web.go b/routers/web/web.go index ca75bd5967271..d571795e718f0 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1212,6 +1212,7 @@ func registerRoutes(m *web.Route) { m.Post("/artifacts", actions.ArtifactsView) m.Get("/artifacts/{artifact_name}", actions.ArtifactsDownloadView) m.Post("/rerun", reqRepoActionsWriter, actions.RerunAll) + m.Post("/delete", reqRepoActionsWriter, actions.Delete) }) }, reqRepoActionsReader, actions.MustEnableActions)