Skip to content

Commit 1f2c4e7

Browse files
committed
Create inputs and outputs extension namespaces
Authored-by: Leonhardt Koepsell <hello@lnhrdt.com>
1 parent 90aeefb commit 1f2c4e7

9 files changed

Lines changed: 84 additions & 78 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
## [Unreleased]
1313

14-
### Chore
14+
### Added
1515

16-
- Improve image input/output API.
17-
- Groovy syntax accesses image input/output features on container extension.
16+
- Introduce container task extension with inputs and outputs.
1817

1918
## [0.2.1] - 2025-04-23
2019

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import dev.codebandits.container.gradle.tasks.ContainerTask
2929

3030
tasks {
3131
register<ContainerTask>("writeHello") {
32-
container.inputLocalImage("alpine:latest")
32+
container.inputs.localImage("alpine:latest")
3333
dockerPull { image = "alpine:latest" }
3434
dockerRun {
3535
image = "alpine:latest"

examples/buildpacks/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ tasks {
99
register<ContainerTask>("buildImage") {
1010
inputs.file("index.html")
1111
inputs.file("project.toml")
12-
container.outputLocalImage("my-image:latest")
12+
container.outputs.localImage("my-image:latest")
1313
dockerPull {
1414
image = "buildpacksio/pack:latest"
1515
}

examples/dind-build/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ plugins {
88
tasks {
99
register<ContainerTask>("buildImage") {
1010
inputs.file("Dockerfile")
11-
container.outputLocalImage("my-image:latest")
11+
container.outputs.localImage("my-image:latest")
1212
dockerPull {
1313
image = "docker:dind"
1414
}

examples/input-output-chaining/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ plugins {
99
tasks {
1010
register("printImageID") {
1111
dependsOn("buildImage")
12-
container.inputLocalImage("my-image:latest")
12+
container.inputs.localImage("my-image:latest")
1313
doLast {
1414
serviceOf<ExecOperations>().exec {
1515
commandLine("sh", "-c", "docker images --filter reference=my-image:latest --format {{.ID}}")
@@ -19,7 +19,7 @@ tasks {
1919

2020
register<ContainerTask>("buildImage") {
2121
inputs.file("Dockerfile")
22-
container.outputLocalImage("my-image:latest")
22+
container.outputs.localImage("my-image:latest")
2323
dockerPull {
2424
image = "docker:dind"
2525
}

src/main/kotlin/dev/codebandits/container/gradle/ContainerTaskExtension.kt

Lines changed: 69 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,79 +8,86 @@ import org.gradle.api.provider.Provider
88
import java.net.URLEncoder
99
import java.nio.charset.StandardCharsets
1010

11-
public abstract class ContainerTaskExtension(private val task: Task) {
12-
public fun inputLocalImage(imageReference: String) {
13-
val trackingFile = task.getLocalImageTrackingFile(imageReference)
14-
task.inputs.file(trackingFile.map { regularFile ->
15-
writeLocalImageId(imageReference, regularFile)
16-
regularFile
17-
})
18-
}
11+
public abstract class ContainerTaskExtension(task: Task) {
12+
public val inputs: Inputs = Inputs(task)
13+
public val outputs: Outputs = Outputs(task)
1914

20-
public fun outputLocalImage(imageReference: String) {
21-
val trackingFile = task.getLocalImageTrackingFile(imageReference)
22-
task.outputs.file(trackingFile.map { regularFile ->
23-
writeLocalImageId(imageReference, regularFile)
24-
regularFile
25-
})
26-
task.doLast { writeLocalImageId(imageReference, trackingFile.get()) }
27-
}
15+
public class Inputs internal constructor(private val task: Task) {
16+
public fun localImage(imageReference: String) {
17+
val trackingFile = task.getLocalImageTrackingFile(imageReference)
18+
task.inputs.file(trackingFile.map { regularFile ->
19+
writeLocalImageId(imageReference, regularFile)
20+
regularFile
21+
})
22+
}
2823

29-
public fun inputRegistryImage(imageReference: String, autoRefresh: Boolean = false) {
30-
val trackingFile = task.getRegistryImageTrackingFile(imageReference)
31-
task.inputs.file(trackingFile.map { regularFile ->
32-
if (autoRefresh || !regularFile.asFile.exists()) {
33-
writeRegistryImageDigest(imageReference, regularFile)
34-
}
35-
regularFile
36-
})
24+
public fun registryImage(imageReference: String, autoRefresh: Boolean = false) {
25+
val trackingFile = task.getRegistryImageTrackingFile(imageReference)
26+
task.inputs.file(trackingFile.map { regularFile ->
27+
if (autoRefresh || !regularFile.asFile.exists()) {
28+
writeRegistryImageDigest(imageReference, regularFile)
29+
}
30+
regularFile
31+
})
32+
}
3733
}
3834

39-
public fun outputRegistryImage(imageReference: String, autoRefresh: Boolean = false) {
40-
val trackingFile = task.getLocalImageTrackingFile(imageReference)
41-
task.outputs.file(trackingFile.map { regularFile ->
42-
if (autoRefresh || !regularFile.asFile.exists()) {
43-
writeRegistryImageDigest(imageReference, regularFile)
44-
}
45-
regularFile
46-
})
47-
task.doLast {
48-
val regularFile = trackingFile.get()
49-
if (autoRefresh || !regularFile.asFile.exists()) {
50-
writeRegistryImageDigest(imageReference, regularFile)
35+
public class Outputs internal constructor(private val task: Task) {
36+
public fun localImage(imageReference: String) {
37+
val trackingFile = task.getLocalImageTrackingFile(imageReference)
38+
task.outputs.file(trackingFile.map { regularFile ->
39+
writeLocalImageId(imageReference, regularFile)
40+
regularFile
41+
})
42+
task.doLast { writeLocalImageId(imageReference, trackingFile.get()) }
43+
}
44+
45+
public fun registryImage(imageReference: String, autoRefresh: Boolean = false) {
46+
val trackingFile = task.getLocalImageTrackingFile(imageReference)
47+
task.outputs.file(trackingFile.map { regularFile ->
48+
if (autoRefresh || !regularFile.asFile.exists()) {
49+
writeRegistryImageDigest(imageReference, regularFile)
50+
}
51+
regularFile
52+
})
53+
task.doLast {
54+
val regularFile = trackingFile.get()
55+
if (autoRefresh || !regularFile.asFile.exists()) {
56+
writeRegistryImageDigest(imageReference, regularFile)
57+
}
5158
}
5259
}
5360
}
61+
}
5462

55-
private fun Task.getLocalImageTrackingFile(
56-
imageReference: String,
57-
): Provider<RegularFile> {
58-
val fileName = URLEncoder.encode(imageReference, StandardCharsets.UTF_8)
59-
return project.layout.buildDirectory.file("images/local/$fileName")
60-
}
63+
private fun Task.getLocalImageTrackingFile(
64+
imageReference: String,
65+
): Provider<RegularFile> {
66+
val fileName = URLEncoder.encode(imageReference, StandardCharsets.UTF_8)
67+
return project.layout.buildDirectory.file("images/local/$fileName")
68+
}
6169

62-
private fun Task.getRegistryImageTrackingFile(
63-
imageReference: String,
64-
): Provider<RegularFile> {
65-
val fileName = URLEncoder.encode(imageReference, StandardCharsets.UTF_8)
66-
return project.layout.buildDirectory.file("images/registry/$fileName")
67-
}
70+
private fun Task.getRegistryImageTrackingFile(
71+
imageReference: String,
72+
): Provider<RegularFile> {
73+
val fileName = URLEncoder.encode(imageReference, StandardCharsets.UTF_8)
74+
return project.layout.buildDirectory.file("images/registry/$fileName")
75+
}
6876

69-
private fun writeLocalImageId(imageReference: String, regularFile: RegularFile) {
70-
val file = regularFile.asFile
71-
if (!file.parentFile.exists()) {
72-
file.parentFile.mkdirs()
73-
}
74-
val imageId = Local.getImageId(imageReference)
75-
file.writeText(imageId ?: "")
77+
private fun writeLocalImageId(imageReference: String, regularFile: RegularFile) {
78+
val file = regularFile.asFile
79+
if (!file.parentFile.exists()) {
80+
file.parentFile.mkdirs()
7681
}
82+
val imageId = Local.getImageId(imageReference)
83+
file.writeText(imageId ?: "")
84+
}
7785

78-
private fun writeRegistryImageDigest(imageReference: String, regularFile: RegularFile) {
79-
val file = regularFile.asFile
80-
if (!file.parentFile.exists()) {
81-
file.parentFile.mkdirs()
82-
}
83-
val imageDigest = Registry.getImageDigest(imageReference)
84-
file.writeText(imageDigest ?: "")
86+
private fun writeRegistryImageDigest(imageReference: String, regularFile: RegularFile) {
87+
val file = regularFile.asFile
88+
if (!file.parentFile.exists()) {
89+
file.parentFile.mkdirs()
8590
}
91+
val imageDigest = Registry.getImageDigest(imageReference)
92+
file.writeText(imageDigest ?: "")
8693
}

src/testFeatures/kotlin/dev/codebandits/container/gradle/GroovySyntaxTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class GroovySyntaxTest : GradleProjectTest() {
3232
}
3333
3434
tasks.register("buildImage", ContainerTask) {
35-
container.outputLocalImage("$imageReference")
35+
container.outputs.localImage("$imageReference")
3636
dockerPull { it.image.set("docker:dind") }
3737
dockerRun {
3838
it.image.set("docker:dind")

src/testFeatures/kotlin/dev/codebandits/container/gradle/TaskImagesTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class TaskImagesTest : GradleProjectTest() {
3030
3131
tasks {
3232
register("useImage") {
33-
container.inputLocalImage("$imageReference")
33+
container.inputs.localImage("$imageReference")
3434
outputs.upToDateWhen { true }
3535
doLast { }
3636
}
@@ -97,7 +97,7 @@ class TaskImagesTest : GradleProjectTest() {
9797
9898
tasks {
9999
register<ContainerTask>("buildImage") {
100-
container.outputLocalImage("$imageReference")
100+
container.outputs.localImage("$imageReference")
101101
dockerPull { image = "docker:dind" }
102102
dockerRun {
103103
image = "docker:dind"
@@ -162,7 +162,7 @@ class TaskImagesTest : GradleProjectTest() {
162162
163163
tasks {
164164
register("useImage") {
165-
container.inputRegistryImage("hello-world:latest")
165+
container.inputs.registryImage("hello-world:latest")
166166
outputs.upToDateWhen { true }
167167
doLast { }
168168
}
@@ -205,7 +205,7 @@ class TaskImagesTest : GradleProjectTest() {
205205
206206
tasks {
207207
register("useImage") {
208-
container.inputRegistryImage("docker.io/library/hello-world:latest")
208+
container.inputs.registryImage("docker.io/library/hello-world:latest")
209209
outputs.upToDateWhen { true }
210210
doLast { }
211211
}
@@ -235,7 +235,7 @@ class TaskImagesTest : GradleProjectTest() {
235235
236236
tasks {
237237
register("useImage") {
238-
container.inputRegistryImage("quay.io/argoproj/argocd:latest")
238+
container.inputs.registryImage("quay.io/argoproj/argocd:latest")
239239
outputs.upToDateWhen { true }
240240
doLast { }
241241
}
@@ -265,7 +265,7 @@ class TaskImagesTest : GradleProjectTest() {
265265
266266
tasks {
267267
register("useImage") {
268-
container.inputRegistryImage("ghcr.io/linuxserver/kasm:latest")
268+
container.inputs.registryImage("ghcr.io/linuxserver/kasm:latest")
269269
outputs.upToDateWhen { true }
270270
doLast { }
271271
}

src/testToolIntegrations/kotlin/dev/codebandits/container/gradle/BuildpacksIntegrationTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class BuildpacksIntegrationTest : GradleProjectTest() {
4545
4646
tasks {
4747
register<ContainerTask>("buildImage") {
48-
container.outputLocalImage("$imageReference")
48+
container.outputs.localImage("$imageReference")
4949
dockerPull {
5050
image = "buildpacksio/pack:latest"
5151
}

0 commit comments

Comments
 (0)