runservice: allow restart run only if possible

This commit is contained in:
Simone Gotti 2019-03-29 09:09:57 +01:00
parent 1657a35a6f
commit c9089c3ccc
2 changed files with 41 additions and 1 deletions

View File

@ -216,6 +216,16 @@ func (s *CommandHandler) recreateRun(ctx context.Context, req *RunCreateRequest)
return nil, errors.Wrapf(err, "run %q doens't exist", req.RunID)
}
if req.FromStart {
if canRestart, reason := run.CanRestartFromScratch(); !canRestart {
return nil, errors.Errorf("run cannot be restarted: %s", reason)
}
} else {
if canRestart, reason := run.CanRestartFromFailedTasks(); !canRestart {
return nil, errors.Errorf("run cannot be restarted: %s", reason)
}
}
// update the run ID
run.ID = id
// reset run revision
@ -231,7 +241,6 @@ func (s *CommandHandler) recreateRun(ctx context.Context, req *RunCreateRequest)
tasksToAdd := []*types.RunTask{}
tasksToDelete := []string{}
s.log.Infof("fromStart: %t", req.FromStart)
for _, rt := range run.RunTasks {
if req.FromStart || rt.Status != types.RunTaskStatusSuccess {
rct := rc.Tasks[rt.ID]

View File

@ -17,6 +17,7 @@ package types
import (
"encoding/base64"
"encoding/json"
"fmt"
"time"
"github.com/sorintlab/agola/internal/util"
@ -131,6 +132,36 @@ func (r *Run) TasksWaitingApproval() []string {
return runTasksIDs
}
// CanRestartFromScratch reports if the run can be restarted from scratch
func (r *Run) CanRestartFromScratch() (bool, string) {
// can restart only if the run phase is finished or cancelled
if !r.Phase.IsFinished() {
return false, fmt.Sprintf("run is not finished, phase: %q", r.Phase)
}
return true, ""
}
// CanRestartFromFailedTasks reports if the run can be restarted from failed tasks
func (r *Run) CanRestartFromFailedTasks() (bool, string) {
// can restart only if the run phase is finished or cancelled
if !r.Phase.IsFinished() {
return false, fmt.Sprintf("run is not finished, phase: %q", r.Phase)
}
// can restart from failed tasks only if there're some failed tasks
if r.Result == RunResultSuccess {
return false, fmt.Sprintf("run %q has success result, cannot restart from failed tasks", r.ID)
}
// can restart only if the successful tasks are fully archived
for _, rt := range r.RunTasks {
if rt.Status == RunTaskStatusSuccess {
if !rt.LogsFetchFinished() || !rt.ArchivesFetchFinished() {
return false, fmt.Sprintf("run %q task %q not fully archived", r.ID, rt.ID)
}
}
}
return true, ""
}
type RunTaskStatus string
const (