Skip to content

Commit 292275d

Browse files
committed
feat: publish runtime platform artifacts (#2)
* feat: add runtime library catalog * feat: publish runtime platform artifacts * docs: document runtime dependency updates * refactor: generate runtime library catalog with build config * refactor: apply runtime dependencies as convention plugin * refactor: centralize loader api versions
1 parent 7e89cbd commit 292275d

16 files changed

Lines changed: 399 additions & 41 deletions

File tree

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "0.1.0"
2+
".": "0.0.1"
33
}

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,42 @@
33
Shared runtime library provider plugins for Grounds Paper and Velocity workloads.
44

55
The Paper and Velocity artifacts expose selected shared JVM libraries for internal Grounds plugins that use the runtime-consumer Gradle conventions.
6+
7+
## Runtime platform artifacts
8+
9+
This repository owns the shared runtime platform:
10+
11+
- `plugin-grounds-runtime-paper`
12+
- `plugin-grounds-runtime-velocity`
13+
- `grounds-runtime-bom`
14+
- `grounds-runtime-catalog`
15+
16+
`runtime-catalog/grounds-runtime-libraries.json` is the source of truth for shared runtime library versions. The BOM and runtime diagnostics are generated from that catalog.
17+
18+
## Adding or updating a shared dependency
19+
20+
Use this flow when a library should be provided by `plugin-grounds-runtime` instead of bundled into each consumer plugin.
21+
22+
1. Decide whether the library is actually shared runtime surface.
23+
24+
Add it only when multiple internal Paper or Velocity plugins need the same library at runtime and all target environments install `plugin-grounds-runtime`. Keep plugin-private clients, app-specific libraries, and test-only libraries in consumer plugin builds.
25+
26+
2. Update `runtime-catalog/grounds-runtime-libraries.json`.
27+
28+
Add or change the Maven `group`, `name`, and `version`. This updates the published `grounds-runtime-bom`, the runtime catalog artifact, and `/grounds-runtime` diagnostics.
29+
30+
3. Update provider shading when needed.
31+
32+
If the dependency exposes packages that can conflict with server or plugin classpaths, add relocations in the runtime catalog fields used by the convention plugin and keep Paper and Velocity provider relocation behavior aligned.
33+
34+
4. Update `library-gradle-plugin` only when the module set changes.
35+
36+
Version-only changes stay in this repository. Additions or removals also need the versionless module list, relocation policy, shadow exclusions, and forbidden package prefixes updated in `library-gradle-plugin`.
37+
38+
5. Verify locally.
39+
40+
Run `./gradlew test`, `./gradlew spotlessApply`, and `./gradlew build`. For consumer behavior, publish this runtime platform and the matching convention plugin to Maven Local, then build a real runtime-consumer plugin.
41+
42+
6. Release in order.
43+
44+
Merge and release `plugin-grounds-runtime` first. Then release `library-gradle-plugin` if its convention policy changed. Finally bump consumer plugin `groundsRuntime.version` and container `GROUNDS_RUNTIME_PLUGIN_VERSION` to the released runtime version.

buildSrc/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
plugins { `kotlin-dsl` }
2+
3+
repositories { gradlePluginPortal() }
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import groovy.json.JsonSlurper
2+
3+
data class RuntimeCatalogLibrary(val group: String, val name: String, val version: String) {
4+
val notation = "$group:$name:$version"
5+
}
6+
7+
fun runtimeCatalogLibraries(): List<RuntimeCatalogLibrary> {
8+
val catalogFile =
9+
rootProject.layout.projectDirectory.file("runtime-catalog/grounds-runtime-libraries.json").asFile
10+
val catalog = JsonSlurper().parse(catalogFile) as Map<*, *>
11+
val libraries = catalog["libraries"] as List<*>
12+
13+
return libraries.map { item ->
14+
val library = item as Map<*, *>
15+
RuntimeCatalogLibrary(
16+
group = library["group"] as String,
17+
name = library["name"] as String,
18+
version = library["version"] as String,
19+
)
20+
}
21+
}
22+
23+
dependencies {
24+
runtimeCatalogLibraries().forEach { library -> add("implementation", library.notation) }
25+
}

