aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-01-19 14:28:01 +0100
committerAleksandr Nogikh <wp32pw@gmail.com>2023-01-19 16:56:30 +0100
commit7cec19129d29eb6e3a6559bcebb46bd4097f080b (patch)
treeb8b62ee1af87e862e82599efdaa8751af62cddcf
parent7990722a6099be6cb949b042064f62b1ecad997b (diff)
dashboard: handle decommissioned managers in repro retesting
Especially for old bugs, it's likely that the corresponding syz-manager instance has already been deprecated. The current code creates a patch testing job for the old repository, but then only accepts the result if the repository is equal to that of the new syz-manager instance. As a result, patch retesting goes crazy and creates many unnecessary jobs. Take the repo and branch data for the currently active syz-manager right away. This should resolve the issue. Add a test to verify the behavior.
-rw-r--r--dashboard/app/jobs.go38
-rw-r--r--dashboard/app/jobs_test.go68
2 files changed, 94 insertions, 12 deletions
diff --git a/dashboard/app/jobs.go b/dashboard/app/jobs.go
index 6d2efc75a..f97f443ad 100644
--- a/dashboard/app/jobs.go
+++ b/dashboard/app/jobs.go
@@ -95,17 +95,10 @@ func addTestJob(c context.Context, args *testJobArgs, now time.Time) error {
args.repo, args.branch); reason != "" {
return &BadTestRequestError{reason}
}
- manager := args.crash.Manager
- for _, ns := range config.Namespaces {
- if mgr, ok := ns.Managers[manager]; ok {
- if mgr.RestrictedTestingRepo != "" && args.repo != mgr.RestrictedTestingRepo {
- return &BadTestRequestError{mgr.RestrictedTestingReason}
- }
- if mgr.Decommissioned {
- manager = mgr.DelegatedTo
- }
- break
- }
+ manager, mgrConfig := activeManager(args.crash.Manager, args.bug.Namespace)
+ if mgrConfig != nil && mgrConfig.RestrictedTestingRepo != "" &&
+ args.repo != mgrConfig.RestrictedTestingRepo {
+ return &BadTestRequestError{mgrConfig.RestrictedTestingReason}
}
patchID, err := putText(c, args.bug.Namespace, textPatch, args.patch, false)
if err != nil {
@@ -319,9 +312,14 @@ func handleRetestForBug(c context.Context, now time.Time, bug *Bug, bugKey *db.K
if managerHasJob[crash.Manager] {
continue
}
+ // We could have decommissioned the original manager since then.
+ manager, _ := activeManager(crash.Manager, bug.Namespace)
+ if manager == "" {
+ continue
+ }
// Take the last successful build -- the build on which this crash happened
// might contain already obsolete repro and branch values.
- build, err := lastManagerBuild(c, bug.Namespace, crash.Manager)
+ build, err := lastManagerBuild(c, bug.Namespace, manager)
if err != nil {
return err
}
@@ -1145,6 +1143,22 @@ func loadPendingJob(c context.Context, managers map[string]dashapi.ManagerJobs)
return nil, nil, nil
}
+// activeManager determines the manager currently responsible for all bugs found by
+// the specified manager.
+func activeManager(manager, ns string) (string, *ConfigManager) {
+ nsConfig := config.Namespaces[ns]
+ if mgr, ok := nsConfig.Managers[manager]; ok {
+ if mgr.Decommissioned {
+ newMgr := nsConfig.Managers[mgr.DelegatedTo]
+ return mgr.DelegatedTo, &newMgr
+ }
+ return manager, &mgr
+ }
+ // This manager is not mentioned in the configuration, therefore it was
+ // definitely not decommissioned.
+ return manager, nil
+}
+
func extJobID(jobKey *db.Key) string {
return fmt.Sprintf("%v|%v", jobKey.Parent().StringID(), jobKey.IntID())
}
diff --git a/dashboard/app/jobs_test.go b/dashboard/app/jobs_test.go
index a473bc03b..961310724 100644
--- a/dashboard/app/jobs_test.go
+++ b/dashboard/app/jobs_test.go
@@ -488,6 +488,74 @@ func TestReproRetestJob(t *testing.T) {
c.expectEQ(bug.StatusReason, dashapi.InvalidatedByRevokedRepro)
}
+func TestDelegatedManagerReproRetest(t *testing.T) {
+ c := NewCtx(t)
+ defer c.Close()
+
+ client := c.client2
+ oldManager := noFixBisectionManager
+ newManager := specialCCManager
+
+ oldBuild := testBuild(1)
+ oldBuild.KernelRepo = "git://delegated.repo/git.git"
+ oldBuild.KernelBranch = "main"
+ oldBuild.Manager = oldManager
+ client.UploadBuild(oldBuild)
+
+ crash := testCrash(oldBuild, 1)
+ crash.ReproOpts = []byte("repro opts")
+ crash.ReproSyz = []byte("repro syz")
+ crash.ReproC = []byte("repro C")
+ client.ReportCrash(crash)
+ sender := c.pollEmailBug().Sender
+ _, extBugID, err := email.RemoveAddrContext(sender)
+ c.expectOK(err)
+
+ // Deprecate the oldManager.
+ mgrConfig := config.Namespaces["test2"].Managers[oldManager]
+ mgrConfig.Decommissioned = true
+ mgrConfig.DelegatedTo = newManager
+ config.Namespaces["test2"].Managers[oldManager] = mgrConfig
+
+ // Upload a build for the new manager.
+ c.advanceTime(time.Minute)
+ build := testBuild(1)
+ build.ID = "new-build"
+ build.KernelRepo = "git://delegated.repo/new-git.git"
+ build.KernelBranch = "new-main"
+ build.KernelConfig = []byte{0xAB, 0xCD, 0xEF}
+ build.Manager = newManager
+ client.UploadBuild(build)
+
+ // Wait until the bug is upstreamed.
+ c.advanceTime(20 * 24 * time.Hour)
+ c.pollEmailBug()
+ c.pollEmailBug()
+
+ // Let's say that the C repro testing has failed.
+ c.advanceTime(config.Obsoleting.ReproRetestPeriod + time.Hour)
+ c.updRetestReproJobs()
+
+ resp := client.pollSpecificJobs(build.Manager, dashapi.ManagerJobs{TestPatches: true})
+ c.expectEQ(resp.Type, dashapi.JobTestPatch)
+ c.expectEQ(resp.KernelRepo, build.KernelRepo)
+ c.expectEQ(resp.KernelBranch, build.KernelBranch)
+ c.expectEQ(resp.KernelConfig, build.KernelConfig)
+ c.expectEQ(resp.Patch, []uint8(nil))
+
+ // Pretend that the C repro fails.
+ done := &dashapi.JobDoneReq{
+ ID: resp.ID,
+ }
+
+ client.expectOK(client.JobDone(done))
+
+ // If it has worked, the repro is revoked and the bug is obsoleted.
+ c.pollEmailBug()
+ bug, _, _ := c.loadBug(extBugID)
+ c.expectEQ(bug.HeadReproLevel, ReproLevelNone)
+}
+
// Test on a restricted manager.
func TestJobRestrictedManager(t *testing.T) {
c := NewCtx(t)