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 |