common/build.gradle.kts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,62 @@
1-
plugins { id("gg.grounds.kotlin-conventions") }
1+
import com.github.gmazzo.buildconfig.BuildConfigExtension
2+
import groovy.json.JsonSlurper
3+
import org.gradle.language.jvm.tasks.ProcessResources
4+
5+
plugins {
6+
id("com.github.gmazzo.buildconfig")
7+
id("gg.grounds.kotlin-conventions")
8+
}
29

310
dependencies { testImplementation(kotlin("test")) }
11+
12+
val runtimeCatalogFile =
13+
rootProject.layout.projectDirectory.file("runtime-catalog/grounds-runtime-libraries.json")
14+
15+
data class RuntimeCatalogLibrary(val group: String, val name: String, val version: String)
16+
17+
val RuntimeCatalogLibrary.coordinate: String
18+
get() = "$group:$name:$version"
19+
20+
fun runtimeCatalogLibraries(catalogContent: String): List<RuntimeCatalogLibrary> {
21+
val catalog =
22+
(JsonSlurper().parseText(catalogContent) as? Map<*, *>)
23+
?: error("Runtime catalog must be a JSON object")
24+
val libraries =
25+
(catalog["libraries"] as? List<*>)
26+
?: error("Runtime catalog field libraries must be an array")
27+
28+
return libraries.mapIndexed { index, value ->
29+
val library =
30+
(value as? Map<*, *>)
31+
?: error("Runtime catalog field libraries[$index] must be an object")
32+
RuntimeCatalogLibrary(
33+
group = library.requiredString(index, "group"),
34+
name = library.requiredString(index, "name"),
35+
version = library.requiredString(index, "version"),
36+
)
37+
}
38+
}
39+
40+
fun Map<*, *>.requiredString(index: Int, field: String): String {
41+
val value =
42+
this[field] as? String
43+
?: error("Runtime catalog field libraries[$index].$field must be a string")
44+
require(value.isNotBlank()) {
45+
"Runtime catalog field libraries[$index].$field must not be blank"
46+
}
47+
return value
48+
}
49+
50+
val runtimeLibraryCoordinates =
51+
providers.fileContents(runtimeCatalogFile).asText.map { catalogContent ->
52+
ArrayList(runtimeCatalogLibraries(catalogContent).map { it.coordinate })
53+
}
54+
55+
configure<BuildConfigExtension> {
56+
className("RuntimeLibraryCatalog")
57+
packageName("gg.grounds.runtime")
58+
useKotlinOutput()
59+
buildConfigField("List<String>", "providedCoordinates", runtimeLibraryCoordinates)
60+
}
61+
62+
tasks.named<ProcessResources>("processResources") { from(runtimeCatalogFile) { into("") } }
Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
package gg.grounds.runtime
22

33
object RuntimeLibraries {
4-
val provided =
5-
listOf(
6-
RuntimeLibraryInfo("org.jetbrains.kotlin", "kotlin-stdlib", "2.3.0"),
7-
RuntimeLibraryInfo("org.jetbrains.kotlin", "kotlin-stdlib-jdk8", "2.3.0"),
8-
RuntimeLibraryInfo("org.jetbrains.kotlinx", "kotlinx-coroutines-core", "1.10.2"),
9-
RuntimeLibraryInfo("com.google.protobuf", "protobuf-java", "4.34.1"),
10-
RuntimeLibraryInfo("io.grpc", "grpc-api", "1.81.0"),
11-
RuntimeLibraryInfo("io.grpc", "grpc-core", "1.81.0"),
12-
RuntimeLibraryInfo("io.grpc", "grpc-context", "1.81.0"),
13-
RuntimeLibraryInfo("io.grpc", "grpc-stub", "1.81.0"),
14-
RuntimeLibraryInfo("io.grpc", "grpc-protobuf", "1.81.0"),
15-
RuntimeLibraryInfo("io.grpc", "grpc-netty-shaded", "1.81.0"),
16-
)
4+
val provided: List<RuntimeLibraryInfo> =
5+
RuntimeLibraryCatalog.providedCoordinates.map { coordinate ->
6+
val parts = coordinate.split(':', limit = 3)
7+
check(parts.size == 3) {
8+
"Runtime library coordinate must use group:name:version format (coordinate=$coordinate)"
9+
}
10+
RuntimeLibraryInfo(group = parts[0], name = parts[1], version = parts[2])
11+
}
1712
}

