mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-08-29 21:53:53 +00:00
feat: move StopTask, CancelPreviousJobs and CleanRepoScheduleTasks to services/actions
This enables all action run state changes (from a not done to a done state) to also send a notification. Moved these: - models/actions/task.go|423 col 6| func StopTask(ctx context.Context, taskID int64, status Status) error { - models/actions/run.go|190 col 6| func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error { - models/actions/schedule.go|122 col 6| func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository, cancelPreviousJobs bool) error {
This commit is contained in:
parent
c977585e4c
commit
81b5c7ca6f
12 changed files with 156 additions and 156 deletions
|
@ -17,6 +17,7 @@ import (
|
|||
webhook_module "forgejo.org/modules/webhook"
|
||||
|
||||
"github.com/nektos/act/pkg/jobparser"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
// StartScheduleTasks start the task
|
||||
|
@ -55,7 +56,7 @@ func startTasks(ctx context.Context) error {
|
|||
// cancel running jobs if the event is push
|
||||
if row.Schedule.Event == webhook_module.HookEventPush {
|
||||
// cancel running jobs of the same workflow
|
||||
if err := actions_model.CancelPreviousJobs(
|
||||
if err := CancelPreviousJobs(
|
||||
ctx,
|
||||
row.RepoID,
|
||||
row.Schedule.Ref,
|
||||
|
@ -152,3 +153,93 @@ func CreateScheduleTask(ctx context.Context, cron *actions_model.ActionSchedule)
|
|||
// Return nil if no errors occurred
|
||||
return nil
|
||||
}
|
||||
|
||||
// CancelPreviousJobs cancels all previous jobs of the same repository, reference, workflow, and event.
|
||||
// It's useful when a new run is triggered, and all previous runs needn't be continued anymore.
|
||||
func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error {
|
||||
// Find all runs in the specified repository, reference, and workflow with non-final status
|
||||
runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, actions_model.FindRunOptions{
|
||||
RepoID: repoID,
|
||||
Ref: ref,
|
||||
WorkflowID: workflowID,
|
||||
TriggerEvent: event,
|
||||
Status: []actions_model.Status{actions_model.StatusRunning, actions_model.StatusWaiting, actions_model.StatusBlocked},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If there are no runs found, there's no need to proceed with cancellation, so return nil.
|
||||
if total == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Iterate over each found run and cancel its associated jobs.
|
||||
for _, run := range runs {
|
||||
// Find all jobs associated with the current run.
|
||||
jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{
|
||||
RunID: run.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Iterate over each job and attempt to cancel it.
|
||||
for _, job := range jobs {
|
||||
// Skip jobs that are already in a terminal state (completed, cancelled, etc.).
|
||||
status := job.Status
|
||||
if status.IsDone() {
|
||||
continue
|
||||
}
|
||||
|
||||
// If the job has no associated task (probably an error), set its status to 'Cancelled' and stop it.
|
||||
if job.TaskID == 0 {
|
||||
job.Status = actions_model.StatusCancelled
|
||||
job.Stopped = timeutil.TimeStampNow()
|
||||
|
||||
// Update the job's status and stopped time in the database.
|
||||
n, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the update affected 0 rows, it means the job has changed in the meantime, so we need to try again.
|
||||
if n == 0 {
|
||||
return fmt.Errorf("job has changed, try again")
|
||||
}
|
||||
|
||||
// Continue with the next job.
|
||||
continue
|
||||
}
|
||||
|
||||
// If the job has an associated task, try to stop the task, effectively cancelling the job.
|
||||
if err := StopTask(ctx, job.TaskID, actions_model.StatusCancelled); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return nil to indicate successful cancellation of all running and waiting jobs.
|
||||
return nil
|
||||
}
|
||||
|
||||
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository, cancelPreviousJobs bool) error {
|
||||
// If actions disabled when there is schedule task, this will remove the outdated schedule tasks
|
||||
// There is no other place we can do this because the app.ini will be changed manually
|
||||
if err := actions_model.DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil {
|
||||
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
|
||||
}
|
||||
if cancelPreviousJobs {
|
||||
// cancel running cron jobs of this repository and delete old schedules
|
||||
if err := CancelPreviousJobs(
|
||||
ctx,
|
||||
repo.ID,
|
||||
repo.DefaultBranch,
|
||||
"",
|
||||
webhook_module.HookEventSchedule,
|
||||
); err != nil {
|
||||
return fmt.Errorf("CancelPreviousJobs: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue