// TryResetTask resets a task func TryResetTask(taskId, user, origin string, p *Project, detail *apimodels.TaskEndDetail) (err error) { t, err := task.FindOne(task.ById(taskId)) if err != nil { return err } // if we've reached the max number of executions for this task, mark it as finished and failed if t.Execution >= evergreen.MaxTaskExecution { // restarting from the UI bypasses the restart cap message := fmt.Sprintf("Task '%v' reached max execution (%v):", t.Id, evergreen.MaxTaskExecution) if origin == evergreen.UIPackage { evergreen.Logger.Logf(slogger.DEBUG, "%v allowing exception for %v", message, user) } else { evergreen.Logger.Logf(slogger.DEBUG, "%v marking as failed", message) if detail != nil { return MarkEnd(t.Id, origin, time.Now(), detail, p, false) } else { panic(fmt.Sprintf("TryResetTask called with nil TaskEndDetail by %v", origin)) } } } // only allow re-execution for failed or successful tasks if !task.IsFinished(*t) { // this is to disallow terminating running tasks via the UI if origin == evergreen.UIPackage { evergreen.Logger.Logf(slogger.DEBUG, "Unsatisfiable '%v' reset request on '%v' (status: '%v')", user, t.Id, t.Status) return fmt.Errorf("Task '%v' is currently '%v' - can not reset task in this status", t.Id, t.Status) } } if detail != nil { if err = t.MarkEnd(origin, time.Now(), detail); err != nil { return fmt.Errorf("Error marking task as ended: %v", err) } } if err = resetTask(t.Id); err == nil { if origin == evergreen.UIPackage { event.LogTaskRestarted(t.Id, user) } else { event.LogTaskRestarted(t.Id, origin) } } return err }
// ActivatePreviousTask will set the Active state for the first task with a // revision order number less than the current task's revision order number. func ActivatePreviousTask(taskId, caller string) error { // find the task first t, err := task.FindOne(task.ById(taskId)) if err != nil { return err } // find previous task limiting to just the last one prevTask, err := task.FindOne(task.ByBeforeRevision(t.RevisionOrderNumber, t.BuildVariant, t.DisplayName, t.Project, t.Requester)) if err != nil { return fmt.Errorf("Error finding previous task: %v:", err.Error()) } // if this is the first time we're running the task, or it's finished or it is blacklisted if prevTask == nil || task.IsFinished(*prevTask) || prevTask.Priority < 0 { return nil } // activate the task if err = SetActiveState(prevTask.Id, caller, true); err != nil { return err } return nil }
// UpdateBuildStatusForTask finds all the builds for a task and updates the // status of the build based on the task's status. func UpdateBuildAndVersionStatusForTask(taskId string) error { // retrieve the task by the task id t, err := task.FindOne(task.ById(taskId)) if err != nil { return err } finishTime := time.Now() // get all of the tasks in the same build b, err := build.FindOne(build.ById(t.BuildId)) if err != nil { return err } buildTasks, err := task.Find(task.ByBuildId(b.Id)) if err != nil { return err } pushTaskExists := false for _, t := range buildTasks { if t.DisplayName == evergreen.PushStage { pushTaskExists = true } } failedTask := false pushSuccess := true pushCompleted := false finishedTasks := 0 // update the build's status based on tasks for this build for _, t := range buildTasks { if task.IsFinished(t) { finishedTasks += 1 // if it was a compile task, mark the build status accordingly if t.DisplayName == evergreen.CompileStage { if t.Status != evergreen.TaskSucceeded { failedTask = true finishedTasks = -1 err = b.MarkFinished(evergreen.BuildFailed, finishTime) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking build as finished: %v", err) return err } break } } else if t.DisplayName == evergreen.PushStage { pushCompleted = true // if it's a finished push, check if it was successful if t.Status != evergreen.TaskSucceeded { err = b.UpdateStatus(evergreen.BuildFailed) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error updating build status: %v", err) return err } pushSuccess = false } } else { // update the build's status when a test task isn't successful if t.Status != evergreen.TaskSucceeded { err = b.UpdateStatus(evergreen.BuildFailed) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error updating build status: %v", err) return err } failedTask = true } } } } // if there are no failed tasks, mark the build as started if !failedTask { err = b.UpdateStatus(evergreen.BuildStarted) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error updating build status: %v", err) return err } } // if a compile task didn't fail, then the // build is only finished when both the compile // and test tasks are completed or when those are // both completed in addition to a push (a push // does not occur if there's a failed task) if finishedTasks >= len(buildTasks)-1 { if !failedTask { if pushTaskExists { // this build has a push task associated with it. if pushCompleted && pushSuccess { // the push succeeded, so mark the build as succeeded. err = b.MarkFinished(evergreen.BuildSucceeded, finishTime) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking build as finished: %v", err) return err } } else if pushCompleted && !pushSuccess { // the push failed, mark build failed. err = b.MarkFinished(evergreen.BuildFailed, finishTime) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking build as finished: %v", err) return err } } else { //This build does have a "push" task, but it hasn't finished yet //So do nothing, since we don't know the status yet. } if err = MarkVersionCompleted(b.Version, finishTime); err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking version as finished: %v", err) return err } } else { // this build has no push task. so go ahead and mark it success/failure. if err = b.MarkFinished(evergreen.BuildSucceeded, finishTime); err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking build as finished: %v", err) return err } if b.Requester == evergreen.PatchVersionRequester { if err = TryMarkPatchBuildFinished(b, finishTime); err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking patch as finished: %v", err) return err } } if err = MarkVersionCompleted(b.Version, finishTime); err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking version as finished: %v", err) return err } } } else { // some task failed if err = b.MarkFinished(evergreen.BuildFailed, finishTime); err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking build as finished: %v", err) return err } if b.Requester == evergreen.PatchVersionRequester { if err = TryMarkPatchBuildFinished(b, finishTime); err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking patch as finished: %v", err) return err } } if err = MarkVersionCompleted(b.Version, finishTime); err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error marking version as finished: %v", err) return err } } // update the build's makespan information if the task has finished err = updateMakespans(b) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error updating makespan information: %v", err) return err } } // this is helpful for when we restart a compile task if finishedTasks == 0 { err = b.UpdateStatus(evergreen.BuildCreated) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error updating build status: %v", err) return err } } return nil }