@@ -155,41 +155,139 @@ func runOnce(
155
155
// Fetch builds for Go repo commits.
156
156
for _ , c := range dashResp .Commits {
157
157
repo , commit := "go" , c .Commit
158
- buildList , err := fetchBuildsForCommit (ctx , buildsCl , repo , commit , "id" , "builder.builder" , "status" , "input.gitiles_commit" , "input.properties" )
158
+ buildList , err := fetchBuildsForCommit (ctx , buildsCl , repo , commit , "id" , "builder.builder" , "status" , "input.gitiles_commit" )
159
159
if err != nil {
160
160
return nil , nil , err
161
161
}
162
162
total += len (buildList )
163
163
for _ , b := range buildList {
164
+ if c := b .GetInput ().GetGitilesCommit (); c .Project != repo {
165
+ return nil , nil , fmt .Errorf (`internal error: in Go repo commit loop, c.Project is %q but expected it to be "go"` , c .Project )
166
+ } else if c .Id != commit {
167
+ return nil , nil , fmt .Errorf ("internal error: in Go repo commit loop, c.Id is %q but expected it to be %q" , c .Id , commit )
168
+ }
169
+ switch b .GetStatus () {
170
+ case bbpb .Status_STARTED , bbpb .Status_SUCCESS , bbpb .Status_FAILURE , bbpb .Status_INFRA_FAILURE :
171
+ default :
172
+ // Skip builds with other statuses at this time.
173
+ // Such builds can be included when the callers deem it useful.
174
+ continue
175
+ }
164
176
builder , ok := builders [b .GetBuilder ().GetBuilder ()]
165
177
if ! ok {
166
178
// A build that isn't associated with a current builder we're tracking.
167
179
// It might've been removed, or has a known issue. Skip this build too.
168
180
continue
181
+ } else if builder .Repo != "go" {
182
+ // Not a Go repo build. Those are handled below, so out of scope here.
183
+ continue
169
184
}
170
- c := b .GetInput ().GetGitilesCommit ()
171
- if c .Project != builder .Repo {
172
- // A build that was triggered from a different project than the builder is for.
173
- // If the build hasn't completed, the exact repo commit hasn't been chosen yet.
174
- // For now such builds are not represented in the simple model of this package,
175
- // so skip it.
185
+ if builds [repo ] == nil {
186
+ builds [repo ] = make (map [string ]map [string ]Build )
187
+ }
188
+ if builds [repo ][commit ] == nil {
189
+ builds [repo ][commit ] = make (map [string ]Build )
190
+ }
191
+ builds [repo ][commit ][b .GetBuilder ().GetBuilder ()] = Build {
192
+ ID : b .GetId (),
193
+ BuilderName : b .GetBuilder ().GetBuilder (),
194
+ Status : b .GetStatus (),
195
+ }
196
+ used ++
197
+ }
198
+ }
199
+ // Fetch builds for the single latest commit of each golang.org/x repo,
200
+ // ones that were invoked from the Go repository side.
201
+ var repoHeads = make (map [string ]string ) // A repo → head commit ID map.
202
+ for _ , rh := range dashResp .RepoHeads {
203
+ repoHeads [rh .GerritProject ] = rh .Commit .Commit
204
+ }
205
+ for _ , r := range dashResp .Releases {
206
+ repo , commit := "go" , r .GetBranchCommit ()
207
+ buildList , err := fetchBuildsForCommit (ctx , buildsCl , repo , commit , "id" , "builder.builder" , "status" , "input.gitiles_commit" , "output.properties" )
208
+ if err != nil {
209
+ return nil , nil , err
210
+ }
211
+ total += len (buildList )
212
+ for _ , b := range buildList {
213
+ if c := b .GetInput ().GetGitilesCommit (); c .Project != "go" {
214
+ return nil , nil , fmt .Errorf (`internal error: in x/ repo loop for builds invoked from the Go repo side, c.Project is %q but expected it to be "go"` , c .Project )
215
+ }
216
+ switch b .GetStatus () {
217
+ case bbpb .Status_STARTED , bbpb .Status_SUCCESS , bbpb .Status_FAILURE , bbpb .Status_INFRA_FAILURE :
218
+ default :
219
+ // Skip builds with other statuses at this time.
220
+ // Such builds can be included when the callers deem it useful.
221
+ continue
222
+ }
223
+ builder , ok := builders [b .GetBuilder ().GetBuilder ()]
224
+ if ! ok {
225
+ // A build that isn't associated with a current builder we're tracking.
226
+ // It might've been removed, or has a known issue. Skip this build too.
227
+ continue
228
+ } else if builder .Repo == "go" {
229
+ // A Go repo build. Those were handled above, so out of scope here.
230
+ continue
231
+ }
232
+ var buildOutputProps struct {
233
+ Sources []struct {
234
+ GitilesCommit struct {
235
+ Project string
236
+ Ref string
237
+ Id string
238
+ }
239
+ }
240
+ }
241
+ if data , err := b .GetOutput ().GetProperties ().MarshalJSON (); err != nil {
242
+ return nil , nil , fmt .Errorf ("marshaling build output properties to JSON failed: %v" , err )
243
+ } else if err := json .Unmarshal (data , & buildOutputProps ); err != nil {
244
+ return nil , nil , err
245
+ }
246
+ repoCommit , ok := func () (string , bool ) {
247
+ for _ , s := range buildOutputProps .Sources {
248
+ if c := s .GitilesCommit ; c .Project == builder .Repo {
249
+ if c .Ref != "refs/heads/master" {
250
+ panic (fmt .Errorf (`internal error: in x/ repo loop for project %s, c.Ref != "refs/heads/master"` , c .Project ))
251
+ }
252
+ return c .Id , true
253
+ }
254
+ }
255
+ return "" , false
256
+ }()
257
+ if ! ok && b .GetStatus () == bbpb .Status_STARTED {
258
+ // A started build that hasn't selected the x/ repo commit yet.
259
+ // As an approximation, assume it'll pick the latest x/ repo head commit.
260
+ repoCommit = repoHeads [builder .Repo ]
261
+ } else if ! ok {
262
+ // Repo commit not found in output properties, and it's not a started build.
263
+ // As an example, this can happen if a build failed due to an infra failure
264
+ // early on, before selecting the x/ repo commit. Skip such builds.
265
+ continue
266
+ }
267
+ if repoCommit != repoHeads [builder .Repo ] {
268
+ // Skip builds that are not for the x/ repository's head commit.
176
269
continue
177
270
}
178
271
if builds [builder .Repo ] == nil {
179
272
builds [builder .Repo ] = make (map [string ]map [string ]Build )
180
273
}
181
- if builds [builder.Repo ][c. Id ] == nil {
182
- builds [builder.Repo ][c. Id ] = make (map [string ]Build )
274
+ if builds [builder.Repo ][repoCommit ] == nil {
275
+ builds [builder.Repo ][repoCommit ] = make (map [string ]Build )
183
276
}
184
- builds [builder.Repo ][c. Id ][b .GetBuilder ().GetBuilder ()] = Build {
277
+ builds [builder.Repo ][repoCommit ][b .GetBuilder ().GetBuilder ()] = Build {
185
278
ID : b .GetId (),
186
279
BuilderName : b .GetBuilder ().GetBuilder (),
187
280
Status : b .GetStatus (),
188
281
}
189
282
used ++
190
283
}
191
284
}
192
- // Fetch builds for a single commit in each golang.org/x repo.
285
+ // Fetch builds for the single latest commit of each golang.org/x repo,
286
+ // ones that were invoked from the x/ repository side.
287
+ var goHeads = make (map [string ]string ) // A branch → head commit ID map.
288
+ for _ , r := range dashResp .Releases {
289
+ goHeads [r .GetBranchName ()] = r .GetBranchCommit ()
290
+ }
193
291
for _ , rh := range dashResp .RepoHeads {
194
292
if rh .GerritProject == "go" {
195
293
continue
@@ -200,25 +298,71 @@ func runOnce(
200
298
continue
201
299
}
202
300
repo , commit := rh .GerritProject , rh .Commit .Commit
203
- buildList , err := fetchBuildsForCommit (ctx , buildsCl , repo , commit , "id" , "builder.builder" , "status" , "input.gitiles_commit" , "input .properties" )
301
+ buildList , err := fetchBuildsForCommit (ctx , buildsCl , repo , commit , "id" , "builder.builder" , "status" , "input.gitiles_commit" , "output .properties" )
204
302
if err != nil {
205
303
return nil , nil , err
206
304
}
207
305
total += len (buildList )
208
306
for _ , b := range buildList {
307
+ switch b .GetStatus () {
308
+ case bbpb .Status_STARTED , bbpb .Status_SUCCESS , bbpb .Status_FAILURE , bbpb .Status_INFRA_FAILURE :
309
+ default :
310
+ // Skip builds with other statuses at this time.
311
+ // Such builds can be included when the callers deem it useful.
312
+ continue
313
+ }
209
314
builder , ok := builders [b .GetBuilder ().GetBuilder ()]
210
315
if ! ok {
211
316
// A build that isn't associated with a current builder we're tracking.
212
317
// It might've been removed, or has a known issue. Skip this build too.
213
318
continue
214
319
}
320
+ var buildOutputProps struct {
321
+ Sources []struct {
322
+ GitilesCommit struct {
323
+ Project string
324
+ Ref string
325
+ Id string
326
+ }
327
+ }
328
+ }
329
+ if data , err := b .GetOutput ().GetProperties ().MarshalJSON (); err != nil {
330
+ return nil , nil , fmt .Errorf ("marshaling build output properties to JSON failed: %v" , err )
331
+ } else if err := json .Unmarshal (data , & buildOutputProps ); err != nil {
332
+ return nil , nil , err
333
+ }
334
+ goCommit , ok := func () (string , bool ) {
335
+ for _ , s := range buildOutputProps .Sources {
336
+ if c := s .GitilesCommit ; c .Project == "go" {
337
+ if c .Ref != "refs/heads/" + builder .GoBranch {
338
+ panic (fmt .Errorf (`internal error: in Go repo loop, c.Ref != "refs/heads/%s"` , builder .GoBranch ))
339
+ }
340
+ return c .Id , true
341
+ }
342
+ }
343
+ return "" , false
344
+ }()
345
+ if ! ok && b .GetStatus () == bbpb .Status_STARTED {
346
+ // A started build that hasn't selected the Go repo commit yet.
347
+ // As an approximation, assume it'll pick the latest Go repo head commit.
348
+ goCommit = goHeads [builder .GoBranch ]
349
+ } else if ! ok {
350
+ // Repo commit not found in output properties, and it's not a started build.
351
+ // As an example, this can happen if a build failed due to an infra failure
352
+ // early on, before selecting the Go repo commit. Skip such builds.
353
+ continue
354
+ }
355
+ if goCommit != goHeads [builder .GoBranch ] {
356
+ // Skip builds that are not for the Go repository's head commit.
357
+ continue
358
+ }
215
359
c := b .GetInput ().GetGitilesCommit ()
216
360
if c .Project != builder .Repo {
217
361
// When fetching builds for commits in x/ repos, it's expected
218
362
// that build repo will always match builder repo. This isn't
219
363
// true for the main Go repo because it triggers builds for x/
220
364
// repos. But x/ repo builds don't trigger builds elsewhere.
221
- return nil , nil , fmt .Errorf ("internal error: build repo %q doesn't match builder repo %q" , b . GetInput (). GetGitilesCommit (). GetProject () , builder .Repo )
365
+ return nil , nil , fmt .Errorf ("internal error: build repo %q doesn't match builder repo %q" , c . Project , builder .Repo )
222
366
}
223
367
if builds [builder .Repo ] == nil {
224
368
builds [builder .Repo ] = make (map [string ]map [string ]Build )
@@ -234,8 +378,7 @@ func runOnce(
234
378
used ++
235
379
}
236
380
}
237
- fmt .Printf ("runOnce: aggregate GetBuildsForCommit calls fetched %d builds in %v\n " , total , time .Since (t0 ))
238
- fmt .Printf ("runOnce: used %d of those %d builds\n " , used , total )
381
+ log .Printf ("lucipoll.runOnce: aggregate GetBuildsForCommit calls fetched %d builds (and used %d of them) in %v\n " , total , used , time .Since (t0 ))
239
382
240
383
return builders , builds , nil
241
384
}
0 commit comments