github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/notify/task_success_to_failure_handler.go (about) 1 package notify 2 3 import ( 4 "fmt" 5 6 "github.com/evergreen-ci/evergreen" 7 "github.com/evergreen-ci/evergreen/model" 8 "github.com/evergreen-ci/evergreen/model/task" 9 "github.com/evergreen-ci/evergreen/web" 10 "github.com/mongodb/grip" 11 ) 12 13 // Handler for notifications generated specifically when a task fails and the 14 // previous finished task succeeded. Implements NotificationHandler from 15 // notification_handler.go. 16 type TaskSuccessToFailureHandler struct { 17 TaskNotificationHandler 18 Name string 19 } 20 21 func (self *TaskSuccessToFailureHandler) GetNotifications(ae *web.App, key *NotificationKey) ([]Email, error) { 22 var emails []Email 23 tasks, err := getRecentlyFinishedTasks(key) 24 if err != nil { 25 return nil, err 26 } 27 28 preface := mciFailurePreface 29 if key.NotificationRequester == evergreen.PatchVersionRequester { 30 preface = patchFailurePreface 31 } 32 33 for _, currentTask := range tasks { 34 // Copy by value to make pointer safe 35 curr := currentTask 36 37 // get previous task for this project/build variant 38 previousTask, err := currentTask.PreviousCompletedTask(key.Project, []string{}) 39 if previousTask == nil { 40 grip.Debugf("No previous completed task found for %s in %s "+ 41 "with %s notification", currentTask.Id, key.Project, 42 key.NotificationName) 43 continue 44 } else if err != nil { 45 return nil, err 46 } 47 grip.Debugf("Previous completed task found for %s on %s %s notification is %s", 48 currentTask.Id, key.Project, key.NotificationName, previousTask.Id) 49 50 if previousTask.Status == evergreen.TaskSucceeded && 51 currentTask.Status == evergreen.TaskFailed { 52 53 // this is now a potential candidate but we must 54 // ensure that no other more recent build has 55 // triggered a notification for this event 56 history, err := model.FindNotificationRecord(previousTask.Id, key.NotificationName, 57 getType(key.NotificationName), key.Project, evergreen.RepotrackerVersionRequester) 58 59 // if there's an error log it and move on 60 if err != nil { 61 grip.Errorln("Error finding notification record:", err) 62 continue 63 } 64 65 // get the task's project to add to the notification subject line 66 branchName := UnknownProjectBranch 67 if projectRef, err := getProjectRef(currentTask.Project); err != nil { 68 grip.Warningf("Unable to find project ref for task '%s': %+v", currentTask.Id, err) 69 } else if projectRef != nil { 70 branchName = projectRef.Branch 71 } 72 73 // if no notification for this handler has been registered, register it 74 if history == nil { 75 grip.Debugf("Adding '%s' on %s %s notification", 76 currentTask.Id, key.NotificationName, key.Project) 77 notification := TriggeredTaskNotification{ 78 Current: &curr, 79 Previous: previousTask, 80 Key: *key, 81 Preface: fmt.Sprintf(preface, branchName), 82 Transition: transitionSubject, 83 } 84 85 email, err := self.TemplateNotification(ae, ¬ification) 86 if err != nil { 87 grip.Errorf("Error executing template for '%s: %s", 88 currentTask.Id, err) 89 continue 90 } 91 92 emails = append(emails, email) 93 94 err = model.InsertNotificationRecord(previousTask.Id, currentTask.Id, 95 key.NotificationName, getType(key.NotificationName), key.Project, 96 evergreen.RepotrackerVersionRequester) 97 if err != nil { 98 grip.Errorln("Error inserting notification record:", err) 99 continue 100 } 101 } else { 102 grip.Debugf("Skipping intermediate %s handler trigger on '%s'", 103 key.NotificationName, currentTask.Id) 104 } 105 } 106 } 107 108 return emails, nil 109 } 110 111 func (self *TaskSuccessToFailureHandler) TemplateNotification(ae *web.App, notification *TriggeredTaskNotification) (Email, error) { 112 changeInfo, err := self.GetChangeInfo(notification) 113 if err != nil { 114 return nil, err 115 } 116 return self.templateNotification(ae, notification, changeInfo) 117 } 118 119 func (self *TaskSuccessToFailureHandler) GetChangeInfo( 120 notification *TriggeredTaskNotification) ([]ChangeInfo, error) { 121 current := notification.Current 122 previous := current 123 if notification.Previous != nil { 124 previous = notification.Previous 125 } 126 127 intermediateTasks, err := current.FindIntermediateTasks(previous) 128 if err != nil { 129 return nil, err 130 } 131 allTasks := make([]task.Task, len(intermediateTasks)+1) 132 133 // include the current/previous task 134 allTasks[len(allTasks)-1] = *current 135 136 // copy any intermediate task(s) 137 if len(intermediateTasks) != 0 { 138 copy(allTasks[0:len(allTasks)-1], intermediateTasks) 139 } 140 return self.constructChangeInfo(allTasks, ¬ification.Key) 141 }