Skip to content

Commit 866b3e0

Browse files
authored
fix(offline): report all ecosystems without local databases in one single line (google#1279)
This reduces the amount of noise generated when using `--offline` if a database is not available for a particular ecosystem. While it was suggested that we could have some form of general error cache, for now I've just optimized for this specific case as really it's the one we expect the most and (in part) I think the nature of Go makes the more generic improvement a bit too faffy vs the gain. Resolves google#1005
1 parent ce76735 commit 866b3e0

File tree

3 files changed

+90
-2
lines changed

3 files changed

+90
-2
lines changed

cmd/osv-scanner/__snapshots__/main_test.snap

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,6 +2091,48 @@ databases can only be downloaded when running in offline mode
20912091

20922092
---
20932093

2094+
[TestRun_LocalDatabases_AlwaysOffline/#00 - 1]
2095+
Scanning dir ./fixtures/locks-requirements
2096+
Scanned <rootdir>/fixtures/locks-requirements/my-requirements.txt file and found 1 package
2097+
Scanned <rootdir>/fixtures/locks-requirements/requirements-dev.txt file and found 1 package
2098+
Scanned <rootdir>/fixtures/locks-requirements/requirements.prod.txt file and found 1 package
2099+
Scanned <rootdir>/fixtures/locks-requirements/requirements.txt file and found 3 packages
2100+
Scanned <rootdir>/fixtures/locks-requirements/the_requirements_for_test.txt file and found 1 package
2101+
Scanning dir ./fixtures/locks-many
2102+
Scanned <rootdir>/fixtures/locks-many/Gemfile.lock file and found 1 package
2103+
Scanned <rootdir>/fixtures/locks-many/alpine.cdx.xml as CycloneDX SBOM and found 14 packages
2104+
Scanned <rootdir>/fixtures/locks-many/composer.lock file and found 1 package
2105+
Scanned <rootdir>/fixtures/locks-many/package-lock.json file and found 1 package
2106+
Scanned <rootdir>/fixtures/locks-many/yarn.lock file and found 1 package
2107+
2108+
---
2109+
2110+
[TestRun_LocalDatabases_AlwaysOffline/#00 - 2]
2111+
could not find local databases for ecosystems: Alpine, Packagist, PyPI, RubyGems, npm
2112+
2113+
---
2114+
2115+
[TestRun_LocalDatabases_AlwaysOffline/#00 - 3]
2116+
Scanning dir ./fixtures/locks-requirements
2117+
Scanned <rootdir>/fixtures/locks-requirements/my-requirements.txt file and found 1 package
2118+
Scanned <rootdir>/fixtures/locks-requirements/requirements-dev.txt file and found 1 package
2119+
Scanned <rootdir>/fixtures/locks-requirements/requirements.prod.txt file and found 1 package
2120+
Scanned <rootdir>/fixtures/locks-requirements/requirements.txt file and found 3 packages
2121+
Scanned <rootdir>/fixtures/locks-requirements/the_requirements_for_test.txt file and found 1 package
2122+
Scanning dir ./fixtures/locks-many
2123+
Scanned <rootdir>/fixtures/locks-many/Gemfile.lock file and found 1 package
2124+
Scanned <rootdir>/fixtures/locks-many/alpine.cdx.xml as CycloneDX SBOM and found 14 packages
2125+
Scanned <rootdir>/fixtures/locks-many/composer.lock file and found 1 package
2126+
Scanned <rootdir>/fixtures/locks-many/package-lock.json file and found 1 package
2127+
Scanned <rootdir>/fixtures/locks-many/yarn.lock file and found 1 package
2128+
2129+
---
2130+
2131+
[TestRun_LocalDatabases_AlwaysOffline/#00 - 4]
2132+
could not find local databases for ecosystems: Alpine, Packagist, PyPI, RubyGems, npm
2133+
2134+
---
2135+
20942136
[TestRun_LockfileWithExplicitParseAs/#00 - 1]
20952137

20962138
---

cmd/osv-scanner/main_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,35 @@ func TestRun_LocalDatabases(t *testing.T) {
641641
}
642642
}
643643

644+
func TestRun_LocalDatabases_AlwaysOffline(t *testing.T) {
645+
t.Parallel()
646+
647+
tests := []cliTestCase{
648+
// a bunch of different lockfiles and ecosystem
649+
{
650+
name: "",
651+
args: []string{"", "--config=./fixtures/osv-scanner-empty-config.toml", "--experimental-offline", "./fixtures/locks-requirements", "./fixtures/locks-many"},
652+
exit: 127,
653+
},
654+
}
655+
656+
for _, tt := range tests {
657+
t.Run(tt.name, func(t *testing.T) {
658+
t.Parallel()
659+
660+
testDir := testutility.CreateTestDir(t)
661+
old := tt.args
662+
tt.args = []string{"", "--experimental-local-db-path", testDir}
663+
tt.args = append(tt.args, old[1:]...)
664+
665+
// run each test twice since they should provide the same output,
666+
// and the second run should be fast as the db is already available
667+
testCli(t, tt)
668+
testCli(t, tt)
669+
})
670+
}
671+
}
672+
644673
func TestRun_Licenses(t *testing.T) {
645674
t.Parallel()
646675
tests := []cliTestCase{

internal/local/check.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"os"
77
"path"
8+
"slices"
9+
"strings"
810

911
"github.com/google/osv-scanner/pkg/lockfile"
1012
"github.com/google/osv-scanner/pkg/models"
@@ -116,6 +118,9 @@ func MakeRequest(r reporter.Reporter, query osv.BatchedQuery, offline bool, loca
116118
return db, nil
117119
}
118120

121+
// slice to track ecosystems that did not have an offline database available
122+
var missingDbs []string
123+
119124
for _, query := range query.Queries {
120125
pkg, err := toPackageDetails(query)
121126

@@ -143,8 +148,13 @@ func MakeRequest(r reporter.Reporter, query osv.BatchedQuery, offline bool, loca
143148
db, err := loadDBFromCache(pkg.Ecosystem)
144149

145150
if err != nil {
146-
// currently, this will actually only error if the PURL cannot be parses
147-
r.Errorf("could not load db for %s ecosystem: %v\n", pkg.Ecosystem, err)
151+
if errors.Is(err, ErrOfflineDatabaseNotFound) {
152+
missingDbs = append(missingDbs, string(pkg.Ecosystem))
153+
} else {
154+
// the most likely error at this point is that the PURL could not be parsed
155+
r.Errorf("could not load db for %s ecosystem: %v\n", pkg.Ecosystem, err)
156+
}
157+
148158
results = append(results, osv.Response{Vulns: []models.Vulnerability{}})
149159

150160
continue
@@ -153,5 +163,12 @@ func MakeRequest(r reporter.Reporter, query osv.BatchedQuery, offline bool, loca
153163
results = append(results, osv.Response{Vulns: db.VulnerabilitiesAffectingPackage(pkg)})
154164
}
155165

166+
if len(missingDbs) > 0 {
167+
missingDbs = slices.Compact(missingDbs)
168+
slices.Sort(missingDbs)
169+
170+
r.Errorf("could not find local databases for ecosystems: %s\n", strings.Join(missingDbs, ", "))
171+
}
172+
156173
return &osv.HydratedBatchedResponse{Results: results}, nil
157174
}

0 commit comments

Comments
 (0)