| OLD | NEW |
| 1 package frontend | 1 package frontend |
| 2 | 2 |
| 3 import ( | 3 import ( |
| 4 "bytes" | 4 "bytes" |
| 5 "encoding/json" | 5 "encoding/json" |
| 6 "io" | 6 "io" |
| 7 "net/http" | 7 "net/http" |
| 8 "regexp" | 8 "regexp" |
| 9 "sort" | 9 "sort" |
| 10 "strings" | 10 "strings" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 "infra/appengine/test-results/masters" | 22 "infra/appengine/test-results/masters" |
| 23 ) | 23 ) |
| 24 | 24 |
| 25 // BuilderData is the data returned from the GET "/builders" | 25 // BuilderData is the data returned from the GET "/builders" |
| 26 // endpoint. | 26 // endpoint. |
| 27 type BuilderData struct { | 27 type BuilderData struct { |
| 28 Masters []Master `json:"masters"` | 28 Masters []Master `json:"masters"` |
| 29 NoUploadTestTypes []string `json:"no_upload_test_types"` | 29 NoUploadTestTypes []string `json:"no_upload_test_types"` |
| 30 } | 30 } |
| 31 | 31 |
| 32 // Master represents information about a build master. |
| 32 type Master struct { | 33 type Master struct { |
| 33 Name string `json:"name"` | 34 Name string `json:"name"` |
| 34 Identifier string `json:"url_name"` | 35 Identifier string `json:"url_name"` |
| 35 Groups []string `json:"groups"` | 36 Groups []string `json:"groups"` |
| 36 Tests map[string]Test `json:"tests"` | 37 Tests map[string]Test `json:"tests"` |
| 37 } | 38 } |
| 38 | 39 |
| 40 // Test represents information about Tests in a master. |
| 39 type Test struct { | 41 type Test struct { |
| 40 Builders []string `json:"builders"` | 42 Builders []string `json:"builders"` |
| 41 } | 43 } |
| 42 | 44 |
| 43 const buildbotMemcacheKey = "buildbot_data" | 45 const buildbotMemcacheKey = "buildbot_data" |
| 44 | 46 |
| 45 var nonTestStepNames = []string{ | 47 var nonTestStepNames = []string{ |
| 46 "archive", | 48 "archive", |
| 47 "Run tests", | 49 "Run tests", |
| 48 "find isolated tests", | 50 "find isolated tests", |
| (...skipping 15 matching lines...) Expand all Loading... |
| 64 "test_mini_installer", | 66 "test_mini_installer", |
| 65 "webkit_python_tests", | 67 "webkit_python_tests", |
| 66 } | 68 } |
| 67 | 69 |
| 68 func makeBuildExtractClient(ctx context.Context) *buildextract.Client { | 70 func makeBuildExtractClient(ctx context.Context) *buildextract.Client { |
| 69 return buildextract.NewClient(&http.Client{ | 71 return buildextract.NewClient(&http.Client{ |
| 70 Transport: urlfetch.Get(ctx), | 72 Transport: urlfetch.Get(ctx), |
| 71 }) | 73 }) |
| 72 } | 74 } |
| 73 | 75 |
| 74 func GetBuilders(ctx *router.Context) { | 76 func getBuildersHandler(ctx *router.Context) { |
| 75 c, w, r := ctx.Context, ctx.Writer, ctx.Request | 77 c, w, r := ctx.Context, ctx.Writer, ctx.Request |
| 76 var res []byte | 78 var res []byte |
| 77 item, err := memcache.Get(c).Get(buildbotMemcacheKey) | 79 item, err := memcache.Get(c).Get(buildbotMemcacheKey) |
| 78 | 80 |
| 79 switch err { | 81 switch err { |
| 80 case memcache.ErrCacheMiss: | 82 case memcache.ErrCacheMiss: |
| 81 start := time.Now() | 83 start := time.Now() |
| 82 data, err := getBuilderData(c, masters.Known, makeBuildExtractCl
ient(c)) | 84 data, err := getBuilderData(c, masters.Known, makeBuildExtractCl
ient(c)) |
| 83 if err != nil { | 85 if err != nil { |
| 84 logging.WithError(err).Errorf(c, "builders: GetBuilders:
failed to fetch builders") | 86 logging.WithError(err).Errorf(c, "builders: GetBuilders:
failed to fetch builders") |
| (...skipping 28 matching lines...) Expand all Loading... |
| 113 n, err := io.Copy(w, out) | 115 n, err := io.Copy(w, out) |
| 114 | 116 |
| 115 if err != nil { | 117 if err != nil { |
| 116 logging.Fields{ | 118 logging.Fields{ |
| 117 logging.ErrorKey: err, | 119 logging.ErrorKey: err, |
| 118 "n": n, | 120 "n": n, |
| 119 }.Errorf(c, "builders: GetBuilders: failed to write response") | 121 }.Errorf(c, "builders: GetBuilders: failed to write response") |
| 120 } | 122 } |
| 121 } | 123 } |
| 122 | 124 |
| 123 func UpdateBuilders(ctx *router.Context) { | 125 func updateBuildersHandler(ctx *router.Context) { |
| 124 c, w := ctx.Context, ctx.Writer | 126 c, w := ctx.Context, ctx.Writer |
| 125 | 127 |
| 126 start := time.Now() | 128 start := time.Now() |
| 127 data, err := getBuilderData(c, masters.Known, makeBuildExtractClient(c)) | 129 data, err := getBuilderData(c, masters.Known, makeBuildExtractClient(c)) |
| 128 if err != nil { | 130 if err != nil { |
| 129 logging.WithError(err).Errorf(c, "builders: UpdateBuilders: fail
ed to fetch builders") | 131 logging.WithError(err).Errorf(c, "builders: UpdateBuilders: fail
ed to fetch builders") |
| 130 http.Error(w, err.Error(), http.StatusInternalServerError) | 132 http.Error(w, err.Error(), http.StatusInternalServerError) |
| 131 return | 133 return |
| 132 } | 134 } |
| 133 logging.Fields{"duration": time.Since(start)}.Infof(c, "builders: getBui
lderData") | 135 logging.Fields{"duration": time.Since(start)}.Infof(c, "builders: getBui
lderData") |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 } | 181 } |
| 180 results := make(chan result, len(list)) | 182 results := make(chan result, len(list)) |
| 181 wg := sync.WaitGroup{} | 183 wg := sync.WaitGroup{} |
| 182 wg.Add(len(list)) | 184 wg.Add(len(list)) |
| 183 | 185 |
| 184 for _, master := range list { | 186 for _, master := range list { |
| 185 m := Master{ | 187 m := Master{ |
| 186 Name: master.Name, | 188 Name: master.Name, |
| 187 Identifier: master.Identifier, | 189 Identifier: master.Identifier, |
| 188 Groups: master.Groups, | 190 Groups: master.Groups, |
| 189 » » » Tests: map[string]Test{}, | 191 » » » Tests: make(map[string]Test), |
| 190 } | 192 } |
| 191 | 193 |
| 192 go func() { | 194 go func() { |
| 193 defer wg.Done() | 195 defer wg.Done() |
| 194 builders, err := getBuilderNames(ctx, m.Identifier, clie
nt) | 196 builders, err := getBuilderNames(ctx, m.Identifier, clie
nt) |
| 195 if err != nil { | 197 if err != nil { |
| 196 results <- result{Err: err} | 198 results <- result{Err: err} |
| 197 return | 199 return |
| 198 } | 200 } |
| 199 | 201 |
| 202 if len(builders) == 0 { |
| 203 return |
| 204 } |
| 205 |
| 200 for _, b := range builders { | 206 for _, b := range builders { |
| 201 stepNames, err := getStepNames(ctx, m.Identifier
, b, client) | 207 stepNames, err := getStepNames(ctx, m.Identifier
, b, client) |
| 202 if err != nil { | 208 if err != nil { |
| 203 results <- result{Err: err} | 209 results <- result{Err: err} |
| 204 return | 210 return |
| 205 } | 211 } |
| 206 for _, s := range stepNames { | 212 for _, s := range stepNames { |
| 207 t, ok := m.Tests[s] | 213 t, ok := m.Tests[s] |
| 208 if !ok { | 214 if !ok { |
| 209 t = Test{} | 215 t = Test{} |
| 210 } | 216 } |
| 211 t.Builders = append(t.Builders, b) | 217 t.Builders = append(t.Builders, b) |
| 212 m.Tests[s] = t | 218 m.Tests[s] = t |
| 213 } | 219 } |
| 214 } | 220 } |
| 221 |
| 215 results <- result{Master: m} | 222 results <- result{Master: m} |
| 216 }() | 223 }() |
| 217 } | 224 } |
| 218 | 225 |
| 219 wg.Wait() | 226 wg.Wait() |
| 220 close(results) | 227 close(results) |
| 221 for res := range results { | 228 for res := range results { |
| 222 if res.Err != nil { | 229 if res.Err != nil { |
| 223 return BuilderData{}, res.Err | 230 return BuilderData{}, res.Err |
| 224 } | 231 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 | 326 |
| 320 var ignoreTestNameRx = regexp.MustCompile(`_only|_ignore|_perf$`) | 327 var ignoreTestNameRx = regexp.MustCompile(`_only|_ignore|_perf$`) |
| 321 var gtestUploaderStepRx = regexp.MustCompile(`Upload to test-results \[([^]]*)\]
`) | 328 var gtestUploaderStepRx = regexp.MustCompile(`Upload to test-results \[([^]]*)\]
`) |
| 322 | 329 |
| 323 func cleanTestStep(name string) (clean string, ok bool) { | 330 func cleanTestStep(name string) (clean string, ok bool) { |
| 324 if !strings.Contains(name, "test") { | 331 if !strings.Contains(name, "test") { |
| 325 return "", false | 332 return "", false |
| 326 } | 333 } |
| 327 | 334 |
| 328 for _, n := range nonTestStepNames { | 335 for _, n := range nonTestStepNames { |
| 329 » » if strings.HasPrefix(name, n) { | 336 » » if strings.Contains(name, n) { |
| 330 return "", false | 337 return "", false |
| 331 } | 338 } |
| 332 } | 339 } |
| 333 | 340 |
| 334 if ignoreTestNameRx.MatchString(name) { | 341 if ignoreTestNameRx.MatchString(name) { |
| 335 return "", false | 342 return "", false |
| 336 } | 343 } |
| 337 | 344 |
| 338 // Ignore triggering and collecting steps on swarming: | 345 // Ignore triggering and collecting steps on swarming: |
| 339 // they are not actual tests. | 346 // they are not actual tests. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 // data, we just keep everything before the first space. | 389 // data, we just keep everything before the first space. |
| 383 if i := strings.Index(name, " "); i != -1 { | 390 if i := strings.Index(name, " "); i != -1 { |
| 384 name = name[:i] | 391 name = name[:i] |
| 385 } | 392 } |
| 386 | 393 |
| 387 if withPatch { | 394 if withPatch { |
| 388 name += " (with patch)" | 395 name += " (with patch)" |
| 389 } | 396 } |
| 390 return name | 397 return name |
| 391 } | 398 } |
| OLD | NEW |