github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/model/build/db.go (about) 1 package build 2 3 import ( 4 "time" 5 6 "github.com/evergreen-ci/evergreen" 7 "github.com/evergreen-ci/evergreen/db" 8 "github.com/evergreen-ci/evergreen/db/bsonutil" 9 "gopkg.in/mgo.v2" 10 "gopkg.in/mgo.v2/bson" 11 ) 12 13 // The MongoDB collection for build documents. 14 const Collection = "builds" 15 16 var ( 17 // bson fields for the build struct 18 IdKey = bsonutil.MustHaveTag(Build{}, "Id") 19 CreateTimeKey = bsonutil.MustHaveTag(Build{}, "CreateTime") 20 StartTimeKey = bsonutil.MustHaveTag(Build{}, "StartTime") 21 FinishTimeKey = bsonutil.MustHaveTag(Build{}, "FinishTime") 22 PushTimeKey = bsonutil.MustHaveTag(Build{}, "PushTime") 23 VersionKey = bsonutil.MustHaveTag(Build{}, "Version") 24 ProjectKey = bsonutil.MustHaveTag(Build{}, "Project") 25 RevisionKey = bsonutil.MustHaveTag(Build{}, "Revision") 26 BuildVariantKey = bsonutil.MustHaveTag(Build{}, "BuildVariant") 27 BuildNumberKey = bsonutil.MustHaveTag(Build{}, "BuildNumber") 28 StatusKey = bsonutil.MustHaveTag(Build{}, "Status") 29 ActivatedKey = bsonutil.MustHaveTag(Build{}, "Activated") 30 ActivatedByKey = bsonutil.MustHaveTag(Build{}, "ActivatedBy") 31 ActivatedTimeKey = bsonutil.MustHaveTag(Build{}, "ActivatedTime") 32 RevisionOrderNumberKey = bsonutil.MustHaveTag(Build{}, "RevisionOrderNumber") 33 TasksKey = bsonutil.MustHaveTag(Build{}, "Tasks") 34 TimeTakenKey = bsonutil.MustHaveTag(Build{}, "TimeTaken") 35 DisplayNameKey = bsonutil.MustHaveTag(Build{}, "DisplayName") 36 RequesterKey = bsonutil.MustHaveTag(Build{}, "Requester") 37 PredictedMakespanKey = bsonutil.MustHaveTag(Build{}, "PredictedMakespan") 38 ActualMakespanKey = bsonutil.MustHaveTag(Build{}, "ActualMakespan") 39 40 // bson fields for the task caches 41 TaskCacheIdKey = bsonutil.MustHaveTag(TaskCache{}, "Id") 42 TaskCacheDisplayNameKey = bsonutil.MustHaveTag(TaskCache{}, "DisplayName") 43 TaskCacheStatusKey = bsonutil.MustHaveTag(TaskCache{}, "Status") 44 TaskCacheStatusDetailsKey = bsonutil.MustHaveTag(TaskCache{}, "StatusDetails") 45 TaskCacheStartTimeKey = bsonutil.MustHaveTag(TaskCache{}, "StartTime") 46 TaskCacheTimeTakenKey = bsonutil.MustHaveTag(TaskCache{}, "TimeTaken") 47 TaskCacheActivatedKey = bsonutil.MustHaveTag(TaskCache{}, "Activated") 48 ) 49 50 // Queries 51 52 // All returns all builds. 53 var All = db.Query(nil) 54 55 // ById creates a query that finds a build by its _id. 56 func ById(id string) db.Q { 57 return db.Query(bson.D{{IdKey, id}}) 58 } 59 60 // ByIds creates a query that finds all builds with the given ids. 61 func ByIds(ids []string) db.Q { 62 return db.Query(bson.D{{IdKey, bson.D{{"$in", ids}}}}) 63 } 64 65 // ByVersion creates a query that returns all builds for a given version. 66 func ByVersion(version string) db.Q { 67 return db.Query(bson.D{{VersionKey, version}}) 68 } 69 70 // ByVersions creates a query that finds all builds with the given version ids. 71 func ByVersions(vIds []string) db.Q { 72 return db.Query(bson.D{{VersionKey, bson.D{{"$in", vIds}}}}) 73 } 74 75 // ByVariant creates a query that finds all builds for a given variant. 76 func ByVariant(bv string) db.Q { 77 return db.Query(bson.D{{BuildVariantKey, bv}}) 78 } 79 80 // ByProject creates a query that finds all builds for a given project id. 81 func ByProject(proj string) db.Q { 82 return db.Query(bson.D{{ProjectKey, proj}}) 83 } 84 85 // ByProjectAndVariant creates a query that finds all completed builds for a given project 86 // and variant, while also specifying a requester 87 func ByProjectAndVariant(project, variant, requester string) db.Q { 88 return db.Query(bson.M{ 89 ProjectKey: project, 90 StatusKey: bson.M{"$in": evergreen.CompletedStatuses}, 91 BuildVariantKey: variant, 92 RequesterKey: requester, 93 }) 94 } 95 96 // ByRevisionAndVariant creates a query that returns the non-patch build for 97 // a revision + buildvariant combionation. 98 func ByRevisionAndVariant(revision, variant string) db.Q { 99 return db.Query(bson.M{ 100 RevisionKey: revision, 101 RequesterKey: evergreen.RepotrackerVersionRequester, 102 BuildVariantKey: variant, 103 }) 104 } 105 106 // ByRevision creates a query that returns all builds for a revision. 107 func ByRevision(revision string) db.Q { 108 return db.Query(bson.M{ 109 RevisionKey: revision, 110 RequesterKey: evergreen.RepotrackerVersionRequester, 111 }) 112 } 113 114 // ByRecentlyActivatedForProjectAndVariant builds a query that returns all 115 // builds before a given revision that were activated for a project + variant. 116 // Builds are sorted from most to least recent. 117 func ByRecentlyActivatedForProjectAndVariant(revision int, project, variant, requester string) db.Q { 118 return db.Query(bson.M{ 119 RevisionOrderNumberKey: bson.M{"$lt": revision}, 120 ActivatedKey: true, 121 BuildVariantKey: variant, 122 ProjectKey: project, 123 RequesterKey: requester, 124 }).Sort([]string{"-" + RevisionOrderNumberKey}) 125 } 126 127 // ByRecentlySuccessfulForProjectAndVariant builds a query that returns all 128 // builds before a given revision that were successful for a project + variant. 129 // Builds are sorted from most to least recent. 130 func ByRecentlySuccessfulForProjectAndVariant(revision int, project, variant string) db.Q { 131 return db.Query(bson.M{ 132 RevisionOrderNumberKey: bson.M{"$lt": revision}, 133 BuildVariantKey: variant, 134 ProjectKey: project, 135 StatusKey: evergreen.BuildSucceeded, 136 RequesterKey: evergreen.RepotrackerVersionRequester, 137 }).Sort([]string{"-" + RevisionOrderNumberKey}) 138 } 139 140 // ByFinishedAfter creates a query that returns all builds for a project/requester 141 // that were finished after the given time. 142 func ByFinishedAfter(finishTime time.Time, project string, requester string) db.Q { 143 query := bson.M{ 144 TimeTakenKey: bson.M{"$ne": time.Duration(0)}, 145 FinishTimeKey: bson.M{"$gt": finishTime}, 146 RequesterKey: requester, 147 } 148 // filter by project, optionally 149 if project != "" { 150 query[ProjectKey] = project 151 } 152 return db.Query(query) 153 } 154 155 // ByBetweenBuilds returns all builds that happened between 156 // the current and previous build. 157 func ByBetweenBuilds(current, previous *Build) db.Q { 158 intermediateRevisions := bson.M{ 159 "$lt": current.RevisionOrderNumber, 160 "$gt": previous.RevisionOrderNumber, 161 } 162 q := db.Query(bson.M{ 163 BuildVariantKey: current.BuildVariant, 164 RequesterKey: current.Requester, 165 RevisionOrderNumberKey: intermediateRevisions, 166 ProjectKey: current.Project, 167 }).Sort([]string{RevisionOrderNumberKey}) 168 return q 169 } 170 171 // ByBeforeRevision builds a query that returns all builds 172 // that happened before the given revision for the project/variant. 173 // Results are sorted by revision order, descending. 174 func ByBeforeRevision(project, buildVariant string, revision int) db.Q { 175 return db.Query(bson.M{ 176 ProjectKey: project, 177 BuildVariantKey: buildVariant, 178 RequesterKey: evergreen.RepotrackerVersionRequester, 179 RevisionOrderNumberKey: bson.M{"$lt": revision}, 180 }).Sort([]string{"-" + RevisionOrderNumberKey}) 181 } 182 183 // ByAfterRevision builds a query that returns all builds 184 // that happened at or after the given revision for the project/variant. 185 // Results are sorted by revision order, ascending. 186 func ByAfterRevision(project, buildVariant string, revision int) db.Q { 187 return db.Query(bson.M{ 188 ProjectKey: project, 189 BuildVariantKey: buildVariant, 190 RequesterKey: evergreen.RepotrackerVersionRequester, 191 RevisionOrderNumberKey: bson.M{"$gte": revision}, 192 }).Sort([]string{RevisionOrderNumberKey}) 193 } 194 195 // ByRecentlyFinished builds a query that returns all builds for a given project 196 // that are versions (not patches), that have finished. 197 func ByRecentlyFinished(limit int) db.Q { 198 return db.Query(bson.M{ 199 RequesterKey: evergreen.RepotrackerVersionRequester, 200 StatusKey: bson.M{"$in": evergreen.CompletedStatuses}, 201 }).Sort([]string{RevisionOrderNumberKey}).Limit(limit) 202 } 203 204 // DB Boilerplate 205 206 // FindOne returns one build that satisfies the query. 207 func FindOne(query db.Q) (*Build, error) { 208 build := &Build{} 209 err := db.FindOneQ(Collection, query, build) 210 if err == mgo.ErrNotFound { 211 return nil, nil 212 } 213 return build, err 214 } 215 216 // Find returns all builds that satisfy the query. 217 func Find(query db.Q) ([]Build, error) { 218 builds := []Build{} 219 err := db.FindAllQ(Collection, query, &builds) 220 if err == mgo.ErrNotFound { 221 return nil, nil 222 } 223 return builds, err 224 } 225 226 // UpdateOne updates one build. 227 func UpdateOne(query interface{}, update interface{}) error { 228 return db.Update( 229 Collection, 230 query, 231 update, 232 ) 233 } 234 235 func UpdateAllBuilds(query interface{}, update interface{}) (*mgo.ChangeInfo, error) { 236 return db.UpdateAll( 237 Collection, 238 query, 239 update, 240 ) 241 } 242 243 // Remove deletes the build of the given id from the database 244 func Remove(id string) error { 245 return db.Remove( 246 Collection, 247 bson.M{IdKey: id}, 248 ) 249 }