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

     1  package build
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/evergreen-ci/evergreen"
     7  	"github.com/evergreen-ci/evergreen/apimodels"
     8  	"github.com/evergreen-ci/evergreen/db"
     9  	"gopkg.in/mgo.v2"
    10  	"gopkg.in/mgo.v2/bson"
    11  )
    12  
    13  // IdTimeLayout is used time time.Time.Format() to produce timestamps for our ids.
    14  const IdTimeLayout = "06_01_02_15_04_05"
    15  
    16  // TaskCache represents some duped information about tasks,
    17  // mainly for ui purposes.
    18  type TaskCache struct {
    19  	Id            string                  `bson:"id" json:"id"`
    20  	DisplayName   string                  `bson:"d" json:"display_name"`
    21  	Status        string                  `bson:"s" json:"status"`
    22  	StatusDetails apimodels.TaskEndDetail `bson:"ed" json:"task_end_details"`
    23  	StartTime     time.Time               `bson:"st" json:"start_time"`
    24  	TimeTaken     time.Duration           `bson:"tt" json:"time_taken"`
    25  	Activated     bool                    `bson:"a" json:"activated"`
    26  }
    27  
    28  // Build represents a set of tasks on one variant of a Project
    29  // 	e.g. one build might be "Ubuntu with Python 2.4" and
    30  //  another might be "OSX with Python 3.0", etc.
    31  type Build struct {
    32  	Id                  string        `bson:"_id" json:"_id"`
    33  	CreateTime          time.Time     `bson:"create_time" json:"create_time,omitempty"`
    34  	StartTime           time.Time     `bson:"start_time" json:"start_time,omitempty"`
    35  	FinishTime          time.Time     `bson:"finish_time" json:"finish_time,omitempty"`
    36  	PushTime            time.Time     `bson:"push_time" json:"push_time,omitempty"`
    37  	Version             string        `bson:"version" json:"version,omitempty"`
    38  	Project             string        `bson:"branch" json:"branch,omitempty"`
    39  	Revision            string        `bson:"gitspec" json:"gitspec,omitempty"`
    40  	BuildVariant        string        `bson:"build_variant" json:"build_variant,omitempty"`
    41  	BuildNumber         string        `bson:"build_number" json:"build_number,omitempty"`
    42  	Status              string        `bson:"status" json:"status,omitempty"`
    43  	Activated           bool          `bson:"activated" json:"activated,omitempty"`
    44  	ActivatedBy         string        `bson:"activated_by" json:"activated_by,omitempty"`
    45  	ActivatedTime       time.Time     `bson:"activated_time" json:"activated_time,omitempty"`
    46  	RevisionOrderNumber int           `bson:"order,omitempty" json:"order,omitempty"`
    47  	Tasks               []TaskCache   `bson:"tasks" json:"tasks,omitempty"`
    48  	TimeTaken           time.Duration `bson:"time_taken" json:"time_taken,omitempty"`
    49  	DisplayName         string        `bson:"display_name" json:"display_name,omitempty"`
    50  	PredictedMakespan   time.Duration `bson:"predicted_makespan" json:"predicted_makespan,omitempty"`
    51  	ActualMakespan      time.Duration `bson:"actual_makespan" json:"actual_makespan,omitempty"`
    52  
    53  	// build requester - this is used to help tell the
    54  	// reason this build was created. e.g. it could be
    55  	// because the repotracker requested it (via tracking the
    56  	// repository) or it was triggered by a developer
    57  	// patch request
    58  	Requester string `bson:"r" json:"r,omitempty"`
    59  }
    60  
    61  // Returns whether or not the build has finished, based on its status.
    62  func (b *Build) IsFinished() bool {
    63  	return b.Status == evergreen.BuildFailed ||
    64  		b.Status == evergreen.BuildSucceeded
    65  }
    66  
    67  // Find
    68  
    69  // FindBuildOnBaseCommit returns the build that a patch build is based on.
    70  func (b *Build) FindBuildOnBaseCommit() (*Build, error) {
    71  	return FindOne(ByRevisionAndVariant(b.Revision, b.BuildVariant))
    72  }
    73  
    74  // Find all builds on the same project + variant + requester between
    75  // the current b and the specified previous build.
    76  func (b *Build) FindIntermediateBuilds(previous *Build) ([]Build, error) {
    77  	return Find(ByBetweenBuilds(b, previous))
    78  }
    79  
    80  // Find the most recent activated build with the same variant +
    81  // requester + project as the current build.
    82  func (b *Build) PreviousActivated(project string, requester string) (*Build, error) {
    83  	return FindOne(ByRecentlyActivatedForProjectAndVariant(
    84  		b.RevisionOrderNumber, project, b.BuildVariant, requester))
    85  }
    86  
    87  // Find the most recent b on with the same build variant + requester +
    88  // project as the current build, with any of the specified statuses.
    89  func (b *Build) PreviousSuccessful() (*Build, error) {
    90  	return FindOne(ByRecentlySuccessfulForProjectAndVariant(
    91  		b.RevisionOrderNumber, b.Project, b.BuildVariant))
    92  }
    93  
    94  // UpdateActivation updates one build with the given id
    95  // to the given activation setting.
    96  func UpdateActivation(buildId string, active bool, caller string) error {
    97  	var err error
    98  	if !active && (evergreen.IsSystemActivator(caller)) {
    99  		_, err = UpdateAllBuilds(
   100  			bson.M{IdKey: buildId,
   101  				ActivatedByKey: caller,
   102  			},
   103  			bson.M{
   104  				"$set": bson.M{
   105  					ActivatedKey:     active,
   106  					ActivatedTimeKey: time.Now(),
   107  					ActivatedByKey:   caller,
   108  				},
   109  			},
   110  		)
   111  	} else {
   112  		_, err = UpdateAllBuilds(
   113  			bson.M{IdKey: buildId},
   114  			bson.M{
   115  				"$set": bson.M{
   116  					ActivatedKey:     active,
   117  					ActivatedTimeKey: time.Now(),
   118  					ActivatedByKey:   caller,
   119  				},
   120  			},
   121  		)
   122  	}
   123  	return err
   124  
   125  }
   126  
   127  // UpdateStatus sets the build status to the given string.
   128  func (b *Build) UpdateStatus(status string) error {
   129  	b.Status = status
   130  	return UpdateOne(
   131  		bson.M{IdKey: b.Id},
   132  		bson.M{"$set": bson.M{StatusKey: status}},
   133  	)
   134  }
   135  
   136  // UpdateMakespans sets the builds predicted and actual makespans to given durations
   137  func (b *Build) UpdateMakespans(predictedMakespan, actualMakespan time.Duration) error {
   138  	b.PredictedMakespan = predictedMakespan
   139  	b.ActualMakespan = actualMakespan
   140  
   141  	return UpdateOne(
   142  		bson.M{IdKey: b.Id},
   143  		bson.M{"$set": bson.M{PredictedMakespanKey: predictedMakespan, ActualMakespanKey: actualMakespan}},
   144  	)
   145  }
   146  
   147  // TryMarkBuildStarted attempts to mark a b as started if it
   148  // isn't already marked as such
   149  func TryMarkStarted(buildId string, startTime time.Time) error {
   150  	selector := bson.M{
   151  		IdKey:     buildId,
   152  		StatusKey: evergreen.BuildCreated,
   153  	}
   154  	update := bson.M{"$set": bson.M{
   155  		StatusKey:    evergreen.BuildStarted,
   156  		StartTimeKey: startTime,
   157  	}}
   158  	err := UpdateOne(selector, update)
   159  	if err == mgo.ErrNotFound {
   160  		return nil
   161  	}
   162  	return err
   163  }
   164  
   165  // MarkFinished sets the build to finished status in the database (this does
   166  // not update task or version data).
   167  func (b *Build) MarkFinished(status string, finishTime time.Time) error {
   168  	b.Status = status
   169  	b.FinishTime = finishTime
   170  	b.TimeTaken = finishTime.Sub(b.StartTime)
   171  	return UpdateOne(
   172  		bson.M{IdKey: b.Id},
   173  		bson.M{
   174  			"$set": bson.M{
   175  				StatusKey:     status,
   176  				FinishTimeKey: finishTime,
   177  				TimeTakenKey:  b.TimeTaken,
   178  			},
   179  		},
   180  	)
   181  }
   182  
   183  // Create
   184  
   185  // Insert writes the b to the db.
   186  func (b *Build) Insert() error {
   187  	return db.Insert(Collection, b)
   188  }