Skip to content

Commit 47d6523

Browse files
ryandensclaude
andauthored
Add minimal Jib container-customizer extension support (#341)
## Summary - Introduces `JibExtensionConfiguration` to expose javaagent files to the Jib plugin extension via the standard extra-config mechanism - Replaces the fragile `lateinit var javaagentPathProvider` field with proper `JibGradlePluginExtension<JibExtensionConfiguration>` typing - Wires agent files lazily through `project.provider { }` so configuration remains deferred until task execution ## Test plan - [x] `./gradlew :plugin:test` passes - [ ] Manual end-to-end test with a project that uses the Jib plugin 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 52bdf65 commit 47d6523

4 files changed

Lines changed: 89 additions & 28 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Ignore Gradle project-specific cache directory
22
.gradle
33

4+
# claude
5+
.claude
6+
47
# Ignore Gradle build output directory
58
build
69

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAME
55
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
66
org.gradle.configuration-cache=true
77
org.gradle.caching=true
8-
version=0.11.0
8+
version=0.12.0
99
group=com.ryandens
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.ryandens.javaagent;
2+
3+
import java.io.File;
4+
import javax.inject.Inject;
5+
import org.gradle.api.Project;
6+
import org.gradle.api.model.ObjectFactory;
7+
import org.gradle.api.provider.ListProperty;
8+
import org.gradle.api.tasks.Input;
9+
10+
/**
11+
* Extra configuration for {@link JavaagentJibExtension}. Declares the javaagent files that should
12+
* be copied into the container image and referenced via {@code -javaagent} JVM flags.
13+
*
14+
* <p>Instances are created by Jib's plugin extension mechanism via {@link
15+
* org.gradle.api.model.ObjectFactory}, so this class must have a single-argument constructor
16+
* accepting {@link ObjectFactory}.
17+
*/
18+
public class JibExtensionConfiguration {
19+
20+
private final ListProperty<File> javaagentFiles;
21+
22+
/**
23+
* Instantiated by Jib's plugin extension mechanism
24+
*
25+
* <p>Not compatible with configuration cache due to usage of Project at task execution time.
26+
*/
27+
@Inject
28+
public JibExtensionConfiguration(final Project project) {
29+
this(project.getObjects());
30+
}
31+
32+
public JibExtensionConfiguration(final ObjectFactory objectFactory) {
33+
javaagentFiles = objectFactory.listProperty(File.class);
34+
}
35+
36+
/**
37+
* Returns the list of javaagent {@link File}s to include in the container image. Each file is
38+
* placed under {@code /opt/jib-agents/} in the image and added to the container entrypoint as a
39+
* {@code -javaagent} flag. Package-private: intended to be accessed only by {@link
40+
* JavaagentJibExtension}.
41+
*/
42+
@Input
43+
ListProperty<File> getJavaagentFiles() {
44+
return javaagentFiles;
45+
}
46+
}

plugin/src/main/kotlin/com/ryandens/javaagent/JavaagentJibExtension.kt

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import com.google.cloud.tools.jib.gradle.JibExtension
1010
import com.google.cloud.tools.jib.gradle.extension.GradleData
1111
import com.google.cloud.tools.jib.gradle.extension.JibGradlePluginExtension
1212
import com.google.cloud.tools.jib.plugins.extension.ExtensionLogger
13+
import org.gradle.api.Action
14+
import org.gradle.api.GradleException
1315
import org.gradle.api.NamedDomainObjectProvider
1416
import org.gradle.api.Project
1517
import org.gradle.api.artifacts.Configuration
@@ -24,31 +26,24 @@ import java.util.Optional
2426
*/
2527
@ExperimentalStdlibApi
2628
class JavaagentJibExtension :
27-
JibGradlePluginExtension<Void>,
29+
JibGradlePluginExtension<JibExtensionConfiguration>,
2830
JavaagentPlugin {
29-
override fun getExtraConfigType(): Optional<Class<Void>> = Optional.empty()
31+
override fun getExtraConfigType(): Optional<Class<JibExtensionConfiguration>> = Optional.of(JibExtensionConfiguration::class.java)
3032

3133
override fun extendContainerBuildPlan(
32-
buildPlan: ContainerBuildPlan?,
33-
properties: MutableMap<String, String>?,
34-
extraConfig: Optional<Void>?,
34+
buildPlan: ContainerBuildPlan,
35+
properties: MutableMap<String, String>,
36+
extraConfig: Optional<JibExtensionConfiguration>,
3537
gradleData: GradleData?,
3638
logger: ExtensionLogger?,
3739
): ContainerBuildPlan {
38-
checkNotNull(buildPlan)
3940
val entrypoint = checkNotNull(buildPlan.entrypoint)
4041
check(entrypoint.isNotEmpty())
42+
if (extraConfig.isEmpty) {
43+
throw GradleException("Javaagent Jib plugin must be provided an extraConfig containing javaagent files to configure")
44+
}
4145

42-
val localAgentPaths =
43-
checkNotNull(
44-
gradleData
45-
?.project
46-
?.plugins
47-
?.getPlugin(
48-
JavaagentJibExtension::class.java,
49-
)?.javaagentPathProvider
50-
?.invoke(),
51-
)
46+
val localAgentPaths = extraConfig.get().javaagentFiles.get()
5247

5348
val planBuilder = buildPlan.toBuilder()
5449
val newEntrypoint =
@@ -90,24 +85,41 @@ class JavaagentJibExtension :
9085
it.into(destinationDirectory)
9186
}
9287

93-
listOf("jib", "jibDockerBuild", "jibBuildTar").forEach { jibTaskName ->
94-
project.tasks.named(jibTaskName) { jibTask ->
95-
jibTask.dependsOn(copyAgents)
88+
if (project.pluginManager.hasPlugin("com.google.cloud.tools.jib")) {
89+
listOf("jib", "jibDockerBuild", "jibBuildTar").forEach { jibTaskName ->
90+
project.tasks.named(jibTaskName) { jibTask ->
91+
jibTask.dependsOn(copyAgents)
92+
}
93+
}
94+
} else if (project.pluginManager.hasPlugin("tel.schich.tinyjib")) {
95+
listOf("tinyJibPublish", "tinyJibDocker", "tinyJibTar").forEach { jibTaskName ->
96+
project.tasks.named(jibTaskName) { jibTask ->
97+
jibTask.dependsOn(copyAgents)
98+
}
9699
}
100+
} else {
101+
throw IllegalStateException("Should not be possible")
97102
}
98103

99104
val jibExtension: JibExtension? = project.extensions.findByType(JibExtension::class.java)
100105

101106
jibExtension?.pluginExtensions { extensionParametersSpec ->
102-
extensionParametersSpec.pluginExtension {
103-
it.implementation = "com.ryandens.javaagent.JavaagentJibExtension"
107+
extensionParametersSpec.pluginExtension { extension ->
108+
extension.implementation = "com.ryandens.javaagent.JavaagentJibExtension"
109+
extension.configuration(
110+
Action<JibExtensionConfiguration> { extensionConfiguration ->
111+
extensionConfiguration.javaagentFiles.set(
112+
project.provider {
113+
javaagentConfiguration
114+
.get()
115+
.files
116+
.map { File(destinationDirectory.get().asFile, it.name) }
117+
.toList()
118+
},
119+
)
120+
},
121+
)
104122
}
105123
}
106-
107-
javaagentPathProvider = {
108-
javaagentConfiguration.get().files.map { File(destinationDirectory.get().asFile, it.name) }
109-
}
110124
}
111-
112-
private lateinit var javaagentPathProvider: () -> List<File>
113125
}

0 commit comments

Comments
 (0)