Skip to content

Commit

Permalink
Support package driver running within test dirs (#188)
Browse files Browse the repository at this point in the history
* split up methods

* tie it up

* Working on an in-repo test

* Clean things up

* version

* can't remember what I added this for
  • Loading branch information
peterebden authored Dec 13, 2023
1 parent 002b60d commit 4691ace
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 4 deletions.
18 changes: 18 additions & 0 deletions third_party/binary/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
remote_file(
name = "gosec_download",
url = ["https://github.com/securego/gosec/releases/download/v2.14.0/gosec_2.14.0_linux_amd64.tar.gz"],
hashes = ["226bd8825b7aed3d454446d1ec094f817f37859dded4211a5b707d0f36c5fdb7"],
test_only = True,
)

genrule(
name = "gosec",
srcs = [":gosec_download"],
tools = [CONFIG.ARCAT_TOOL],
outs = ["gosec"],
cmd = "$TOOLS x $SRCS -s v2.14.0",
binary = True,
test_only = True,
visibility = ["//tools/driver/..."],
)

5 changes: 5 additions & 0 deletions tools/driver/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
Version 0.3.0
-------------
* Add search dir option which walks a current directory rather than querying plz.
Allows running within a Please test.

Version 0.2.3
-------------
* Allow the caller not to provide any input files at all
Expand Down
2 changes: 1 addition & 1 deletion tools/driver/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.3
0.3.0
10 changes: 9 additions & 1 deletion tools/driver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var opts = struct {
NoInput bool `short:"n" long:"no_input" description:"Assume a default config and don't try to read from stdin"`
WorkingDir string `short:"w" long:"working_dir" description:"Change to this working directory before running"`
OutputFile string `short:"o" long:"output_file" env:"PLZ_GOPACKAGESDRIVER_OUTPUT_FILE" description:"File to write output to (in addition to stdout)"`
SearchDir string `short:"s" long:"search_dir" env:"PLZ_GOPACKAGESDRIVER_SEARCHDIR" description:"Search this directory for modinfo files, instead of querying plz"`
Args struct {
Files []string `positional-arg-name:"file"`
} `positional-args:"true"`
Expand Down Expand Up @@ -52,7 +53,7 @@ func main() {
}
log.Debug("Received driver request: %v", req)
}
resp, err := packages.Load(req, opts.Args.Files)
resp, err := load(req)
if err != nil {
log.Fatalf("Failed to load packages: %s", err)
}
Expand All @@ -70,3 +71,10 @@ func main() {
log.Fatalf("Failed to write packages: %s", err)
}
}

func load(req *packages.DriverRequest) (*packages.DriverResponse, error) {
if opts.SearchDir == "" {
return packages.Load(req, opts.Args.Files)
}
return packages.LoadOffline(req, opts.SearchDir, opts.Args.Files)
}
39 changes: 37 additions & 2 deletions tools/driver/packages/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"go/build"
"go/types"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -97,6 +98,35 @@ func Load(req *DriverRequest, files []string) (*DriverResponse, error) {
if err != nil {
return nil, err
}
return packagesToResponse(rootpath, pkgs, dirs)
}

// LoadOffline is like Load but rather than querying plz to find the file to load, it just
// walks a file tree looking for pkg_info.json files.
func LoadOffline(req *DriverRequest, searchDir string, files []string) (*DriverResponse, error) {
pkgs := []*packages.Package{}
if err := filepath.WalkDir(searchDir, func(path string, d fs.DirEntry, err error) error {
lpkgs := []*packages.Package{}
if err != nil || d.IsDir() || !strings.HasSuffix(path, "pkg_info.json") {
return err
} else if b, err := os.ReadFile(path); err != nil {
return fmt.Errorf("failed to read %s: %w", path, err)
} else if err := json.Unmarshal(b, &lpkgs); err != nil {
return fmt.Errorf("failed to decode %s: %w", path, err)
}
pkgs = append(pkgs, lpkgs...)
return nil
}); err != nil {
return nil, err
}
dirs := map[string]struct{}{}
for _, file := range files {
dirs[filepath.Dir(file)] = struct{}{}
}
return packagesToResponse(searchDir, pkgs, dirs)
}

func packagesToResponse(rootpath string, pkgs []*packages.Package, dirs map[string]struct{}) (*DriverResponse, error) {
// Build the set of root packages
seenRoots := map[string]struct{}{}
roots := []string{}
Expand Down Expand Up @@ -207,13 +237,18 @@ func loadPackageInfo(files []string) ([]*packages.Package, error) {
if err := build.Wait(); err != nil {
return nil, handleSubprocessErr(build, err)
}
log.Debug("Loading plz package info files...")
// Now we can read all the package info files from the build process' stdout.
return loadPackageInfoFiles(strings.Fields(strings.TrimSpace(build.Stdout.(*bytes.Buffer).String())))
}

// loadPackageInfoFiles loads the given set of package info files
func loadPackageInfoFiles(paths []string) ([]*packages.Package, error) {
log.Debug("Loading plz package info files...")
pkgs := []*packages.Package{}
var lock sync.Mutex
var g errgroup.Group
g.SetLimit(8) // arbitrary limit since we're doing I/O
for _, file := range strings.Fields(strings.TrimSpace(build.Stdout.(*bytes.Buffer).String())) {
for _, file := range paths {
file := file
if !strings.HasSuffix(file, ".json") {
continue // Ignore all the various Go sources etc.
Expand Down
26 changes: 26 additions & 0 deletions tools/driver/test/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
subinclude("//build_defs:go")

# This is an integration test proving we can run within a test directory; without the
# package driver running, gosec will get import errors from the package and fail.
gentest(
name = "gosec_test",
tools = {
"driver": ["//tools/driver:plz-gopackagesdriver"],
"gosec": ["//third_party/binary:gosec"],
},
deps = [
"//tools/driver/packages",
],
needs_transitive_deps = True,
cmd = [
'export PLZ_GOPACKAGESDRIVER_SEARCHDIR="$TMP_DIR"',
'export GOPACKAGESDRIVER="$TOOLS_DRIVER"',
'"$TOOLS_GOSEC" --exclude G104,G304,G307 tools/driver/packages',
],
test_cmd = "true",
no_test_output = True,
requires = [
"go",
"go_src",
],
)

0 comments on commit 4691ace

Please sign in to comment.