@@ -132,10 +132,21 @@ var _ = g.Describe("[builds][Slow] using build configuration runPolicy", func()
132
132
defer buildWatch .Stop ()
133
133
o .Expect (err ).NotTo (o .HaveOccurred ())
134
134
135
+ sawCompletion := false
135
136
for {
136
137
event := <- buildWatch .ResultChan ()
137
138
build := event .Object .(* buildapi.Build )
139
+ var lastCompletion time.Time
140
+ if build .Status .Phase == buildapi .BuildPhaseComplete {
141
+ lastCompletion = time .Now ()
142
+ o .Expect (build .Status .StartTimestamp ).ToNot (o .BeNil (), "completed builds should have a valid start time" )
143
+ o .Expect (build .Status .CompletionTimestamp ).ToNot (o .BeNil (), "completed builds should have a valid completion time" )
144
+ sawCompletion = true
145
+ }
138
146
if build .Status .Phase == buildapi .BuildPhaseRunning {
147
+ latency := lastCompletion .Sub (time .Now ())
148
+ o .Expect (latency ).To (o .BeNumerically ("<" , 10 * time .Second ), "next build should have started less than 10s after last completed build" )
149
+
139
150
// Ignore events from complete builds (if there are any) if we already
140
151
// verified the build.
141
152
if _ , exists := buildVerified [build .Name ]; exists {
@@ -166,6 +177,7 @@ var _ = g.Describe("[builds][Slow] using build configuration runPolicy", func()
166
177
break
167
178
}
168
179
}
180
+ o .Expect (sawCompletion ).To (o .BeTrue (), "should have seen at least one build complete" )
169
181
})
170
182
})
171
183
@@ -212,6 +224,78 @@ var _ = g.Describe("[builds][Slow] using build configuration runPolicy", func()
212
224
})
213
225
})
214
226
227
+ g .Describe ("build configuration with Serial build run policy handling failure" , func () {
228
+ g .It ("starts the next build immediately after one fails" , func () {
229
+ g .By ("starting multiple builds" )
230
+ bcName := "sample-serial-build-fail"
231
+
232
+ for i := 0 ; i < 3 ; i ++ {
233
+ _ , _ , err := exutil .StartBuild (oc , bcName )
234
+ o .Expect (err ).NotTo (o .HaveOccurred ())
235
+ }
236
+
237
+ buildWatch , err := oc .Client ().Builds (oc .Namespace ()).Watch (kapi.ListOptions {
238
+ LabelSelector : buildutil .BuildConfigSelector (bcName ),
239
+ })
240
+ defer buildWatch .Stop ()
241
+ o .Expect (err ).NotTo (o .HaveOccurred ())
242
+
243
+ var failTime , failTime2 time.Time
244
+ done , timestamps1 , timestamps2 , timestamps3 := false , false , false , false
245
+
246
+ for done == false {
247
+ select {
248
+ case event := <- buildWatch .ResultChan ():
249
+ build := event .Object .(* buildapi.Build )
250
+ if build .Status .Phase == buildapi .BuildPhaseFailed {
251
+ if build .Name == "sample-serial-build-fail-1" {
252
+ // this may not be set on the first build modified to failed event because
253
+ // the build gets marked failed by the build pod, but the timestamps get
254
+ // set by the buildpod controller.
255
+ if build .Status .CompletionTimestamp != nil {
256
+ o .Expect (build .Status .StartTimestamp ).ToNot (o .BeNil (), "failed builds should have a valid start time" )
257
+ o .Expect (build .Status .CompletionTimestamp ).ToNot (o .BeNil (), "failed builds should have a valid completion time" )
258
+ timestamps1 = true
259
+ }
260
+ failTime = time .Now ()
261
+ }
262
+ if build .Name == "sample-serial-build-fail-2" {
263
+ duration := time .Now ().Sub (failTime )
264
+ o .Expect (duration ).To (o .BeNumerically ("<" , 10 * time .Second ), "next build should have started less than 10s after failed build" )
265
+ if build .Status .CompletionTimestamp != nil {
266
+ o .Expect (build .Status .StartTimestamp ).ToNot (o .BeNil (), "failed builds should have a valid start time" )
267
+ o .Expect (build .Status .CompletionTimestamp ).ToNot (o .BeNil (), "failed builds should have a valid completion time" )
268
+ timestamps2 = true
269
+ }
270
+ failTime2 = time .Now ()
271
+ }
272
+ if build .Name == "sample-serial-build-fail-3" {
273
+ duration := time .Now ().Sub (failTime2 )
274
+ o .Expect (duration ).To (o .BeNumerically ("<" , 10 * time .Second ), "next build should have started less than 10s after failed build" )
275
+ if build .Status .CompletionTimestamp != nil {
276
+ o .Expect (build .Status .StartTimestamp ).ToNot (o .BeNil (), "failed builds should have a valid start time" )
277
+ o .Expect (build .Status .CompletionTimestamp ).ToNot (o .BeNil (), "failed builds should have a valid completion time" )
278
+ timestamps3 = true
279
+ }
280
+ }
281
+ }
282
+ // once we have all the expected timestamps, or we run out of time, we can bail.
283
+ if timestamps1 && timestamps2 && timestamps3 {
284
+ done = true
285
+ }
286
+ case <- time .After (2 * time .Minute ):
287
+ // we've waited as long as we dare, go see if we got all the timestamp data we expected.
288
+ // if we have the timestamp data, we also know that we checked the next build start latency.
289
+ done = true
290
+ }
291
+ }
292
+ o .Expect (timestamps1 ).To (o .BeTrue (), "failed builds should have start and completion timestamps set" )
293
+ o .Expect (timestamps2 ).To (o .BeTrue (), "failed builds should have start and completion timestamps set" )
294
+ o .Expect (timestamps3 ).To (o .BeTrue (), "failed builds should have start and completion timestamps set" )
295
+
296
+ })
297
+ })
298
+
215
299
g .Describe ("build configuration with SerialLatestOnly build run policy" , func () {
216
300
g .It ("runs the builds in serial order but cancel previous builds" , func () {
217
301
g .By ("starting multiple builds" )
0 commit comments