Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the GetDependenciesList for Go to accept an error handler #255

Merged
merged 5 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/golang.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (gm *GoModule) loadDependencies() ([]entities.Dependency, error) {
}

func (gm *GoModule) getGoDependencies(cachePath string) (map[string]entities.Dependency, error) {
modulesMap, err := utils.GetDependenciesList(gm.srcPath, gm.containingBuild.logger)
modulesMap, err := utils.GetDependenciesList(gm.srcPath, gm.containingBuild.logger, nil)
if err != nil || len(modulesMap) == 0 {
return nil, err
}
Expand Down
13 changes: 11 additions & 2 deletions utils/goutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,25 @@ func getListCmdArgs() (cmdArgs []string, err error) {
return []string{"list", "-mod=mod"}, nil
}

// The handle error function is designed to manage errors that occur while running the
// 'go list' command. If the function returns true, the error will be propagated back to the caller.
type HandleErrorFunc func(err error) (bool, error)
asafambar marked this conversation as resolved.
Show resolved Hide resolved

// Runs go list -f {{with .Module}}{{.Path}}:{{.Version}}{{end}} all command and returns map of the dependencies
func GetDependenciesList(projectDir string, log Log) (map[string]bool, error) {
func GetDependenciesList(projectDir string, log Log, handleError HandleErrorFunc) (map[string]bool, error) {
cmdArgs, err := getListCmdArgs()
if err != nil {
return nil, err
}
output, err := runDependenciesCmd(projectDir, append(cmdArgs, "-f", "{{with .Module}}{{.Path}}:{{.Version}}{{end}}", "all"), log)
if err != nil {
// Errors occurred while running "go list". Run again and this time ignore errors (with '-e')
log.Warn("Errors occurred while building the Go dependency tree. The dependency tree may be incomplete: " + err.Error())
if handleError != nil {
if stop, newErr := handleError(err); stop {
return nil, newErr
}
}
// Errors occurred while running "go list". Run again and this time ignore errors (with '-e')
output, err = runDependenciesCmd(projectDir, append(cmdArgs, "-e", "-f", "{{with .Module}}{{.Path}}:{{.Version}}{{end}}", "all"), log)
attiasas marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
Expand Down
20 changes: 16 additions & 4 deletions utils/goutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,24 @@ func TestGetProjectRoot(t *testing.T) {
}

func TestGetDependenciesList(t *testing.T) {
testGetDependenciesList(t, "testGoList")
testGetDependenciesList(t, "testGoList", nil)
}

func TestGetDependenciesListWithIgnoreErrors(t *testing.T) {
// In some cases, we see that running go list on some Go packages may fail.
// We should allow ignoring the errors in such cases and build the Go dependency tree, even if partial.
testGetDependenciesList(t, "testBadGoList")
testGetDependenciesList(t, "testBadGoList", nil)
// In some cases we would like to exit after we receive an error. This can be done with custom error handle func.
// This test handleErrorFunc return an error
testGetDependenciesList(t, "testBadGoList", func(err error) (bool, error) {
if err != nil {
return true, err
}
return false, nil
})
}

func testGetDependenciesList(t *testing.T, testDir string) {
func testGetDependenciesList(t *testing.T, testDir string, errorFunc HandleErrorFunc) {
log := NewDefaultLogger(ERROR)
goModPath := filepath.Join("testdata", "mods", testDir)
err := os.Rename(filepath.Join(goModPath, "go.mod.txt"), filepath.Join(goModPath, "go.mod"))
Expand All @@ -113,7 +121,11 @@ func testGetDependenciesList(t *testing.T, testDir string) {
err = os.Rename(filepath.Join(goModPath, "test.go"), filepath.Join(goModPath, "test.go.txt"))
assert.NoError(t, err)
}()
actual, err := GetDependenciesList(goModPath, log)
actual, err := GetDependenciesList(goModPath, log, errorFunc)
if errorFunc != nil {
assert.Error(t, err)
return
}
assert.NoError(t, err)

// Since Go 1.16 'go list' command won't automatically update go.mod and go.sum.
Expand Down
Loading