common/src/test/kotlin/gg/grounds/runtime/RuntimeDiagnosticsTest.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package gg.grounds.runtime
22

33
import kotlin.test.Test
44
import kotlin.test.assertContains
5+
import kotlin.test.assertEquals
56

67
class RuntimeDiagnosticsTest {
78
@Test
@@ -19,4 +20,11 @@ class RuntimeDiagnosticsTest {
1920
assertContains(diagnostics, "- io.grpc:grpc-api:1.81.0")
2021
assertContains(diagnostics, "- com.google.protobuf:protobuf-java:4.34.1")
2122
}
23+
24+
@Test
25+
fun `provided runtime libraries have unique coordinates`() {
26+
val coordinates = RuntimeLibraries.provided.map { it.coordinate() }
27+
28+
assertEquals(coordinates.distinct(), coordinates)
29+
}
2230
}

gradle/libs.versions.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[versions]
2+
paperApi = "26.1.2.build.63-stable"
3+
velocityApi = "3.5.0-SNAPSHOT"
4+
5+
[libraries]
6+
paper-api = { module = "io.papermc.paper:paper-api", version.ref = "paperApi" }
7+
velocity-api = { module = "com.velocitypowered:velocity-api", version.ref = "velocityApi" }

paper/build.gradle.kts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2+
import org.gradle.api.publish.maven.MavenPublication
23

34
plugins {
45
id("com.gradleup.shadow")
56
id("gg.grounds.kotlin-conventions")
7+
id("gg.grounds.runtime-provider-dependencies")
8+
`maven-publish`
69
}
710

811
repositories { maven("https://repo.papermc.io/repository/maven-public/") }
912

1013
dependencies {
11-
compileOnly("io.papermc.paper:paper-api:26.1.2.build.63-stable")
14+
compileOnly(libs.paper.api)
1215
implementation(project(":common"))
13-
implementation("org.jetbrains.kotlin:kotlin-stdlib:2.3.0")
14-
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.3.0")
15-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
16-
implementation("com.google.protobuf:protobuf-java:4.34.1")
17-
implementation("io.grpc:grpc-api:1.81.0")
18-
implementation("io.grpc:grpc-core:1.81.0")
19-
implementation("io.grpc:grpc-context:1.81.0")
20-
implementation("io.grpc:grpc-stub:1.81.0")
21-
implementation("io.grpc:grpc-protobuf:1.81.0")
22-
implementation("io.grpc:grpc-netty-shaded:1.81.0")
2316
}
2417

2518
tasks.named("build") { dependsOn("shadowJar") }
@@ -39,3 +32,23 @@ tasks.named<ShadowJar>("shadowJar") {
3932
relocate("com.google.protobuf", "gg.grounds.runtime.libs.protobuf")
4033
mergeServiceFiles()
4134
}
35+
36+
publishing {
37+
repositories {
38+
maven {
39+
name = "GitHubPackages"
40+
url = uri("https://maven.pkg.github.com/groundsgg/${rootProject.name}")
41+
credentials {
42+
username = System.getenv("GITHUB_ACTOR")
43+
password = System.getenv("GITHUB_TOKEN")
44+
}
45+
}
46+
}
47+
48+
publications {
49+
withType<MavenPublication>().configureEach {
50+
artifactId = "${rootProject.name}-${project.name}"
51+
setArtifacts(listOf(tasks.named<ShadowJar>("shadowJar")))
52+
}
53+
}
54+
}

paper/src/main/resources/plugin.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: plugin-grounds-runtime
1+
name: GroundsPluginRuntime
22
main: gg.grounds.runtime.paper.GroundsRuntimePaperPlugin
33
version: ${VERSION}
44
description: Shared runtime libraries for Grounds Paper plugins

0 commit comments

Comments
 (0)