Skip to content

Commit 37392bd

Browse files
committed
refactor to fix caching issues
1 parent 479f5fa commit 37392bd

File tree

4 files changed

+288
-231
lines changed

4 files changed

+288
-231
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package io.opentelemetry.gradle
2+
3+
import java.io.IOException
4+
import org.gradle.api.DefaultTask
5+
import org.gradle.api.GradleException
6+
import org.gradle.api.file.DirectoryProperty
7+
import org.gradle.api.file.RegularFileProperty
8+
import org.gradle.api.provider.ListProperty
9+
import org.gradle.api.provider.Property
10+
import org.gradle.api.tasks.Input
11+
import org.gradle.api.tasks.InputFiles
12+
import org.gradle.api.tasks.Optional
13+
import org.gradle.api.tasks.OutputDirectory
14+
import org.gradle.api.tasks.OutputFile
15+
import org.gradle.api.tasks.PathSensitive
16+
import org.gradle.api.tasks.PathSensitivity
17+
import org.gradle.api.tasks.TaskAction
18+
import org.gradle.process.ExecOperations
19+
import org.gradle.work.DisableCachingByDefault
20+
import javax.inject.Inject
21+
22+
@DisableCachingByDefault(because = "Docker run is external and side-effectful")
23+
abstract class WeaverTasks @Inject constructor(
24+
private val execOps: ExecOperations
25+
) : DefaultTask() {
26+
27+
companion object {
28+
private const val WEAVER_MODEL_PATH = "/home/weaver/model"
29+
private const val WEAVER_TEMPLATES_PATH = "/home/weaver/templates"
30+
private const val WEAVER_TARGET_PATH = "/home/weaver/target"
31+
}
32+
33+
@get:Input
34+
abstract val dockerExecutable: Property<String>
35+
@get:Input
36+
abstract val platform: Property<String>
37+
@get:Input
38+
abstract val image: Property<String>
39+
40+
@get:InputFiles
41+
@get:PathSensitive(PathSensitivity.RELATIVE)
42+
abstract val modelDir: DirectoryProperty
43+
44+
@get:InputFiles
45+
@get:Optional
46+
@get:PathSensitive(PathSensitivity.RELATIVE)
47+
abstract val templatesDir: DirectoryProperty
48+
49+
// Choose ONE of these per task
50+
@get:OutputDirectory
51+
@get:Optional
52+
abstract val outputDir: DirectoryProperty
53+
@get:OutputFile
54+
@get:Optional
55+
abstract val outputFile: RegularFileProperty
56+
57+
// e.g., ["registry","check","--registry=/home/weaver/model"]
58+
@get:Input
59+
abstract val toolArgs: ListProperty<String>
60+
61+
@TaskAction
62+
fun runWeaver() {
63+
// Validate Docker is available
64+
validateDockerAvailable()
65+
66+
val mounts = mutableListOf(
67+
"--mount", "type=bind,source=${modelDir.get().asFile.absolutePath},target=$WEAVER_MODEL_PATH,readonly"
68+
)
69+
70+
val templates = templatesDir.orNull
71+
if (templates != null) {
72+
when {
73+
templates.asFile.isDirectory -> {
74+
mounts += listOf("--mount", "type=bind,source=${templates.asFile.absolutePath},target=$WEAVER_TEMPLATES_PATH,readonly")
75+
}
76+
templates.asFile.exists() -> {
77+
logger.warn("templatesDir exists but is not a directory: ${templates.asFile.absolutePath}. Skipping templates mount.")
78+
}
79+
}
80+
}
81+
82+
val targetMount = when {
83+
outputDir.isPresent -> {
84+
outputDir.get().asFile.mkdirs()
85+
listOf("--mount", "type=bind,source=${outputDir.get().asFile.absolutePath},target=$WEAVER_TARGET_PATH")
86+
}
87+
88+
outputFile.isPresent -> {
89+
// Mount parent directory and ensure weaver writes to the correct filename
90+
val outputFileObj = outputFile.get().asFile
91+
val parent = outputFileObj.parentFile.also { it.mkdirs() }
92+
logger.info("Mounting ${parent.absolutePath} for output file: ${outputFileObj.name}")
93+
listOf("--mount", "type=bind,source=${parent.absolutePath},target=$WEAVER_TARGET_PATH")
94+
}
95+
96+
else -> error("Either outputDir or outputFile must be set")
97+
}
98+
mounts += targetMount
99+
100+
val base = mutableListOf("run", "--rm", "--platform=${platform.get()}")
101+
val os = System.getProperty("os.name").lowercase()
102+
if (os.contains("linux")) {
103+
try {
104+
val uid = ProcessBuilder("id", "-u").start().inputStream.bufferedReader().readText().trim()
105+
val gid = ProcessBuilder("id", "-g").start().inputStream.bufferedReader().readText().trim()
106+
base += listOf("-u", "$uid:$gid")
107+
} catch (e: IOException) {
108+
logger.warn("Could not determine uid/gid: ${e.message}. Generated files may be owned by root")
109+
}
110+
}
111+
112+
execOps.exec {
113+
executable = dockerExecutable.get()
114+
args = base + mounts + listOf(image.get()) + toolArgs.get()
115+
standardOutput = System.out
116+
errorOutput = System.err
117+
isIgnoreExitValue = false
118+
}
119+
}
120+
121+
private fun validateDockerAvailable() {
122+
try {
123+
val process = ProcessBuilder(dockerExecutable.get(), "--version")
124+
.redirectErrorStream(true)
125+
.start()
126+
val exitCode = process.waitFor()
127+
if (exitCode != 0) {
128+
throw GradleException("Docker is not available or not functioning correctly. Please ensure Docker is installed and running.")
129+
}
130+
} catch (e: IOException) {
131+
throw GradleException("Docker is required but could not be executed. Please install and start Docker. Error: ${e.message}", e)
132+
}
133+
}
134+
}
135+

0 commit comments

Comments
 (0)