diff --git a/go.mod b/go.mod index c062d9c..ac7a8c6 100644 --- a/go.mod +++ b/go.mod @@ -3,90 +3,107 @@ module github.com/DataDog/ddtest go 1.24.5 require ( - github.com/DataDog/dd-trace-go/v2 v2.1.0 + github.com/DataDog/dd-trace-go/v2 v2.4.1 github.com/bmatcuk/doublestar/v4 v4.9.1 - github.com/spf13/cobra v1.9.1 - github.com/spf13/viper v1.20.1 - github.com/tinylib/msgp v1.2.5 - golang.org/x/sync v0.13.0 - golang.org/x/sys v0.33.0 + github.com/spf13/cobra v1.10.2 + github.com/spf13/viper v1.21.0 + github.com/tinylib/msgp v1.6.1 + golang.org/x/sync v0.19.0 + golang.org/x/sys v0.39.0 ) require ( github.com/DataDog/appsec-internal-go v1.13.0 // indirect - github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.66.1 // indirect - github.com/DataDog/datadog-agent/pkg/obfuscate v0.66.1 // indirect - github.com/DataDog/datadog-agent/pkg/proto v0.66.1 // indirect - github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.66.1 // indirect - github.com/DataDog/datadog-agent/pkg/trace v0.66.1 // indirect - github.com/DataDog/datadog-agent/pkg/util/log v0.66.1 // indirect - github.com/DataDog/datadog-agent/pkg/util/scrubber v0.66.1 // indirect - github.com/DataDog/datadog-agent/pkg/version v0.66.1 // indirect - github.com/DataDog/datadog-go/v5 v5.6.0 // indirect - github.com/DataDog/go-libddwaf/v4 v4.3.0 // indirect - github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20250603194815-7edb7c2ad56a // indirect - github.com/DataDog/go-sqllexer v0.1.6 // indirect - github.com/DataDog/go-tuf v1.1.0-0.5.2 // indirect + github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.73.1 // indirect + github.com/DataDog/datadog-agent/pkg/obfuscate v0.73.1 // indirect + github.com/DataDog/datadog-agent/pkg/opentelemetry-mapping-go/otlp/attributes v0.73.1 // indirect + github.com/DataDog/datadog-agent/pkg/proto v0.73.1 // indirect + github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.73.1 // indirect + github.com/DataDog/datadog-agent/pkg/trace v0.73.1 // indirect + github.com/DataDog/datadog-agent/pkg/util/log v0.73.1 // indirect + github.com/DataDog/datadog-agent/pkg/util/scrubber v0.73.1 // indirect + github.com/DataDog/datadog-agent/pkg/version v0.73.1 // indirect + github.com/DataDog/datadog-go/v5 v5.8.2 // indirect + github.com/DataDog/go-libddwaf/v4 v4.8.0 // indirect + github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20251212063323-045b5797c628 // indirect + github.com/DataDog/go-sqllexer v0.1.10 // indirect + github.com/DataDog/go-tuf v1.1.1-0.5.2 // indirect github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes v0.26.0 // indirect github.com/DataDog/sketches-go v1.4.7 // indirect - github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 // indirect - github.com/ebitengine/purego v0.8.3 // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/ebitengine/purego v0.9.1 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect + github.com/klauspost/compress v1.18.2 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect + github.com/minio/simdjson-go v0.4.5 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/outcaste-io/ristretto v0.2.3 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect - github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/philhofer/fwd v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect - github.com/sagikazarmark/locafero v0.7.0 // indirect - github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect - github.com/shirou/gopsutil/v4 v4.25.1 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.12.0 // indirect - github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect - github.com/stretchr/testify v1.10.0 // indirect + github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect + github.com/shirou/gopsutil/v4 v4.25.11 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/stretchr/testify v1.11.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/tklauser/go-sysconf v0.3.14 // indirect - github.com/tklauser/numcpus v0.8.0 // indirect + github.com/theckman/httpforwarded v0.4.0 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.opentelemetry.io/collector/component v1.28.1 // indirect - go.opentelemetry.io/collector/pdata v1.28.1 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.122.1 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/collector/component v1.48.0 // indirect + go.opentelemetry.io/collector/featuregate v1.48.0 // indirect + go.opentelemetry.io/collector/internal/telemetry v0.142.0 // indirect + go.opentelemetry.io/collector/pdata v1.48.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.138.0 // indirect go.opentelemetry.io/collector/semconv v0.122.1 // indirect - go.opentelemetry.io/otel v1.35.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect + go.opentelemetry.io/contrib/bridges/otelzap v0.14.0 // indirect + go.opentelemetry.io/otel v1.39.0 // indirect + go.opentelemetry.io/otel/log v0.15.0 // indirect + go.opentelemetry.io/otel/metric v1.39.0 // indirect + go.opentelemetry.io/otel/sdk v1.39.0 // indirect + go.opentelemetry.io/otel/trace v1.39.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect - golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.23.0 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/text v0.24.0 // indirect - golang.org/x/time v0.11.0 // indirect - golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99 // indirect - google.golang.org/grpc v1.71.1 // indirect - google.golang.org/protobuf v1.36.6 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/exp v0.0.0-20251209150349-8475f28825e9 // indirect + golang.org/x/mod v0.31.0 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/text v0.32.0 // indirect + golang.org/x/time v0.14.0 // indirect + golang.org/x/tools v0.40.0 // indirect + golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251213004720-97cd9d5aeac2 // indirect + google.golang.org/grpc v1.77.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 7634e1c..39902b0 100644 --- a/go.sum +++ b/go.sum @@ -2,32 +2,74 @@ github.com/DataDog/appsec-internal-go v1.13.0 h1:aO6DmHYsAU8BNFuvYJByhMKGgcQT3WA github.com/DataDog/appsec-internal-go v1.13.0/go.mod h1:9YppRCpElfGX+emXOKruShFYsdPq7WEPq/Fen4tYYpk= github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.66.1 h1:tUnckL/NqYQiSN4ceOe5E/qM9vxmU3p77RdHgXC3VNE= github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.66.1/go.mod h1:u/ZS2pzrBQ1LokbEvFULjn1SfX+If31uqtz6MJ7UaFo= +github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.71.0/go.mod h1:y05SPqKEtrigKul+JBVM69ehv3lOgyKwrUIwLugoaSI= +github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.73.1 h1:u1C8qzKMXs9MAzLOXHnJNUF/jtPxvTe0R/L5WX1a6yw= +github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.73.1/go.mod h1:/Pbx7d3ZcatpCazPG0tEpUUTAZ30oMT/jAKF3C0peQ8= github.com/DataDog/datadog-agent/pkg/obfuscate v0.66.1 h1:sZEua4ArlPJyn8DxpIw85iYuDSmCXp1h/utS4jHj8Lo= github.com/DataDog/datadog-agent/pkg/obfuscate v0.66.1/go.mod h1:NH6IHfS2BEWP3i8JBxr6EIuD4TXprGny8dJZZs5QdwQ= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.71.0/go.mod h1:B3T0If+WdWAwPMpawjm1lieJyqSI0v04dQZHq15WGxY= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.73.1 h1:Oz9h4pxhFIeoT8tD8sTuUOaF3eCRcXxgXey32wG9NzY= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.73.1/go.mod h1:09fwpmPZ058CfhFUmSwMd/7OADA/dCP/L0RH3tXsNFY= +github.com/DataDog/datadog-agent/pkg/opentelemetry-mapping-go/otlp/attributes v0.73.1 h1:uC5BTniVC73ZbeuC2L/LHzSrtkCxBPX52A20EMIy3aQ= +github.com/DataDog/datadog-agent/pkg/opentelemetry-mapping-go/otlp/attributes v0.73.1/go.mod h1:vJVeGjnFFkiMTB9tqLljia1vU1aMhfVrsUyoCxZbCTc= github.com/DataDog/datadog-agent/pkg/proto v0.66.1 h1:Uqg1gcYDI3RktFr599PWwF05FOEQQgbPMvE9oTSi8NA= github.com/DataDog/datadog-agent/pkg/proto v0.66.1/go.mod h1:W81BWdx7VxgdshvJuyZhDfWWwJAHROEi4yXX25yzX5A= +github.com/DataDog/datadog-agent/pkg/proto v0.71.0/go.mod h1:KSn4jt3CykV6CT1C8Rknn/Nj3E+VYHK/UDWolg/+kzw= +github.com/DataDog/datadog-agent/pkg/proto v0.73.1 h1:QLwHnTbwRGBcJoaRhmdhp2lSfpDLV4b3cy8JDl72WSM= +github.com/DataDog/datadog-agent/pkg/proto v0.73.1/go.mod h1:6GW+FTy5w8cRZUCdeH6jVV1imr5SIFGaGGqmhyyAeOs= github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.66.1 h1:hA8dg5pgpUXEKFBhcrcb+U6r9h1q3hy+6jYqeC3rZX8= github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.66.1/go.mod h1:/AzUUTZn8FZj3xUFJxMh/0/NPqpjsv2z+IMXG/IxRFc= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.73.0-rc.1/go.mod h1:lwkSvCXABHXyqy6mG9WBU6MTK9/E0i0R8JVApUtT+XA= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.73.1 h1:SDvt6KNaiD1Lu5YuJxluXgVPYMdv2kr3sKcg8+jGs7o= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.73.1/go.mod h1:h1Re2DnnB2qT/rzRNdQ4FAzxjhVsIJlscPA5SFiz7+U= github.com/DataDog/datadog-agent/pkg/trace v0.66.1 h1:MuZqPlRLEF3dPKtGbn4H4cvdfLIQRncZft6JUtAwy5I= github.com/DataDog/datadog-agent/pkg/trace v0.66.1/go.mod h1:S+GWyA8N6JT/DHi08xt63kn957wPZs0Kg5ClaY2FPgc= +github.com/DataDog/datadog-agent/pkg/trace v0.71.0/go.mod h1:wfVwOlKORIB4IB1vdncTuCTx/OrVU69TLBIiBpewe1Q= +github.com/DataDog/datadog-agent/pkg/trace v0.73.1 h1:WDUEhRbc93A/Te8XdD3RyicNxaTHhA3tE/VcCtFWHf8= +github.com/DataDog/datadog-agent/pkg/trace v0.73.1/go.mod h1:rjS+1XwMGpCFrlBw1khuJMHPSXVlJ+K8pBaYzjzSPUM= github.com/DataDog/datadog-agent/pkg/util/log v0.66.1 h1:QE97RJCDO2ZplOqlQM2Oq3S/JKDpI3okdpj+y6rmncU= github.com/DataDog/datadog-agent/pkg/util/log v0.66.1/go.mod h1:TBGT1NFg9Essf3ypyegWT74PKbIzTuHAHM9V3B+3vXY= +github.com/DataDog/datadog-agent/pkg/util/log v0.71.0/go.mod h1:oG6f6Qe23zPTLOVh0nXjlIXohrjUGXeFjh7S3Na/WyU= +github.com/DataDog/datadog-agent/pkg/util/log v0.73.1 h1:cRoZF3/5zyatqSdYXRBnr9zKZqBz0iir3UFE3SkscwE= +github.com/DataDog/datadog-agent/pkg/util/log v0.73.1/go.mod h1:yT7FVP+Yo0FCEmNUNDYL1x5pFWOOkDvQG3Ru2e4MiNE= github.com/DataDog/datadog-agent/pkg/util/scrubber v0.66.1 h1:K7b6+7ZxrC8mvgMJNpCzCshmNUMEkAWRrNWQZvHVIh8= github.com/DataDog/datadog-agent/pkg/util/scrubber v0.66.1/go.mod h1:1ebZZr2A/0LnD76aK+m1leTOAjKVkJUjCvaw+wTQEcI= +github.com/DataDog/datadog-agent/pkg/util/scrubber v0.71.0/go.mod h1:/JHi9UFqdFYy/SFmFozY26dNOl/ODVLSQaF1LKDPiBI= +github.com/DataDog/datadog-agent/pkg/util/scrubber v0.73.1 h1:k7Ok12nDySjw/5pEWi9nIhgCMt0Yydwdo2UL27u0Lw4= +github.com/DataDog/datadog-agent/pkg/util/scrubber v0.73.1/go.mod h1:Olp6tk+EQq2s9WwV3JaSmXERPNV9z17IdiOHyhQFFQg= github.com/DataDog/datadog-agent/pkg/version v0.66.1 h1:8eJdgkO/o4/5RlF3u29j0QO8eotaqE+fwKOkIHNJ8RY= github.com/DataDog/datadog-agent/pkg/version v0.66.1/go.mod h1:LXOHXAHH+vqBwmQKcZa5FgBEi4ECKIC2WsV2Jd9VVJ0= +github.com/DataDog/datadog-agent/pkg/version v0.71.0/go.mod h1:FYj51C1ib86rpr5tlLEep9jitqvljIJ5Uz2rrimGTeY= +github.com/DataDog/datadog-agent/pkg/version v0.73.1 h1:mk/nD9bhOKRtlClgPAPxLBJb8tYdhIhH94BgKUrTHN0= +github.com/DataDog/datadog-agent/pkg/version v0.73.1/go.mod h1:6NoHdUrJ/ttav4SSas6XiDLfYbF4Ulx0D0cBpbk4vvI= github.com/DataDog/datadog-go/v5 v5.6.0 h1:2oCLxjF/4htd55piM75baflj/KoE6VYS7alEUqFvRDw= github.com/DataDog/datadog-go/v5 v5.6.0/go.mod h1:K9kcYBlxkcPP8tvvjZZKs/m1edNAUFzBbdpTUKfCsuw= +github.com/DataDog/datadog-go/v5 v5.8.2 h1:9IEfH1Mw9AjWwhAMqCAkhbxjuJeMxm2ARX2VdgL+ols= +github.com/DataDog/datadog-go/v5 v5.8.2/go.mod h1:K9kcYBlxkcPP8tvvjZZKs/m1edNAUFzBbdpTUKfCsuw= github.com/DataDog/dd-trace-go/v2 v2.1.0 h1:hnwcE5qwj/sPbi+GW0O8UDQx5sNCRBwF4m4QRlgWMDA= github.com/DataDog/dd-trace-go/v2 v2.1.0/go.mod h1:W1W3dR5b77xwozt/o9JqLGh1cdhydIQOHIfzcyQVHVs= +github.com/DataDog/dd-trace-go/v2 v2.4.1 h1:1WU/Kv1jPIo7QT8boObUbZMrnTlGE7346mSyq4l6aag= +github.com/DataDog/dd-trace-go/v2 v2.4.1/go.mod h1:EEOkhOJlb37u+k07/9cwKCvtDC/mWjWnHrGkkk/iZCo= github.com/DataDog/go-libddwaf/v4 v4.3.0 h1:BZfKyLSbY2YMSn7hEBFN1qlDXI2rMEquOeTiRbSg4xk= github.com/DataDog/go-libddwaf/v4 v4.3.0/go.mod h1:/AZqP6zw3qGJK5mLrA0PkfK3UQDk1zCI2fUNCt4xftE= +github.com/DataDog/go-libddwaf/v4 v4.6.1 h1:wGUioRkQ2a5MYr2wTn5uZfMENbLV4uKXrkr6zCVInCs= +github.com/DataDog/go-libddwaf/v4 v4.6.1/go.mod h1:/AZqP6zw3qGJK5mLrA0PkfK3UQDk1zCI2fUNCt4xftE= +github.com/DataDog/go-libddwaf/v4 v4.8.0 h1:m6Bl1lS2RtVN4MtdTYhR5vJ2fWQ3WmNy4FiNBpzrp6w= +github.com/DataDog/go-libddwaf/v4 v4.8.0/go.mod h1:/AZqP6zw3qGJK5mLrA0PkfK3UQDk1zCI2fUNCt4xftE= github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20250603194815-7edb7c2ad56a h1:+tlbkP/WtD+t0ZDoXIkvqeCd5kj8sl5jN/POUhqFNS8= github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20250603194815-7edb7c2ad56a/go.mod h1:quaQJ+wPN41xEC458FCpTwyROZm3MzmTZ8q8XOXQiPs= +github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20250721125240-fdf1ef85b633/go.mod h1:YFoTl1xsMzdSRFIu33oCSPS/3+HZAPGpO3oOM96wXCM= +github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20251212063323-045b5797c628 h1:EGXA5ywBPeIPuuTwwlbGqUCXJvyyUfKc1TS0MAY1ID8= +github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20251212063323-045b5797c628/go.mod h1:YFoTl1xsMzdSRFIu33oCSPS/3+HZAPGpO3oOM96wXCM= github.com/DataDog/go-sqllexer v0.1.6 h1:skEXpWEVCpeZFIiydoIa2f2rf+ymNpjiIMqpW4w3YAk= github.com/DataDog/go-sqllexer v0.1.6/go.mod h1:GGpo1h9/BVSN+6NJKaEcJ9Jn44Hqc63Rakeb+24Mjgo= +github.com/DataDog/go-sqllexer v0.1.8/go.mod h1:GGpo1h9/BVSN+6NJKaEcJ9Jn44Hqc63Rakeb+24Mjgo= +github.com/DataDog/go-sqllexer v0.1.10 h1:lisiFE4du178mdBooAx3KlV3MsdwzJePNHbtdCMmFBw= +github.com/DataDog/go-sqllexer v0.1.10/go.mod h1:vOw7Ia7z+z6nl3zGZlLIZe0vQlPtCPR906WIPBJadxc= github.com/DataDog/go-tuf v1.1.0-0.5.2 h1:4CagiIekonLSfL8GMHRHcHudo1fQnxELS9g4tiAupQ4= github.com/DataDog/go-tuf v1.1.0-0.5.2/go.mod h1:zBcq6f654iVqmkk8n2Cx81E1JnNTMOAx1UEO/wZR+P0= +github.com/DataDog/go-tuf v1.1.1-0.5.2 h1:YWvghV4ZvrQsPcUw8IOUMSDpqc3W5ruOIC+KJxPknv0= +github.com/DataDog/go-tuf v1.1.1-0.5.2/go.mod h1:zBcq6f654iVqmkk8n2Cx81E1JnNTMOAx1UEO/wZR+P0= github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4= github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes v0.26.0 h1:GlvoS6hJN0uANUC3fjx72rOgM4StAKYo2HtQGaasC7s= @@ -36,11 +78,15 @@ github.com/DataDog/sketches-go v1.4.7 h1:eHs5/0i2Sdf20Zkj0udVFWuCrXGRFig2Dcfm5rt github.com/DataDog/sketches-go v1.4.7/go.mod h1:eAmQ/EBmtSO+nQp7IZMZVRPT4BQTmIc5RZQ+deGlTPM= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE= github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -54,6 +100,7 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -61,12 +108,20 @@ github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 h1:8EXxF+tCLqaVk8 github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4/go.mod h1:I5sHm0Y0T1u5YjlyqC5GVArM7aNZRUYtTjmJ8mPJFds= github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc= github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= +github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -91,6 +146,8 @@ github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgY github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -99,27 +156,47 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= +github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI= github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 h1:PwQumkgq4/acIiZhtifTV5OUqqiP82UAl0h87xj/l9k= +github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/minio/simdjson-go v0.4.5 h1:r4IQwjRGmWCQ2VeMc7fGiilu1z5du0gJ/I/FsKwgo5A= +github.com/minio/simdjson-go v0.4.5/go.mod h1:eoNz0DcLQRyEDeaPr4Ru6JpjlZPzbA0IodxVJk8lO8E= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/sampling v0.122.0 h1:n0nWcGanaHanlih+YRp8etj1/fYZoQFRk+7+/J85dpU= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/sampling v0.122.0/go.mod h1:MMvJIC26DIEZo5DR4Ub/WJD1aPVxKGpgJolXxTtjgLE= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/sampling v0.133.0 h1:iPei+89a2EK4LuN4HeIRzZNE6XxCyrKfBKG3BkK/ViU= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/sampling v0.138.0 h1:1F3Bw4+unBsQYEaUYyW12PRd4ABLfGjXI3qasvmO8Hg= github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.122.0 h1:zuqwUU8P+IqQMHvMYHlTBXt8lRn1Zu2B9QNAscLP+9A= github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.122.0/go.mod h1:vtHjtQU0UlTHBthmnTv8nK0h0GFWQhgxtOVbav87YoU= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.133.0 h1:4ca2pM3+xDMB9H3UnhjAiNg7EpIydZ7HdohOexU8xb8= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.138.0 h1:z1vDaoN5aXpvn3l3IpRRTOdsMGe5F4NKSl3TK8ZSy/w= github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY= github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= +github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= +github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= @@ -138,25 +215,46 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc= github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw= +github.com/secure-systems-lab/go-securesystemslib v0.9.1 h1:nZZaNz4DiERIQguNy0cL5qTdn9lR8XKHf4RUyG1Sx3g= +github.com/secure-systems-lab/go-securesystemslib v0.9.1/go.mod h1:np53YzT0zXGMv6x4iEWc9Z59uR+x+ndLwCLqPYpLXVU= github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= +github.com/shirou/gopsutil/v4 v4.25.8-0.20250809033336-ffcdc2b7662f h1:S+PHRM3lk96X0/cGEGUukqltzkX/ekUx0F9DoCGK1G0= +github.com/shirou/gopsutil/v4 v4.25.8-0.20250809033336-ffcdc2b7662f/go.mod h1:4f4j4w8HLMPWEFs3BO2UBBLigKAaWYwkSkbIt/6Q4Ss= +github.com/shirou/gopsutil/v4 v4.25.11 h1:X53gB7muL9Gnwwo2evPSE+SfOrltMoR6V3xJAXZILTY= +github.com/shirou/gopsutil/v4 v4.25.11/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -170,14 +268,27 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/theckman/httpforwarded v0.4.0 h1:N55vGJT+6ojTnLY3LQCNliJC4TW0P0Pkeys1G1WpX2w= +github.com/theckman/httpforwarded v0.4.0/go.mod h1:GVkFynv6FJreNbgH/bpOU9ITDZ7a5WuzdNCtIMI1pVI= github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po= github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0= +github.com/tinylib/msgp v1.6.1 h1:ESRv8eL3u+DNHUoSAAQRE50Hm162zqAnBoGv9PzScPY= +github.com/tinylib/msgp v1.6.1/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= +github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= +github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= +github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/vmihailenco/msgpack/v4 v4.3.13 h1:A2wsiTbvp63ilDaWmsk2wjx6xZdxQOvpiNlKBGKKXKI= github.com/vmihailenco/msgpack/v4 v4.3.13/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= @@ -189,44 +300,99 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/collector/component v1.28.1 h1:JjwfvLR0UdadRDAANAdM4mOSwGmfGO3va2X+fdk4YdA= go.opentelemetry.io/collector/component v1.28.1/go.mod h1:jwZRDML3tXo1whueZdRf+y6z3DeEYTLPBmb/O1ujB40= +go.opentelemetry.io/collector/component v1.39.0 h1:GJw80zXURBG4h0sh97bPLEn2Ra+NAWUpskaooA0wru4= +go.opentelemetry.io/collector/component v1.39.0/go.mod h1:NPaMPTLQuxm5QaaWdqkxYKztC0bRdV+86Q9ir7xS/2k= +go.opentelemetry.io/collector/component v1.48.0 h1:0hZKOvT6fIlXoE+6t40UXbXOH7r/h9jyE3eIt0W19Qg= +go.opentelemetry.io/collector/component v1.48.0/go.mod h1:Kmc9Z2CT53M2oRRf+WXHUHHgjCC+ADbiqfPO5mgZe3g= go.opentelemetry.io/collector/component/componentstatus v0.122.1 h1:zMQC0y8ZBITa87GOwEANdOoAox5I4UgaIHxY79nwCbk= go.opentelemetry.io/collector/component/componentstatus v0.122.1/go.mod h1:ZYwOgoXyPu4gGqfQ5DeaEpStpUCD/Clctz4rMd9qQYw= +go.opentelemetry.io/collector/component/componentstatus v0.133.0 h1:fIcFKg+yPhpvOJKeMph9TtSC4DIGdIuNmxvUB0UGcoc= +go.opentelemetry.io/collector/component/componentstatus v0.138.0 h1:KUZyp1b6W2UUb/m/IhakL4bBdX6cbBj0PPx7MZ/jtOo= go.opentelemetry.io/collector/component/componenttest v0.122.1 h1:HE4oeLub2FWVTUzCQG6SWwfnJfcK1FMknXhGQ2gOxnY= go.opentelemetry.io/collector/component/componenttest v0.122.1/go.mod h1:o3Xq6z3C0aVhrd/fD56aKxShrILVnHnbgQVP5NoFuic= +go.opentelemetry.io/collector/component/componenttest v0.133.0 h1:mg54QqXC+GNqLHa9y6Efh3X5Di4XivjgJr6mzvfVQR8= +go.opentelemetry.io/collector/component/componenttest v0.138.0 h1:7a8whPDFu80uPk73iqeMdhYDVxl4oZEsuaBYb2ysXTc= go.opentelemetry.io/collector/consumer v1.28.1 h1:3lHW2e0i7kEkbDqK1vErA8illqPpwDxMzgc5OUDsJ0Y= go.opentelemetry.io/collector/consumer v1.28.1/go.mod h1:g0T16JPMYFN6T2noh+1YBxJSt5i5Zp+Y0Y6pvkMqsDQ= +go.opentelemetry.io/collector/consumer v1.39.0 h1:Jc6la3uacHbznX5ORmh16Nddh23ZxBzoiNF2L0wD2Ks= +go.opentelemetry.io/collector/consumer v1.44.0 h1:vkKJTfQYBQNuKas0P1zv1zxJjHvmMa/n7d6GiSHT0aw= go.opentelemetry.io/collector/consumer/consumertest v0.122.1 h1:LKkLMdWwJCuOYyCMVzwc0OG9vncIqpl8Tp9+H8RikNg= go.opentelemetry.io/collector/consumer/consumertest v0.122.1/go.mod h1:pYqWgx62ou3uUn8nlt2ohRyKod+7xLTf/uA3YfRwVkA= +go.opentelemetry.io/collector/consumer/consumertest v0.133.0 h1:MteqaGpgmHVHFqnB7A2voGleA2j51qJyVfX5x/wm+8I= +go.opentelemetry.io/collector/consumer/consumertest v0.138.0 h1:1PwWhjQ3msYhcml/YeeSegjUAVC4nlA8+LY5uKqJbHk= go.opentelemetry.io/collector/consumer/xconsumer v0.122.1 h1:iK1hGbho/XICdBfGb4MnKwF9lnhLmv09yQ4YlVm+LGo= go.opentelemetry.io/collector/consumer/xconsumer v0.122.1/go.mod h1:xYbRPP1oWcYUUDQJTlv78M/rlYb+qE4weiv++ObZRSU= +go.opentelemetry.io/collector/consumer/xconsumer v0.133.0 h1:Xx4Yna/We4qDlbAla1nfxgkvujzWRuR8bqqwsLLvYSg= +go.opentelemetry.io/collector/consumer/xconsumer v0.138.0 h1:peQ59TyBmt30lv4YH8gfBbTSJPuPIZW0kpFTfk45rVk= +go.opentelemetry.io/collector/featuregate v1.48.0 h1:jiGRcl93yzUFgZVDuskMAftFraE21jANdxXTQfSQScc= +go.opentelemetry.io/collector/featuregate v1.48.0/go.mod h1:/1bclXgP91pISaEeNulRxzzmzMTm4I5Xih2SnI4HRSo= +go.opentelemetry.io/collector/internal/telemetry v0.142.0 h1:ALK9O2AYWuptSGSFzNW0BL6hFq7sf2lxwTrGQa45Nic= +go.opentelemetry.io/collector/internal/telemetry v0.142.0/go.mod h1:Nuf7neseGamZJQjpf8f6yk4qrvb0YrSnuSzh5u0GwbQ= go.opentelemetry.io/collector/pdata v1.28.1 h1:ORl5WLpQJvjzBVpHu12lqKMdcf/qDBwRXMcUubhybiQ= go.opentelemetry.io/collector/pdata v1.28.1/go.mod h1:asKE8MD/4SOKz1mCrGdAz4VO2U2HUNg8A6094uK7pq0= +go.opentelemetry.io/collector/pdata v1.39.0 h1:jr0f033o57Hpbj2Il8M15tPbvrOgY/Aoc+/+sxzhSFU= +go.opentelemetry.io/collector/pdata v1.39.0/go.mod h1:jmolu6zwqNaq8qJ4IgCpNWBEwJNPLE1qqOz9GnpqxME= +go.opentelemetry.io/collector/pdata v1.48.0 h1:CKZ+9v/lGTX/cTGx2XVp8kp0E8R//60kHFCBdZudrTg= +go.opentelemetry.io/collector/pdata v1.48.0/go.mod h1:jaf2JQGpfUreD1TOtGBPsq00ecOqM66NG15wALmdxKA= go.opentelemetry.io/collector/pdata/pprofile v0.122.1 h1:25Fs0eL/J/M2ZEaVplesbI1H7pYx462zUUVxVOszpOg= go.opentelemetry.io/collector/pdata/pprofile v0.122.1/go.mod h1:+jSjgb4zRnNmr1R/zgVLVyTVSm9irfGrvGTrk3lDxSE= +go.opentelemetry.io/collector/pdata/pprofile v0.133.0 h1:ewFYqV2FU4D0ixTdkJueaI2JGCoeiIJisX8EdHejDi8= +go.opentelemetry.io/collector/pdata/pprofile v0.133.0/go.mod h1:5l4/B0iCxzoVkA7eOLzIHV0AUEO2IKypTHTLq9JKsHs= +go.opentelemetry.io/collector/pdata/pprofile v0.138.0 h1:ElnIPJK8jVzHYSnzbIVjg/v2Yq8iVLUKf7kB00zUFlE= +go.opentelemetry.io/collector/pdata/pprofile v0.138.0/go.mod h1:M7/5+Q4LohEkEB38kHhFu3S3XCA1eGSGz5uSXvNyMlM= go.opentelemetry.io/collector/pdata/testdata v0.122.1 h1:9DO8nUUnPAGYMKmrep6wLAfOHprvKY4w/7LpE4jldPQ= go.opentelemetry.io/collector/pdata/testdata v0.122.1/go.mod h1:hYdNrn8KxFwq1nf44YYRgNhDjJTBzoyEr/Qa26pN0t4= +go.opentelemetry.io/collector/pdata/testdata v0.133.0 h1:K0q47qecWVJf0sWbeWfifbJ72TiqR+A2PCsMkCEKvus= +go.opentelemetry.io/collector/pdata/testdata v0.138.0 h1:6geeGQ4Rsb88OARLcACKn09PVIbhExaNJ1aC9OVLZaw= go.opentelemetry.io/collector/pipeline v0.122.1 h1:f0uuiDmanVyKwfYo6cWveJsGbLXidV7i+Z7u8QJwWxI= go.opentelemetry.io/collector/pipeline v0.122.1/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= +go.opentelemetry.io/collector/pipeline v1.39.0 h1:CcEn30qdoHEzehFxgx0Ma0pWYGhrrIkRkcu218NG4V4= +go.opentelemetry.io/collector/pipeline v1.44.0 h1:EFdFBg3Wm2BlMtQbUeork5a4KFpS6haInSr+u/dk8rg= go.opentelemetry.io/collector/processor v0.122.1 h1:AvZvEujq8+FYdJsm9lmAMwuuae5Y2/vKIkOJwsoxsxQ= go.opentelemetry.io/collector/processor v0.122.1/go.mod h1:nYKctftba7SbdLml6LxgIrnYRXCShDe2bnNWjTIpF7g= +go.opentelemetry.io/collector/processor v1.39.0 h1:QwPJxJnFZwojo09Vfnvph7A27TauxxvA1koO6nr87O8= +go.opentelemetry.io/collector/processor v1.44.0 h1:jB+vfkYSR9f7HJlGJrtncld9dmnPWndCoTHZ0Wz4nvg= go.opentelemetry.io/collector/processor/processortest v0.122.1 h1:n4UOx1mq+kLaRiHGsu7vBLq+EGXfzWhSxyFweMjMl54= go.opentelemetry.io/collector/processor/processortest v0.122.1/go.mod h1:8/NRWx18tNJMBwCQ8/YPWr4qsFUrwk27qE7/dXoJb1M= +go.opentelemetry.io/collector/processor/processortest v0.133.0 h1:PAuOr8Pwj/LAuey2LW1fix0vvnE+WwGpSF7bghaxjEE= +go.opentelemetry.io/collector/processor/processortest v0.138.0 h1:WSHPESV1NqPHlt9ShzTlc9y7ZLf83223fyfC4wzJoZg= go.opentelemetry.io/collector/processor/xprocessor v0.122.1 h1:Wfv4/7n4YK1HunAVTMS6yf0xmDjCkftJ6EECNcSwzfs= go.opentelemetry.io/collector/processor/xprocessor v0.122.1/go.mod h1:9zMW3NQ9+DzcJ1cUq5BhZg3ajoUEMGhNY0ZdYjpX+VI= +go.opentelemetry.io/collector/processor/xprocessor v0.133.0 h1:V5YMrXUgClh3awWOdigGXHxvq/Ira2wLDj4DJLqB+Eo= +go.opentelemetry.io/collector/processor/xprocessor v0.138.0 h1:V+zKVy2kstPhIDsGvEBIRUxq8HzAdG1zdJP/hAuwENQ= go.opentelemetry.io/collector/semconv v0.122.1 h1:WLzDi3QC4/+LpNMLY90zn5aMDJKyqg/ujW2O4T4sxHg= go.opentelemetry.io/collector/semconv v0.122.1/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= +go.opentelemetry.io/contrib/bridges/otelzap v0.14.0 h1:2nKw2ZXZOC0N8RBsBbYwGwfKR7kJWzzyCZ6QfUGW/es= +go.opentelemetry.io/contrib/bridges/otelzap v0.14.0/go.mod h1:kvyVt0WEI5BB6XaIStXPIkCSQ2nSkyd8IZnAHLEXge4= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel/log v0.15.0 h1:0VqVnc3MgyYd7QqNVIldC3dsLFKgazR6P3P3+ypkyDY= +go.opentelemetry.io/otel/log v0.15.0/go.mod h1:9c/G1zbyZfgu1HmQD7Qj84QMmwTp2QCQsZH1aeoWDE4= go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -236,18 +402,28 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs= golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= +golang.org/x/exp v0.0.0-20251209150349-8475f28825e9 h1:MDfG8Cvcqlt9XXrmEiD4epKn7VJHZO84hejP9Jmp0MM= +golang.org/x/exp v0.0.0-20251209150349-8475f28825e9/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -255,12 +431,16 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -275,32 +455,54 @@ golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99 h1:ZSlhAUqC4r8TPzqLXQ0m3upBNZeF+Y8jQ3c4CR3Ujms= google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251213004720-97cd9d5aeac2 h1:2I6GHUeJ/4shcDpoUlLs/2WPnhg7yJwvXtqcMJt9liA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251213004720-97cd9d5aeac2/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= +google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/framework/framework.go b/internal/framework/framework.go index e205fce..197094b 100644 --- a/internal/framework/framework.go +++ b/internal/framework/framework.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "log/slog" + "maps" "os" "path/filepath" "time" @@ -22,6 +23,8 @@ type Framework interface { DiscoverTests(ctx context.Context) ([]testoptimization.Test, error) DiscoverTestFiles() ([]string, error) RunTests(ctx context.Context, testFiles []string, envMap map[string]string) error + SetPlatformEnv(platformEnv map[string]string) + GetPlatformEnv() map[string]string } // cleanupDiscoveryFile removes the discovery file, ignoring "not exists" errors @@ -85,3 +88,25 @@ func globTestFiles(pattern string) ([]string, error) { return matches, nil } + +// mergeEnvMaps merges base env vars with overrides. +// Values in overrides take precedence over base values. +func mergeEnvMaps(base, overrides map[string]string) map[string]string { + result := make(map[string]string) + maps.Copy(result, base) + maps.Copy(result, overrides) + return result +} + +// BaseDiscoveryEnv returns environment variables required for all test discovery processes. +// These env vars ensure the test framework runs in discovery mode without requiring +// actual Datadog credentials or agent connectivity. +func BaseDiscoveryEnv() map[string]string { + return map[string]string{ + "DD_CIVISIBILITY_ENABLED": "1", + "DD_CIVISIBILITY_AGENTLESS_ENABLED": "true", + "DD_API_KEY": "dummy_key", + "DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED": "1", + "DD_TEST_OPTIMIZATION_DISCOVERY_FILE": TestsDiscoveryFilePath, + } +} diff --git a/internal/framework/framework_test.go b/internal/framework/framework_test.go new file mode 100644 index 0000000..cff3cef --- /dev/null +++ b/internal/framework/framework_test.go @@ -0,0 +1,91 @@ +package framework + +import ( + "testing" +) + +func TestBaseDiscoveryEnv(t *testing.T) { + env := BaseDiscoveryEnv() + + expectedVars := map[string]string{ + "DD_CIVISIBILITY_ENABLED": "1", + "DD_CIVISIBILITY_AGENTLESS_ENABLED": "true", + "DD_API_KEY": "dummy_key", + "DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED": "1", + "DD_TEST_OPTIMIZATION_DISCOVERY_FILE": TestsDiscoveryFilePath, + } + + for key, expectedValue := range expectedVars { + if actualValue, exists := env[key]; !exists { + t.Errorf("expected %q to be present in BaseDiscoveryEnv", key) + } else if actualValue != expectedValue { + t.Errorf("expected %q=%q, got %q", key, expectedValue, actualValue) + } + } + + // Verify no extra unexpected keys + if len(env) != len(expectedVars) { + t.Errorf("expected %d env vars, got %d", len(expectedVars), len(env)) + } +} + +func TestMergeEnvMaps(t *testing.T) { + t.Run("merges two maps", func(t *testing.T) { + platform := map[string]string{"A": "1", "B": "2"} + additional := map[string]string{"C": "3", "D": "4"} + + result := mergeEnvMaps(platform, additional) + + if len(result) != 4 { + t.Errorf("expected 4 keys, got %d", len(result)) + } + if result["A"] != "1" || result["B"] != "2" || result["C"] != "3" || result["D"] != "4" { + t.Errorf("unexpected result: %v", result) + } + }) + + t.Run("additional overrides platform", func(t *testing.T) { + platform := map[string]string{"A": "platform", "B": "2"} + additional := map[string]string{"A": "additional", "C": "3"} + + result := mergeEnvMaps(platform, additional) + + if result["A"] != "additional" { + t.Errorf("expected additional to override platform, got %q", result["A"]) + } + if result["B"] != "2" { + t.Errorf("expected B to be preserved, got %q", result["B"]) + } + if result["C"] != "3" { + t.Errorf("expected C to be present, got %q", result["C"]) + } + }) + + t.Run("handles nil maps", func(t *testing.T) { + result := mergeEnvMaps(nil, nil) + if result == nil { + t.Error("expected non-nil result") + } + if len(result) != 0 { + t.Errorf("expected empty map, got %v", result) + } + }) + + t.Run("handles nil platform", func(t *testing.T) { + additional := map[string]string{"A": "1"} + result := mergeEnvMaps(nil, additional) + + if result["A"] != "1" { + t.Errorf("expected A=1, got %q", result["A"]) + } + }) + + t.Run("handles nil additional", func(t *testing.T) { + platform := map[string]string{"A": "1"} + result := mergeEnvMaps(platform, nil) + + if result["A"] != "1" { + t.Errorf("expected A=1, got %q", result["A"]) + } + }) +} diff --git a/internal/framework/minitest.go b/internal/framework/minitest.go index bbb24d9..d25da85 100644 --- a/internal/framework/minitest.go +++ b/internal/framework/minitest.go @@ -20,15 +20,25 @@ const ( type Minitest struct { executor ext.CommandExecutor commandOverride []string + platformEnv map[string]string } func NewMinitest() *Minitest { return &Minitest{ executor: &ext.DefaultCommandExecutor{}, commandOverride: loadCommandOverride(), + platformEnv: make(map[string]string), } } +func (m *Minitest) SetPlatformEnv(platformEnv map[string]string) { + m.platformEnv = platformEnv +} + +func (m *Minitest) GetPlatformEnv() map[string]string { + return m.platformEnv +} + func (m *Minitest) Name() string { return "minitest" } @@ -37,14 +47,15 @@ func (m *Minitest) DiscoverTests(ctx context.Context) ([]testoptimization.Test, cleanupDiscoveryFile(TestsDiscoveryFilePath) pattern := m.testPattern() - name, args, envMap, isRails := m.createDiscoveryCommand() + name, args, isRails := m.createDiscoveryCommand() slog.Debug("Using test discovery pattern", "pattern", pattern) + + // Merge env maps: platform env -> base discovery env + envMap := mergeEnvMaps(m.platformEnv, BaseDiscoveryEnv()) + if isRails { args = append(args, pattern) } else { - if envMap == nil { - envMap = make(map[string]string) - } envMap["TEST"] = pattern } @@ -98,7 +109,8 @@ func (m *Minitest) RunTests(ctx context.Context, testFiles []string, envMap map[ } } - return m.executor.Run(ctx, command, args, envMap) + mergedEnv := mergeEnvMaps(m.platformEnv, envMap) + return m.executor.Run(ctx, command, args, mergedEnv) } // isRailsApplication determines if the current project is a Rails application @@ -163,12 +175,7 @@ func (m *Minitest) getMinitestCommand() (string, []string, bool) { return "bundle", []string{"exec", "rake", "test"}, false } -func (m *Minitest) createDiscoveryCommand() (string, []string, map[string]string, bool) { +func (m *Minitest) createDiscoveryCommand() (string, []string, bool) { command, args, isRails := m.getMinitestCommand() - - envMap := map[string]string{ - "DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED": "1", - "DD_TEST_OPTIMIZATION_DISCOVERY_FILE": TestsDiscoveryFilePath, - } - return command, args, envMap, isRails + return command, args, isRails } diff --git a/internal/framework/minitest_test.go b/internal/framework/minitest_test.go index 0b95cf6..aa8b01b 100644 --- a/internal/framework/minitest_test.go +++ b/internal/framework/minitest_test.go @@ -92,7 +92,7 @@ func TestMinitest_createDiscoveryCommand(t *testing.T) { } minitest := &Minitest{executor: mockExecutor} - command, args, envMap, isRails := minitest.createDiscoveryCommand() + command, args, isRails := minitest.createDiscoveryCommand() // Verify command structure: bundle exec rake test (non-Rails) if command != "bundle" { @@ -109,13 +109,6 @@ func TestMinitest_createDiscoveryCommand(t *testing.T) { } } - // Verify environment variables - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED"] != "1" { - t.Error("expected DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED=1 in envMap") - } - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_FILE"] != TestsDiscoveryFilePath { - t.Errorf("expected DD_TEST_OPTIMIZATION_DISCOVERY_FILE=%q in envMap, got %q", TestsDiscoveryFilePath, envMap["DD_TEST_OPTIMIZATION_DISCOVERY_FILE"]) - } if isRails { t.Error("expected Rails detection to be false for default Minitest discovery") } @@ -124,7 +117,7 @@ func TestMinitest_createDiscoveryCommand(t *testing.T) { func TestMinitest_createDiscoveryCommand_WithOverride(t *testing.T) { mockExecutor := &mockRailsCommandExecutor{isRails: false} minitest := &Minitest{executor: mockExecutor, commandOverride: []string{"./custom-minitest", "--flag"}} - command, args, envMap, isRails := minitest.createDiscoveryCommand() + command, args, isRails := minitest.createDiscoveryCommand() if command != "./custom-minitest" { t.Errorf("expected command to be './custom-minitest', got %q", command) @@ -132,9 +125,6 @@ func TestMinitest_createDiscoveryCommand_WithOverride(t *testing.T) { if len(args) == 0 || args[0] != "--flag" { t.Errorf("expected args to start with '--flag', got %v", args) } - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED"] != "1" { - t.Error("expected discovery env map to include DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED") - } if isRails { t.Error("expected Rails detection to be false when override is provided") } @@ -548,7 +538,7 @@ func TestMinitest_createDiscoveryCommand_RailsApplication(t *testing.T) { } minitest := &Minitest{executor: mockExecutor} - command, args, envMap, isRails := minitest.createDiscoveryCommand() + command, args, isRails := minitest.createDiscoveryCommand() // Verify command structure: bundle exec rails test (Rails) if command != "bundle" { @@ -565,13 +555,6 @@ func TestMinitest_createDiscoveryCommand_RailsApplication(t *testing.T) { } } - // Verify environment variables - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED"] != "1" { - t.Error("expected DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED=1 in envMap") - } - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_FILE"] != TestsDiscoveryFilePath { - t.Errorf("expected DD_TEST_OPTIMIZATION_DISCOVERY_FILE=%q in envMap, got %q", TestsDiscoveryFilePath, envMap["DD_TEST_OPTIMIZATION_DISCOVERY_FILE"]) - } if !isRails { t.Error("expected Rails detection to be true for rails discovery command") } @@ -1187,7 +1170,7 @@ func TestMinitest_createDiscoveryCommand_RailsApplication_WithBinRails(t *testin } minitest := &Minitest{executor: mockExecutor} - command, args, envMap, isRails := minitest.createDiscoveryCommand() + command, args, isRails := minitest.createDiscoveryCommand() // Verify command structure: bin/rails test (Rails with bin/rails) if command != "bin/rails" { @@ -1204,14 +1187,235 @@ func TestMinitest_createDiscoveryCommand_RailsApplication_WithBinRails(t *testin } } - // Verify environment variables - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED"] != "1" { - t.Error("expected DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED=1 in envMap") - } - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_FILE"] != TestsDiscoveryFilePath { - t.Errorf("expected DD_TEST_OPTIMIZATION_DISCOVERY_FILE=%q in envMap, got %q", TestsDiscoveryFilePath, envMap["DD_TEST_OPTIMIZATION_DISCOVERY_FILE"]) - } if !isRails { t.Error("expected Rails detection to be true when bin/rails is used for discovery") } } + +func TestMinitest_SetPlatformEnv(t *testing.T) { + minitest := NewMinitest() + + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + } + minitest.SetPlatformEnv(platformEnv) + + if minitest.platformEnv["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected platformEnv to be set, got %v", minitest.platformEnv) + } +} + +func TestMinitest_RunTests_UsesPlatformEnv(t *testing.T) { + testFiles := []string{"test/models/user_test.rb"} + + mockExecutor := &mockRailsCommandExecutor{ + isRails: false, + } + + minitest := &Minitest{executor: mockExecutor} + + // Set platform env + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + } + minitest.SetPlatformEnv(platformEnv) + + err := minitest.RunTests(context.Background(), testFiles, nil) + if err != nil { + t.Fatalf("RunTests failed: %v", err) + } + + // Verify platform env is passed to executor + if mockExecutor.capturedEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be %q, got %q", platformEnv["RUBYOPT"], mockExecutor.capturedEnvMap["RUBYOPT"]) + } +} + +func TestMinitest_RunTests_MergesPlatformEnvWithPassedEnv(t *testing.T) { + testFiles := []string{"test/models/user_test.rb"} + + mockExecutor := &mockRailsCommandExecutor{ + isRails: false, + } + + minitest := &Minitest{executor: mockExecutor} + + // Set platform env + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + "PLATFORM_VAR": "platform_value", + } + minitest.SetPlatformEnv(platformEnv) + + // Pass additional env vars + additionalEnv := map[string]string{ + "RAILS_DB": "my_project_test_1", + "TEST_ENV": "minitest", + } + + err := minitest.RunTests(context.Background(), testFiles, additionalEnv) + if err != nil { + t.Fatalf("RunTests failed: %v", err) + } + + // Verify platform env is present + if mockExecutor.capturedEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be %q, got %q", platformEnv["RUBYOPT"], mockExecutor.capturedEnvMap["RUBYOPT"]) + } + if mockExecutor.capturedEnvMap["PLATFORM_VAR"] != platformEnv["PLATFORM_VAR"] { + t.Errorf("expected PLATFORM_VAR to be %q, got %q", platformEnv["PLATFORM_VAR"], mockExecutor.capturedEnvMap["PLATFORM_VAR"]) + } + + // Verify additional env is present + if mockExecutor.capturedEnvMap["RAILS_DB"] != additionalEnv["RAILS_DB"] { + t.Errorf("expected RAILS_DB to be %q, got %q", additionalEnv["RAILS_DB"], mockExecutor.capturedEnvMap["RAILS_DB"]) + } + if mockExecutor.capturedEnvMap["TEST_ENV"] != additionalEnv["TEST_ENV"] { + t.Errorf("expected TEST_ENV to be %q, got %q", additionalEnv["TEST_ENV"], mockExecutor.capturedEnvMap["TEST_ENV"]) + } +} + +func TestMinitest_RunTests_AdditionalEnvOverridesPlatformEnv(t *testing.T) { + testFiles := []string{"test/models/user_test.rb"} + + mockExecutor := &mockRailsCommandExecutor{ + isRails: false, + } + + minitest := &Minitest{executor: mockExecutor} + + // Set platform env with a value that will be overridden + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + "SHARED_VAR": "platform_value", + "ANOTHER_VAR": "platform_another", + } + minitest.SetPlatformEnv(platformEnv) + + // Pass additional env that overrides SHARED_VAR + additionalEnv := map[string]string{ + "SHARED_VAR": "additional_value", + } + + err := minitest.RunTests(context.Background(), testFiles, additionalEnv) + if err != nil { + t.Fatalf("RunTests failed: %v", err) + } + + // Verify SHARED_VAR is overridden by additional env + if mockExecutor.capturedEnvMap["SHARED_VAR"] != additionalEnv["SHARED_VAR"] { + t.Errorf("expected SHARED_VAR to be overridden to %q, got %q", additionalEnv["SHARED_VAR"], mockExecutor.capturedEnvMap["SHARED_VAR"]) + } + + // Verify non-overridden platform env values are preserved + if mockExecutor.capturedEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be preserved as %q, got %q", platformEnv["RUBYOPT"], mockExecutor.capturedEnvMap["RUBYOPT"]) + } + if mockExecutor.capturedEnvMap["ANOTHER_VAR"] != platformEnv["ANOTHER_VAR"] { + t.Errorf("expected ANOTHER_VAR to be preserved as %q, got %q", platformEnv["ANOTHER_VAR"], mockExecutor.capturedEnvMap["ANOTHER_VAR"]) + } +} + +func TestMinitest_DiscoverTests_UsesPlatformEnv(t *testing.T) { + if err := os.MkdirAll(filepath.Dir(TestsDiscoveryFilePath), 0755); err != nil { + t.Fatalf("failed to create discovery directory: %v", err) + } + defer cleanupDiscoveryDir() + if err := os.MkdirAll("test/models", 0755); err != nil { + t.Fatalf("failed to create test/models directory: %v", err) + } + if err := os.WriteFile("test/models/user_test.rb", []byte("# test"), 0644); err != nil { + t.Fatalf("failed to create user test file: %v", err) + } + defer func() { + _ = os.RemoveAll("test") + }() + + testData := []testoptimization.Test{ + { + Name: "test_user_validation", + Suite: "UserTest", + Module: "minitest", + Parameters: "{}", + SuiteSourceFile: "test/models/user_test.rb", + }, + } + + mockExecutor := &mockRailsCommandExecutor{ + isRails: false, + onTestExecution: func(name string, args []string) { + file, err := os.Create(TestsDiscoveryFilePath) + if err != nil { + t.Fatalf("mock failed to create test file: %v", err) + } + defer func() { _ = file.Close() }() + + encoder := json.NewEncoder(file) + for _, test := range testData { + if err := encoder.Encode(test); err != nil { + t.Fatalf("mock failed to encode test data: %v", err) + } + } + }, + } + + minitest := &Minitest{executor: mockExecutor} + + // Set platform env + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + } + minitest.SetPlatformEnv(platformEnv) + + _, err := minitest.DiscoverTests(context.Background()) + if err != nil { + t.Fatalf("DiscoverTests failed: %v", err) + } + + // Verify platform env is passed to executor during discovery + if mockExecutor.capturedEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be %q, got %q", platformEnv["RUBYOPT"], mockExecutor.capturedEnvMap["RUBYOPT"]) + } + + // Verify framework-specific discovery env vars are present + if mockExecutor.capturedEnvMap["DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED"] != "1" { + t.Error("expected DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED to be set") + } + + // Verify base discovery env vars are present + if mockExecutor.capturedEnvMap["DD_CIVISIBILITY_ENABLED"] != "1" { + t.Error("expected DD_CIVISIBILITY_ENABLED to be set") + } + if mockExecutor.capturedEnvMap["DD_CIVISIBILITY_AGENTLESS_ENABLED"] != "true" { + t.Error("expected DD_CIVISIBILITY_AGENTLESS_ENABLED to be set") + } + if mockExecutor.capturedEnvMap["DD_API_KEY"] != "dummy_key" { + t.Error("expected DD_API_KEY to be set") + } +} + +func TestMinitest_RunTests_RailsApplication_UsesPlatformEnv(t *testing.T) { + testFiles := []string{"test/models/user_test.rb"} + + mockExecutor := &mockRailsCommandExecutor{ + isRails: true, + } + + minitest := &Minitest{executor: mockExecutor} + + // Set platform env + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + } + minitest.SetPlatformEnv(platformEnv) + + err := minitest.RunTests(context.Background(), testFiles, nil) + if err != nil { + t.Fatalf("RunTests failed: %v", err) + } + + // Verify platform env is passed to executor for Rails + if mockExecutor.capturedEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be %q, got %q", platformEnv["RUBYOPT"], mockExecutor.capturedEnvMap["RUBYOPT"]) + } +} diff --git a/internal/framework/rspec.go b/internal/framework/rspec.go index 4cf4a6f..4b10d3d 100644 --- a/internal/framework/rspec.go +++ b/internal/framework/rspec.go @@ -19,15 +19,25 @@ const ( type RSpec struct { executor ext.CommandExecutor commandOverride []string + platformEnv map[string]string } func NewRSpec() *RSpec { return &RSpec{ executor: &ext.DefaultCommandExecutor{}, commandOverride: loadCommandOverride(), + platformEnv: make(map[string]string), } } +func (r *RSpec) SetPlatformEnv(platformEnv map[string]string) { + r.platformEnv = platformEnv +} + +func (r *RSpec) GetPlatformEnv() map[string]string { + return r.platformEnv +} + func (r *RSpec) Name() string { return "rspec" } @@ -37,9 +47,12 @@ func (r *RSpec) DiscoverTests(ctx context.Context) ([]testoptimization.Test, err pattern := r.testPattern() - name, args, envMap := r.createDiscoveryCommand() + name, args := r.createDiscoveryCommand() args = append(args, "--pattern", pattern) + // Merge env maps: platform env -> base discovery env + envMap := mergeEnvMaps(r.platformEnv, BaseDiscoveryEnv()) + slog.Info("Using test discovery pattern", "pattern", pattern) slog.Info("Discovering tests with command", "command", name, "args", args) _, err := executeDiscoveryCommand(ctx, r.executor, name, args, envMap, r.Name()) @@ -79,7 +92,8 @@ func (r *RSpec) RunTests(ctx context.Context, testFiles []string, envMap map[str slog.Info("Running tests with command", "command", command, "args", args) args = append(args, testFiles...) - return r.executor.Run(ctx, command, args, envMap) + mergedEnv := mergeEnvMaps(r.platformEnv, envMap) + return r.executor.Run(ctx, command, args, mergedEnv) } // getRSpecCommand determines whether to use bin/rspec or bundle exec rspec @@ -101,13 +115,7 @@ func (r *RSpec) getRSpecCommand() (string, []string) { return "bundle", []string{"exec", "rspec"} } -func (r *RSpec) createDiscoveryCommand() (string, []string, map[string]string) { - command, baseArgs := r.getRSpecCommand() - args := append(baseArgs, "--format", "progress", "--dry-run") - - envMap := map[string]string{ - "DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED": "1", - "DD_TEST_OPTIMIZATION_DISCOVERY_FILE": TestsDiscoveryFilePath, - } - return command, args, envMap +func (r *RSpec) createDiscoveryCommand() (string, []string) { + // Always use bundle exec rspec for discovery, as bin/rspec is often customized + return "bundle", []string{"exec", "rspec", "--format", "progress", "--dry-run"} } diff --git a/internal/framework/rspec_test.go b/internal/framework/rspec_test.go index 087a0d2..e62a5bd 100644 --- a/internal/framework/rspec_test.go +++ b/internal/framework/rspec_test.go @@ -190,7 +190,7 @@ func TestRSpec_createDiscoveryCommand(t *testing.T) { _ = os.RemoveAll("bin") rspec := NewRSpec() - command, args, envMap := rspec.createDiscoveryCommand() + command, args := rspec.createDiscoveryCommand() // Verify command contains necessary arguments if !slices.Contains(args, "--format") { @@ -210,33 +210,26 @@ func TestRSpec_createDiscoveryCommand(t *testing.T) { if !slices.Contains(args, "rspec") { t.Errorf("expected 'rspec' in arguments, got: %v", args) } - - // Verify environment variables - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED"] != "1" { - t.Error("expected DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED=1 in envMap") - } - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_FILE"] != TestsDiscoveryFilePath { - t.Errorf("expected DD_TEST_OPTIMIZATION_DISCOVERY_FILE=%q in envMap, got %q", TestsDiscoveryFilePath, envMap["DD_TEST_OPTIMIZATION_DISCOVERY_FILE"]) - } } func TestRSpec_createDiscoveryCommand_WithOverride(t *testing.T) { + // Even with command override, discovery should always use bundle exec rspec rspec := &RSpec{commandOverride: []string{"./custom-rspec", "--profile"}} - command, args, envMap := rspec.createDiscoveryCommand() + command, args := rspec.createDiscoveryCommand() - if command != "./custom-rspec" { - t.Errorf("expected command to be './custom-rspec', got %q", command) + if command != "bundle" { + t.Errorf("expected command to be 'bundle', got %q", command) + } + if !slices.Contains(args, "exec") { + t.Errorf("expected args to contain 'exec', got %v", args) } - if !slices.Contains(args, "--profile") { - t.Errorf("expected args to contain '--profile', got %v", args) + if !slices.Contains(args, "rspec") { + t.Errorf("expected args to contain 'rspec', got %v", args) } if !slices.Contains(args, "--dry-run") { t.Error("expected args to contain '--dry-run'") } - if envMap["DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED"] != "1" { - t.Error("expected discovery env map to be set") - } } func TestRSpec_DiscoverTests_Success(t *testing.T) { @@ -496,7 +489,8 @@ func TestRSpec_RunTestsWithEnvMap(t *testing.T) { } func TestRSpec_createDiscoveryCommand_WithBinRSpec(t *testing.T) { - // Create a temporary bin/rspec file + // Even with bin/rspec present, discovery should always use bundle exec rspec + // because bin/rspec is often heavily customized and cannot be used for discovery if err := os.MkdirAll("bin", 0755); err != nil { t.Fatalf("failed to create bin directory: %v", err) } @@ -510,14 +504,18 @@ func TestRSpec_createDiscoveryCommand_WithBinRSpec(t *testing.T) { } rspec := NewRSpec() - command, args, _ := rspec.createDiscoveryCommand() + command, args := rspec.createDiscoveryCommand() - // Verify command uses bin/rspec - if command != "bin/rspec" { - t.Errorf("expected command to use bin/rspec, got %q", command) + // Verify discovery always uses bundle exec rspec + if command != "bundle" { + t.Errorf("expected command to use bundle, got %q", command) + } + if !slices.Contains(args, "exec") { + t.Error("expected 'exec' argument") + } + if !slices.Contains(args, "rspec") { + t.Error("expected 'rspec' argument") } - - // Verify necessary arguments are present if !slices.Contains(args, "--format") { t.Error("expected --format argument") } @@ -906,3 +904,230 @@ func TestRSpec_DiscoverTestFiles_NoSpecDirectory(t *testing.T) { t.Errorf("expected 0 test files, got %d", len(discoveredFiles)) } } + +func TestRSpec_SetPlatformEnv(t *testing.T) { + rspec := NewRSpec() + + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + } + rspec.SetPlatformEnv(platformEnv) + + if rspec.platformEnv["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected platformEnv to be set, got %v", rspec.platformEnv) + } +} + +func TestRSpec_RunTests_UsesPlatformEnv(t *testing.T) { + _ = os.RemoveAll("bin") + + testFiles := []string{"spec/models/user_spec.rb"} + + mockExecutor := &mockCommandExecutor{ + err: nil, + } + + rspec := &RSpec{executor: mockExecutor} + + // Set platform env + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + } + rspec.SetPlatformEnv(platformEnv) + + err := rspec.RunTests(context.Background(), testFiles, nil) + if err != nil { + t.Fatalf("RunTests failed: %v", err) + } + + // Verify platform env is passed to executor + if mockExecutor.capturedEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be %q, got %q", platformEnv["RUBYOPT"], mockExecutor.capturedEnvMap["RUBYOPT"]) + } +} + +func TestRSpec_RunTests_MergesPlatformEnvWithPassedEnv(t *testing.T) { + _ = os.RemoveAll("bin") + + testFiles := []string{"spec/models/user_spec.rb"} + + mockExecutor := &mockCommandExecutor{ + err: nil, + } + + rspec := &RSpec{executor: mockExecutor} + + // Set platform env + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + "PLATFORM_VAR": "platform_value", + } + rspec.SetPlatformEnv(platformEnv) + + // Pass additional env vars + additionalEnv := map[string]string{ + "RAILS_DB": "my_project_test_1", + "TEST_ENV": "rspec", + } + + err := rspec.RunTests(context.Background(), testFiles, additionalEnv) + if err != nil { + t.Fatalf("RunTests failed: %v", err) + } + + // Verify platform env is present + if mockExecutor.capturedEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be %q, got %q", platformEnv["RUBYOPT"], mockExecutor.capturedEnvMap["RUBYOPT"]) + } + if mockExecutor.capturedEnvMap["PLATFORM_VAR"] != platformEnv["PLATFORM_VAR"] { + t.Errorf("expected PLATFORM_VAR to be %q, got %q", platformEnv["PLATFORM_VAR"], mockExecutor.capturedEnvMap["PLATFORM_VAR"]) + } + + // Verify additional env is present + if mockExecutor.capturedEnvMap["RAILS_DB"] != additionalEnv["RAILS_DB"] { + t.Errorf("expected RAILS_DB to be %q, got %q", additionalEnv["RAILS_DB"], mockExecutor.capturedEnvMap["RAILS_DB"]) + } + if mockExecutor.capturedEnvMap["TEST_ENV"] != additionalEnv["TEST_ENV"] { + t.Errorf("expected TEST_ENV to be %q, got %q", additionalEnv["TEST_ENV"], mockExecutor.capturedEnvMap["TEST_ENV"]) + } +} + +func TestRSpec_RunTests_AdditionalEnvOverridesPlatformEnv(t *testing.T) { + _ = os.RemoveAll("bin") + + testFiles := []string{"spec/models/user_spec.rb"} + + mockExecutor := &mockCommandExecutor{ + err: nil, + } + + rspec := &RSpec{executor: mockExecutor} + + // Set platform env with a value that will be overridden + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + "SHARED_VAR": "platform_value", + "ANOTHER_VAR": "platform_another", + } + rspec.SetPlatformEnv(platformEnv) + + // Pass additional env that overrides SHARED_VAR + additionalEnv := map[string]string{ + "SHARED_VAR": "additional_value", + } + + err := rspec.RunTests(context.Background(), testFiles, additionalEnv) + if err != nil { + t.Fatalf("RunTests failed: %v", err) + } + + // Verify SHARED_VAR is overridden by additional env + if mockExecutor.capturedEnvMap["SHARED_VAR"] != additionalEnv["SHARED_VAR"] { + t.Errorf("expected SHARED_VAR to be overridden to %q, got %q", additionalEnv["SHARED_VAR"], mockExecutor.capturedEnvMap["SHARED_VAR"]) + } + + // Verify non-overridden platform env values are preserved + if mockExecutor.capturedEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be preserved as %q, got %q", platformEnv["RUBYOPT"], mockExecutor.capturedEnvMap["RUBYOPT"]) + } + if mockExecutor.capturedEnvMap["ANOTHER_VAR"] != platformEnv["ANOTHER_VAR"] { + t.Errorf("expected ANOTHER_VAR to be preserved as %q, got %q", platformEnv["ANOTHER_VAR"], mockExecutor.capturedEnvMap["ANOTHER_VAR"]) + } +} + +// mockCommandExecutorWithEnvCapture extends mockCommandExecutor to capture envMap from CombinedOutput +type mockCommandExecutorWithEnvCapture struct { + output []byte + err error + onExecution func(name string, args []string) + capturedEnvMap map[string]string + combinedOutputEnvMap map[string]string +} + +func (m *mockCommandExecutorWithEnvCapture) CombinedOutput(ctx context.Context, name string, args []string, envMap map[string]string) ([]byte, error) { + m.combinedOutputEnvMap = envMap + if m.onExecution != nil { + m.onExecution(name, args) + } + return m.output, m.err +} + +func (m *mockCommandExecutorWithEnvCapture) Run(ctx context.Context, name string, args []string, envMap map[string]string) error { + m.capturedEnvMap = envMap + if m.onExecution != nil { + m.onExecution(name, args) + } + return m.err +} + +func TestRSpec_DiscoverTests_UsesPlatformEnv(t *testing.T) { + _ = os.RemoveAll("bin") + + if err := os.MkdirAll(filepath.Dir(TestsDiscoveryFilePath), 0755); err != nil { + t.Fatalf("failed to create discovery directory: %v", err) + } + defer cleanupDiscoveryDir() + + testData := []testoptimization.Test{ + { + Name: "User should be valid", + Suite: "User", + Module: "rspec", + Parameters: "{}", + SuiteSourceFile: "spec/models/user_spec.rb", + }, + } + + mockExecutor := &mockCommandExecutorWithEnvCapture{ + output: []byte("Finished in 0.12345 seconds"), + err: nil, + onExecution: func(name string, args []string) { + file, err := os.Create(TestsDiscoveryFilePath) + if err != nil { + t.Fatalf("mock failed to create test file: %v", err) + } + defer func() { _ = file.Close() }() + + encoder := json.NewEncoder(file) + for _, test := range testData { + if err := encoder.Encode(test); err != nil { + t.Fatalf("mock failed to encode test data: %v", err) + } + } + }, + } + + rspec := &RSpec{executor: mockExecutor} + + // Set platform env + platformEnv := map[string]string{ + "RUBYOPT": "-rbundler/setup -rdatadog/ci/auto_instrument", + } + rspec.SetPlatformEnv(platformEnv) + + _, err := rspec.DiscoverTests(context.Background()) + if err != nil { + t.Fatalf("DiscoverTests failed: %v", err) + } + + // Verify platform env is passed to executor during discovery + if mockExecutor.combinedOutputEnvMap["RUBYOPT"] != platformEnv["RUBYOPT"] { + t.Errorf("expected RUBYOPT to be %q, got %q", platformEnv["RUBYOPT"], mockExecutor.combinedOutputEnvMap["RUBYOPT"]) + } + + // Verify framework-specific discovery env vars are present + if mockExecutor.combinedOutputEnvMap["DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED"] != "1" { + t.Error("expected DD_TEST_OPTIMIZATION_DISCOVERY_ENABLED to be set") + } + + // Verify base discovery env vars are present + if mockExecutor.combinedOutputEnvMap["DD_CIVISIBILITY_ENABLED"] != "1" { + t.Error("expected DD_CIVISIBILITY_ENABLED to be set") + } + if mockExecutor.combinedOutputEnvMap["DD_CIVISIBILITY_AGENTLESS_ENABLED"] != "true" { + t.Error("expected DD_CIVISIBILITY_AGENTLESS_ENABLED to be set") + } + if mockExecutor.combinedOutputEnvMap["DD_API_KEY"] != "dummy_key" { + t.Error("expected DD_API_KEY to be set") + } +} diff --git a/internal/git/git.go b/internal/git/git.go new file mode 100644 index 0000000..0697e18 --- /dev/null +++ b/internal/git/git.go @@ -0,0 +1,30 @@ +package git + +import ( + "fmt" + "os/exec" +) + +// LookPathFunc is the function used to look up executables in PATH. +// It can be overridden in tests. +var LookPathFunc = exec.LookPath + +// RunGitCommandFunc is the function used to run git commands. +// It can be overridden in tests. +var RunGitCommandFunc = func(args ...string) error { + return exec.Command("git", args...).Run() +} + +// CheckAvailable verifies that git is available and the current directory is a git repository. +// Returns an error if git is not installed or the current directory is not a git repository. +func CheckAvailable() error { + if _, err := LookPathFunc("git"); err != nil { + return fmt.Errorf("git executable not found: git is required for ddtest to work") + } + + if err := RunGitCommandFunc("rev-parse", "--git-dir"); err != nil { + return fmt.Errorf("current directory is not a git repository: git is required for ddtest to work") + } + + return nil +} diff --git a/internal/git/git_test.go b/internal/git/git_test.go new file mode 100644 index 0000000..87f9424 --- /dev/null +++ b/internal/git/git_test.go @@ -0,0 +1,155 @@ +package git + +import ( + "errors" + "os/exec" + "strings" + "testing" +) + +func TestCheckAvailable_Success(t *testing.T) { + // Save original functions + origLookPath := LookPathFunc + origRunGit := RunGitCommandFunc + defer func() { + LookPathFunc = origLookPath + RunGitCommandFunc = origRunGit + }() + + // Mock both functions to succeed + LookPathFunc = func(file string) (string, error) { + if file == "git" { + return "/usr/bin/git", nil + } + return "", errors.New("not found") + } + RunGitCommandFunc = func(args ...string) error { + return nil + } + + err := CheckAvailable() + if err != nil { + t.Errorf("expected no error, got %v", err) + } +} + +func TestCheckAvailable_GitNotInstalled(t *testing.T) { + // Save original functions + origLookPath := LookPathFunc + origRunGit := RunGitCommandFunc + defer func() { + LookPathFunc = origLookPath + RunGitCommandFunc = origRunGit + }() + + // Mock LookPath to fail + LookPathFunc = func(file string) (string, error) { + return "", errors.New("executable file not found in $PATH") + } + RunGitCommandFunc = func(args ...string) error { + return nil + } + + err := CheckAvailable() + if err == nil { + t.Error("expected error when git is not installed") + } + if !strings.Contains(err.Error(), "git executable not found") { + t.Errorf("expected 'git executable not found' in error message, got: %v", err) + } + if !strings.Contains(err.Error(), "git is required for ddtest to work") { + t.Errorf("expected 'git is required for ddtest to work' in error message, got: %v", err) + } +} + +func TestCheckAvailable_NotAGitRepo(t *testing.T) { + // Save original functions + origLookPath := LookPathFunc + origRunGit := RunGitCommandFunc + defer func() { + LookPathFunc = origLookPath + RunGitCommandFunc = origRunGit + }() + + // Mock LookPath to succeed, but git command to fail + LookPathFunc = func(file string) (string, error) { + if file == "git" { + return "/usr/bin/git", nil + } + return "", errors.New("not found") + } + RunGitCommandFunc = func(args ...string) error { + return errors.New("fatal: not a git repository") + } + + err := CheckAvailable() + if err == nil { + t.Error("expected error when not in a git repository") + } + if !strings.Contains(err.Error(), "current directory is not a git repository") { + t.Errorf("expected 'current directory is not a git repository' in error message, got: %v", err) + } + if !strings.Contains(err.Error(), "git is required for ddtest to work") { + t.Errorf("expected 'git is required for ddtest to work' in error message, got: %v", err) + } +} + +func TestCheckAvailable_CorrectGitCommand(t *testing.T) { + // Save original functions + origLookPath := LookPathFunc + origRunGit := RunGitCommandFunc + defer func() { + LookPathFunc = origLookPath + RunGitCommandFunc = origRunGit + }() + + var capturedArgs []string + + LookPathFunc = func(file string) (string, error) { + return "/usr/bin/git", nil + } + RunGitCommandFunc = func(args ...string) error { + capturedArgs = args + return nil + } + + _ = CheckAvailable() + + expectedArgs := []string{"rev-parse", "--git-dir"} + if len(capturedArgs) != len(expectedArgs) { + t.Errorf("expected args %v, got %v", expectedArgs, capturedArgs) + } + for i, arg := range expectedArgs { + if capturedArgs[i] != arg { + t.Errorf("expected arg[%d] = %q, got %q", i, arg, capturedArgs[i]) + } + } +} + +func TestCheckAvailable_Integration(t *testing.T) { + // This test uses real git commands to verify the function works in a real environment + // Skip if git is not available + if _, err := exec.LookPath("git"); err != nil { + t.Skip("git not available, skipping integration test") + } + + // Save original functions to ensure we use real ones + origLookPath := LookPathFunc + origRunGit := RunGitCommandFunc + defer func() { + LookPathFunc = origLookPath + RunGitCommandFunc = origRunGit + }() + + // Reset to real implementations + LookPathFunc = exec.LookPath + RunGitCommandFunc = func(args ...string) error { + return exec.Command("git", args...).Run() + } + + // Since tests run in the project directory which is a git repo, this should succeed + err := CheckAvailable() + if err != nil { + t.Errorf("expected no error in git repository, got %v", err) + } +} diff --git a/internal/platform/ruby.go b/internal/platform/ruby.go index e92ded3..de4f9db 100644 --- a/internal/platform/ruby.go +++ b/internal/platform/ruby.go @@ -5,6 +5,7 @@ import ( _ "embed" "encoding/json" "fmt" + "log/slog" "maps" "os" "strings" @@ -22,6 +23,8 @@ var rubyEnvScript string const ( requiredGemName = "datadog-ci" requiredGemMinVersion = "1.23.0" + rubyOptEnvVar = "RUBYOPT" + rubyOptDefaultValue = "-rbundler/setup -rdatadog/ci/auto_instrument" ) type Ruby struct { @@ -38,6 +41,21 @@ func (r *Ruby) Name() string { return "ruby" } +// GetPlatformEnv returns environment variables required for Ruby commands. +// It sets RUBYOPT to auto-instrument with datadog-ci if not already set. +func (r *Ruby) GetPlatformEnv() map[string]string { + envMap := make(map[string]string) + + // Check if RUBYOPT is already set in the environment + if _, exists := os.LookupEnv(rubyOptEnvVar); !exists { + slog.Debug("Setting RUBYOPT to auto-instrument with datadog-ci", "rubyOpt", rubyOptDefaultValue) + + envMap[rubyOptEnvVar] = rubyOptDefaultValue + } + + return envMap +} + func (r *Ruby) CreateTagsMap() (map[string]string, error) { tags := make(map[string]string) tags["language"] = r.Name() @@ -77,15 +95,20 @@ func (r *Ruby) CreateTagsMap() (map[string]string, error) { func (r *Ruby) DetectFramework() (framework.Framework, error) { frameworkName := settings.GetFramework() + platformEnv := r.GetPlatformEnv() + var fw framework.Framework switch frameworkName { case "rspec": - return framework.NewRSpec(), nil + fw = framework.NewRSpec() case "minitest": - return framework.NewMinitest(), nil + fw = framework.NewMinitest() default: return nil, fmt.Errorf("framework '%s' is not supported by platform 'ruby'", frameworkName) } + + fw.SetPlatformEnv(platformEnv) + return fw, nil } func (r *Ruby) SanityCheck() error { diff --git a/internal/platform/ruby_test.go b/internal/platform/ruby_test.go index 163a039..5b336d8 100644 --- a/internal/platform/ruby_test.go +++ b/internal/platform/ruby_test.go @@ -412,3 +412,73 @@ func TestDetectPlatform_Unsupported(t *testing.T) { t.Errorf("expected error %q, got %q", expectedError, err.Error()) } } + +func TestRuby_GetPlatformEnv_SetsRUBYOPT_WhenNotSet(t *testing.T) { + // Ensure RUBYOPT is not set + originalValue, existed := os.LookupEnv("RUBYOPT") + if existed { + _ = os.Unsetenv("RUBYOPT") + defer func() { _ = os.Setenv("RUBYOPT", originalValue) }() + } + + ruby := NewRuby() + envMap := ruby.GetPlatformEnv() + + expectedValue := "-rbundler/setup -rdatadog/ci/auto_instrument" + if envMap["RUBYOPT"] != expectedValue { + t.Errorf("expected RUBYOPT to be %q, got %q", expectedValue, envMap["RUBYOPT"]) + } +} + +func TestRuby_GetPlatformEnv_DoesNotOverride_WhenAlreadySet(t *testing.T) { + // Set RUBYOPT to a custom value + originalValue, existed := os.LookupEnv("RUBYOPT") + customValue := "-rbundler/setup -rsome_other_require" + _ = os.Setenv("RUBYOPT", customValue) + defer func() { + if existed { + _ = os.Setenv("RUBYOPT", originalValue) + } else { + _ = os.Unsetenv("RUBYOPT") + } + }() + + ruby := NewRuby() + envMap := ruby.GetPlatformEnv() + + // When RUBYOPT is already set, GetPlatformEnv should not include it + if _, exists := envMap["RUBYOPT"]; exists { + t.Error("expected RUBYOPT to not be in envMap when it's already set in environment") + } +} + +func TestRuby_DetectFramework_SetsPlatformEnv(t *testing.T) { + // Ensure RUBYOPT is not set so we can verify it gets set + originalValue, existed := os.LookupEnv("RUBYOPT") + if existed { + _ = os.Unsetenv("RUBYOPT") + defer func() { _ = os.Setenv("RUBYOPT", originalValue) }() + } + + viper.Reset() + viper.Set("framework", "rspec") + defer viper.Reset() + + ruby := NewRuby() + fw, err := ruby.DetectFramework() + + if err != nil { + t.Fatalf("DetectFramework failed: %v", err) + } + + if fw == nil { + t.Fatal("expected framework to be non-nil") + } + + // Verify the framework received the correct platform env + frameworkPlatformEnv := fw.GetPlatformEnv() + expectedRubyOpt := "-rbundler/setup -rdatadog/ci/auto_instrument" + if frameworkPlatformEnv["RUBYOPT"] != expectedRubyOpt { + t.Errorf("expected framework platformEnv RUBYOPT=%q, got %q", expectedRubyOpt, frameworkPlatformEnv["RUBYOPT"]) + } +} diff --git a/internal/runner/runner_test.go b/internal/runner/runner_test.go index 55605fa..c68045c 100644 --- a/internal/runner/runner_test.go +++ b/internal/runner/runner_test.go @@ -98,6 +98,14 @@ func (m *MockFramework) RunTests(ctx context.Context, testFiles []string, envMap return m.Err } +func (m *MockFramework) SetPlatformEnv(platformEnv map[string]string) { + // No-op for mock +} + +func (m *MockFramework) GetPlatformEnv() map[string]string { + return nil +} + func (m *MockFramework) GetRunTestsCallsCount() int { m.mu.Lock() defer m.mu.Unlock() diff --git a/main.go b/main.go index ab5f319..7564fa9 100644 --- a/main.go +++ b/main.go @@ -5,9 +5,19 @@ import ( "os" "github.com/DataDog/ddtest/internal/cmd" + "github.com/DataDog/ddtest/internal/git" ) func main() { + if err := git.CheckAvailable(); err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + // it doesn't make sense to use ddtest without test optimization mode, + // so we just enable it + _ = os.Setenv("DD_CIVISIBILITY_ENABLED", "1") + // this is weird, I know: I am trying to get rid of annoying appsec telemetry // warning that is polluting the logs when Datadog Agent is not available _ = os.Setenv("DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED", "0")