Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download dependencies at runtime on all platforms (not just Paper), and read dependency info from file in plugin jar generated by Gradle task #259

Merged
merged 13 commits into from
Jul 4, 2023
Merged
12 changes: 6 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ jobs:
env:
MODRINTH_TOKEN: "${{ secrets.MODRINTH_TOKEN }}"
RELEASE_NOTES: "${{ github.event.release.body }}"
# - name: Publish (Pre-)Release to Hangar
# if: "${{ env.STATUS == 'release' && github.event_name == 'release' }}"
# run: ./gradlew publishAllPublicationsToHangar
# env:
# HANGAR_UPLOAD_KEY: "${{ secrets.HANGAR_UPLOAD_KEY }}"
# RELEASE_NOTES: "${{ github.event.release.body }}"
- name: Publish (Pre-)Release to Hangar
if: "${{ env.STATUS == 'release' && github.event_name == 'release' }}"
run: ./gradlew publishAllPublicationsToHangar
env:
HANGAR_UPLOAD_KEY: "${{ secrets.HANGAR_UPLOAD_KEY }}"
RELEASE_NOTES: "${{ github.event.release.body }}"
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
Expand Down
9 changes: 0 additions & 9 deletions build-logic/src/main/kotlin/CarbonShadowPlatformExtension.kt

This file was deleted.

106 changes: 106 additions & 0 deletions build-logic/src/main/kotlin/WriteDependencies.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.artifacts.result.DependencyResult
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.gradle.api.artifacts.result.ResolvedDependencyResult
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.initialization.Settings
import org.gradle.api.internal.GradleInternal
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction

abstract class WriteDependencies : DefaultTask() {
@get:Input
abstract val tree: Property<ResolvedComponentResult>

@get:InputFiles
abstract val files: ConfigurableFileCollection

@get:Input
abstract val outputFileName: Property<String>

@get:OutputDirectory
abstract val outputDir: DirectoryProperty

@get:Input
abstract val repos: ListProperty<String>

@get:Input
abstract val transitive: Property<Boolean>

@get:Input
abstract val relocations: ListProperty<String>

init {
init()
}

private fun init() {
transitive.convention(true)
}

fun relocate(from: String, to: String) {
relocations.add("$from $to")
}

@TaskAction
fun run() {
val outputLines = StringBuilder()
val outputFile = outputDir.get().file(outputFileName.get()).asFile
val files = files.files
for (repo in repos()) {
outputLines.append(repo).append("\n")
}
outputLines.append("end_repos\n")
for (dependency in deps()) {
val id = dependency.resolvedVariant.owner as ModuleComponentIdentifier
val file = files.single { it.name.equals("${id.module}-${id.version}.jar") }
outputLines.append(id.displayName).append(" ").append(file.toPath().hashFile(HashingAlgorithm.SHA256).asHexString()).append("\n")
}
outputLines.append("end_deps\n")
for (r in relocations.get().sorted()) {
outputLines.append(r).append("\n")
}
outputFile.parentFile.mkdirs()
outputFile.delete()
outputFile.writeText(outputLines.toString())
}

private fun repos(): List<String> {
if (repos.get().isNotEmpty()) {
return repos.get()
}
if (project.repositories.isNotEmpty()) {
return project.repositories.mapNotNull { (it as? MavenArtifactRepository)?.url.toString() }
}
return project.settings.dependencyResolutionManagement.repositories.mapNotNull { (it as? MavenArtifactRepository)?.url.toString() }
}

private val Project.settings: Settings
get() = (gradle as GradleInternal).settings

private fun deps(): List<ResolvedDependencyResult> {
val set = mutableSetOf<ResolvedDependencyResult>()
set.addFrom(tree.get().dependencies)
return set.associateBy { it.resolvedVariant.owner.displayName }
.map { it.value }
.sortedBy { it.resolvedVariant.owner.displayName }
}

private fun MutableSet<ResolvedDependencyResult>.addFrom(dependencies: Set<DependencyResult>) {
for (dependency in dependencies) {
dependency as ResolvedDependencyResult
add(dependency)
if (transitive.get()) {
addFrom(dependency.selected.dependencies)
}
}
}
}
44 changes: 44 additions & 0 deletions build-logic/src/main/kotlin/carbon.platform-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,37 @@ plugins {
id("com.modrinth.minotaur")
}

