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, &notification)
    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, &notification.Key)
   141  }