Skip to content

Commit f1397f6

Browse files
committed
adding gradle task to verify configs defined are documented
1 parent cdebbd8 commit f1397f6

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ plugins {
55
id("datadog.dependency-locking")
66
id("datadog.tracer-version")
77
id("datadog.dump-hanged-test")
8+
id("config-inversion-linter")
89

910
id("com.diffplug.spotless") version "6.13.0"
1011
id("com.github.spotbugs") version "5.0.14"

buildSrc/src/main/kotlin/datadog/gradle/plugin/config/ConfigInversionLinter.kt

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class ConfigInversionLinter : Plugin<Project> {
1414
val extension = target.extensions.create("supportedTracerConfigurations", SupportedTracerConfigurations::class.java)
1515
registerLogEnvVarUsages(target, extension)
1616
registerCheckEnvironmentVariablesUsage(target)
17+
registerCheckConfigStringsTask(target, extension)
1718
}
1819
}
1920

@@ -124,3 +125,79 @@ private fun registerCheckEnvironmentVariablesUsage(project: Project) {
124125
}
125126
}
126127
}
128+
129+
/** Registers `checkConfigStrings` to validate config strings against documented supported configurations. */
130+
private fun registerCheckConfigStringsTask(project: Project, extension: SupportedTracerConfigurations) {
131+
val ownerPath = extension.configOwnerPath
132+
val generatedFile = extension.className
133+
134+
project.tasks.register("checkConfigStrings") {
135+
group = "verification"
136+
description = "Validates that all config definitions in dd-trace-api/src/main/java/datadog/trace/api/config exist in metadata/supported-configurations.json"
137+
138+
val mainSourceSetOutput = ownerPath.map {
139+
project.project(it)
140+
.extensions.getByType<SourceSetContainer>()
141+
.named(SourceSet.MAIN_SOURCE_SET_NAME)
142+
.map { main -> main.output }
143+
}
144+
inputs.files(mainSourceSetOutput)
145+
146+
doLast {
147+
val repoRoot: Path = project.rootProject.projectDir.toPath()
148+
val configDir = repoRoot.resolve("dd-trace-api/src/main/java/datadog/trace/api/config").toFile()
149+
150+
if (!configDir.exists()) {
151+
throw GradleException("Config directory not found: ${configDir.absolutePath}")
152+
}
153+
154+
val urls = mainSourceSetOutput.get().get().files.map { it.toURI().toURL() }.toTypedArray()
155+
val (supported, aliasMapping) = URLClassLoader(urls, javaClass.classLoader).use { cl ->
156+
val clazz = Class.forName(generatedFile.get(), true, cl)
157+
@Suppress("UNCHECKED_CAST")
158+
val supportedSet = clazz.getField("SUPPORTED").get(null) as Set<String>
159+
@Suppress("UNCHECKED_CAST")
160+
val aliasMappingMap = clazz.getField("ALIAS_MAPPING").get(null) as Map<String, String>
161+
Pair(supportedSet, aliasMappingMap)
162+
}
163+
164+
val stringFieldRegex = Regex("""public\s+static\s+final\s+String\s+\w+\s*=\s*"([^"]+)"\s*;""")
165+
166+
val violations = buildList {
167+
configDir.listFiles()?.filter { it.extension == "java" }?.forEach { file ->
168+
var inBlockComment = false
169+
file.readLines().forEachIndexed { idx, line ->
170+
val trimmed = line.trim()
171+
172+
if (trimmed.startsWith("//")) return@forEachIndexed
173+
if (!inBlockComment && trimmed.contains("/*")) inBlockComment = true
174+
if (inBlockComment) {
175+
if (trimmed.contains("*/")) inBlockComment = false
176+
return@forEachIndexed
177+
}
178+
179+
stringFieldRegex.findAll(line).forEach { match ->
180+
val configValue = match.groupValues[1]
181+
182+
val normalized = "DD_" + configValue.uppercase()
183+
.replace("-", "_")
184+
.replace(".", "_")
185+
186+
if (normalized !in supported && normalized !in aliasMapping) {
187+
add("${file.name}:${idx + 1} -> Config '$configValue' normalizes to '$normalized' which is not in supported-configurations.json")
188+
}
189+
}
190+
}
191+
}
192+
}
193+
194+
if (violations.isNotEmpty()) {
195+
project.logger.lifecycle("\nFound config strings not in supported-configurations.json:")
196+
violations.forEach { project.logger.lifecycle(it) }
197+
throw GradleException("Config strings validation failed. See errors above.")
198+
} else {
199+
project.logger.info("All config strings are present in supported-configurations.json.")
200+
}
201+
}
202+
}
203+
}

0 commit comments

Comments
 (0)