github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/notify/build_handler.go (about)

     1  package notify
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/evergreen-ci/evergreen/model/build"
     8  	"github.com/evergreen-ci/evergreen/model/version"
     9  	"github.com/evergreen-ci/evergreen/web"
    10  	"github.com/mongodb/grip"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // "Base class" for all build_*_handler.go structs. Contains code that's common
    15  // to all the build_*_handlers. Note that this struct does NOT implement
    16  // NotificationHandler
    17  type BuildNotificationHandler struct {
    18  	Type string
    19  }
    20  
    21  type BuildNotificationForTemplate struct {
    22  	Notification *TriggeredBuildNotification
    23  	FailedTasks  []build.TaskCache
    24  	Subject      string
    25  }
    26  
    27  // convenience wrapper about everything we want to know about a build
    28  // notification before it goes off for templating.
    29  type TriggeredBuildNotification struct {
    30  	Current    *build.Build
    31  	Previous   *build.Build
    32  	Info       []ChangeInfo
    33  	Key        NotificationKey
    34  	Preface    string
    35  	Transition string
    36  }
    37  
    38  func (self *BuildNotificationHandler) getRecentlyFinishedBuildsWithStatus(key *NotificationKey,
    39  	status string, preface string, transition string) ([]TriggeredBuildNotification, error) {
    40  	buildNotifications := []TriggeredBuildNotification{}
    41  	builds, err := getRecentlyFinishedBuilds(key)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	for _, currentBuild := range builds {
    47  		// Copy by value to make pointer safe
    48  		curr := currentBuild
    49  		if status == "" || curr.Status == status {
    50  			grip.Debugf("Adding '%s' on %s %s notification", curr.Id, key.Project,
    51  				key.NotificationName)
    52  
    53  			// get the build's project to add to the notification subject line
    54  			branchName := UnknownProjectBranch
    55  			if projectRef, err := getProjectRef(curr.Project); err != nil {
    56  				grip.Warningf("Unable to find project ref for build '%s': %+v",
    57  					curr.Id, err)
    58  			} else if projectRef != nil {
    59  				branchName = projectRef.Branch
    60  			}
    61  
    62  			notification := TriggeredBuildNotification{
    63  				Current:    &curr,
    64  				Previous:   nil,
    65  				Key:        *key,
    66  				Preface:    fmt.Sprintf(preface, branchName),
    67  				Transition: transition,
    68  			}
    69  			buildNotifications = append(buildNotifications, notification)
    70  		}
    71  	}
    72  	return buildNotifications, nil
    73  }
    74  
    75  func (self *BuildNotificationHandler) templateNotification(ae *web.App,
    76  	notification *TriggeredBuildNotification, changeInfo []ChangeInfo) (email Email, err error) {
    77  	current := notification.Current
    78  
    79  	// add change information to notification
    80  	notification.Info = changeInfo
    81  
    82  	// get the failed tasks (if any)
    83  	failedTasks := getFailedTasks(current, notification.Key.NotificationName)
    84  
    85  	subject := fmt.Sprintf("%v Build #%v %v on %v", notification.Preface,
    86  		current.BuildNumber, notification.Transition, current.DisplayName)
    87  
    88  	buildNotification := BuildNotificationForTemplate{notification, failedTasks, subject}
    89  
    90  	body, err := TemplateEmailBody(ae, "build_notification.html", buildNotification)
    91  	if err != nil {
    92  		return
    93  	}
    94  
    95  	// for notifications requiring comparisons
    96  	// include what it was compared against here
    97  	if notification.Previous != nil {
    98  		previous := notification.Previous
    99  		body += fmt.Sprintf(`(compared with this <a href="%v/build/%v">previous build</a>)`,
   100  			ae.TemplateFuncs["Global"].(func(string) interface{})("UIRoot"), // FIXME
   101  			previous.Id)
   102  	}
   103  
   104  	email = &BuildEmail{EmailBase{body, subject, notification.Info}, *notification}
   105  	return
   106  }
   107  
   108  func (self *BuildNotificationHandler) constructChangeInfo(allBuilds []build.Build,
   109  	key *NotificationKey) ([]ChangeInfo, error) {
   110  	changeInfoSlice := make([]ChangeInfo, 0)
   111  
   112  	for _, build := range allBuilds {
   113  		// add blamelist information for each build
   114  		v, err := version.FindOne(version.ById(build.Version))
   115  		if err != nil {
   116  			return changeInfoSlice, err
   117  		}
   118  
   119  		if v == nil {
   120  			return changeInfoSlice, errors.Errorf(
   121  				"No version found for build %s with version id %s",
   122  				build.Id, build.Version)
   123  		}
   124  		changeInfo := constructChangeInfo(v, key)
   125  		changeInfo.Pushtime = build.PushTime.Format(time.RFC850)
   126  		changeInfoSlice = append(changeInfoSlice, *changeInfo)
   127  	}
   128  	return changeInfoSlice, nil
   129  }