internal/worker: consolidate classification for errors

Some loading errors needs to be classified at the point of loading since
they require file system access, which might not be available outside of
sandbox. Other errors can be classified at a single place once in
ScanModule. This CL does that.

It also makes sure that govulncheck binary loading errors are
recognized. They need to be recognized by matching on govulncheck error
messages.

Change-Id: If3f2cdbc351866f8f5a044d10296b0eead2bcd67
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/474195
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
diff --git a/internal/load/load.go b/internal/load/load.go
index 56f6f13..354a891 100644
--- a/internal/load/load.go
+++ b/internal/load/load.go
@@ -42,10 +42,6 @@
 			err = fmt.Errorf("%v: %w", err, derrors.LoadPackagesNoGoModError)
 		case !fileExists(filepath.Join(cfg.Dir, "go.sum")):
 			err = fmt.Errorf("%v: %w", err, derrors.LoadPackagesNoGoSumError)
-		case isNoRequiredModule(err):
-			err = fmt.Errorf("%v: %w", err, derrors.LoadPackagesNoRequiredModuleError)
-		case isMissingGoSumEntry(err.Error()):
-			err = fmt.Errorf("%v: %w", err, derrors.LoadPackagesMissingGoSumEntryError)
 		default:
 			err = fmt.Errorf("%v: %w", err, derrors.LoadPackagesError)
 		}
@@ -67,14 +63,6 @@
 	return pkgs, errors, nil
 }
 
-func isNoRequiredModule(err error) bool {
-	return strings.Contains(err.Error(), "no required module")
-}
-
-func isMissingGoSumEntry(errMsg string) bool {
-	return strings.Contains(errMsg, "missing go.sum entry")
-}
-
 // fileExists checks if file path exists. Returns true
 // if the file exists or it cannot prove that it does
 // not exist. Otherwise, returns false.
diff --git a/internal/worker/vulncheck_scan.go b/internal/worker/vulncheck_scan.go
index a71050c..8ef2925 100644
--- a/internal/worker/vulncheck_scan.go
+++ b/internal/worker/vulncheck_scan.go
@@ -203,12 +203,26 @@
 	row.PkgsMemory = int64(stats.pkgsMemory)
 	row.Workers = config.GetEnvInt("CLOUD_RUN_CONCURRENCY", "0", -1)
 	if err != nil {
-		// If an error occurred, wrap it accordingly
-		if isVulnDBConnection(err) {
+		switch {
+		case errors.Is(err, derrors.LoadPackagesNoGoModError) ||
+			errors.Is(err, derrors.LoadPackagesNoGoSumError):
+			// errors already classified by package loading.
+		case isMissingGoMod(err):
+			// specific for govulncheck
+			err = fmt.Errorf("%v: %w", err, derrors.LoadPackagesNoGoModError)
+		case isNoRequiredModule(err):
+			err = fmt.Errorf("%v: %w", err, derrors.LoadPackagesNoRequiredModuleError)
+		case isMissingGoSumEntry(err):
+			err = fmt.Errorf("%v: %w", err, derrors.LoadPackagesMissingGoSumEntryError)
+		case errors.Is(err, derrors.LoadPackagesError):
+			// general load packages error
+		case isVulnDBConnection(err):
 			err = fmt.Errorf("%v: %w", err, derrors.ScanModuleVulncheckDBConnectionError)
-		} else if !errors.Is(err, derrors.ScanModuleMemoryLimitExceeded) && sreq.Mode != ModeGovulncheck {
+		default:
 			err = fmt.Errorf("%v: %w", err, derrors.ScanModuleVulncheckError)
 		}
+
+		fmt.Printf("ZP: %v\n", derrors.CategorizeError(err))
 		row.AddError(err)
 		log.Infof(ctx, "scanner.runScanModule return error for %s (%v)", sreq.Path(), err)
 	} else {
@@ -630,6 +644,18 @@
 	return err
 }
 
+func isNoRequiredModule(err error) bool {
+	return strings.Contains(err.Error(), "no required module")
+}
+
+func isMissingGoSumEntry(err error) bool {
+	return strings.Contains(err.Error(), "missing go.sum entry")
+}
+
+func isMissingGoMod(err error) bool {
+	return strings.Contains(err.Error(), "no go.mod file")
+}
+
 func isVulnDBConnection(err error) bool {
 	s := err.Error()
 	return strings.Contains(s, "https://vuln.go.dev") &&