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 }