Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
140e25d
Refactored EnvironmentVariables to be testable.
AlexeyKuznetsov-DD Sep 20, 2025
2b8305e
WIP.
AlexeyKuznetsov-DD Sep 22, 2025
0969a7d
adding supported-configurations.json file
mhlidd Sep 18, 2025
0eda863
removing extra supported-configurations.json
mhlidd Sep 23, 2025
d4cf4fb
migrating config-utils tests and ConfigInversionMetric telemetry
mhlidd Sep 18, 2025
76281ab
config inversion init
mhlidd Sep 15, 2025
83f0f98
migrating config-utils tests
mhlidd Sep 15, 2025
e9f9689
undo move of test files that rely on inject*config
mhlidd Sep 16, 2025
9625dd4
adding deprecation handling
mhlidd Sep 16, 2025
a2926f9
updating tests
mhlidd Sep 16, 2025
bcb6db6
spotless
mhlidd Sep 16, 2025
31fc7b4
excluding json from shadowjar
mhlidd Sep 19, 2025
71e309f
updating gradle files
mhlidd Sep 19, 2025
c65460a
responding to PR comments
mhlidd Sep 19, 2025
a4de955
updating class coverage exclude
mhlidd Sep 19, 2025
cad575c
updating ConfigHelper to be a singleton
mhlidd Sep 23, 2025
5fe0a88
refactoring ConfigHelper and ConfigurationSources to simplify code re…
mhlidd Sep 23, 2025
4c924eb
responding to PR comments and refactoring ConfigHelperTest to utilize…
mhlidd Sep 25, 2025
3bbf486
updating PR comments
mhlidd Sep 25, 2025
8ba684e
cleanup and code coverage
mhlidd Sep 25, 2025
3ad209b
init migration
mhlidd Sep 25, 2025
6e107b2
creating noop implementation of ConfigInversionMetricCollector
mhlidd Sep 30, 2025
0777920
adding Noop implementation to exclude code coverage
mhlidd Sep 30, 2025
089eedd
adding to bootstrap classpath for testing
mhlidd Sep 30, 2025
62c8530
bugfixes
mhlidd Sep 30, 2025
ebaad98
adding more configurations to supported-configurations and updating n…
mhlidd Oct 1, 2025
ed338ba
fix native build and update telemetry test with clear error message
mhlidd Oct 1, 2025
6642903
PR comments
mhlidd Oct 3, 2025
2401cfd
removing explicit dependency on environment component
mhlidd Oct 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {
id("de.thetaphi.forbiddenapis") version "3.8"

id("tracer-version")
id("config-inversion-linter")
id("io.github.gradle-nexus.publish-plugin") version "2.0.0"

id("com.gradleup.shadow") version "8.3.6" apply false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ private fun registerCheckEnvironmentVariablesUsage(project: Project) {
val javaFiles = project.fileTree(project.projectDir) {
include("**/src/main/java/**/*.java")
exclude("**/build/**")
exclude("internal-api/src/main/java/datadog/trace/api/ConfigHelper.java")
exclude("utils/config-utils/src/main/java/datadog/trace/config/inversion/ConfigHelper.java")
exclude("dd-java-agent/agent-bootstrap/**")
exclude("dd-java-agent/src/main/java/datadog/trace/bootstrap/BootstrapInitializationTelemetry.java")
exclude("dd-java-agent/src/main/java/datadog/trace/bootstrap/**")
}

val pattern = Regex("""EnvironmentVariables\.get\s*\(""")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;

import de.thetaphi.forbiddenapis.SuppressForbidden;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
Expand All @@ -16,6 +17,24 @@
public final class EnvironmentVariables {
private EnvironmentVariables() {}

public static class EnvironmentVariablesProvider {

// Environment Component has SecurityException handling, so it is safe to call System.getenv
// here
@SuppressForbidden
public String get(String name) {
return System.getenv(name);
}

@SuppressForbidden
public Map<String, String> getAll() {
return System.getenv();
}
}

// Make it accessible from tests.
public static volatile EnvironmentVariablesProvider provider = new EnvironmentVariablesProvider();

/**
* Gets an environment variable value.
*
Expand All @@ -41,7 +60,7 @@ public static String getOrDefault(String name, String defaultValue) {
return defaultValue;
}
try {
String value = System.getenv(name);
String value = provider.get(name);
return value == null ? defaultValue : value;
} catch (SecurityException e) {
return defaultValue;
Expand All @@ -56,7 +75,7 @@ public static String getOrDefault(String name, String defaultValue) {
*/
public static Map<String, String> getAll() {
try {
return unmodifiableMap(new HashMap<>(System.getenv()));
return unmodifiableMap(new HashMap<>(provider.getAll()));
} catch (SecurityException e) {
return emptyMap();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public final class Constants {
"datadog.appsec.api",
"datadog.trace.api",
"datadog.trace.bootstrap",
"datadog.trace.config.inversion",
"datadog.trace.context",
"datadog.trace.instrumentation.api",
"datadog.trace.logging",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package datadog.trace.agent.test


import datadog.environment.EnvironmentVariables
import datadog.trace.agent.tooling.InstrumenterModule
import datadog.trace.agent.tooling.bytebuddy.matcher.DDElementMatchers
import datadog.trace.agent.tooling.bytebuddy.outline.TypePoolFacade
Expand Down Expand Up @@ -118,7 +118,7 @@ class DefaultInstrumenterForkedTest extends DDSpecification {
def target = new TestDefaultInstrumenter(name, altName)

then:
System.getenv("DD_INTEGRATION_${value}_ENABLED") == "true"
EnvironmentVariables.get("DD_INTEGRATION_${value}_ENABLED") == "true"
target.enabled == enabled

where:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package datadog.trace.civisibility
import com.fasterxml.jackson.databind.ObjectMapper
import datadog.communication.serialization.GrowableBuffer
import datadog.communication.serialization.msgpack.MsgPackWriter
import datadog.environment.EnvironmentVariables
import datadog.trace.agent.test.InstrumentationSpecification
import datadog.trace.agent.test.asserts.ListWriterAssert
import datadog.trace.api.Config
Expand Down Expand Up @@ -367,7 +368,7 @@ abstract class CiVisibilityInstrumentationTest extends InstrumentationSpecificat

def additionalIgnoredTags = CiVisibilityTestUtils.IGNORED_TAGS + ignoredTags

if (System.getenv().get("GENERATE_TEST_FIXTURES") != null) {
if (EnvironmentVariables.get("GENERATE_TEST_FIXTURES") != null) {
return generateTestFixtures(testcaseName, events, coverages, additionalReplacements, additionalIgnoredTags)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package datadog.trace.civisibility

import datadog.environment.EnvironmentVariables
import datadog.trace.api.Config
import datadog.trace.api.civisibility.config.TestFQN
import datadog.trace.api.config.CiVisibilityConfig
Expand All @@ -21,9 +22,9 @@ abstract class CiVisibilitySmokeTest extends Specification {

protected static String buildJavaHome() {
if (Jvm.current.isJava8()) {
return System.getenv("JAVA_8_HOME")
return EnvironmentVariables.get("JAVA_8_HOME")
}
return System.getenv("JAVA_" + Jvm.current.getJavaSpecificationVersion() + "_HOME")
return EnvironmentVariables.get("JAVA_" + Jvm.current.getJavaSpecificationVersion() + "_HOME")
}

protected static String javaPath() {
Expand Down Expand Up @@ -67,10 +68,10 @@ abstract class CiVisibilitySmokeTest extends Specification {
Map<String, String> argMap = buildJvmArgMap(mockBackendIntakeUrl, serviceName, additionalArgs)

// for convenience when debugging locally
if (System.getenv("DD_CIVISIBILITY_SMOKETEST_DEBUG_PARENT") != null) {
if (EnvironmentVariables.get("DD_CIVISIBILITY_SMOKETEST_DEBUG_PARENT") != null) {
arguments += "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
}
if (System.getenv("DD_CIVISIBILITY_SMOKETEST_DEBUG_CHILD") != null) {
if (EnvironmentVariables.get("DD_CIVISIBILITY_SMOKETEST_DEBUG_CHILD") != null) {
argMap.put(CiVisibilityConfig.CIVISIBILITY_DEBUG_PORT, "5055")
}

Expand All @@ -83,7 +84,7 @@ abstract class CiVisibilitySmokeTest extends Specification {
protected verifyEventsAndCoverages(String projectName, String toolchain, String toolchainVersion, List<Map<String, Object>> events, List<Map<String, Object>> coverages, List<String> additionalDynamicTags = []) {
def additionalReplacements = ["content.meta.['test.toolchain']": "$toolchain:$toolchainVersion"]

if (System.getenv().get("GENERATE_TEST_FIXTURES") != null) {
if (EnvironmentVariables.get("GENERATE_TEST_FIXTURES") != null) {
def baseTemplatesPath = CiVisibilitySmokeTest.classLoader.getResource(projectName).toURI().schemeSpecificPart.replace('build/resources/test', 'src/test/resources')
CiVisibilityTestUtils.generateTemplates(baseTemplatesPath, events, coverages, additionalReplacements.keySet() + additionalDynamicTags, SMOKE_IGNORED_TAGS)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.jayway.jsonpath.JsonPath
import com.jayway.jsonpath.Option
import com.jayway.jsonpath.ReadContext
import com.jayway.jsonpath.WriteContext
import datadog.environment.EnvironmentVariables
import datadog.trace.api.DDSpanTypes
import datadog.trace.api.civisibility.config.LibraryCapability
import datadog.trace.api.civisibility.config.TestFQN
Expand Down Expand Up @@ -162,7 +163,7 @@ abstract class CiVisibilityTestUtils {
}

private static void compareJson(String expectedJson, String actualJson) {
def environment = System.getenv()
def environment = EnvironmentVariables.getAll()
def ciRun = environment.get("GITHUB_ACTION") != null || environment.get("GITLAB_CI") != null
def comparisonMode = ciRun ? JSONCompareMode.LENIENT : JSONCompareMode.NON_EXTENSIBLE

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package datadog.trace.civisibility.ci

import datadog.trace.api.Config
import datadog.trace.civisibility.ci.env.CiEnvironmentImpl
import org.junit.Rule
import org.junit.contrib.java.lang.system.EnvironmentVariables
import org.junit.contrib.java.lang.system.RestoreSystemProperties
import datadog.trace.test.util.ControllableEnvironmentVariables
import spock.lang.Specification

import java.nio.file.Paths
Expand All @@ -21,25 +19,18 @@ import static datadog.trace.civisibility.ci.JenkinsInfo.JENKINS
import static datadog.trace.civisibility.ci.TravisInfo.TRAVIS

class CIProviderInfoFactoryTest extends Specification {
@Rule
public final EnvironmentVariables environmentVariables = new EnvironmentVariables()
protected ControllableEnvironmentVariables env = ControllableEnvironmentVariables.setup()

@Rule
public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()

def setup() {
// Clear all environment variables to avoid clashes between
// real CI/Git environment variables and the spec CI/Git
// environment variables.
environmentVariables.clear(System.getenv().keySet() as String[])
void cleanup() {
env.clear()
}

def "test correct info is selected"() {
setup:
environmentVariables.set(ciKeySelector, "true")
env.set(ciKeySelector, "true")

when:
def ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), new CiEnvironmentImpl(System.getenv()))
def ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), new CiEnvironmentImpl(env.getAll()))
def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(Paths.get("").toAbsolutePath())

then:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import datadog.trace.civisibility.ci.env.CiEnvironmentImpl
import datadog.trace.civisibility.git.CILocalGitInfoBuilder
import datadog.trace.civisibility.git.CIProviderGitInfoBuilder
import datadog.trace.civisibility.git.tree.GitClient
import org.junit.Rule
import org.junit.contrib.java.lang.system.EnvironmentVariables
import org.junit.contrib.java.lang.system.RestoreSystemProperties
import datadog.trace.test.util.ControllableEnvironmentVariables
import spock.lang.Specification

import java.nio.file.Path
Expand All @@ -19,36 +17,28 @@ import java.nio.file.Paths
import static datadog.trace.util.ConfigStrings.propertyNameToEnvironmentVariableName

abstract class CITagsProviderTest extends Specification {

static final CI_WORKSPACE_PATH_FOR_TESTS = "ci/ci_workspace_for_tests"
static final GIT_FOLDER_FOR_TESTS = "git_folder_for_tests"

@Rule
public final EnvironmentVariables environmentVariables = new EnvironmentVariables()

@Rule
public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()
protected ControllableEnvironmentVariables env = ControllableEnvironmentVariables.setup()

protected final String localFSGitWorkspace = resolve(CI_WORKSPACE_PATH_FOR_TESTS)

def setup() {
// Clear all environment variables to avoid clashes between
// real CI/Git environment variables and the spec CI/Git
// environment variables.
environmentVariables.clear(System.getenv().keySet() as String[])
void cleanup() {
env.clear()
}

def "test ci provider info is set properly: #ciSpec.providerName #ciSpec.idx #ciSpec.testCaseName"() {
setup:
ciSpec.env.each {
environmentVariables.set(it.key, it.value.toString())
env.set(it.key, it.value.toString())
if (it.key == "HOME") {
System.setProperty("user.home", it.value)
}
}

when:
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv()))
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(env.getAll()))
def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath())
def ciInfo = ciProviderInfo.buildCIInfo()
def prInfo = ciProviderInfo.buildPullRequestInfo()
Expand All @@ -68,13 +58,13 @@ abstract class CITagsProviderTest extends Specification {
def "test user supplied commit hash takes precedence over auto-detected git info"() {
setup:
buildRemoteGitInfoEmpty().each {
environmentVariables.set(it.key, it.value)
env.set(it.key, it.value)
}

environmentVariables.set(propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_SHA), "1234567890123456789012345678901234567890")
env.set(propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_SHA), "1234567890123456789012345678901234567890")

when:
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv()))
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(env.getAll()))
def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath())
def ciInfo = ciProviderInfo.buildCIInfo()
def ciTagsProvider = ciTagsProvider()
Expand All @@ -87,13 +77,13 @@ abstract class CITagsProviderTest extends Specification {
def "test user supplied repo url takes precedence over auto-detected git info"() {
setup:
buildRemoteGitInfoEmpty().each {
environmentVariables.set(it.key, it.value)
env.set(it.key, it.value)
}

environmentVariables.set(propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_REPOSITORY_URL), "local supplied repo url")
env.set(propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_REPOSITORY_URL), "local supplied repo url")

when:
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv()))
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(env.getAll()))
def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath())
def ciInfo = ciProviderInfo.buildCIInfo()
def ciTagsProvider = ciTagsProvider()
Expand All @@ -106,11 +96,11 @@ abstract class CITagsProviderTest extends Specification {
def "test set local git info if remote git info is not present"() {
setup:
buildRemoteGitInfoEmpty().each {
environmentVariables.set(it.key, it.value)
env.set(it.key, it.value)
}

when:
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv()))
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(env.getAll()))
def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath())
def ciInfo = ciProviderInfo.buildCIInfo()
def ciTagsProvider = ciTagsProvider()
Expand All @@ -134,15 +124,15 @@ abstract class CITagsProviderTest extends Specification {
def "test avoid setting local git info if remote commit does not match"() {
setup:
buildRemoteGitInfoMismatchLocalGit().each {
environmentVariables.set(it.key, it.value)
env.set(it.key, it.value)
}

when:
def ciTagsProvider = ciTagsProvider()

then:
if (isCi()) {
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv()))
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(env.getAll()))
def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath())
def ciInfo = ciProviderInfo.buildCIInfo()
def tags = ciTagsProvider.getCiTags(ciInfo, PullRequestInfo.EMPTY)
Expand Down Expand Up @@ -176,7 +166,7 @@ abstract class CITagsProviderTest extends Specification {

GitInfoProvider gitInfoProvider = new GitInfoProvider()
gitInfoProvider.registerGitInfoBuilder(new UserSuppliedGitInfoBuilder())
gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(System.getenv())))
gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(env.getAll())))
gitInfoProvider.registerGitInfoBuilder(new CILocalGitInfoBuilder(gitClientFactory, GIT_FOLDER_FOR_TESTS))
return new CITagsProvider(gitInfoProvider)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ class GithubActionsInfoTest extends CITagsProviderTest {
def githubEvent = GithubActionsInfoTest.getResource("/ci/github-event.json")
def githubEventPath = Paths.get(githubEvent.toURI())

environmentVariables.set(GithubActionsInfo.GITHUB_BASE_REF, "base-ref")
environmentVariables.set(GithubActionsInfo.GITHUB_EVENT_PATH, githubEventPath.toString())
env.set(GithubActionsInfo.GITHUB_BASE_REF, "base-ref")
env.set(GithubActionsInfo.GITHUB_EVENT_PATH, githubEventPath.toString())

when:
def pullRequestInfo = new GithubActionsInfo(new CiEnvironmentImpl(System.getenv())).buildPullRequestInfo()
def pullRequestInfo = new GithubActionsInfo(new CiEnvironmentImpl(env.getAll())).buildPullRequestInfo()

then:
pullRequestInfo.getBaseBranch() == "base-ref"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class UnknownCIInfoTest extends CITagsProviderTest {
]

when:
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv()))
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(env.getAll()))
def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(workspaceForTests)
def ciInfo = ciProviderInfo.buildCIInfo()
def ciTagsProvider = ciTagsProvider()
Expand All @@ -62,9 +62,9 @@ class UnknownCIInfoTest extends CITagsProviderTest {

GitInfoProvider gitInfoProvider = new GitInfoProvider()
gitInfoProvider.registerGitInfoBuilder(new UserSuppliedGitInfoBuilder())
gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(System.getenv())))
gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(env.getAll())))
gitInfoProvider.registerGitInfoBuilder(new CILocalGitInfoBuilder(gitClientFactory, "this-target-folder-does-not-exist"))
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), "this-target-folder-does-not-exist", new CiEnvironmentImpl(System.getenv()))
CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), "this-target-folder-does-not-exist", new CiEnvironmentImpl(env.getAll()))

def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(workspaceForTests)
def ciInfo = ciProviderInfo.buildCIInfo()
Expand Down
Loading
Loading