diff --git a/.custom-gcl.yml b/.custom-gcl.yml index 562c21e7a82ddb..1ea22195ccf359 100644 --- a/.custom-gcl.yml +++ b/.custom-gcl.yml @@ -5,3 +5,5 @@ name: golangci-lint plugins: - module: github.com/DataDog/datadog-agent/pkg/linters/components/pkgconfigusage path: ./pkg/linters/components/pkgconfigusage + - module: github.com/DataDog/datadog-agent/pkg/util/testutil + path: ./pkg/util/testutil diff --git a/cmd/trace-agent/test/agent.go b/cmd/trace-agent/test/agent.go index 5d56f75fc24d0e..8deed1feae3364 100644 --- a/cmd/trace-agent/test/agent.go +++ b/cmd/trace-agent/test/agent.go @@ -35,6 +35,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/api/security" pb "github.com/DataDog/datadog-agent/pkg/proto/pbgo/core" grpcutil "github.com/DataDog/datadog-agent/pkg/util/grpc" + utiltest "github.com/DataDog/datadog-agent/pkg/util/testutil" "github.com/DataDog/datadog-agent/pkg/trace/testutil" ) @@ -85,14 +86,7 @@ func buildBinaries(verbose bool) error { if verbose { log.Printf("agent: installing in %s...", binpath) } - // Set environment variables to prevent go build commands from accessing - // the module cache concurrently, which can cause timeouts. - env := append(os.Environ(), - "GOPRIVATE=*", - "GOPROXY=off", - ) - cmd := exec.Command("go", "build", "-tags", "otlp", "-o", binpath, "github.com/DataDog/datadog-agent/cmd/trace-agent") - cmd.Env = env + cmd := utiltest.IsolatedGoBuildCmd(tmpDir, binpath, "-tags", "otlp", "github.com/DataDog/datadog-agent/cmd/trace-agent") o, err := cmd.CombinedOutput() if err != nil { if verbose { @@ -103,8 +97,7 @@ func buildBinaries(verbose bool) error { } binSecrets := filepath.Join(tmpDir, SecretBackendBinary) - cmd = exec.Command("go", "build", "-o", binSecrets, "./testdata/secretscript.go") - cmd.Env = env + cmd = utiltest.IsolatedGoBuildCmd(tmpDir, binSecrets, "./testdata/secretscript.go") o, err = cmd.CombinedOutput() if err != nil { if verbose { diff --git a/comp/core/secrets/impl/fetch_secret_test.go b/comp/core/secrets/impl/fetch_secret_test.go index 14bc590bd6a66d..a43b5ea1c60bc0 100644 --- a/comp/core/secrets/impl/fetch_secret_test.go +++ b/comp/core/secrets/impl/fetch_secret_test.go @@ -12,7 +12,6 @@ import ( "fmt" "maps" "os" - "os/exec" "path/filepath" "runtime" "slices" @@ -26,20 +25,15 @@ import ( "github.com/DataDog/datadog-agent/comp/core/telemetry" nooptelemetry "github.com/DataDog/datadog-agent/comp/core/telemetry/noopsimpl" "github.com/DataDog/datadog-agent/comp/core/telemetry/telemetryimpl" + "github.com/DataDog/datadog-agent/pkg/util/testutil" ) func build(t *testing.T, outTarget string) { - // Create a cache directory for the compiler - pwd, _ := os.Getwd() - cacheDir := filepath.Join(pwd, "cache") - os.Mkdir(cacheDir, 0755) // -mod=vendor ensures the `go` command will not use the network to look // for modules. See https://go.dev/ref/mod#build-commands - cmd := exec.Command("go", "build", "-v", "-mod=vendor", "-o", outTarget) + cmd := testutil.IsolatedGoBuildCmd(t.TempDir(), outTarget, "-v", "-mod=vendor") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - // Append to the command's env vars, which prevents them from affecting other tests - cmd.Env = append(cmd.Env, []string{"GOPROXY=off", "GOPRIVATE=*", "GOCACHE=" + cacheDir}...) err := cmd.Run() if err != nil { t.Fatalf("Could not compile secret backend binary: %s", err) diff --git a/comp/core/secrets/impl/go.mod b/comp/core/secrets/impl/go.mod index 83d917234a00dc..0a65a325c92a49 100644 --- a/comp/core/secrets/impl/go.mod +++ b/comp/core/secrets/impl/go.mod @@ -14,6 +14,7 @@ require ( github.com/DataDog/datadog-agent/pkg/util/defaultpaths v0.70.0 github.com/DataDog/datadog-agent/pkg/util/log v0.68.3 github.com/DataDog/datadog-agent/pkg/util/scrubber v0.68.3 + github.com/DataDog/datadog-agent/pkg/util/testutil v0.59.0 github.com/DataDog/datadog-agent/pkg/util/winutil v0.68.3 github.com/benbjohnson/clock v1.3.5 github.com/stretchr/testify v1.11.1 diff --git a/comp/trace/config/config_test.go b/comp/trace/config/config_test.go index 2bff7eb9a3d039..eefaf34587f803 100644 --- a/comp/trace/config/config_test.go +++ b/comp/trace/config/config_test.go @@ -16,7 +16,6 @@ import ( "net/http" "net/http/httptest" "os" - "os/exec" "path/filepath" "reflect" "regexp" @@ -48,6 +47,7 @@ import ( traceconfig "github.com/DataDog/datadog-agent/pkg/trace/config" "github.com/DataDog/datadog-agent/pkg/util/fxutil" "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/util/testutil" ) // team: agent-apm @@ -380,7 +380,7 @@ func TestConfigHostname(t *testing.T) { } srcpath := filepath.Join(os.TempDir(), stat.Name()) binpath := strings.TrimSuffix(srcpath, ".go") - if err := exec.Command("go", "build", "-o", binpath, srcpath).Run(); err != nil { + if err := testutil.IsolatedGoBuildCmd(t.TempDir(), binpath, srcpath).Run(); err != nil { t.Fatal(err) } os.Remove(srcpath) diff --git a/pkg/linters/components/pkgconfigusage/go.mod b/pkg/linters/components/pkgconfigusage/go.mod index 79007693695913..d2340c6f451bd0 100644 --- a/pkg/linters/components/pkgconfigusage/go.mod +++ b/pkg/linters/components/pkgconfigusage/go.mod @@ -3,6 +3,7 @@ module github.com/DataDog/datadog-agent/pkg/linters/components/pkgconfigusage go 1.24.0 require ( + github.com/DataDog/datadog-agent/pkg/util/testutil v0.0.0-00010101000000-000000000000 github.com/golangci/plugin-module-register v0.1.2 github.com/stretchr/testify v1.11.1 golang.org/x/tools v0.39.0 @@ -11,12 +12,10 @@ require ( require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/rogpeppe/go-internal v1.14.1 // indirect golang.org/x/mod v0.30.0 // indirect golang.org/x/sync v0.18.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/linters/components/pkgconfigusage/go.sum b/pkg/linters/components/pkgconfigusage/go.sum index 3d2c0afeb8e199..a242212b043a86 100644 --- a/pkg/linters/components/pkgconfigusage/go.sum +++ b/pkg/linters/components/pkgconfigusage/go.sum @@ -5,17 +5,12 @@ github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3H github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= diff --git a/pkg/linters/components/pkgconfigusage/pkgconfigusage_test.go b/pkg/linters/components/pkgconfigusage/pkgconfigusage_test.go index 87f75d26ac43df..a24bc3b3e4f9cf 100644 --- a/pkg/linters/components/pkgconfigusage/pkgconfigusage_test.go +++ b/pkg/linters/components/pkgconfigusage/pkgconfigusage_test.go @@ -10,15 +10,15 @@ import ( "path/filepath" "testing" + "github.com/DataDog/datadog-agent/pkg/util/testutil" "github.com/stretchr/testify/assert" "golang.org/x/tools/go/analysis/analysistest" ) func TestAll(t *testing.T) { - // Set environment variables to prevent go commands from accessing - // the module cache concurrently, which can cause timeouts on macOS. - t.Setenv("GOPRIVATE", "*") - t.Setenv("GOPROXY", "off") + for key, value := range testutil.IsolatedGoBuildEnv(t.TempDir()) { + t.Setenv(key, value) + } wd, err := os.Getwd() if err != nil { diff --git a/pkg/util/testutil/gobuild.go b/pkg/util/testutil/gobuild.go new file mode 100644 index 00000000000000..5621f6939b5af2 --- /dev/null +++ b/pkg/util/testutil/gobuild.go @@ -0,0 +1,43 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +// Package testutil provides utilities for testing. +package testutil + +import ( + "os" + "os/exec" +) + +// IsolatedGoBuildCmd creates a "go build" command with isolated build environment. +// This may help reduce timeouts and flakiness when running tests with high parallelism. +// +// cacheDir is the directory to use for GOCACHE. +// output is the path for the output binary. +// args are additional arguments to pass to "go build" (e.g., "-tags", "foo", "source.go"). +// +// See: https://github.com/golang/go/issues/59657 +func IsolatedGoBuildCmd(cacheDir string, output string, args ...string) *exec.Cmd { + cmd := exec.Command("go", append([]string{"build", "-o", output}, args...)...) + cmd.Env = os.Environ() + for key, value := range IsolatedGoBuildEnv(cacheDir) { + cmd.Env = append(cmd.Env, key+"="+value) + } + return cmd +} + +// IsolatedGoBuildEnv returns environment variables for isolated Go build operations. +// This may help reduce timeouts and flakiness when running tests with high parallelism. +// +// cacheDir is the directory to use for GOCACHE. +// +// See: https://github.com/golang/go/issues/59657 +func IsolatedGoBuildEnv(cacheDir string) map[string]string { + return map[string]string{ + "GOCACHE": cacheDir, // avoid concurrent cache access + "GOPRIVATE": "*", // avoid VCS queries + "GOPROXY": "off", // avoid network access + } +}