val runtimeDownload: Configuration by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
}

exclude("org.checkerframework", "checker-qual")
exclude("org.slf4j", "slf4j-api")
exclude("com.google.errorprone", "error_prone_annotations")
exclude("io.leangen.geantyref", "geantyref")
}

val platformExtension = extensions.create<CarbonPlatformExtension>("carbonPlatform")

dependencies {
runtimeDownload(libs.postgresql)
runtimeDownload(libs.mariadb)
runtimeDownload(libs.zstdjni)
runtimeDownload(libs.jdbiCore)
runtimeDownload(libs.jdbiObject)
runtimeDownload(libs.jdbiPostgres)
runtimeDownload(libs.caffeine)
runtimeDownload(libs.jedis)
runtimeDownload(libs.rabbitmq)
runtimeDownload(libs.nats)
runtimeDownload(libs.assistedInject) {
isTransitive = false
}
}

tasks {
val copyJar = register<FileCopyTask>("copyJar") {
fileToCopy.set(platformExtension.jarTask.flatMap { it.archiveFile })
Expand All @@ -30,6 +59,21 @@ modrinth {
gameVersions.addAll("1.19.4", "1.20.1")
}

val writeDeps = tasks.register("writeDependencies", WriteDependencies::class) {
tree.set(runtimeDownload.incoming.resolutionResult.rootComponent)
files.from(runtimeDownload)
outputFileName.set("carbon-dependencies.list")
outputDir.set(layout.buildDirectory.dir("generated/dependencyList"))
repos.add("https://repo.papermc.io/repository/maven-public/")
repos.add("https://repo.maven.apache.org/maven2/")
}

sourceSets.main {
resources {
srcDir(writeDeps)
}
}

//val projectVersion = version as String
//if (projectVersion.endsWith("-SNAPSHOT")) {
// // Add git commit hash to version for platforms
Expand Down
13 changes: 0 additions & 13 deletions build-logic/src/main/kotlin/carbon.shadow-platform.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ plugins {
id("com.github.johnrengelman.shadow")
}

val shadowPlatform = extensions.create<CarbonShadowPlatformExtension>("carbonShadowPlatform")

tasks {
jar {
archiveClassifier.set("unshaded")
Expand All @@ -19,14 +17,3 @@ tasks {
extensions.configure<CarbonPlatformExtension> {
jarTask.set(tasks.shadowJar)
}

afterEvaluate {
tasks.shadowJar {
if (shadowPlatform.relocateGuice.get()) {
relocateGuice()
}
if (shadowPlatform.relocateCloud.get()) {
relocateCloud()
}
}
}
46 changes: 34 additions & 12 deletions build-logic/src/main/kotlin/extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,52 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import net.kyori.indra.git.IndraGitExtension
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.provider.Provider
import org.gradle.kotlin.dsl.the

val Project.releaseNotes: Provider<String>
get() = providers.environmentVariable("RELEASE_NOTES")

fun Task.relocateDependency(pkg: String) {
when (this) {
is ShadowJar -> relocateDependency(pkg)
is WriteDependencies -> relocateDependency(pkg)
else -> error("relocateDependency must be called on a ShadowJar or WriteDependencies task, not ${this.javaClass.name}")
}
}

/**
* Relocate a package into the `net.draycia.carbon.libs` namespace.
* Relocate a package into the `carbonchat.libs.` namespace.
*/
fun ShadowJar.relocateDependency(pkg: String) {
relocate(pkg, "net.draycia.carbon.libs.$pkg")
relocate(pkg, "carbonchat.libs.$pkg")
}

fun WriteDependencies.relocateDependency(pkg: String) {
relocate(pkg, "carbonchat.libs.$pkg")
}

fun Task.standardRuntimeRelocations() {
relocateDependency("com.github.benmanes")
relocateDependency("com.github.luben.zstd")
relocateDependency("com.google.protobuf")
relocateDependency("com.mysql.cj")
relocateDependency("com.mysql.jdbc")
relocateDependency("com.rabbitmq")
relocateDependency("io.nats")
relocateDependency("net.i2p.crypto")
relocateDependency("org.apache.commons.pool2")
relocateDependency("org.jdbi")
relocateDependency("org.mariadb.jdbc")
relocateDependency("org.postgresql")
relocateDependency("redis.clients.jedis")
}

/**
* Relocates dependencies which we bundle and relocate on all platforms.
*/
fun ShadowJar.standardRelocations() {
fun Task.standardRelocations() {
relocateDependency("org.bstats")
relocateDependency("net.kyori.adventure.serializer.configurate4")
relocateDependency("com.seiama.event")
Expand All @@ -27,25 +56,18 @@ fun ShadowJar.standardRelocations() {
relocateDependency("org.spongepowered.configurate")
relocateDependency("com.typesafe.config")
relocateDependency("com.google.thirdparty.publicsuffix")
relocateDependency("org.jdbi")
relocateDependency("com.github.benmanes")
relocateDependency("com.zaxxer.hikari")
relocateDependency("redis.clients.jedis")
relocateDependency("ninja.egg82.messenger")
relocateDependency("org.antlr")
relocateDependency("io.nats")
relocateDependency("com.rabbitmq")
relocateDependency("com.electronwill")
relocateDependency("net.i2p.crypto")
relocateDependency("org.apache.commons.pool2")
relocateDependency("org.flywaydb")
}

fun ShadowJar.relocateCloud() {
fun Task.relocateCloud() {
relocateDependency("cloud.commandframework")
}

fun ShadowJar.relocateGuice() {
fun Task.relocateGuice() {
relocateDependency("com.google.inject")
relocateDependency("org.aopalliance")
relocateDependency("javax.inject")
Expand Down
36 changes: 36 additions & 0 deletions build-logic/src/main/kotlin/utils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import java.io.InputStream
import java.nio.file.Path
import java.security.DigestInputStream
import java.security.MessageDigest
import kotlin.io.path.inputStream

enum class HashingAlgorithm(algorithm: String) {
SHA256("SHA-256"),
SHA1("SHA-1");

private val threadLocalMessageDigest = ThreadLocal.withInitial { MessageDigest.getInstance(algorithm) }

val digest: MessageDigest
get() = threadLocalMessageDigest.get()
}

fun Path.hashFile(algorithm: HashingAlgorithm): ByteArray = inputStream().use { input -> input.hash(algorithm) }

fun InputStream.hash(algorithm: HashingAlgorithm): ByteArray {
val digestStream = DigestInputStream(this, algorithm.digest)
digestStream.use { stream ->
val buffer = ByteArray(1024)
while (stream.read(buffer) != -1) {
// reading
}
}
return digestStream.messageDigest.digest()
}

fun ByteArray.asHexString(): String {
val sb: StringBuilder = StringBuilder(size * 2)
for (aHash in this) {
sb.append("%02x".format(aHash.toInt() and 0xFF))
}
return sb.toString()
}
21 changes: 11 additions & 10 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,31 @@ dependencies {
}

// Other
api(libs.guice) {
compileOnlyApi(libs.guice) {
exclude("com.google.guava")
}
api(libs.assistedInject)
compileOnlyApi(libs.assistedInject) {
isTransitive = false
}
compileOnlyApi(libs.luckPermsApi)

// Storage
api(libs.jdbiCore)
api(libs.jdbiObject)
api(libs.jdbiPostgres)
compileOnlyApi(libs.jdbiCore)
compileOnlyApi(libs.jdbiObject)
compileOnlyApi(libs.jdbiPostgres)
api(libs.hikariCP)
api(libs.flyway)
api(libs.flywayMysql)
api(libs.caffeine)

// Messaging
api(libs.messenger)
api(libs.messengerNats)
api(libs.messengerRabbitmq)
api(libs.messengerRedis)
api(libs.netty)
api(libs.jedis)
api(libs.rabbitmq)
api(libs.nats)
compileOnlyApi(libs.netty)

compileOnlyApi(libs.jarRelocator)
compileOnlyApi(libs.caffeine)

// we shade and relocate a newer version than minecraft provides
compileOnlyApi(libs.guava)
Expand Down