Skip to content
This repository was archived by the owner on Apr 17, 2019. It is now read-only.

Commit 8b3c3bf

Browse files
authored
Merge pull request #1193 from lavalamp/ff5
File issues for failures even in non-blocking jobs
2 parents 93247c5 + 5e9be45 commit 8b3c3bf

File tree

7 files changed

+92
-27
lines changed

7 files changed

+92
-27
lines changed

hack/verify-flags/known-flags.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ max-pr-number
4949
max-sync-failures
5050
min-pr-number
5151
network-config
52+
nonblocking-jenkins-jobs
5253
nginx-configmap
5354
number-of-old-test-results
5455
on-change

mungegithub/mungers/e2e/e2e.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ type BuildInfo struct {
4949
// RealE2ETester is the object which will get status from a google bucket
5050
// information about recent jobs
5151
type RealE2ETester struct {
52-
JobNames []string
53-
WeakStableJobNames []string
52+
BlockingJobNames []string
53+
NonBlockingJobNames []string
54+
WeakStableJobNames []string
5455

5556
sync.Mutex
5657
BuildStatus map[string]BuildInfo // protect by mutex
@@ -143,6 +144,11 @@ func (e *RealE2ETester) getGCSResult(j cache.Job, n cache.Number) (*cache.Result
143144
}
144145
if len(thisFailures) == 0 {
145146
r.Status = cache.ResultFailed
147+
// We add a "flake" just to make sure this appears in the flake
148+
// cache as something that needs to be synced.
149+
r.Flakes = map[cache.Test]string{
150+
cache.RunBrokenTestName: "Unable to get data-- please look at the logs",
151+
}
146152
return r, nil
147153
}
148154

@@ -159,7 +165,7 @@ func (e *RealE2ETester) getGCSResult(j cache.Job, n cache.Number) (*cache.Result
159165
func (e *RealE2ETester) GCSBasedStable() (allStable, ignorableFlakes bool) {
160166
allStable = true
161167

162-
for _, job := range e.JobNames {
168+
for _, job := range e.BlockingJobNames {
163169
lastBuildNumber, err := e.GoogleGCSBucketUtils.GetLastestBuildNumberFromJenkinsGoogleBucket(job)
164170
glog.V(4).Infof("Checking status of %v, %v", job, lastBuildNumber)
165171
if err != nil {
@@ -217,6 +223,23 @@ func (e *RealE2ETester) GCSBasedStable() (allStable, ignorableFlakes bool) {
217223
e.setBuildStatus(job, "Not Stable", strconv.Itoa(lastBuildNumber))
218224
}
219225

226+
// Also get status for non-blocking jobs
227+
for _, job := range e.NonBlockingJobNames {
228+
lastBuildNumber, err := e.GoogleGCSBucketUtils.GetLastestBuildNumberFromJenkinsGoogleBucket(job)
229+
glog.V(4).Infof("Checking status of %v, %v", job, lastBuildNumber)
230+
if err != nil {
231+
glog.Errorf("Error while getting data for %v: %v", job, err)
232+
e.setBuildStatus(job, "[nonblocking] Not Stable", strconv.Itoa(lastBuildNumber))
233+
continue
234+
}
235+
236+
if thisResult, err := e.GetBuildResult(job, lastBuildNumber); err != nil || thisResult.Status != cache.ResultStable {
237+
e.setBuildStatus(job, "[nonblocking] Not Stable", strconv.Itoa(lastBuildNumber))
238+
} else {
239+
e.setBuildStatus(job, "[nonblocking] Stable", strconv.Itoa(lastBuildNumber))
240+
}
241+
}
242+
220243
return allStable, ignorableFlakes
221244
}
222245

mungegithub/mungers/e2e/e2e_test.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,19 @@ func marshalOrDie(obj interface{}, t *testing.T) []byte {
4747
}
4848

4949
func genMockGCSListResponse(files ...string) []byte {
50-
resptemplate := "{\"items\":[%s]}"
51-
itemTempalte := "{\"name\":\"%s\"}"
50+
respTemplate := "{\"items\":[%s]}"
51+
itemTemplate := "{\"name\":\"%s\"}"
5252
items := []string{}
5353
for _, file := range files {
54-
items = append(items, fmt.Sprintf(itemTempalte, file))
54+
items = append(items, fmt.Sprintf(itemTemplate, file))
5555
}
56-
return []byte(fmt.Sprintf(resptemplate, strings.Join(items, ",")))
56+
return []byte(fmt.Sprintf(respTemplate, strings.Join(items, ",")))
5757
}
5858

5959
func TestCheckGCSBuilds(t *testing.T) {
6060
latestBuildNumberFoo := 42
6161
latestBuildNumberBar := 44
62+
latestBuildNumberBaz := 99
6263
tests := []struct {
6364
paths map[string][]byte
6465
expectStable bool
@@ -77,12 +78,18 @@ func TestCheckGCSBuilds(t *testing.T) {
7778
Result: "SUCCESS",
7879
Timestamp: 1234,
7980
}, t),
81+
"/baz/latest-build.txt": []byte(strconv.Itoa(latestBuildNumberBaz)),
82+
fmt.Sprintf("/baz/%v/finished.json", latestBuildNumberBaz): marshalOrDie(utils.FinishedFile{
83+
Result: "UNSTABLE",
84+
Timestamp: 1234,
85+
}, t),
8086
"/": genMockGCSListResponse(),
8187
},
8288
expectStable: true,
8389
expectedStatus: map[string]BuildInfo{
8490
"foo": {Status: "Stable", ID: "42"},
8591
"bar": {Status: "Stable", ID: "44"},
92+
"baz": {Status: "[nonblocking] Not Stable", ID: "99"},
8693
},
8794
},
8895
{
@@ -97,12 +104,18 @@ func TestCheckGCSBuilds(t *testing.T) {
97104
Result: "UNSTABLE",
98105
Timestamp: 1234,
99106
}, t),
107+
"/baz/latest-build.txt": []byte(strconv.Itoa(latestBuildNumberBaz)),
108+
fmt.Sprintf("/baz/%v/finished.json", latestBuildNumberBaz): marshalOrDie(utils.FinishedFile{
109+
Result: "SUCCESS",
110+
Timestamp: 1234,
111+
}, t),
100112
"/": genMockGCSListResponse(),
101113
},
102114
expectStable: false,
103115
expectedStatus: map[string]BuildInfo{
104116
"foo": {Status: "Stable", ID: "42"},
105117
"bar": {Status: "Not Stable", ID: "44"},
118+
"baz": {Status: "[nonblocking] Stable", ID: "99"},
106119
},
107120
},
108121
{
@@ -140,6 +153,7 @@ func TestCheckGCSBuilds(t *testing.T) {
140153
expectedStatus: map[string]BuildInfo{
141154
"foo": {Status: "Stable", ID: "42"},
142155
"bar": {Status: "Ignorable flake", ID: "44"},
156+
"baz": {Status: "[nonblocking] Not Stable", ID: "-1"},
143157
},
144158
},
145159
{
@@ -177,6 +191,7 @@ func TestCheckGCSBuilds(t *testing.T) {
177191
expectedStatus: map[string]BuildInfo{
178192
"foo": {Status: "Stable", ID: "42"},
179193
"bar": {Status: "Ignorable flake", ID: "44"},
194+
"baz": {Status: "[nonblocking] Not Stable", ID: "-1"},
180195
},
181196
},
182197
{
@@ -214,6 +229,7 @@ func TestCheckGCSBuilds(t *testing.T) {
214229
expectedStatus: map[string]BuildInfo{
215230
"foo": {Status: "Stable", ID: "42"},
216231
"bar": {Status: "Not Stable", ID: "44"},
232+
"baz": {Status: "[nonblocking] Not Stable", ID: "-1"},
217233
},
218234
},
219235

@@ -235,6 +251,7 @@ func TestCheckGCSBuilds(t *testing.T) {
235251
expectedStatus: map[string]BuildInfo{
236252
"foo": {Status: "Stable", ID: "42"},
237253
"bar": {Status: "Not Stable", ID: "44"},
254+
"baz": {Status: "[nonblocking] Not Stable", ID: "-1"},
238255
},
239256
},
240257
{
@@ -255,6 +272,7 @@ func TestCheckGCSBuilds(t *testing.T) {
255272
expectedStatus: map[string]BuildInfo{
256273
"foo": {Status: "Not Stable", ID: "42"},
257274
"bar": {Status: "Not Stable", ID: "44"},
275+
"baz": {Status: "[nonblocking] Not Stable", ID: "-1"},
258276
},
259277
},
260278
{
@@ -275,6 +293,7 @@ func TestCheckGCSBuilds(t *testing.T) {
275293
expectedStatus: map[string]BuildInfo{
276294
"foo": {Status: "Not Stable", ID: "42"},
277295
"bar": {Status: "Stable", ID: "44"},
296+
"baz": {Status: "[nonblocking] Not Stable", ID: "-1"},
278297
},
279298
},
280299
}
@@ -292,10 +311,13 @@ func TestCheckGCSBuilds(t *testing.T) {
292311
},
293312
})
294313
e2e := &RealE2ETester{
295-
JobNames: []string{
314+
BlockingJobNames: []string{
296315
"foo",
297316
"bar",
298317
},
318+
NonBlockingJobNames: []string{
319+
"baz",
320+
},
299321
BuildStatus: map[string]BuildInfo{},
300322
GoogleGCSBucketUtils: utils.NewTestUtils(server.URL),
301323
}

mungegithub/mungers/flake-manager.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,18 +124,23 @@ func (p *FlakeManager) isIndividualFlake(f cache.Flake) bool {
124124
return false
125125
}
126126

127+
if len(f.Result.Flakes) > 0 {
128+
// If this flake really represents an entire suite failure,
129+
// this key will be present.
130+
if _, ok := f.Result.Flakes[cache.RunBrokenTestName]; ok {
131+
return false
132+
}
133+
}
134+
127135
return true
128136
}
129137

130138
func (p *FlakeManager) listPreviousIssues(title string) []string {
131-
if previousIssues := p.finder.AllIssuesForKey(title); len(previousIssues) > 0 {
132-
s := []string{}
133-
for _, i := range previousIssues {
134-
s = append(s, fmt.Sprintf("#%v", i))
135-
}
136-
return s
139+
s := []string{}
140+
for _, i := range p.finder.AllIssuesForKey(title) {
141+
s = append(s, fmt.Sprintf("#%v", i))
137142
}
138-
return nil
143+
return s
139144
}
140145

141146
// makeGubernatorLink returns a URL to view the build results in a GCS path.

mungegithub/mungers/flakesync/cache.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ const (
4444
// ResultFailed means it failed without generating readable JUnit
4545
// files, and introspection is not possible.
4646
ResultFailed ResultStatus = "failed"
47+
48+
// RunBrokenTestName names a "flake" which really represents the fact
49+
// that the entire run was broken.
50+
RunBrokenTestName Test = "Suite so broken it failed to produce JUnit output"
4751
)
4852

4953
// Result records a test job completion.

mungegithub/mungers/submit-queue.go

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,12 @@ type submitQueueInterruptedObject struct {
133133
// SubmitQueue will merge PR which meet a set of requirements.
134134
// PR must have LGTM after the last commit
135135
// PR must have passed all github CI checks
136-
// The google internal jenkins instance must be passing the JobNames e2e tests
136+
// The google internal jenkins instance must be passing the BlockingJobNames e2e tests
137137
type SubmitQueue struct {
138-
githubConfig *github.Config
139-
JobNames []string
140-
WeakStableJobNames []string
138+
githubConfig *github.Config
139+
BlockingJobNames []string
140+
NonBlockingJobNames []string
141+
WeakStableJobNames []string
141142

142143
// If FakeE2E is true, don't try to connect to JenkinsHost, all jobs are passing.
143144
FakeE2E bool
@@ -302,7 +303,8 @@ func (sq *SubmitQueue) internalInitialize(config *github.Config, features *featu
302303
defer sq.Unlock()
303304

304305
// Clean up all of our flags which we wish --flag="" to mean []string{}
305-
sq.JobNames = cleanStringSlice(sq.JobNames)
306+
sq.BlockingJobNames = cleanStringSlice(sq.BlockingJobNames)
307+
sq.NonBlockingJobNames = cleanStringSlice(sq.NonBlockingJobNames)
306308
sq.WeakStableJobNames = cleanStringSlice(sq.WeakStableJobNames)
307309
sq.RequiredStatusContexts = cleanStringSlice(sq.RequiredStatusContexts)
308310
sq.RequiredRetestContexts = cleanStringSlice(sq.RequiredRetestContexts)
@@ -313,7 +315,7 @@ func (sq *SubmitQueue) internalInitialize(config *github.Config, features *featu
313315
// TODO: This is not how injection for tests should work.
314316
if sq.FakeE2E {
315317
sq.e2e = &fake_e2e.FakeE2ETester{
316-
JobNames: sq.JobNames,
318+
JobNames: sq.BlockingJobNames,
317319
WeakStableJobNames: sq.WeakStableJobNames,
318320
}
319321
} else {
@@ -325,7 +327,8 @@ func (sq *SubmitQueue) internalInitialize(config *github.Config, features *featu
325327
}
326328

327329
sq.e2e = (&e2e.RealE2ETester{
328-
JobNames: sq.JobNames,
330+
BlockingJobNames: sq.BlockingJobNames,
331+
NonBlockingJobNames: sq.NonBlockingJobNames,
329332
WeakStableJobNames: sq.WeakStableJobNames,
330333
BuildStatus: map[string]e2e.BuildInfo{},
331334
GoogleGCSBucketUtils: gcs,
@@ -387,7 +390,13 @@ func (sq *SubmitQueue) EachLoop() error {
387390

388391
// AddFlags will add any request flags to the cobra `cmd`
389392
func (sq *SubmitQueue) AddFlags(cmd *cobra.Command, config *github.Config) {
390-
cmd.Flags().StringSliceVar(&sq.JobNames, "jenkins-jobs", []string{
393+
cmd.Flags().StringSliceVar(&sq.NonBlockingJobNames, "nonblocking-jenkins-jobs", []string{
394+
"kubernetes-e2e-gke-prod",
395+
"kubernetes-e2e-gke-subnet",
396+
"kubernetes-e2e-gke-test",
397+
"kubernetes-e2e-gce-examples",
398+
}, "Comma separated list of jobs that don't block merges, but will have status reported and issues filed.")
399+
cmd.Flags().StringSliceVar(&sq.BlockingJobNames, "jenkins-jobs", []string{
391400
"kubelet-gce-e2e-ci",
392401
"kubernetes-build",
393402
"kubernetes-test-go",
@@ -399,7 +408,7 @@ func (sq *SubmitQueue) AddFlags(cmd *cobra.Command, config *github.Config) {
399408
"kubernetes-e2e-gke-slow",
400409
"kubernetes-e2e-gce-scalability",
401410
"kubernetes-kubemark-5-gce",
402-
}, "Comma separated list of jobs in Jenkins to use for stability testing")
411+
}, "Comma separated list of jobs in Jenkins that should block merges if failing.")
403412
cmd.Flags().StringSliceVar(&sq.WeakStableJobNames, "weak-stable-jobs",
404413
[]string{},
405414
"Comma separated list of jobs in Jenkins to use for stability testing that needs only weak success")
@@ -426,7 +435,8 @@ func (sq *SubmitQueue) updateHealth() {
426435
Jobs: map[string]bool{},
427436
}
428437
for job, status := range sq.e2e.GetBuildStatus() {
429-
newEntry.Jobs[job] = status.Status == "Stable"
438+
// Ignore flakes.
439+
newEntry.Jobs[job] = status.Status != "Not Stable"
430440
}
431441
sq.healthHistory = append(sq.healthHistory, newEntry)
432442
// Now compute the health structure so we don't have to do it on page load

mungegithub/mungers/submit-queue_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ func getTestSQ(startThreads bool, config *github_util.Config, server *httptest.S
182182
sq := new(SubmitQueue)
183183
sq.RequiredStatusContexts = []string{notRequiredReTestContext1, notRequiredReTestContext2}
184184
sq.RequiredRetestContexts = []string{requiredReTestContext1, requiredReTestContext2}
185-
sq.JobNames = []string{"foo"}
185+
sq.BlockingJobNames = []string{"foo"}
186186
sq.WeakStableJobNames = []string{"bar"}
187187
sq.githubE2EQueue = map[int]*github_util.MungeObject{}
188188
sq.githubE2EPollTime = 50 * time.Millisecond
@@ -199,7 +199,7 @@ func getTestSQ(startThreads bool, config *github_util.Config, server *httptest.S
199199
sq.doNotMergeMilestones = []string{doNotMergeMilestone}
200200

201201
sq.e2e = &fake_e2e.FakeE2ETester{
202-
JobNames: sq.JobNames,
202+
JobNames: sq.BlockingJobNames,
203203
WeakStableJobNames: sq.WeakStableJobNames,
204204
}
205205

0 commit comments

Comments
 (0)