Skip to content

Commit f2f7fc8

Browse files
authored
feat(jit): build and cache all artifacts for version (#1351)
Part of #1318.
1 parent 7f4b41b commit f2f7fc8

File tree

10 files changed

+159
-50
lines changed

10 files changed

+159
-50
lines changed

.github/workflows/end-to-end-tests.main.kts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
@file:DependsOn("io.github.typesafegithub:github-workflows-kt:1.13.0")
33

44
import io.github.typesafegithub.workflows.actions.actions.CheckoutV4
5-
import io.github.typesafegithub.workflows.actions.actions.SetupJavaV4
65
import io.github.typesafegithub.workflows.actions.gradle.ActionsSetupGradleV3
76
import io.github.typesafegithub.workflows.annotations.ExperimentalKotlinLogicStep
87
import io.github.typesafegithub.workflows.domain.RunnerType.UbuntuLatest
@@ -37,13 +36,6 @@ workflow(
3736
) {
3837
// Using bundled bindings to avoid generating them here.
3938
uses(action = CheckoutV4())
40-
uses(
41-
name = "Set up JDK",
42-
action = SetupJavaV4(
43-
javaVersion = "11",
44-
distribution = SetupJavaV4.Distribution.Zulu,
45-
)
46-
)
4739
uses(action = ActionsSetupGradleV3())
4840

4941
run(
@@ -54,7 +46,7 @@ workflow(
5446
run(name = "Wait for the server to respond") {
5547
val timeSource = TimeSource.Monotonic
5648
val waitStart = timeSource.markNow()
57-
val timeout = 1.minutes
49+
val timeout = 3.minutes
5850

5951
while (timeSource.markNow() - waitStart < timeout) {
6052
try {

.github/workflows/end-to-end-tests.yaml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,14 @@ jobs:
3131
- id: 'step-0'
3232
uses: 'actions/checkout@v4'
3333
- id: 'step-1'
34-
name: 'Set up JDK'
35-
uses: 'actions/setup-java@v4'
36-
with:
37-
java-version: '11'
38-
distribution: 'zulu'
39-
- id: 'step-2'
4034
uses: 'gradle/actions/setup-gradle@v3'
41-
- id: 'step-3'
35+
- id: 'step-2'
4236
name: 'Start the server'
4337
run: './gradlew :jit-binding-server:run &'
44-
- id: 'step-4'
38+
- id: 'step-3'
4539
name: 'Wait for the server to respond'
46-
run: 'GHWKT_RUN_STEP=''test-jit-server:step-4'' ''.github/workflows/end-to-end-tests.main.kts'''
47-
- id: 'step-5'
40+
run: 'GHWKT_RUN_STEP=''test-jit-server:step-3'' ''.github/workflows/end-to-end-tests.main.kts'''
41+
- id: 'step-4'
4842
name: 'Execute the script using the bindings from the server'
4943
run: |-
5044
mv .github/workflows/test-script-consuming-jit-bindings.main.do-not-compile.kts .github/workflows/test-script-consuming-jit-bindings.main.kts
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package buildsrc.convention
2+
3+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
4+
5+
plugins {
6+
kotlin("jvm")
7+
`java-library`
8+
9+
// Code quality.
10+
id("org.jmailen.kotlinter")
11+
}
12+
13+
dependencies {
14+
testImplementation(platform("io.kotest:kotest-bom:5.8.1"))
15+
testImplementation("io.kotest:kotest-assertions-core")
16+
testImplementation("io.kotest:kotest-runner-junit5")
17+
}
18+
19+
java {
20+
withJavadocJar()
21+
withSourcesJar()
22+
23+
toolchain {
24+
requiredJdkVersion()
25+
}
26+
}
27+
28+
kotlin {
29+
jvmToolchain {
30+
requiredJdkVersion()
31+
}
32+
}
33+
34+
fun JavaToolchainSpec.requiredJdkVersion() {
35+
languageVersion.set(JavaLanguageVersion.of(17))
36+
}
37+
38+
tasks.withType<KotlinCompile> {
39+
kotlinOptions {
40+
jvmTarget = "17"
41+
42+
allWarningsAsErrors = true
43+
}
44+
45+
compilerOptions {
46+
freeCompilerArgs.addAll(
47+
"-opt-in=kotlin.ExperimentalStdlibApi",
48+
"-opt-in=kotlin.time.ExperimentalTime",
49+
)
50+
}
51+
}
52+
53+
tasks.withType<Test>().configureEach {
54+
useJUnitPlatform()
55+
}

jit-binding-server/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import io.ktor.plugin.features.*
22

33
plugins {
4-
buildsrc.convention.`kotlin-jvm`
4+
buildsrc.convention.`kotlin-jvm-server`
55
application
66
id("io.ktor.plugin") version "2.3.9"
77
}
@@ -10,6 +10,7 @@ dependencies {
1010
implementation(platform("io.ktor:ktor-bom:2.3.9"))
1111
implementation("io.ktor:ktor-server-core")
1212
implementation("io.ktor:ktor-server-netty")
13+
implementation("io.github.reactivecircus.cache4k:cache4k:0.13.0")
1314
implementation("ch.qos.logback:logback-classic:1.5.3")
1415

1516
implementation(projects.mavenBindingBuilder)

jit-binding-server/src/main/kotlin/io/github/typesafegithub/workflows/jitbindingserver/Main.kt

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package io.github.typesafegithub.workflows.jitbindingserver
22

3-
import io.github.typesafegithub.workflows.mavenbinding.buildJar
4-
import io.github.typesafegithub.workflows.mavenbinding.buildModuleFile
5-
import io.github.typesafegithub.workflows.mavenbinding.buildPomFile
3+
import io.github.reactivecircus.cache4k.Cache
4+
import io.github.typesafegithub.workflows.mavenbinding.ActionCoords
5+
import io.github.typesafegithub.workflows.mavenbinding.Artifact
6+
import io.github.typesafegithub.workflows.mavenbinding.JarArtifact
7+
import io.github.typesafegithub.workflows.mavenbinding.TextArtifact
8+
import io.github.typesafegithub.workflows.mavenbinding.buildVersionArtifacts
69
import io.ktor.http.ContentType
710
import io.ktor.http.HttpStatusCode
811
import io.ktor.server.application.call
@@ -12,39 +15,69 @@ import io.ktor.server.response.respondBytes
1215
import io.ktor.server.response.respondText
1316
import io.ktor.server.routing.get
1417
import io.ktor.server.routing.head
18+
import io.ktor.server.routing.route
1519
import io.ktor.server.routing.routing
20+
import kotlin.time.Duration.Companion.hours
1621

1722
fun main() {
23+
val bindingsCache =
24+
Cache.Builder<ActionCoords, Map<String, Artifact>>()
25+
.expireAfterAccess(1.hours)
26+
.build()
27+
1828
embeddedServer(Netty, port = 8080) {
1929
routing {
20-
get("/binding/{owner}/{name}/{version}/{file}") {
21-
val owner = call.parameters["owner"]!!
22-
val name = call.parameters["name"]!!
23-
val version = call.parameters["version"]!!
24-
val file = call.parameters["file"]!!
25-
when (file) {
26-
"$name-$version.jar" -> {
27-
val jarByteArray = buildJar(owner = owner, name = name, version = version)
28-
call.respondBytes(
29-
bytes = jarByteArray,
30-
contentType = ContentType.parse("application/java-archive"),
30+
route("/binding/{owner}/{name}/{version}/{file}") {
31+
get {
32+
val owner = call.parameters["owner"]!!
33+
val name = call.parameters["name"]!!
34+
val version = call.parameters["version"]!!
35+
val actionCoords =
36+
ActionCoords(
37+
owner = owner,
38+
name = name,
39+
version = version,
3140
)
41+
val bindingArtifacts =
42+
bindingsCache.get(actionCoords) {
43+
actionCoords.buildVersionArtifacts()
44+
}
45+
val file = call.parameters["file"]!!
46+
if (file in bindingArtifacts) {
47+
when (val artifact = bindingArtifacts[file]) {
48+
is TextArtifact -> call.respondText(artifact.data)
49+
is JarArtifact ->
50+
call.respondBytes(
51+
bytes = artifact.data,
52+
contentType = ContentType.parse("application/java-archive"),
53+
)
54+
else -> call.respondText(text = "Not found", status = HttpStatusCode.NotFound)
55+
}
56+
} else {
57+
call.respondText(text = "Not found", status = HttpStatusCode.NotFound)
3258
}
33-
"$name-$version.pom" -> call.respondText(buildPomFile(owner = owner, name = name, version = version))
34-
"$name-$version.module" -> call.respondText(buildModuleFile(owner = owner, name = name, version = version))
35-
else -> call.respondText(text = "Not found", status = HttpStatusCode.NotFound)
3659
}
37-
}
3860

39-
head("/binding/{owner}/{name}/{version}/{file}") {
40-
val name = call.parameters["name"]!!
41-
val version = call.parameters["version"]!!
42-
val file = call.parameters["file"]!!
43-
when (file) {
44-
"$name-$version.jar" -> call.respondText("ok", status = HttpStatusCode.OK)
45-
"$name-$version.pom" -> call.respondText("ok", status = HttpStatusCode.OK)
46-
"$name-$version.module" -> call.respondText("ok", status = HttpStatusCode.OK)
47-
else -> call.respondText(text = "Not found", status = HttpStatusCode.NotFound)
61+
head {
62+
val owner = call.parameters["owner"]!!
63+
val name = call.parameters["name"]!!
64+
val version = call.parameters["version"]!!
65+
val file = call.parameters["file"]!!
66+
val actionCoords =
67+
ActionCoords(
68+
owner = owner,
69+
name = name,
70+
version = version,
71+
)
72+
val bindingArtifacts =
73+
bindingsCache.get(actionCoords) {
74+
actionCoords.buildVersionArtifacts()
75+
}
76+
if (file in bindingArtifacts) {
77+
call.respondText("Exists", status = HttpStatusCode.OK)
78+
} else {
79+
call.respondText(text = "Not found", status = HttpStatusCode.NotFound)
80+
}
4881
}
4982
}
5083

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.github.typesafegithub.workflows.mavenbinding
2+
3+
data class ActionCoords(
4+
val owner: String,
5+
val name: String,
6+
val version: String,
7+
)

maven-binding-builder/src/main/kotlin/io/github/typesafegithub/workflows/mavenbinding/JarBuilding.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import kotlin.io.path.createTempDirectory
2020
import kotlin.io.path.div
2121
import kotlin.io.path.writeText
2222

23-
fun buildJar(
23+
internal fun buildJar(
2424
owner: String,
2525
name: String,
2626
version: String,

maven-binding-builder/src/main/kotlin/io/github/typesafegithub/workflows/mavenbinding/ModuleBuilding.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.github.typesafegithub.workflows.mavenbinding
22

3-
fun buildModuleFile(
3+
internal fun buildModuleFile(
44
owner: String,
55
name: String,
66
version: String,

maven-binding-builder/src/main/kotlin/io/github/typesafegithub/workflows/mavenbinding/PomBuilding.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.github.typesafegithub.workflows.mavenbinding
22

3-
fun buildPomFile(
3+
internal fun buildPomFile(
44
owner: String,
55
name: String,
66
version: String,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.github.typesafegithub.workflows.mavenbinding
2+
3+
sealed interface Artifact
4+
5+
data class TextArtifact(val data: String) : Artifact
6+
7+
data class JarArtifact(val data: ByteArray) : Artifact {
8+
override fun equals(other: Any?): Boolean {
9+
if (this === other) return true
10+
if (javaClass != other?.javaClass) return false
11+
12+
other as JarArtifact
13+
14+
return data.contentEquals(other.data)
15+
}
16+
17+
override fun hashCode(): Int {
18+
return data.contentHashCode()
19+
}
20+
}
21+
22+
fun ActionCoords.buildVersionArtifacts(): Map<String, Artifact> =
23+
mapOf(
24+
"$name-$version.jar" to JarArtifact(buildJar(owner = owner, name = name, version = version)),
25+
"$name-$version.pom" to TextArtifact(buildPomFile(owner = owner, name = name, version = version)),
26+
"$name-$version.module" to TextArtifact(buildModuleFile(owner = owner, name = name, version = version)),
27+
)

0 commit comments

Comments
 (0)