diff --git a/docs/settings.md b/docs/settings.md index b2690e4..96047d6 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -19,5 +19,5 @@ CLI flags take precedence over environment variables. | `--test-discovery-cache` | `DD_TEST_OPTIMIZATION_RUNNER_TEST_DISCOVERY_CACHE` | | `""` | Path to a restored test discovery cache file. DDTest imports it before planning and refreshes the internal discovery cache after successful full discovery. | | `--force-full-test-discovery` | `DD_TEST_OPTIMIZATION_RUNNER_FORCE_FULL_TEST_DISCOVERY` | | `false` | Force full test discovery when the framework supports it, including in suite-level skipping mode. | | `--strict-discovery` | `DD_TEST_OPTIMIZATION_RUNNER_STRICT_DISCOVERY` | | `false` | Fail planning when full test discovery fails. Cancelled full discovery still uses fast test file discovery fallback. | -| `--runtime-tags` | `DD_TEST_OPTIMIZATION_RUNNER_RUNTIME_TAGS` | | `""` | JSON string to override runtime tags used to fetch skippable tests. Useful for local development on a different OS than CI, such as `--runtime-tags '{"os.platform":"linux","runtime.version":"3.2.0"}'`. | +| `--runtime-tags` | `DD_TEST_OPTIMIZATION_RUNNER_RUNTIME_TAGS` | `DD_TEST_OPTIMIZATION_RUNTIME_TAGS` | `""` | JSON string to override runtime tags used to fetch skippable tests. Useful for local development on a different OS than CI, such as `--runtime-tags '{"os.platform":"linux","runtime.version":"3.2.0"}'`. | | | `DD_TEST_OPTIMIZATION_RUNNER_REPORT_ENABLED` | | `true` | Print human-readable plan and run reports. Set to `false` to disable them. | diff --git a/internal/settings/settings.go b/internal/settings/settings.go index b159cf4..ef6a50c 100644 --- a/internal/settings/settings.go +++ b/internal/settings/settings.go @@ -17,13 +17,25 @@ const ( defaultCiNodeWorkers = 1 defaultParallelRunnerOverhead = 25 * time.Second ncpuCiNodeWorkers = "ncpu" + envPrefix = "DD_TEST_OPTIMIZATION_RUNNER" + platformEnv = "DD_TEST_OPTIMIZATION_RUNNER_PLATFORM" + frameworkEnv = "DD_TEST_OPTIMIZATION_RUNNER_FRAMEWORK" + minParallelismEnv = "DD_TEST_OPTIMIZATION_RUNNER_MIN_PARALLELISM" + maxParallelismEnv = "DD_TEST_OPTIMIZATION_RUNNER_MAX_PARALLELISM" parallelRunnerOverheadEnv = "DD_TEST_OPTIMIZATION_RUNNER_CI_JOB_OVERHEAD" + workerEnv = "DD_TEST_OPTIMIZATION_RUNNER_WORKER_ENV" + ciNodeEnv = "DD_TEST_OPTIMIZATION_RUNNER_CI_NODE" + ciNodeWorkersEnv = "DD_TEST_OPTIMIZATION_RUNNER_CI_NODE_WORKERS" + commandEnv = "DD_TEST_OPTIMIZATION_RUNNER_COMMAND" testsLocationEnv = "DD_TEST_OPTIMIZATION_RUNNER_TESTS_LOCATION" testsExcludePatternEnv = "DD_TEST_OPTIMIZATION_RUNNER_TESTS_EXCLUDE_PATTERN" testDiscoveryCacheEnv = "DD_TEST_OPTIMIZATION_RUNNER_TEST_DISCOVERY_CACHE" testSkippingModeEnv = "DD_TESTOPTIMIZATION_TIA_TEST_SKIPPING_MODE" forceFullTestDiscoveryEnv = "DD_TEST_OPTIMIZATION_RUNNER_FORCE_FULL_TEST_DISCOVERY" strictDiscoveryEnv = "DD_TEST_OPTIMIZATION_RUNNER_STRICT_DISCOVERY" + runtimeTagsEnv = "DD_TEST_OPTIMIZATION_RUNNER_RUNTIME_TAGS" + runtimeTagsAliasEnv = "DD_TEST_OPTIMIZATION_RUNTIME_TAGS" + reportEnabledEnv = "DD_TEST_OPTIMIZATION_RUNNER_REPORT_ENABLED" knapsackTestFilePatternEnv = "KNAPSACK_PRO_TEST_FILE_PATTERN" knapsackTestFileExcludeEnv = "KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN" ) @@ -120,7 +132,7 @@ var ( func Init() { viper.AutomaticEnv() - viper.SetEnvPrefix("DD_TEST_OPTIMIZATION_RUNNER") + viper.SetEnvPrefix(envPrefix) viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) if err := viper.BindEnv("parallel_runner_overhead", parallelRunnerOverheadEnv); err != nil { fmt.Fprintf(os.Stderr, "Error binding parallel runner overhead env: %v\n", err) @@ -150,6 +162,10 @@ func Init() { fmt.Fprintf(os.Stderr, "Error binding strict discovery env: %v\n", err) os.Exit(1) } + if err := viper.BindEnv("runtime_tags", runtimeTagsEnv, runtimeTagsAliasEnv); err != nil { + fmt.Fprintf(os.Stderr, "Error binding runtime tags env: %v\n", err) + os.Exit(1) + } setDefaults() diff --git a/internal/settings/settings_test.go b/internal/settings/settings_test.go index e3d9512..5563134 100644 --- a/internal/settings/settings_test.go +++ b/internal/settings/settings_test.go @@ -288,41 +288,41 @@ func TestEnvironmentVariables(t *testing.T) { viper.Reset() // Set environment variables - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_PLATFORM", "python") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_FRAMEWORK", "pytest") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_MIN_PARALLELISM", "2") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_MAX_PARALLELISM", "8") + _ = os.Setenv(platformEnv, "python") + _ = os.Setenv(frameworkEnv, "pytest") + _ = os.Setenv(minParallelismEnv, "2") + _ = os.Setenv(maxParallelismEnv, "8") _ = os.Setenv(parallelRunnerOverheadEnv, "40s") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_WORKER_ENV", "RAILS_DB=my_project_dev_{{nodeIndex}}") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_CI_NODE", "5") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_CI_NODE_WORKERS", "4") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_COMMAND", "bundle exec rspec") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_TESTS_LOCATION", "spec/**/*_spec.rb") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_TESTS_EXCLUDE_PATTERN", "spec/system/**/*_spec.rb") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_TEST_DISCOVERY_CACHE", "/tmp/ddtest-tests.json") - _ = os.Setenv("DD_TESTOPTIMIZATION_TIA_TEST_SKIPPING_MODE", "suite") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_FORCE_FULL_TEST_DISCOVERY", "true") + _ = os.Setenv(workerEnv, "RAILS_DB=my_project_dev_{{nodeIndex}}") + _ = os.Setenv(ciNodeEnv, "5") + _ = os.Setenv(ciNodeWorkersEnv, "4") + _ = os.Setenv(commandEnv, "bundle exec rspec") + _ = os.Setenv(testsLocationEnv, "spec/**/*_spec.rb") + _ = os.Setenv(testsExcludePatternEnv, "spec/system/**/*_spec.rb") + _ = os.Setenv(testDiscoveryCacheEnv, "/tmp/ddtest-tests.json") + _ = os.Setenv(testSkippingModeEnv, "suite") + _ = os.Setenv(forceFullTestDiscoveryEnv, "true") _ = os.Setenv(strictDiscoveryEnv, "true") - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_RUNTIME_TAGS", `{"os.platform":"linux","runtime.version":"3.2.0"}`) - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_REPORT_ENABLED", "false") + _ = os.Setenv(runtimeTagsEnv, `{"os.platform":"linux","runtime.version":"3.2.0"}`) + _ = os.Setenv(reportEnabledEnv, "false") defer func() { - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_PLATFORM") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_FRAMEWORK") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_MIN_PARALLELISM") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_MAX_PARALLELISM") + _ = os.Unsetenv(platformEnv) + _ = os.Unsetenv(frameworkEnv) + _ = os.Unsetenv(minParallelismEnv) + _ = os.Unsetenv(maxParallelismEnv) _ = os.Unsetenv(parallelRunnerOverheadEnv) - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_WORKER_ENV") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_CI_NODE") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_CI_NODE_WORKERS") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_COMMAND") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_TESTS_LOCATION") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_TESTS_EXCLUDE_PATTERN") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_TEST_DISCOVERY_CACHE") - _ = os.Unsetenv("DD_TESTOPTIMIZATION_TIA_TEST_SKIPPING_MODE") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_FORCE_FULL_TEST_DISCOVERY") + _ = os.Unsetenv(workerEnv) + _ = os.Unsetenv(ciNodeEnv) + _ = os.Unsetenv(ciNodeWorkersEnv) + _ = os.Unsetenv(commandEnv) + _ = os.Unsetenv(testsLocationEnv) + _ = os.Unsetenv(testsExcludePatternEnv) + _ = os.Unsetenv(testDiscoveryCacheEnv) + _ = os.Unsetenv(testSkippingModeEnv) + _ = os.Unsetenv(forceFullTestDiscoveryEnv) _ = os.Unsetenv(strictDiscoveryEnv) - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_RUNTIME_TAGS") - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_REPORT_ENABLED") + _ = os.Unsetenv(runtimeTagsEnv) + _ = os.Unsetenv(reportEnabledEnv) }() Init() @@ -667,6 +667,42 @@ func TestCanonicalTestPatternEnvVarsTakePrecedenceOverKnapsackAliases(t *testing } } +func TestRuntimeTagsAlias(t *testing.T) { + config = nil + viper.Reset() + + _ = os.Setenv(runtimeTagsEnv, "") + _ = os.Setenv(runtimeTagsAliasEnv, `{"os.platform":"linux","runtime.version":"3.2.0"}`) + defer func() { + _ = os.Unsetenv(runtimeTagsEnv) + _ = os.Unsetenv(runtimeTagsAliasEnv) + }() + + Init() + + if config.RuntimeTags != `{"os.platform":"linux","runtime.version":"3.2.0"}` { + t.Errorf("expected runtime_tags from alias env var to be JSON string, got %q", config.RuntimeTags) + } +} + +func TestCanonicalRuntimeTagsEnvVarTakesPrecedenceOverAlias(t *testing.T) { + config = nil + viper.Reset() + + _ = os.Setenv(runtimeTagsEnv, `{"os.platform":"linux"}`) + _ = os.Setenv(runtimeTagsAliasEnv, `{"os.platform":"darwin"}`) + defer func() { + _ = os.Unsetenv(runtimeTagsEnv) + _ = os.Unsetenv(runtimeTagsAliasEnv) + }() + + Init() + + if config.RuntimeTags != `{"os.platform":"linux"}` { + t.Errorf("expected canonical runtime_tags env var to win, got %q", config.RuntimeTags) + } +} + func TestGetRuntimeTags(t *testing.T) { config = nil viper.Reset() @@ -938,9 +974,9 @@ func TestEnvironmentVariableCiNodeWorkersNCPU(t *testing.T) { config = nil viper.Reset() - _ = os.Setenv("DD_TEST_OPTIMIZATION_RUNNER_CI_NODE_WORKERS", "ncpu") + _ = os.Setenv(ciNodeWorkersEnv, "ncpu") defer func() { - _ = os.Unsetenv("DD_TEST_OPTIMIZATION_RUNNER_CI_NODE_WORKERS") + _ = os.Unsetenv(ciNodeWorkersEnv) }() Init()