From 4d8da6e30210a1b09ef2471d48ee2cf8a478563b Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 16 Apr 2025 20:14:43 +0200 Subject: [PATCH 01/45] wip --- build-extensions/build.gradle.kts | 23 ++- build-extensions/settings.gradle.kts | 25 +++ .../src/main/kotlin/extensions.kt | 102 +++------ .../src/main/kotlin/publishing-extensions.kt | 2 +- .../src/main/kotlin/settings-plugin.kt | 193 ++++++++++++++++++ build-extensions/src/main/kotlin/tasks.kt | 180 ++++++++++++++++ build.gradle.kts | 145 +------------ driver/impl/build.gradle.kts | 2 +- .../loader/build.gradle.kts | 4 +- .../runtime/build.gradle.kts | 2 +- gradle.properties | 5 +- gradle/libs.versions.toml | 6 +- launcher/java22/build.gradle.kts | 2 +- launcher/java8/build.gradle.kts | 2 +- launcher/patcher/build.gradle.kts | 4 +- modules/bridge/impl/build.gradle.kts | 8 +- modules/build.gradle.kts | 2 +- modules/cloudflare/impl/build.gradle.kts | 2 +- .../database-mongodb/impl/build.gradle.kts | 2 +- modules/database-mysql/impl/build.gradle.kts | 4 +- .../dockerized-services/impl/build.gradle.kts | 2 +- modules/influx/impl/build.gradle.kts | 2 +- modules/labymod/impl/build.gradle.kts | 2 +- modules/npcs/impl/build.gradle.kts | 6 +- modules/report/impl/build.gradle.kts | 2 +- modules/signs/impl/build.gradle.kts | 4 +- modules/smart/impl/build.gradle.kts | 2 +- modules/storage-s3/impl/build.gradle.kts | 2 +- modules/storage-sftp/impl/build.gradle.kts | 2 +- modules/syncproxy/impl/build.gradle.kts | 4 +- node/impl/build.gradle.kts | 25 ++- plugins/build.gradle.kts | 2 +- plugins/luckperms/build.gradle.kts | 2 +- plugins/papi-expansion/build.gradle.kts | 2 +- settings.gradle.kts | 18 +- wrapper-jvm/impl/build.gradle.kts | 23 ++- 36 files changed, 545 insertions(+), 270 deletions(-) create mode 100644 build-extensions/settings.gradle.kts create mode 100644 build-extensions/src/main/kotlin/settings-plugin.kt create mode 100644 build-extensions/src/main/kotlin/tasks.kt diff --git a/build-extensions/build.gradle.kts b/build-extensions/build.gradle.kts index db7d532e7f..c9a6e32223 100644 --- a/build-extensions/build.gradle.kts +++ b/build-extensions/build.gradle.kts @@ -16,13 +16,34 @@ plugins { `kotlin-dsl` + id("java-gradle-plugin") } +kotlin.jvmToolchain(21) + repositories { gradlePluginPortal() + mavenCentral() + maven("https://repo.stellardrift.ca/repository/snapshots/") { + content { + includeGroup("net.kyori") + } + } } dependencies { - implementation("net.kyori", "indra-common", "3.1.3") + implementation("net.kyori", "indra-common", "4.0.0-SNAPSHOT") implementation("com.google.code.gson", "gson", "2.13.1") + + implementation("com.diffplug.spotless", "spotless-plugin-gradle", libs.versions.spotless.get()) + implementation("com.gradleup.shadow", "shadow-gradle-plugin", libs.versions.shadow.get()) +} + +gradlePlugin { + plugins { + register("settings-plugin") { + id = "settings-plugin" + implementationClass = "SettingsPlugin" + } + } } diff --git a/build-extensions/settings.gradle.kts b/build-extensions/settings.gradle.kts new file mode 100644 index 0000000000..46034abe95 --- /dev/null +++ b/build-extensions/settings.gradle.kts @@ -0,0 +1,25 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +dependencyResolutionManagement { + versionCatalogs { + register("libs") { + from(files("./../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-extensions" diff --git a/build-extensions/src/main/kotlin/extensions.kt b/build-extensions/src/main/kotlin/extensions.kt index 1a8a3c05c3..118696533f 100644 --- a/build-extensions/src/main/kotlin/extensions.kt +++ b/build-extensions/src/main/kotlin/extensions.kt @@ -15,9 +15,12 @@ */ import net.kyori.indra.git.IndraGitExtension +import net.kyori.indra.git.RepositoryValueSource +import net.kyori.indra.git.internal.IndraGitExtensionImpl +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.lib.Constants import org.gradle.api.Project import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.api.internal.artifacts.repositories.resolver.MavenUniqueSnapshotComponentIdentifier import org.gradle.api.plugins.JavaPluginExtension @@ -27,8 +30,10 @@ import org.gradle.kotlin.dsl.attributes import org.gradle.kotlin.dsl.findByType import org.gradle.kotlin.dsl.named import org.gradle.kotlin.dsl.the +import java.io.IOException import java.net.HttpURLConnection -import java.net.URL +import java.util.logging.Level +import java.util.logging.Logger fun Project.applyJarMetadata(mainClass: String, module: String) { applyJarMetadata(mainClass, module, null) @@ -48,20 +53,42 @@ fun Project.applyJarMetadata(mainClass: String, module: String, preMain: String? manifest.attributes("Premain-Class" to preMain) } // apply git information to manifest - git()?.applyVcsInformationToManifest(manifest) + git()?.let { git -> + val commit = git.commit().map { it.name.substring(0, 8) } + val branchName = git.repositoryValue(BranchName::class.java) + if (commit.isPresent) manifest.attributes(IndraGitExtension.MANIFEST_ATTRIBUTE_GIT_COMMIT to commit.get()) + if (branchName.isPresent) manifest.attributes(IndraGitExtension.MANIFEST_ATTRIBUTE_GIT_BRANCH to branchName.get()) + } + } + } +} + +/** + * Indra does not properly support configuration caching for #branchName yet + */ +private abstract class BranchName : RepositoryValueSource.Parameterless() { + override fun obtain(repository: Git): String? { + try { + val ref = repository.repository.exactRef(Constants.HEAD) + if (ref == null || !ref.isSymbolic) return null // no HEAD, or detached HEAD + + return ref.target.name + } catch (ex: IOException) { + Logger.getGlobal().log(Level.SEVERE, "Failed to query current branch name from git:", ex) + return null } } } fun Project.shortCommitHash(): String { - return git()?.commit()?.name?.substring(0, 8) ?: "unknown" + return git()?.commit()?.get()?.name()?.substring(0, 8) ?: "unknown" } fun Project.git(): IndraGitExtension? = rootProject.extensions.findByType() fun Project.sourceSets(): SourceSetContainer = the().sourceSets -fun ProjectDependency.sourceSets(): SourceSetContainer = dependencyProject.sourceSets() +fun ProjectDependency.sourceSets(project: Project): SourceSetContainer = project.project(path).sourceSets() fun Project.mavenRepositories(): Iterable = repositories.filterIsInstance() @@ -83,68 +110,3 @@ fun Project.exportLanguageFileInformation(): String { return file.absolutePath } - -fun Project.exportCnlFile(fileName: String, ignoredDependencyGroups: Array = arrayOf()): String { - val stringBuilder = StringBuilder("# CloudNet ${Versions.cloudNetCodeName} ${Versions.cloudNet}\n\n") - .append("# repositories\n") - // add all repositories - mavenRepositories().forEach { repo -> - stringBuilder.append("repo ${repo.name} ${repo.url.toString().dropLastWhile { it == '/' }}\n") - } - - // add all dependencies - stringBuilder.append("\n\n# dependencies\n") - configurations.getByName("runtimeClasspath").resolvedConfiguration.resolvedArtifacts.forEach { - // get the module version from the artifact, stop if the dependency is ignored - val id = it.moduleVersion.id - if (id.group.equals(group) || ignoredDependencyGroups.contains(id.group)) { - return@forEach - } - - // check if the dependency is a snapshot version - in this case we need to use another artifact url - var version = id.version - if (id.version.endsWith("-SNAPSHOT") && it.id.componentIdentifier is MavenUniqueSnapshotComponentIdentifier) { - // little hack to get the timestamped ("snapshot") version of the identifier - version = (it.id.componentIdentifier as MavenUniqueSnapshotComponentIdentifier).timestampedVersion - } - - // try to find the repository associated with the module - val repository = resolveRepository( - "${id.group.replace('.', '/')}/${id.name}/${id.version}/${id.name}-$version.jar", - mavenRepositories() - ) ?: throw IllegalStateException("Unable to resolve repository for $id") - - // add the repository - val cs = ChecksumHelper.fileShaSum(it.file) - stringBuilder.append("include ${repository.name} ${id.group} ${id.name} ${id.version} $version $cs ${it.classifier ?: ""}\n") - } - - // write to the output file - val target = project.layout.buildDirectory.file(fileName).get().asFile - target.writeText(stringBuilder.toString()) - - return target.absolutePath -} - -private fun resolveRepository( - testUrlPath: String, - repositories: Iterable -): MavenArtifactRepository? { - return repositories.firstOrNull { - val url = it.url.resolve(testUrlPath).toURL() - with(url.openConnection() as HttpURLConnection) { - useCaches = false - readTimeout = 30000 - connectTimeout = 30000 - instanceFollowRedirects = true - - setRequestProperty( - "User-Agent", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11" - ) - - connect() - responseCode == 200 - } - } -} diff --git a/build-extensions/src/main/kotlin/publishing-extensions.kt b/build-extensions/src/main/kotlin/publishing-extensions.kt index 4c8f491dd4..3ae93e8aa3 100644 --- a/build-extensions/src/main/kotlin/publishing-extensions.kt +++ b/build-extensions/src/main/kotlin/publishing-extensions.kt @@ -109,7 +109,7 @@ fun Project.configurePublishing(publishedComponent: String, withJavadocAndSource sign(extensions.getByType(PublishingExtension::class.java).publications.getByName("maven")) } - tasks.withType { + tasks.withType().configureEach { onlyIf { !rootProject.version.toString().endsWith("-SNAPSHOT") } diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/settings-plugin.kt new file mode 100644 index 0000000000..7c6e5a95dc --- /dev/null +++ b/build-extensions/src/main/kotlin/settings-plugin.kt @@ -0,0 +1,193 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.diffplug.gradle.spotless.SpotlessExtension +import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin +import org.gradle.api.JavaVersion +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.file.DuplicatesStrategy +import org.gradle.api.initialization.Settings +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.plugins.quality.Checkstyle +import org.gradle.api.plugins.quality.CheckstyleExtension +import org.gradle.api.tasks.bundling.Jar +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.api.tasks.testing.Test +import org.gradle.external.javadoc.StandardJavadocDocletOptions +import org.gradle.kotlin.dsl.* +import org.gradle.language.jvm.tasks.ProcessResources + +class SettingsPlugin : Plugin { + override fun apply(settings: Settings) { + settings.gradle.lifecycle.beforeProject { + plugins.apply(AllProjects::class) + if (this != this.rootProject) { + plugins.apply(JavaProjects::class) + } + } + } +} + +class JavaProjects : Plugin { + override fun apply(project: Project) { + project.run { + // these are top level projects which are configured separately + if (name == "modules" || name == "plugins" || name == "ext" || name == "launcher") { + return@run + } + + // these are the plugins which we need to apply to all projects + apply(plugin = "signing") + apply(plugin = "maven-publish") + + // skip further applying to bom - this project is a bit special as we're not allowed to + // apply the java plugin to it (that's why we need to stop here, but we need to publish + // at well (that's why we're applying the publish plugin) + if (name == "bom") { + return@run + } + + apply(plugin = "checkstyle") + apply(plugin = "java-library") + apply(plugin = "com.diffplug.spotless") + + val libs = rootProject.versionCatalogs.named("libs") + + dependencies { + // the 'rootProject.libs.' prefix is needed here - see https://github.com/gradle/gradle/issues/16634 + // lombok + "compileOnly"(libs.findLibrary("lombok").orElseThrow()) + "annotationProcessor"(libs.findLibrary("lombok").orElseThrow()) + // annotations + "compileOnly"(libs.findLibrary("annotations").orElseThrow()) + // testing + "testImplementation"(libs.findLibrary("mockito").orElseThrow()) + "testRuntimeOnly"(libs.findLibrary("junitLauncher").orElseThrow()) + "testImplementation"(libs.findBundle("junit").orElseThrow()) + "testImplementation"(libs.findBundle("testContainers").orElseThrow()) + } + + configurations.all { + // unsure why but every project loves them, and they literally have an import for every letter I type - beware + exclude("org.checkerframework", "checker-qual") + } + + tasks.withType().configureEach { + from(rootProject.file("LICENSE")) + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + + tasks.withType().configureEach { + useJUnitPlatform() + testLogging { + events("started", "passed", "skipped", "failed") + } + + // allow dynamic agent loading for mockito + jvmArgs( + "--enable-preview", + "-XX:+EnableDynamicAgentLoading", + "--enable-native-access=ALL-UNNAMED", + "--add-opens=java.base/java.lang.invoke=ALL-UNNAMED" + ) + + // always pass down all given system properties + systemProperties(System.getProperties().mapKeys { it.key.toString() }) + } + + tasks.withType().configureEach { + val javaVersion = if (project.path.contains("api")) JavaVersion.VERSION_17 else JavaVersion.VERSION_24 + sourceCompatibility = javaVersion.toString() + targetCompatibility = javaVersion.toString() + + options.encoding = "UTF-8" + options.isIncremental = true + + if (project.path != ":launcher:java8" && project.path != ":launcher:patcher" && !project.path.contains("api")) { + options.compilerArgs.add("--enable-preview") + options.compilerArgs.add("-Xlint:-deprecation,-unchecked,-preview") + options.compilerArgs.add("-proc:full") + } + } + + if (project.plugins.hasPlugin(ShadowJavaPlugin::class)) { + tasks.named("assemble").configure { + dependsOn(project.tasks.named("shadowJar")) + } + tasks.named("jar").configure { + // we use the shadow jar task, so move the jar into the task's temporary dir to avoid clutter + destinationDirectory = temporaryDir + } + } + + tasks.withType().configureEach { + maxErrors = 0 + maxWarnings = 0 + configFile = rootProject.file("checkstyle.xml") + } + + extensions.configure { + toolVersion = libs.findVersion("checkstyleTools").orElseThrow().requiredVersion + } + + extensions.configure { + java { + licenseHeaderFile(rootProject.file("LICENSE_HEADER")) + } + } + + val java = project.extensions.getByType() + java.withSourcesJar() + java.withJavadocJar() + + tasks.withType().configureEach { + val options = options as? StandardJavadocDocletOptions ?: return@configureEach + applyDefaultJavadocOptions(options) + } + + tasks.withType().configureEach { + dependsOn(tasks.withType()) + } + + // all these projects are publishing their java artifacts + configurePublishing("java", true) + } + } +} + +class AllProjects : Plugin { + override fun apply(project: Project) { + project.run { + this.version = Versions.cloudNet + this.group = "eu.cloudnetservice.cloudnet" + this.description = "A modern application that can dynamically and easily deliver Minecraft oriented software" + + this.repositories { + releasesOnly(mavenCentral()) + snapshotsOnly(maven("https://central.sonatype.com/repository/maven-snapshots/")) + + // ensure that we use these repositories for snapshots/releases only (improves lookup times) + releasesOnly(maven("https://repository.derklaro.dev/releases/")) + snapshotsOnly(maven("https://repository.derklaro.dev/snapshots/")) + + // must be after sonatype as sponge mirrors sonatype which leads to outdated dependencies + maven("https://repo.spongepowered.org/maven/") + } + } + } +} diff --git a/build-extensions/src/main/kotlin/tasks.kt b/build-extensions/src/main/kotlin/tasks.kt new file mode 100644 index 0000000000..c3a13a5a55 --- /dev/null +++ b/build-extensions/src/main/kotlin/tasks.kt @@ -0,0 +1,180 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("LeakingThis") + +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.repositories.MavenArtifactRepository +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.ProjectLayout +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.internal.artifacts.repositories.resolver.MavenUniqueSnapshotComponentIdentifier +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.SetProperty +import org.gradle.api.tasks.* +import org.gradle.kotlin.dsl.listProperty +import org.gradle.kotlin.dsl.setProperty +import java.io.File +import java.net.HttpURLConnection +import java.net.URI +import javax.inject.Inject + +@CacheableTask +abstract class ExportCnlFile : DefaultTask() { + @get:Inject + abstract val objects: ObjectFactory + + @get:Input + abstract val fileName: Property + + @Input + val ignoredDependencyGroups: SetProperty = objects.setProperty() + + @OutputFile + val outputFile: RegularFileProperty = objects.fileProperty() + + @Nested + val mavenRepositories: ListProperty = objects.listProperty() + + @Nested + val resolvedArtifacts: SetProperty = objects.setProperty() + + @get: Inject + internal abstract val layout: ProjectLayout + + init { + outputFile.convention(layout.file(fileName.map { temporaryDir.resolve(it) })) + mavenRepositories.convention(project.mavenRepositories().map { CacheableMavenRepository(it) }.toList()) + } + + fun setResolvedArtifacts(runtimeClasspath: Configuration) { + val artifacts = runtimeClasspath.resolvedConfiguration.resolvedArtifacts.map { + val group = it.moduleVersion.id.group + val name = it.moduleVersion.id.name + val version = it.moduleVersion.id.version + val timestampedVersion = + if (version.endsWith("-SNAPSHOT") && it.id.componentIdentifier is MavenUniqueSnapshotComponentIdentifier) { + // little hack to get the timestamped ("snapshot") version of the identifier + (it.id.componentIdentifier as MavenUniqueSnapshotComponentIdentifier).timestampedVersion + } else version + + val classifier = it.classifier + val file = it.file + CacheableResolvedArtifact(group, name, version, timestampedVersion, classifier, file) + }.filter { + it.group != project.group + }.toSet() + this.resolvedArtifacts.set(artifacts) + } + + @TaskAction + fun run() { + val ignoredDependencyGroups = this.ignoredDependencyGroups.get() + val mavenRepositories = this.mavenRepositories.get() + + val stringBuilder = + StringBuilder("# CloudNet ${Versions.cloudNetCodeName} ${Versions.cloudNet}\n\n").append("# repositories\n") + // add all repositories + mavenRepositories.forEach { repo -> + stringBuilder.append("repo ${repo.name} ${repo.url.dropLastWhile { it == '/' }}\n") + } + + // add all dependencies + stringBuilder.append("\n\n# dependencies\n") + resolvedArtifacts.get().forEach { + // get the module version from the artifact, stop if the dependency is ignored + if (ignoredDependencyGroups.contains(it.group)) { + return@forEach + } + + // try to find the repository associated with the module + val path = "${it.group.replace('.', '/')}/${it.name}/${it.version}/${it.name}-${it.timestampedVersion}.jar" + val repository = resolveRepository( + path, mavenRepositories + ) ?: throw IllegalStateException( + "Unable to resolve repository for $it.\nSearched in ${ + mavenRepositories.joinToString( + separator = "\n" + ) { r -> r.url + path } + }") + + // add the repository + val cs = ChecksumHelper.fileShaSum(it.file) + stringBuilder.append("include ${repository.name} ${it.group} ${it.name} ${it.version} ${it.timestampedVersion} $cs ${it.classifier ?: ""}\n") + } + + // write to the output file + outputFile.get().asFile.writeText(stringBuilder.toString()) + } +} + +data class CacheableResolvedArtifact( + @Input val group: String, + @Input val name: String, + @Input val version: String, + @Input val timestampedVersion: String, + @Optional @Input val classifier: String?, + @InputFile + @PathSensitive(PathSensitivity.RELATIVE) val file: File +) + +data class CacheableMavenRepository(@Input val name: String, @Input val url: String) { + constructor(repository: MavenArtifactRepository) : this(repository.name, repository.url.toString()) +} + +private fun resolveRepository( + testUrlPath: String, repositories: Iterable +): CacheableMavenRepository? { + return repositories.firstOrNull { + val url = URI.create(it.url).resolve(testUrlPath).toURL() + with(url.openConnection() as HttpURLConnection) { + useCaches = false + readTimeout = 30000 + connectTimeout = 30000 + instanceFollowRedirects = true + + setRequestProperty( + "User-Agent", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11" + ) + + connect() + responseCode == 200 + } + } +} + +@CacheableTask +abstract class ExportLanguageFileInformation : DefaultTask() { + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val languageFiles: ConfigurableFileCollection + + @get:OutputFile + abstract val outputFile: RegularFileProperty + + init { + outputFile.convention { temporaryDir.resolve("languages.txt") } + } + + @TaskAction + fun run() { + outputFile.asFile.get().writeText(languageFiles.files.joinToString(separator = "\n") { it.name }) + } +} diff --git a/build.gradle.kts b/build.gradle.kts index fc49e630e2..aac4a301cc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,152 +14,15 @@ * limitations under the License. */ -import com.diffplug.gradle.spotless.SpotlessExtension - plugins { id("cloudnet.parent-build-logic") - alias(libs.plugins.spotless) alias(libs.plugins.nexusPublish) + alias(libs.plugins.spotless) apply false + alias(libs.plugins.shadow) apply false alias(libs.plugins.fabricLoom) apply false } -defaultTasks("build", "test", "shadowJar") - -allprojects { - version = Versions.cloudNet - group = "eu.cloudnetservice.cloudnet" - description = "A modern application that can dynamically and easily deliver Minecraft oriented software" - - repositories { - releasesOnly(mavenCentral()) - snapshotsOnly(maven("https://central.sonatype.com/repository/maven-snapshots/")) - - // ensure that we use these repositories for snapshots/releases only (improves lookup times) - releasesOnly(maven("https://repository.derklaro.dev/releases/")) - snapshotsOnly(maven("https://repository.derklaro.dev/snapshots/")) - - // must be after sonatype as sponge mirrors sonatype which leads to outdated dependencies - maven("https://repo.spongepowered.org/maven/") - } -} - -subprojects { - // these are top level projects which are configured separately - if (name == "modules" || name == "plugins" || name == "ext" || name == "launcher") { - return@subprojects - } - - // these are the plugins which we need to apply to all projects - apply(plugin = "signing") - apply(plugin = "maven-publish") - - // skip further applying to bom - this project is a bit special as we're not allowed to - // apply the java plugin to it (that's why we need to stop here, but we need to publish - // at well (that's why we're applying the publish plugin) - if (name == "bom") { - return@subprojects - } - - apply(plugin = "checkstyle") - apply(plugin = "java-library") - apply(plugin = "com.diffplug.spotless") - - dependencies { - // the 'rootProject.libs.' prefix is needed here - see https://github.com/gradle/gradle/issues/16634 - // lombok - "compileOnly"(rootProject.libs.lombok) - "annotationProcessor"(rootProject.libs.lombok) - // annotations - "compileOnly"(rootProject.libs.annotations) - // testing - "testImplementation"(rootProject.libs.mockito) - "testRuntimeOnly"(rootProject.libs.junitLauncher) - "testImplementation"(rootProject.libs.bundles.junit) - "testImplementation"(rootProject.libs.bundles.testContainers) - } - - configurations.all { - // unsure why but every project loves them, and they literally have an import for every letter I type - beware - exclude("org.checkerframework", "checker-qual") - } - - tasks.withType { - from(rootProject.file("LICENSE")) - duplicatesStrategy = DuplicatesStrategy.INCLUDE - } - - tasks.withType { - useJUnitPlatform() - testLogging { - events("started", "passed", "skipped", "failed") - } - - // allow dynamic agent loading for mockito - jvmArgs( - "--enable-preview", - "-XX:+EnableDynamicAgentLoading", - "--enable-native-access=ALL-UNNAMED", - "--add-opens=java.base/java.lang.invoke=ALL-UNNAMED" - ) - - // always pass down all given system properties - systemProperties(System.getProperties().mapKeys { it.key.toString() }) - systemProperty("io.netty5.noUnsafe", "true") - } - - tasks.withType().configureEach { - val javaVersion = if (project.path.contains("api")) JavaVersion.VERSION_17 else JavaVersion.VERSION_24 - sourceCompatibility = javaVersion.toString() - targetCompatibility = javaVersion.toString() - - options.encoding = "UTF-8" - options.isIncremental = true - - if (project.path != ":launcher:java8" && project.path != ":launcher:patcher" && !project.path.contains("api")) { - options.compilerArgs.add("--enable-preview") - options.compilerArgs.add("-Xlint:-deprecation,-unchecked,-preview") - options.compilerArgs.add("-proc:full") - } - } - - tasks.withType { - maxErrors = 0 - maxWarnings = 0 - configFile = rootProject.file("checkstyle.xml") - } - - extensions.configure { - toolVersion = rootProject.libs.versions.checkstyleTools.get() - } - - extensions.configure { - java { - licenseHeaderFile(rootProject.file("LICENSE_HEADER")) - } - } - - tasks.register("javadocJar") { - archiveClassifier.set("javadoc") - from(tasks.getByName("javadoc")) - } - - tasks.register("sourcesJar") { - archiveClassifier.set("sources") - from(project.sourceSets()["main"].allJava) - } - - tasks.withType { - val options = options as? StandardJavadocDocletOptions ?: return@withType - applyDefaultJavadocOptions(options) - } - - tasks.withType { - dependsOn(tasks.withType()) - } - - // all these projects are publishing their java artifacts - configurePublishing("java", true) -} +defaultTasks("build") tasks.register("globalJavaDoc", Javadoc::class) { val options = options as? StandardJavadocDocletOptions ?: return@register @@ -189,6 +52,8 @@ nexusPublishing { useStaging.set(!project.version.toString().endsWith("-SNAPSHOT")) } +libs.lombok + gradle.projectsEvaluated { tasks.register("genUpdaterInformation") { subprojects.forEach { diff --git a/driver/impl/build.gradle.kts b/driver/impl/build.gradle.kts index e688b1a4ab..4dfded9b06 100644 --- a/driver/impl/build.gradle.kts +++ b/driver/impl/build.gradle.kts @@ -34,6 +34,6 @@ dependencies { "annotationProcessor"(projects.driver.driverAp) } -tasks.withType { +tasks.withType().configureEach { options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/driver.aero") } diff --git a/ext/platform-inject-support/loader/build.gradle.kts b/ext/platform-inject-support/loader/build.gradle.kts index 72394726e9..8ffba3f8bf 100644 --- a/ext/platform-inject-support/loader/build.gradle.kts +++ b/ext/platform-inject-support/loader/build.gradle.kts @@ -19,9 +19,9 @@ dependencies { "implementation"(projects.utils.utilsBase) } -tasks.withType { +tasks.withType().configureEach { // depend on the output of the jar task - val jarTask = projects.ext.platformInjectSupport.platformInjectRuntime.dependencyProject.tasks.getByName("jar") + val jarTask = project(projects.ext.platformInjectSupport.platformInjectRuntime.path).tasks.getByName("jar") dependsOn(jarTask) // copy over the final output file diff --git a/ext/platform-inject-support/runtime/build.gradle.kts b/ext/platform-inject-support/runtime/build.gradle.kts index 73561c96c1..4b58e37717 100644 --- a/ext/platform-inject-support/runtime/build.gradle.kts +++ b/ext/platform-inject-support/runtime/build.gradle.kts @@ -31,6 +31,6 @@ dependencies { "compileOnly"(projects.ext.platformInjectSupport.platformInjectApi) } -tasks.withType { +tasks.jar.configure { archiveFileName.set(Files.injectSupport) } diff --git a/gradle.properties b/gradle.properties index 1da63925a8..e4bf8fb30e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,10 @@ # limitations under the License. # org.gradle.caching=true +org.gradle.configuration-cache=true +org.gradle.configureondemand=true org.gradle.parallel=true +#org.gradle.unsafe.isolated-projects=true org.gradle.warning.mode=all -org.gradle.logging.level=info +org.gradle.logging.level=warn org.gradle.jvmargs=-Xmx5G -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index df09f78a6d..f987640d2b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] # plugins -shadow = "8.3.8" +shadow = "9.0.0-rc1" juppiter = "0.4.0" spotless = "7.2.1" fabricLoom = "1.11.4" @@ -227,7 +227,7 @@ serverPlatform = ["spigot", "sponge", "nukkitX", "minestom", "minestomExtensions [plugins] fabricLoom = { id = "fabric-loom", version.ref = "fabricLoom" } -spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } -shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } +spotless = { id = "com.diffplug.spotless" } # version on classpath from build-extensions +shadow = { id = "com.gradleup.shadow" } # version on classpath from build-extensions juppiter = { id = "eu.cloudnetservice.juppiter", version.ref = "juppiter" } nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexusPublish" } diff --git a/launcher/java22/build.gradle.kts b/launcher/java22/build.gradle.kts index 566645b08e..e3e3ca7277 100644 --- a/launcher/java22/build.gradle.kts +++ b/launcher/java22/build.gradle.kts @@ -18,7 +18,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.launcher) } diff --git a/launcher/java8/build.gradle.kts b/launcher/java8/build.gradle.kts index 1c412be718..090dcda321 100644 --- a/launcher/java8/build.gradle.kts +++ b/launcher/java8/build.gradle.kts @@ -14,7 +14,7 @@ * limitations under the License. */ -tasks.withType { +tasks.withType().configureEach { sourceCompatibility = JavaVersion.VERSION_1_8.toString() targetCompatibility = JavaVersion.VERSION_1_8.toString() } diff --git a/launcher/patcher/build.gradle.kts b/launcher/patcher/build.gradle.kts index b722bd1b67..3a05c63947 100644 --- a/launcher/patcher/build.gradle.kts +++ b/launcher/patcher/build.gradle.kts @@ -14,11 +14,11 @@ * limitations under the License. */ -tasks.withType { +tasks.jar.configure { archiveFileName.set(Files.launcherPatcher) } -tasks.withType { +tasks.withType().configureEach { sourceCompatibility = JavaVersion.VERSION_17.toString() targetCompatibility = JavaVersion.VERSION_17.toString() } diff --git a/modules/bridge/impl/build.gradle.kts b/modules/bridge/impl/build.gradle.kts index 4ba6439167..fa72b54ee0 100644 --- a/modules/bridge/impl/build.gradle.kts +++ b/modules/bridge/impl/build.gradle.kts @@ -22,12 +22,12 @@ plugins { configurations { // custom configuration for later dependency resolution - create("runtimeImpl") { + register("runtimeImpl") { configurations.getByName("api").extendsFrom(this) } } -tasks.withType { +tasks.withType().configureEach { options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/bridge.aero") } @@ -56,7 +56,7 @@ dependencies { "mappings"(loom.officialMojangMappings()) } -tasks.withType { +tasks.jar.configure { manifest { attributes["paperweight-mappings-namespace"] = "mojang" } @@ -72,7 +72,7 @@ tasks.withType { } } -tasks.withType { +tasks.remapJar.configure { archiveFileName.set(Files.bridge) } diff --git a/modules/build.gradle.kts b/modules/build.gradle.kts index e50c6de7bf..b13441707f 100644 --- a/modules/build.gradle.kts +++ b/modules/build.gradle.kts @@ -53,7 +53,7 @@ subprojects { "compileOnly"(rootProject.libs.guava) } - tasks.create("processSources") { + tasks.register("processSources") { inputs.property("version", project.version) from(sourceSets().getByName("main").java) into(layout.buildDirectory.dir("src")) diff --git a/modules/cloudflare/impl/build.gradle.kts b/modules/cloudflare/impl/build.gradle.kts index 0bb49fb5f8..9217375d21 100644 --- a/modules/cloudflare/impl/build.gradle.kts +++ b/modules/cloudflare/impl/build.gradle.kts @@ -18,7 +18,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.cloudflare) } diff --git a/modules/database-mongodb/impl/build.gradle.kts b/modules/database-mongodb/impl/build.gradle.kts index 7a6c1a8e99..be32eda410 100644 --- a/modules/database-mongodb/impl/build.gradle.kts +++ b/modules/database-mongodb/impl/build.gradle.kts @@ -18,7 +18,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.databaseMongo) } diff --git a/modules/database-mysql/impl/build.gradle.kts b/modules/database-mysql/impl/build.gradle.kts index 1367d226b5..d3889cc7a9 100644 --- a/modules/database-mysql/impl/build.gradle.kts +++ b/modules/database-mysql/impl/build.gradle.kts @@ -1,3 +1,5 @@ +import java.util.* + /* * Copyright 2019-2024 CloudNetService team & contributors * @@ -18,7 +20,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.databaseMysql) } diff --git a/modules/dockerized-services/impl/build.gradle.kts b/modules/dockerized-services/impl/build.gradle.kts index af1351406d..f882d8149f 100644 --- a/modules/dockerized-services/impl/build.gradle.kts +++ b/modules/dockerized-services/impl/build.gradle.kts @@ -18,7 +18,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.dockerizedServices) } diff --git a/modules/influx/impl/build.gradle.kts b/modules/influx/impl/build.gradle.kts index fc0fdb072b..7eb4a86dc3 100644 --- a/modules/influx/impl/build.gradle.kts +++ b/modules/influx/impl/build.gradle.kts @@ -20,7 +20,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.influx) } diff --git a/modules/labymod/impl/build.gradle.kts b/modules/labymod/impl/build.gradle.kts index d449543322..83cfcb4749 100644 --- a/modules/labymod/impl/build.gradle.kts +++ b/modules/labymod/impl/build.gradle.kts @@ -19,7 +19,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.labymod) } diff --git a/modules/npcs/impl/build.gradle.kts b/modules/npcs/impl/build.gradle.kts index 0b9fef880f..3656a275e5 100644 --- a/modules/npcs/impl/build.gradle.kts +++ b/modules/npcs/impl/build.gradle.kts @@ -21,7 +21,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.npcs) manifest { @@ -29,11 +29,11 @@ tasks.withType { } } -tasks.withType { +tasks.withType().configureEach { options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/npcs.aero") } -tasks.withType { +tasks.withType().configureEach { relocate("net.kyori", "eu.cloudnetservice.modules.npc.relocate.net.kyori") relocate("io.papermc.lib", "eu.cloudnetservice.modules.npc.relocate.paperlib") relocate("io.leangen.geantyref", "eu.cloudnetservice.modules.npc.relocate.geantyref") diff --git a/modules/report/impl/build.gradle.kts b/modules/report/impl/build.gradle.kts index 6b64c4490f..295befefb2 100644 --- a/modules/report/impl/build.gradle.kts +++ b/modules/report/impl/build.gradle.kts @@ -18,7 +18,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.report) } diff --git a/modules/signs/impl/build.gradle.kts b/modules/signs/impl/build.gradle.kts index 5913bcee5e..c2c175dcc7 100644 --- a/modules/signs/impl/build.gradle.kts +++ b/modules/signs/impl/build.gradle.kts @@ -20,7 +20,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.signs) manifest { @@ -28,7 +28,7 @@ tasks.withType { } } -tasks.withType { +tasks.withType().configureEach { options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/signs.aero") } diff --git a/modules/smart/impl/build.gradle.kts b/modules/smart/impl/build.gradle.kts index 5ef8a7fa49..b50b179ecb 100644 --- a/modules/smart/impl/build.gradle.kts +++ b/modules/smart/impl/build.gradle.kts @@ -20,7 +20,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.smart) } diff --git a/modules/storage-s3/impl/build.gradle.kts b/modules/storage-s3/impl/build.gradle.kts index d2c5d3dffe..b13ddc8f3b 100644 --- a/modules/storage-s3/impl/build.gradle.kts +++ b/modules/storage-s3/impl/build.gradle.kts @@ -18,7 +18,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.storageS3) } diff --git a/modules/storage-sftp/impl/build.gradle.kts b/modules/storage-sftp/impl/build.gradle.kts index e26b05086c..cc26e6a14e 100644 --- a/modules/storage-sftp/impl/build.gradle.kts +++ b/modules/storage-sftp/impl/build.gradle.kts @@ -18,7 +18,7 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.storageSftp) } diff --git a/modules/syncproxy/impl/build.gradle.kts b/modules/syncproxy/impl/build.gradle.kts index b4933162c4..7744946621 100644 --- a/modules/syncproxy/impl/build.gradle.kts +++ b/modules/syncproxy/impl/build.gradle.kts @@ -20,11 +20,11 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +tasks.shadowJar.configure { archiveFileName.set(Files.syncproxy) } -tasks.withType { +tasks.withType().configureEach { options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/syncproxy.aero") } diff --git a/node/impl/build.gradle.kts b/node/impl/build.gradle.kts index d505d75829..28c8860b12 100644 --- a/node/impl/build.gradle.kts +++ b/node/impl/build.gradle.kts @@ -14,12 +14,19 @@ * limitations under the License. */ -tasks.withType { +val exportCnlFile = tasks.register("exportCnlFile") { + fileName = Files.nodeCnl + setResolvedArtifacts(configurations.runtimeClasspath.get()) +} +val exportLanguageFileInformation = tasks.register("exportLanguageFileInformation") { + languageFiles.from(project.projectDir.resolve("src/main/resources/lang").listFiles()) +} +tasks.jar { archiveFileName.set(Files.node) - from(projects.node.nodeApi.sourceSets()["main"].output) - from(projects.utils.utilsBase.sourceSets()["main"].output) - from(projects.driver.driverApi.sourceSets()["main"].output) - from(projects.driver.driverImpl.sourceSets()["main"].output) + from(projects.node.nodeApi.sourceSets(project)["main"].output) + from(projects.utils.utilsBase.sourceSets(project)["main"].output) + from(projects.driver.driverApi.sourceSets(project)["main"].output) + from(projects.driver.driverImpl.sourceSets(project)["main"].output) dependsOn(":wrapper-jvm:wrapper-jvm-impl:shadowJar") @@ -27,13 +34,11 @@ tasks.withType { include(Files.wrapper) } - doFirst { - from(exportCnlFile(Files.nodeCnl)) - from(exportLanguageFileInformation()) - } + from(exportCnlFile) + from(exportLanguageFileInformation) } -tasks.withType { +tasks.withType().configureEach { options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/node.aero") } diff --git a/plugins/build.gradle.kts b/plugins/build.gradle.kts index 8eae5de66c..80ba396960 100644 --- a/plugins/build.gradle.kts +++ b/plugins/build.gradle.kts @@ -36,7 +36,7 @@ subprojects { "annotationProcessor"(rootProject.projects.ext.platformInjectSupport.platformInjectProcessor) } - tasks.create("processSources") { + tasks.register("processSources") { inputs.property("version", project.version) from(sourceSets().getByName("main").java) into(layout.buildDirectory.dir("src")) diff --git a/plugins/luckperms/build.gradle.kts b/plugins/luckperms/build.gradle.kts index 2cd4b073b5..60908e3634 100644 --- a/plugins/luckperms/build.gradle.kts +++ b/plugins/luckperms/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { "mappings"(loom.officialMojangMappings()) } -tasks.withType { +tasks.remapJar.configure { // base setup archiveFileName.set(Files.luckPermsPlugin) } diff --git a/plugins/papi-expansion/build.gradle.kts b/plugins/papi-expansion/build.gradle.kts index 65cae4941e..9df39b2368 100644 --- a/plugins/papi-expansion/build.gradle.kts +++ b/plugins/papi-expansion/build.gradle.kts @@ -14,7 +14,7 @@ * limitations under the License. */ -tasks.withType { +tasks.jar.configure { archiveFileName.set(Files.papiExpansion) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 0a4e5ce95f..fc33e4403b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,12 +21,28 @@ pluginManagement { includeBuild("build-extensions") repositories { gradlePluginPortal() +// maven("https://repo.stellardrift.ca/repository/snapshots/") { + mavenLocal { + content { + includeGroup("net.kyori") + } + } + mavenLocal { + content { + includeGroup("eu.cloudnetservice.juppiter") + includeGroup("eu.cloudnetservice.gradle") + } + } maven { name = "Fabric" url = uri("https://maven.fabricmc.net/") } } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("settings-plugin") +} rootProject.name = "cloudnet-root" @@ -89,9 +105,7 @@ initializePrefixedSubProjects("modules:dockerized-services", "dockerized-service fun initializeSubProjects(rootProject: String, vararg names: String) { names.forEach { include("$rootProject:$it") - // update the project properties project(":$rootProject:$it").name = it - project(":$rootProject:$it").projectDir = file(rootProject).resolve(it) } } diff --git a/wrapper-jvm/impl/build.gradle.kts b/wrapper-jvm/impl/build.gradle.kts index c595aec4dd..3f685318d1 100644 --- a/wrapper-jvm/impl/build.gradle.kts +++ b/wrapper-jvm/impl/build.gradle.kts @@ -4,12 +4,20 @@ plugins { alias(libs.plugins.shadow) } -tasks.withType { +val ignoredGroupIds = listOf("com.google.guava", "com.google.code.gson") +val exportCnlFile = tasks.register("exportCnlFile") { + fileName = "wrapper.cnl" + ignoredDependencyGroups = ignoredGroupIds + setResolvedArtifacts(configurations.runtimeClasspath.get()) +} +val exportLanguageFileInformation = tasks.register("exportLanguageFileInformation") { + languageFiles.from(project.projectDir.resolve("src/main/resources/lang").listFiles()) +} +tasks.shadowJar.configure { archiveFileName.set(Files.wrapper) - archiveVersion.set(null as String?) // do not shade dependencies which we don't need to shade - val ignoredGroupIds = arrayOf("com.google.guava", "com.google.code.gson") + dependencies { exclude { it.moduleGroup != rootProject.group && !ignoredGroupIds.contains(it.moduleGroup) @@ -23,14 +31,11 @@ tasks.withType { // drop unused classes which are making the jar bigger minimize() - doFirst { - // Note: included dependencies will not be resolved, they must be available from the node resolution already - from(exportLanguageFileInformation()) - from(exportCnlFile("wrapper.cnl", ignoredGroupIds)) - } + from(exportLanguageFileInformation) + from(exportCnlFile) } -tasks.withType { +tasks.withType().configureEach { options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/wrapper.aero") } From 8277cdf21da472cb63cbaaec46640e497ff17fd4 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Thu, 17 Apr 2025 12:49:35 +0200 Subject: [PATCH 02/45] apply shadow configuration late --- .../src/main/kotlin/settings-plugin.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/settings-plugin.kt index 7c6e5a95dc..2b97b0a71c 100644 --- a/build-extensions/src/main/kotlin/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/settings-plugin.kt @@ -125,13 +125,15 @@ class JavaProjects : Plugin { } } - if (project.plugins.hasPlugin(ShadowJavaPlugin::class)) { - tasks.named("assemble").configure { - dependsOn(project.tasks.named("shadowJar")) - } - tasks.named("jar").configure { - // we use the shadow jar task, so move the jar into the task's temporary dir to avoid clutter - destinationDirectory = temporaryDir + project.afterEvaluate { + if (project.plugins.hasPlugin(ShadowJavaPlugin::class)) { + tasks.named("assemble").configure { + dependsOn(project.tasks.named("shadowJar")) + } + tasks.named("jar").configure { + // we use the shadow jar task, so move the jar into the task's temporary dir to avoid clutter + destinationDirectory = temporaryDir + } } } From 38025c380956a7914f478d69eb4ac1da65690feb Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Thu, 17 Apr 2025 18:08:55 +0200 Subject: [PATCH 03/45] build scan auto publishing (if agreed with file) --- .gitignore | 3 +++ settings.gradle.kts | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.gitignore b/.gitignore index 8af103bec8..1d968cac66 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,9 @@ .gradle/ build/ +# gradle build scans +/gradle.tos.agree + # fleet .fleet/ diff --git a/settings.gradle.kts b/settings.gradle.kts index fc33e4403b..ce64f63ef6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -41,6 +41,7 @@ pluginManagement { } plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("com.gradle.develocity") version ("4.0") id("settings-plugin") } @@ -115,3 +116,17 @@ fun initializePrefixedSubProjects(rootProject: String, prefix: String, vararg na project(":$rootProject:$it").name = "$prefix-$it" } } + +develocity { + buildScan { + termsOfUseAgree = if (File("gradle.tos.agree").exists()) "yes" else "" + termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use" + publishing.onlyIf { termsOfUseAgree.get() == "yes" } + obfuscation { + ipAddresses { listOf("0.0.0.0") } + hostname { "removed" } + externalProcessName { "hidden-process-name" } + username { "hidden-username" } + } + } +} From 47a28d513d02e51d5c75083b69a91e5964f57a7f Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Thu, 17 Apr 2025 18:09:10 +0200 Subject: [PATCH 04/45] more work --- build-extensions/build.gradle.kts | 6 ++ .../src/main/kotlin/extensions.kt | 9 -- .../src/main/kotlin/modules-configuration.kt | 71 ++++++++++++++ .../src/main/kotlin/plugins-configuration.kt | 59 ++++++++++++ .../src/main/kotlin/settings-plugin.kt | 93 +++++++++++++++---- build.gradle.kts | 21 ++++- .../loader/build.gradle.kts | 17 ++-- gradle/libs.versions.toml | 2 +- modules/build.gradle.kts | 52 ----------- node/impl/build.gradle.kts | 29 ++++-- plugins/build.gradle.kts | 35 ------- wrapper-jvm/impl/build.gradle.kts | 1 + 12 files changed, 261 insertions(+), 134 deletions(-) create mode 100644 build-extensions/src/main/kotlin/modules-configuration.kt create mode 100644 build-extensions/src/main/kotlin/plugins-configuration.kt diff --git a/build-extensions/build.gradle.kts b/build-extensions/build.gradle.kts index c9a6e32223..98221116cf 100644 --- a/build-extensions/build.gradle.kts +++ b/build-extensions/build.gradle.kts @@ -29,6 +29,11 @@ repositories { includeGroup("net.kyori") } } + mavenLocal { + content { + includeModule("eu.cloudnetservice.gradle", "juppiter") + } + } } dependencies { @@ -37,6 +42,7 @@ dependencies { implementation("com.diffplug.spotless", "spotless-plugin-gradle", libs.versions.spotless.get()) implementation("com.gradleup.shadow", "shadow-gradle-plugin", libs.versions.shadow.get()) + implementation("eu.cloudnetservice.gradle", "juppiter", libs.versions.juppiter.get()) } gradlePlugin { diff --git a/build-extensions/src/main/kotlin/extensions.kt b/build-extensions/src/main/kotlin/extensions.kt index 118696533f..a2368e98e2 100644 --- a/build-extensions/src/main/kotlin/extensions.kt +++ b/build-extensions/src/main/kotlin/extensions.kt @@ -88,8 +88,6 @@ fun Project.git(): IndraGitExtension? = rootProject.extensions.findByType() fun Project.sourceSets(): SourceSetContainer = the().sourceSets -fun ProjectDependency.sourceSets(project: Project): SourceSetContainer = project.project(path).sourceSets() - fun Project.mavenRepositories(): Iterable = repositories.filterIsInstance() fun releasesOnly(repository: MavenArtifactRepository) { @@ -103,10 +101,3 @@ fun snapshotsOnly(repository: MavenArtifactRepository) { snapshotsOnly() } } - -fun Project.exportLanguageFileInformation(): String { - val file = project.layout.buildDirectory.file("languages.txt").get().asFile - file.writeText(project.projectDir.resolve("src/main/resources/lang").listFiles()?.joinToString(separator = "\n") { it.name }!!) - - return file.absolutePath -} diff --git a/build-extensions/src/main/kotlin/modules-configuration.kt b/build-extensions/src/main/kotlin/modules-configuration.kt new file mode 100644 index 0000000000..ec4dc50e74 --- /dev/null +++ b/build-extensions/src/main/kotlin/modules-configuration.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.tools.ant.filters.ReplaceTokens +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.Sync +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.kotlin.dsl.* + +class ModuleGradlePlugin : Plugin { + override fun apply(project: Project) { + project.run { + if (name.endsWith("impl")) { + apply(plugin = "eu.cloudnetservice.juppiter") + + configurations { + getByName("testImplementation").extendsFrom(getByName("moduleLibrary")) + } + } + + repositories { + maven("https://repo.waterdog.dev/releases/") + maven("https://repo.waterdog.dev/snapshots/") + maven("https://repo.loohpjames.com/repository") + maven("https://repo.md-5.net/repository/releases/") + maven("https://repo.md-5.net/repository/snapshots/") + maven("https://repo.opencollab.dev/maven-releases/") + maven("https://repo.opencollab.dev/maven-snapshots/") + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + } + + dependencies { + "compileOnly"(project(":node:node-api")) + "testImplementation"(project(":node:node-api")) + + // generation for platform main classes + "compileOnly"(project(":ext:platform-inject-support:platform-inject-api")) + "annotationProcessor"(project(":ext:platform-inject-support:platform-inject-processor")) + + "compileOnly"(libs.library("guava")) + } + + tasks.register("processSources") { + inputs.property("version", project.version) + from(sourceSets().getByName("main").java) + into(layout.buildDirectory.dir("src")) + filter(ReplaceTokens::class, mapOf("tokens" to mapOf("version" to rootProject.version))) + } + + tasks.named("compileJava") { + dependsOn(tasks.getByName("processSources")) + source = tasks.getByName("processSources").outputs.files.asFileTree + } + } + } +} diff --git a/build-extensions/src/main/kotlin/plugins-configuration.kt b/build-extensions/src/main/kotlin/plugins-configuration.kt new file mode 100644 index 0000000000..ed29cbf8ca --- /dev/null +++ b/build-extensions/src/main/kotlin/plugins-configuration.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.tools.ant.filters.ReplaceTokens +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.Sync +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.kotlin.dsl.* + +class PluginGradlePlugin : Plugin { + override fun apply(project: Project) { + project.run { + repositories { + maven("https://repo.waterdog.dev/releases/") + maven("https://repo.waterdog.dev/snapshots/") + maven("https://repo.spongepowered.org/maven/") + maven("https://repo.loohpjames.com/repository") + maven("https://repo.opencollab.dev/maven-releases/") + maven("https://repo.opencollab.dev/maven-snapshots/") + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + } + + dependencies { + "implementation"(libs.library("guava")) + + // generation for platform main classes + "compileOnly"(project(":ext:platform-inject-support:platform-inject-api")) + "annotationProcessor"(project(":ext:platform-inject-support:platform-inject-processor")) + } + + tasks.register("processSources") { + inputs.property("version", project.version) + from(sourceSets().getByName("main").java) + into(layout.buildDirectory.dir("src")) + filter(ReplaceTokens::class, mapOf("tokens" to mapOf("version" to rootProject.version))) + } + + tasks.named("compileJava") { + dependsOn(tasks.getByName("processSources")) + source = tasks.getByName("processSources").outputs.files.asFileTree + } + } + } +} diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/settings-plugin.kt index 2b97b0a71c..7949aba33f 100644 --- a/build-extensions/src/main/kotlin/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/settings-plugin.kt @@ -19,11 +19,16 @@ import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin import org.gradle.api.JavaVersion import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.artifacts.ExternalModuleDependencyBundle +import org.gradle.api.artifacts.MinimalExternalModuleDependency +import org.gradle.api.artifacts.VersionCatalog +import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.api.file.DuplicatesStrategy import org.gradle.api.initialization.Settings import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.plugins.quality.Checkstyle import org.gradle.api.plugins.quality.CheckstyleExtension +import org.gradle.api.provider.Provider import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.javadoc.Javadoc @@ -35,6 +40,7 @@ import org.gradle.language.jvm.tasks.ProcessResources class SettingsPlugin : Plugin { override fun apply(settings: Settings) { settings.gradle.lifecycle.beforeProject { + println("configuring ${this.path}") plugins.apply(AllProjects::class) if (this != this.rootProject) { plugins.apply(JavaProjects::class) @@ -43,11 +49,45 @@ class SettingsPlugin : Plugin { } } +fun isJavaConfiguredProject(name: String): Boolean { + if (isHelperProject(name)) return false + return name != "bom" +} + +fun isHelperProject(name: String): Boolean { + return name == "modules" || name == "plugins" || name == "ext" || name == "launcher" +} + +object CustomConfigurations { + const val GLOBAL_JAVADOC_SOURCES = "globalJavadocSources" + const val GLOBAL_JAVADOC_CLASSPATH = "globalJavadocClasspath" +} + +internal fun Provider.library(name: String): Provider { + return flatMap { + it.findLibrary(name) + .orElseThrow { NoSuchElementException("Failed to find library named $name. Valid names: ${it.libraryAliases}") } + } +} + +internal fun Provider.bundle(name: String): Provider { + // We can't use flatMap here, because Gradle uses internal magic + return get().let { + it.findBundle(name) + .orElseThrow { NoSuchElementException("Failed to find bundle named $name. Valid names: ${it.bundleAliases}") } + } +} + +internal val Project.libs: Provider + get() = provider { extensions.getByName("versionCatalogs").named("libs") } + class JavaProjects : Plugin { override fun apply(project: Project) { project.run { + + // these are top level projects which are configured separately - if (name == "modules" || name == "plugins" || name == "ext" || name == "launcher") { + if (isHelperProject(name)) { return@run } @@ -58,7 +98,7 @@ class JavaProjects : Plugin { // skip further applying to bom - this project is a bit special as we're not allowed to // apply the java plugin to it (that's why we need to stop here, but we need to publish // at well (that's why we're applying the publish plugin) - if (name == "bom") { + if (!isJavaConfiguredProject(name)) { return@run } @@ -66,20 +106,29 @@ class JavaProjects : Plugin { apply(plugin = "java-library") apply(plugin = "com.diffplug.spotless") - val libs = rootProject.versionCatalogs.named("libs") + if (path.startsWith(":plugins:")) { + apply() + } + if (path.startsWith(":modules:")) { + apply() + } - dependencies { - // the 'rootProject.libs.' prefix is needed here - see https://github.com/gradle/gradle/issues/16634 - // lombok - "compileOnly"(libs.findLibrary("lombok").orElseThrow()) - "annotationProcessor"(libs.findLibrary("lombok").orElseThrow()) - // annotations - "compileOnly"(libs.findLibrary("annotations").orElseThrow()) - // testing - "testImplementation"(libs.findLibrary("mockito").orElseThrow()) - "testRuntimeOnly"(libs.findLibrary("junitLauncher").orElseThrow()) - "testImplementation"(libs.findBundle("junit").orElseThrow()) - "testImplementation"(libs.findBundle("testContainers").orElseThrow()) + val libs = this.libs + + afterEvaluate { + dependencies { + // the 'rootProject.libs.' prefix is needed here - see https://github.com/gradle/gradle/issues/16634 + // lombok + "compileOnly"(libs.library("lombok")) + "annotationProcessor"(libs.library("lombok")) + // annotations + "compileOnly"(libs.library("annotations")) + // testing + "testImplementation"(libs.library("mockito")) + "testRuntimeOnly"(libs.library("junitLauncher")) + "testImplementation"(libs.bundle("junit")) + "testImplementation"(libs.bundle("testContainers")) + } } configurations.all { @@ -143,8 +192,10 @@ class JavaProjects : Plugin { configFile = rootProject.file("checkstyle.xml") } - extensions.configure { - toolVersion = libs.findVersion("checkstyleTools").orElseThrow().requiredVersion + afterEvaluate { + extensions.configure { + toolVersion = libs.map { it.findVersion("checkstyleTools").orElseThrow().requiredVersion }.get() + } } extensions.configure { @@ -168,6 +219,14 @@ class JavaProjects : Plugin { // all these projects are publishing their java artifacts configurePublishing("java", true) + + // create consumable artifacts for global javadoc + configurations.consumable(CustomConfigurations.GLOBAL_JAVADOC_SOURCES) { + outgoing.artifacts(sourceSets().named("main").map { it.allJava.srcDirs }) + } + configurations.consumable(CustomConfigurations.GLOBAL_JAVADOC_CLASSPATH) { + outgoing.artifacts(sourceSets().named("main").map { it.compileClasspath }) + } } } } diff --git a/build.gradle.kts b/build.gradle.kts index aac4a301cc..9f8c885bc8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,6 +24,9 @@ plugins { defaultTasks("build") +val globalJavadocSources = configurations.register("globalJavadocSources") +val globalJavadocClasspath = configurations.register("globalJavadocClasspath") + tasks.register("globalJavaDoc", Javadoc::class) { val options = options as? StandardJavadocDocletOptions ?: return@register @@ -33,9 +36,8 @@ tasks.register("globalJavaDoc", Javadoc::class) { applyDefaultJavadocOptions(options) options.windowTitle = "CloudNet JavaDocs" // set the sources - val sources = subprojects.filter { it.plugins.hasPlugin("java") }.map { it.path } - source(files(sources.flatMap { project(it).sourceSets()["main"].allJava })) - classpath = files(sources.flatMap { project(it).sourceSets()["main"].compileClasspath }) + source(globalJavadocSources) + classpath = globalJavadocClasspath.get() } nexusPublishing { @@ -52,12 +54,23 @@ nexusPublishing { useStaging.set(!project.version.toString().endsWith("-SNAPSHOT")) } -libs.lombok +dependencies { + subprojects.map { it.isolated }.forEach { project -> + if (!isJavaConfiguredProject(project.name)) return@forEach + globalJavadocSources(this.project(project.path)) { + targetConfiguration = CustomConfigurations.GLOBAL_JAVADOC_SOURCES + } + globalJavadocClasspath(this.project(project.path)) { + targetConfiguration = CustomConfigurations.GLOBAL_JAVADOC_CLASSPATH + } + } +} gradle.projectsEvaluated { tasks.register("genUpdaterInformation") { subprojects.forEach { // check if we need to depend on the plugin + // TODO this breaks isolated projects if (!it.plugins.hasPlugin("java")) return@forEach // depend this task on the build output of each subproject dependsOn("${it.path}:build") diff --git a/ext/platform-inject-support/loader/build.gradle.kts b/ext/platform-inject-support/loader/build.gradle.kts index 8ffba3f8bf..b48781dd05 100644 --- a/ext/platform-inject-support/loader/build.gradle.kts +++ b/ext/platform-inject-support/loader/build.gradle.kts @@ -19,13 +19,16 @@ dependencies { "implementation"(projects.utils.utilsBase) } -tasks.withType().configureEach { - // depend on the output of the jar task - val jarTask = project(projects.ext.platformInjectSupport.platformInjectRuntime.path).tasks.getByName("jar") - dependsOn(jarTask) +val includeInJar = configurations.register("includeInJar") { + isCanBeConsumed = false; + isTransitive = false +} +tasks.withType().configureEach { // copy over the final output file - from("../runtime/build/libs") { - include(Files.injectSupport) - } + from(includeInJar) +} + +dependencies { + includeInJar(projects.ext.platformInjectSupport.platformInjectRuntime) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f987640d2b..39b9482901 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ # plugins shadow = "9.0.0-rc1" -juppiter = "0.4.0" +juppiter = "0.5.0-beta.2" spotless = "7.2.1" fabricLoom = "1.11.4" nexusPublish = "2.0.0" diff --git a/modules/build.gradle.kts b/modules/build.gradle.kts index b13441707f..d2d9f18709 100644 --- a/modules/build.gradle.kts +++ b/modules/build.gradle.kts @@ -13,55 +13,3 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import org.apache.tools.ant.filters.ReplaceTokens - -plugins { - alias(libs.plugins.juppiter) apply false -} - -subprojects { - if (name.endsWith("impl")) { - apply(plugin = "eu.cloudnetservice.juppiter") - - configurations { - getByName("testImplementation").extendsFrom(getByName("moduleLibrary")) - } - } - - repositories { - maven("https://repo.waterdog.dev/releases/") - maven("https://repo.waterdog.dev/snapshots/") - maven("https://repo.loohpjames.com/repository") - maven("https://repo.md-5.net/repository/releases/") - maven("https://repo.md-5.net/repository/snapshots/") - maven("https://repo.opencollab.dev/maven-releases/") - maven("https://repo.opencollab.dev/maven-snapshots/") - maven("https://repo.papermc.io/repository/maven-public/") - maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") - } - - dependencies { - "compileOnly"(rootProject.projects.node.nodeApi) - "testImplementation"(rootProject.projects.node.nodeApi) - - // generation for platform main classes - "compileOnly"(rootProject.projects.ext.platformInjectSupport.platformInjectApi) - "annotationProcessor"(rootProject.projects.ext.platformInjectSupport.platformInjectProcessor) - - // internal dependencies - "compileOnly"(rootProject.libs.guava) - } - - tasks.register("processSources") { - inputs.property("version", project.version) - from(sourceSets().getByName("main").java) - into(layout.buildDirectory.dir("src")) - filter(ReplaceTokens::class, mapOf("tokens" to mapOf("version" to rootProject.version))) - } - - tasks.named("compileJava") { - dependsOn(tasks.getByName("processSources")) - source = tasks.getByName("processSources").outputs.files.asFileTree - } -} diff --git a/node/impl/build.gradle.kts b/node/impl/build.gradle.kts index 28c8860b12..073d0bf359 100644 --- a/node/impl/build.gradle.kts +++ b/node/impl/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + alias(libs.plugins.shadow) +} + val exportCnlFile = tasks.register("exportCnlFile") { fileName = Files.nodeCnl setResolvedArtifacts(configurations.runtimeClasspath.get()) @@ -21,17 +25,17 @@ val exportCnlFile = tasks.register("exportCnlFile") { val exportLanguageFileInformation = tasks.register("exportLanguageFileInformation") { languageFiles.from(project.projectDir.resolve("src/main/resources/lang").listFiles()) } -tasks.jar { - archiveFileName.set(Files.node) - from(projects.node.nodeApi.sourceSets(project)["main"].output) - from(projects.utils.utilsBase.sourceSets(project)["main"].output) - from(projects.driver.driverApi.sourceSets(project)["main"].output) - from(projects.driver.driverImpl.sourceSets(project)["main"].output) +val includeInJar = configurations.register("includeInJar") { isTransitive = false } +val wrapperJar = configurations.register("wrapperJar") { isTransitive = false } - dependsOn(":wrapper-jvm:wrapper-jvm-impl:shadowJar") +tasks.shadowJar { + archiveFileName.set(Files.node) + configurations = listOf(includeInJar.get()) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE - from("../../wrapper-jvm/impl/build/libs") { - include(Files.wrapper) + from(wrapperJar) { + // Rename the file to make sure 100% + rename { Files.wrapper } } from(exportCnlFile) @@ -77,6 +81,13 @@ dependencies { "implementation"(libs.logbackClassic) "compileOnly"(libs.bundles.netty) + + includeInJar(projects.node.nodeApi) + includeInJar(projects.utils.utilsBase) + includeInJar(projects.driver.driverApi) + includeInJar(projects.driver.driverImpl) + + wrapperJar(projects.wrapperJvm.wrapperJvmImpl) { targetConfiguration = "shadow" } } applyJarMetadata("eu.cloudnetservice.node.impl.boot.Bootstrap", "eu.cloudnetservice.node") diff --git a/plugins/build.gradle.kts b/plugins/build.gradle.kts index 80ba396960..d2d9f18709 100644 --- a/plugins/build.gradle.kts +++ b/plugins/build.gradle.kts @@ -13,38 +13,3 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import org.apache.tools.ant.filters.ReplaceTokens - -subprojects { - repositories { - maven("https://repo.waterdog.dev/releases/") - maven("https://repo.waterdog.dev/snapshots/") - maven("https://repo.spongepowered.org/maven/") - maven("https://repo.loohpjames.com/repository") - maven("https://repo.opencollab.dev/maven-releases/") - maven("https://repo.opencollab.dev/maven-snapshots/") - maven("https://repo.papermc.io/repository/maven-public/") - maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") - } - - dependencies { - "implementation"(rootProject.libs.guava) - - // generation for platform main classes - "compileOnly"(rootProject.projects.ext.platformInjectSupport.platformInjectApi) - "annotationProcessor"(rootProject.projects.ext.platformInjectSupport.platformInjectProcessor) - } - - tasks.register("processSources") { - inputs.property("version", project.version) - from(sourceSets().getByName("main").java) - into(layout.buildDirectory.dir("src")) - filter(ReplaceTokens::class, mapOf("tokens" to mapOf("version" to rootProject.version))) - } - - tasks.named("compileJava") { - dependsOn(tasks.getByName("processSources")) - source = tasks.getByName("processSources").outputs.files.asFileTree - } -} diff --git a/wrapper-jvm/impl/build.gradle.kts b/wrapper-jvm/impl/build.gradle.kts index 3f685318d1..37fa08ec26 100644 --- a/wrapper-jvm/impl/build.gradle.kts +++ b/wrapper-jvm/impl/build.gradle.kts @@ -23,6 +23,7 @@ tasks.shadowJar.configure { it.moduleGroup != rootProject.group && !ignoredGroupIds.contains(it.moduleGroup) } } + duplicatesStrategy = DuplicatesStrategy.EXCLUDE // google lib relocation relocate("com.google.gson", "eu.cloudnetservice.relocate.gson") From 745b923f2f2a625c6845295b8bf8db9848c82b19 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Thu, 17 Apr 2025 18:42:46 +0200 Subject: [PATCH 05/45] apply indra on all projects to decouple projects --- build-extensions/build.gradle.kts | 3 ++- build-extensions/src/main/kotlin/extensions.kt | 2 +- build-extensions/src/main/kotlin/settings-plugin.kt | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build-extensions/build.gradle.kts b/build-extensions/build.gradle.kts index 98221116cf..ec09c718fe 100644 --- a/build-extensions/build.gradle.kts +++ b/build-extensions/build.gradle.kts @@ -19,6 +19,7 @@ plugins { id("java-gradle-plugin") } +// fabric requires jvm 21, so we can do so too kotlin.jvmToolchain(21) repositories { @@ -37,7 +38,7 @@ repositories { } dependencies { - implementation("net.kyori", "indra-common", "4.0.0-SNAPSHOT") + implementation("net.kyori", "indra-git", "4.0.0-SNAPSHOT") implementation("com.google.code.gson", "gson", "2.13.1") implementation("com.diffplug.spotless", "spotless-plugin-gradle", libs.versions.spotless.get()) diff --git a/build-extensions/src/main/kotlin/extensions.kt b/build-extensions/src/main/kotlin/extensions.kt index a2368e98e2..0620a12e30 100644 --- a/build-extensions/src/main/kotlin/extensions.kt +++ b/build-extensions/src/main/kotlin/extensions.kt @@ -84,7 +84,7 @@ fun Project.shortCommitHash(): String { return git()?.commit()?.get()?.name()?.substring(0, 8) ?: "unknown" } -fun Project.git(): IndraGitExtension? = rootProject.extensions.findByType() +fun Project.git(): IndraGitExtension? = extensions.findByType() fun Project.sourceSets(): SourceSetContainer = the().sourceSets diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/settings-plugin.kt index 7949aba33f..3b9a47354d 100644 --- a/build-extensions/src/main/kotlin/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/settings-plugin.kt @@ -105,6 +105,7 @@ class JavaProjects : Plugin { apply(plugin = "checkstyle") apply(plugin = "java-library") apply(plugin = "com.diffplug.spotless") + apply(plugin = "net.kyori.indra.git") if (path.startsWith(":plugins:")) { apply() From fb0b9f2e6f20a89f06458740f985d8ff4377f6d8 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Thu, 17 Apr 2025 18:46:54 +0200 Subject: [PATCH 06/45] add todo on debug printing --- build-extensions/src/main/kotlin/settings-plugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/settings-plugin.kt index 3b9a47354d..365bc7ad2d 100644 --- a/build-extensions/src/main/kotlin/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/settings-plugin.kt @@ -40,7 +40,7 @@ import org.gradle.language.jvm.tasks.ProcessResources class SettingsPlugin : Plugin { override fun apply(settings: Settings) { settings.gradle.lifecycle.beforeProject { - println("configuring ${this.path}") + println("configuring ${this.path}") // TODO remove, this is temporary to better debug any configuration done (configure-on-demand) plugins.apply(AllProjects::class) if (this != this.rootProject) { plugins.apply(JavaProjects::class) From 2e31aa84c05341b65bfd21e53f58a826935fa511 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 16 Jul 2025 23:50:38 +0200 Subject: [PATCH 07/45] remove unused import --- build-extensions/src/main/kotlin/publishing-extensions.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/build-extensions/src/main/kotlin/publishing-extensions.kt b/build-extensions/src/main/kotlin/publishing-extensions.kt index 3ae93e8aa3..0b12b0be7a 100644 --- a/build-extensions/src/main/kotlin/publishing-extensions.kt +++ b/build-extensions/src/main/kotlin/publishing-extensions.kt @@ -20,7 +20,6 @@ import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication import org.gradle.external.javadoc.JavadocMemberLevel import org.gradle.external.javadoc.StandardJavadocDocletOptions -import org.gradle.internal.impldep.com.amazonaws.util.XpathUtils.asNode import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.withType import org.gradle.plugins.signing.Sign From 5439511ff7f0b122e371b34101da439514da90ba Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 16 Jul 2025 23:51:16 +0200 Subject: [PATCH 08/45] fix some issues regarding build scans --- settings.gradle.kts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index ce64f63ef6..aba1ff3aa7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -41,7 +41,7 @@ pluginManagement { } plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" - id("com.gradle.develocity") version ("4.0") + id("com.gradle.develocity") version ("4.1") id("settings-plugin") } @@ -117,11 +117,22 @@ fun initializePrefixedSubProjects(rootProject: String, prefix: String, vararg na } } +val isCI = System.getenv("CI") != null + develocity { buildScan { - termsOfUseAgree = if (File("gradle.tos.agree").exists()) "yes" else "" + val file = rootDir.resolve("gradle.tos.agree") + val agree = if (file.exists()) "yes" else "" + termsOfUseAgree = agree termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use" + gradle.settingsEvaluated { + // IntelliJ overrides this in windows using an init script %TEMP%/ejNoScan1.gradle + // We agree with the file, so we override IntelliJ again. + termsOfUseAgree = agree + } publishing.onlyIf { termsOfUseAgree.get() == "yes" } + + uploadInBackground = !isCI obfuscation { ipAddresses { listOf("0.0.0.0") } hostname { "removed" } From a966f357e1639d633fbe6f98a4e51296faa8f7ac Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 16 Jul 2025 23:55:18 +0200 Subject: [PATCH 09/45] improve comment --- node/impl/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/impl/build.gradle.kts b/node/impl/build.gradle.kts index 073d0bf359..289e7d5294 100644 --- a/node/impl/build.gradle.kts +++ b/node/impl/build.gradle.kts @@ -34,7 +34,7 @@ tasks.shadowJar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE from(wrapperJar) { - // Rename the file to make sure 100% + // Rename the file to make sure 100% it is correctly named rename { Files.wrapper } } From 7002db4af159aed3eba4fc818e71b664c3af3dc6 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Thu, 17 Jul 2025 00:08:03 +0200 Subject: [PATCH 10/45] improve comment --- settings.gradle.kts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index aba1ff3aa7..228fbac935 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -121,8 +121,11 @@ val isCI = System.getenv("CI") != null develocity { buildScan { + // auto publishing build scans can be enabled by creating a file + // named "gradle.tos.agree" in the root directory with the ToS URL + // as content. val file = rootDir.resolve("gradle.tos.agree") - val agree = if (file.exists()) "yes" else "" + val agree = if (file.exists() && file.readText() == "https://gradle.com/help/legal-terms-of-use") "yes" else "" termsOfUseAgree = agree termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use" gradle.settingsEvaluated { From 081c46f732a76bc0b22e26a8342c71d816fcdba9 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Thu, 17 Jul 2025 01:04:51 +0200 Subject: [PATCH 11/45] use gradle sources+javadoc publishing --- .../src/main/kotlin/publishing-extensions.kt | 17 ++++++----------- .../src/main/kotlin/settings-plugin.kt | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/build-extensions/src/main/kotlin/publishing-extensions.kt b/build-extensions/src/main/kotlin/publishing-extensions.kt index 0b12b0be7a..eae400e924 100644 --- a/build-extensions/src/main/kotlin/publishing-extensions.kt +++ b/build-extensions/src/main/kotlin/publishing-extensions.kt @@ -25,17 +25,12 @@ import org.gradle.kotlin.dsl.withType import org.gradle.plugins.signing.Sign import org.gradle.plugins.signing.SigningExtension -fun Project.configurePublishing(publishedComponent: String, withJavadocAndSource: Boolean = false) { +fun Project.configurePublishing(publishedComponent: String) { extensions.configure { publications.apply { create("maven", MavenPublication::class.java).apply { from(components.getByName(publishedComponent)) - if (withJavadocAndSource) { - artifact(tasks.getByName("sourcesJar")) - artifact(tasks.getByName("javadocJar")) - } - pom.apply { name.set(project.name) description.set(project.description) @@ -64,19 +59,19 @@ fun Project.configurePublishing(publishedComponent: String, withJavadocAndSource scm { tag.set("HEAD") - url.set("git@github.com:CloudNetService/CloudNet-v3.git") - connection.set("scm:git:git@github.com:CloudNetService/CloudNet-v3.git") - developerConnection.set("scm:git:git@github.com:CloudNetService/CloudNet-v3.git") + url.set("git@github.com:CloudNetService/CloudNet.git") + connection.set("scm:git:git@github.com:CloudNetService/CloudNet.git") + developerConnection.set("scm:git:git@github.com:CloudNetService/CloudNet.git") } issueManagement { system.set("GitHub Issues") - url.set("https://github.com/CloudNetService/CloudNet-v3/issues") + url.set("https://github.com/CloudNetService/CloudNet/issues") } ciManagement { system.set("GitHub Actions") - url.set("https://github.com/CloudNetService/CloudNet-v3/actions") + url.set("https://github.com/CloudNetService/CloudNet/actions") } withXml { diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/settings-plugin.kt index 365bc7ad2d..ada1e0afa2 100644 --- a/build-extensions/src/main/kotlin/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/settings-plugin.kt @@ -219,7 +219,7 @@ class JavaProjects : Plugin { } // all these projects are publishing their java artifacts - configurePublishing("java", true) + configurePublishing("java") // create consumable artifacts for global javadoc configurations.consumable(CustomConfigurations.GLOBAL_JAVADOC_SOURCES) { From f1bf988ed223f9a97788f9cda6b5ead7dbe83ed2 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 00:48:34 +0200 Subject: [PATCH 12/45] specify shadowJar exactly --- modules/npcs/impl/build.gradle.kts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/modules/npcs/impl/build.gradle.kts b/modules/npcs/impl/build.gradle.kts index 3656a275e5..436ba94367 100644 --- a/modules/npcs/impl/build.gradle.kts +++ b/modules/npcs/impl/build.gradle.kts @@ -27,13 +27,7 @@ tasks.shadowJar.configure { manifest { attributes["paperweight-mappings-namespace"] = "mojang" } -} - -tasks.withType().configureEach { - options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/npcs.aero") -} -tasks.withType().configureEach { relocate("net.kyori", "eu.cloudnetservice.modules.npc.relocate.net.kyori") relocate("io.papermc.lib", "eu.cloudnetservice.modules.npc.relocate.paperlib") relocate("io.leangen.geantyref", "eu.cloudnetservice.modules.npc.relocate.geantyref") @@ -41,7 +35,6 @@ tasks.withType().configureEach { relocate("com.github.retrooper", "eu.cloudnetservice.modules.npc.relocate.com.packetevents") relocate("com.github.juliarn.npclib", "eu.cloudnetservice.modules.npc.relocate.com.github.juliarn.npclib") - archiveClassifier.set(null as String?) dependencies { exclude("plugin.yml") // excludes the META-INF directory, module infos & html files of all dependencies @@ -50,6 +43,10 @@ tasks.withType().configureEach { } } +tasks.withType().configureEach { + options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/npcs.aero") +} + repositories { maven("https://repo.codemc.io/repository/maven-releases/") { mavenContent { From 0e0479d488720e122b6430749069d384ccfdc425 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 20:27:03 +0200 Subject: [PATCH 13/45] ignore kotlin compiler daemon --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1d968cac66..4204f0427f 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ # gradle .gradle/ build/ +/.kotlin # gradle build scans /gradle.tos.agree From f4a074d66a5ab0a68fb842bd1135a012b4d5c32b Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 20:27:26 +0200 Subject: [PATCH 14/45] remove unused dependency on wrapperJvm --- modules/labymod/impl/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/labymod/impl/build.gradle.kts b/modules/labymod/impl/build.gradle.kts index 83cfcb4749..049d91eb64 100644 --- a/modules/labymod/impl/build.gradle.kts +++ b/modules/labymod/impl/build.gradle.kts @@ -24,7 +24,6 @@ tasks.shadowJar.configure { } dependencies { - "compileOnly"(projects.wrapperJvm) "compileOnly"(projects.node.nodeImpl) "compileOnly"(projects.driver.driverImpl) "compileOnly"(libs.bundles.proxyPlatform) From c55389709219f818982f893d9f8482c7add7ee60 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 22:07:33 +0200 Subject: [PATCH 15/45] add explanation for disabled isolated projects --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e4bf8fb30e..509e2e5a90 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ org.gradle.caching=true org.gradle.configuration-cache=true org.gradle.configureondemand=true org.gradle.parallel=true -#org.gradle.unsafe.isolated-projects=true +#org.gradle.unsafe.isolated-projects=true # blocked on spotless https://github.com/diffplug/spotless/issues/1979 org.gradle.warning.mode=all org.gradle.logging.level=warn org.gradle.jvmargs=-Xmx5G -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 From 20cc7b343400253a55d089a73c2bbda66bc7d29e Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 22:10:37 +0200 Subject: [PATCH 16/45] don't publish glue projects --- .../src/main/kotlin/publishing-extensions.kt | 33 +++++++---- .../src/main/kotlin/settings-plugin.kt | 56 ++++++++++--------- build.gradle.kts | 2 +- 3 files changed, 53 insertions(+), 38 deletions(-) diff --git a/build-extensions/src/main/kotlin/publishing-extensions.kt b/build-extensions/src/main/kotlin/publishing-extensions.kt index eae400e924..38cd0b5f4d 100644 --- a/build-extensions/src/main/kotlin/publishing-extensions.kt +++ b/build-extensions/src/main/kotlin/publishing-extensions.kt @@ -21,19 +21,32 @@ import org.gradle.api.publish.maven.MavenPublication import org.gradle.external.javadoc.JavadocMemberLevel import org.gradle.external.javadoc.StandardJavadocDocletOptions import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.withType import org.gradle.plugins.signing.Sign import org.gradle.plugins.signing.SigningExtension fun Project.configurePublishing(publishedComponent: String) { extensions.configure { + // pull this out because of configuration cache + val projectName = project.name + val projectDescription = project.description + + data class Repository(val id: String, val url: String) + + val selectedRepositories = project.repositories.filterIsInstance().filter { + it.url.scheme == "https" + }.map { + Repository(it.name, it.url.toString()) + } + publications.apply { - create("maven", MavenPublication::class.java).apply { + register("maven") { from(components.getByName(publishedComponent)) pom.apply { - name.set(project.name) - description.set(project.description) + name.set(projectName) + description.set(projectDescription) url.set("https://cloudnetservice.eu") developers { @@ -76,12 +89,10 @@ fun Project.configurePublishing(publishedComponent: String) { withXml { val repositories = asNode().appendNode("repositories") - project.repositories.forEach { - if (it is MavenArtifactRepository && it.url.toString().startsWith("https://")) { - val repo = repositories.appendNode("repository") - repo.appendNode("id", it.name) - repo.appendNode("url", it.url.toString()) - } + selectedRepositories.forEach { + val repo = repositories.appendNode("repository") + repo.appendNode("id", it.id) + repo.appendNode("url", it.url) } } } @@ -103,9 +114,11 @@ fun Project.configurePublishing(publishedComponent: String) { sign(extensions.getByType(PublishingExtension::class.java).publications.getByName("maven")) } + // pull this out because of configuration cache + val version = rootProject.version tasks.withType().configureEach { onlyIf { - !rootProject.version.toString().endsWith("-SNAPSHOT") + !version.toString().endsWith("-SNAPSHOT") } } } diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/settings-plugin.kt index ada1e0afa2..b63cd602c7 100644 --- a/build-extensions/src/main/kotlin/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/settings-plugin.kt @@ -40,22 +40,27 @@ import org.gradle.language.jvm.tasks.ProcessResources class SettingsPlugin : Plugin { override fun apply(settings: Settings) { settings.gradle.lifecycle.beforeProject { - println("configuring ${this.path}") // TODO remove, this is temporary to better debug any configuration done (configure-on-demand) plugins.apply(AllProjects::class) - if (this != this.rootProject) { + if (this != this.rootProject && !isHelperProject(this.path)) { + println("configuring ${this.path}") // TODO remove, this is temporary to better debug any configuration done (configure-on-demand) plugins.apply(JavaProjects::class) } } } } -fun isJavaConfiguredProject(name: String): Boolean { - if (isHelperProject(name)) return false +fun isJavaConfiguredProject(name: String, path: String): Boolean { + if (isHelperProject(path)) return false return name != "bom" } -fun isHelperProject(name: String): Boolean { - return name == "modules" || name == "plugins" || name == "ext" || name == "launcher" +fun isHelperProject(path: String): Boolean { + val guaranteedHelper = + path == ":modules" || path == ":plugins" || path == ":ext" || path == ":launcher" || path == ":node" || path == ":driver" || path == ":wrapper-jvm" + if (guaranteedHelper) return true + val couldBeHelper = path.startsWith(":modules:") || path.startsWith(":node:") || path.startsWith(":wrapper-jvm:") + val apiOrImpl = path.endsWith("-api") || path.endsWith("-impl") + return couldBeHelper && !apiOrImpl } object CustomConfigurations { @@ -84,13 +89,6 @@ internal val Project.libs: Provider class JavaProjects : Plugin { override fun apply(project: Project) { project.run { - - - // these are top level projects which are configured separately - if (isHelperProject(name)) { - return@run - } - // these are the plugins which we need to apply to all projects apply(plugin = "signing") apply(plugin = "maven-publish") @@ -98,7 +96,7 @@ class JavaProjects : Plugin { // skip further applying to bom - this project is a bit special as we're not allowed to // apply the java plugin to it (that's why we need to stop here, but we need to publish // at well (that's why we're applying the publish plugin) - if (!isJavaConfiguredProject(name)) { + if (!isJavaConfiguredProject(name, path)) { return@run } @@ -107,6 +105,19 @@ class JavaProjects : Plugin { apply(plugin = "com.diffplug.spotless") apply(plugin = "net.kyori.indra.git") + // declare repositories before plugins/modules sub-plugins + repositories { + releasesOnly(mavenCentral()) + snapshotsOnly(maven("https://central.sonatype.com/repository/maven-snapshots/")) + + // ensure that we use these repositories for snapshots/releases only (improves lookup times) + releasesOnly(maven("https://repository.derklaro.dev/releases/")) + snapshotsOnly(maven("https://repository.derklaro.dev/snapshots/")) + + // must be after sonatype as sponge mirrors sonatype which leads to outdated dependencies + maven("https://repo.spongepowered.org/maven/") + } + if (path.startsWith(":plugins:")) { apply() } @@ -219,7 +230,10 @@ class JavaProjects : Plugin { } // all these projects are publishing their java artifacts - configurePublishing("java") + // must happen after repository/dependency declaration + afterEvaluate { + configurePublishing("java") + } // create consumable artifacts for global javadoc configurations.consumable(CustomConfigurations.GLOBAL_JAVADOC_SOURCES) { @@ -238,18 +252,6 @@ class AllProjects : Plugin { this.version = Versions.cloudNet this.group = "eu.cloudnetservice.cloudnet" this.description = "A modern application that can dynamically and easily deliver Minecraft oriented software" - - this.repositories { - releasesOnly(mavenCentral()) - snapshotsOnly(maven("https://central.sonatype.com/repository/maven-snapshots/")) - - // ensure that we use these repositories for snapshots/releases only (improves lookup times) - releasesOnly(maven("https://repository.derklaro.dev/releases/")) - snapshotsOnly(maven("https://repository.derklaro.dev/snapshots/")) - - // must be after sonatype as sponge mirrors sonatype which leads to outdated dependencies - maven("https://repo.spongepowered.org/maven/") - } } } } diff --git a/build.gradle.kts b/build.gradle.kts index 9f8c885bc8..0ff58ed777 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -56,7 +56,7 @@ nexusPublishing { dependencies { subprojects.map { it.isolated }.forEach { project -> - if (!isJavaConfiguredProject(project.name)) return@forEach + if (!isJavaConfiguredProject(project.name, project.path)) return@forEach globalJavadocSources(this.project(project.path)) { targetConfiguration = CustomConfigurations.GLOBAL_JAVADOC_SOURCES } From 13af92af7d2bc287808782326540bbc3b8e5e41a Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 22:12:26 +0200 Subject: [PATCH 17/45] ignore whitespaces in gradle.tos.agree --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 228fbac935..ee04fc8a0a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -125,7 +125,7 @@ develocity { // named "gradle.tos.agree" in the root directory with the ToS URL // as content. val file = rootDir.resolve("gradle.tos.agree") - val agree = if (file.exists() && file.readText() == "https://gradle.com/help/legal-terms-of-use") "yes" else "" + val agree = if (file.exists() && file.readText().trim() == "https://gradle.com/help/legal-terms-of-use") "yes" else "" termsOfUseAgree = agree termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use" gradle.settingsEvaluated { From 32be022c4bdede380320faa74cdebb7be6fe9101 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 22:45:32 +0200 Subject: [PATCH 18/45] juppiter is config cache compatible, indra isn't... --- build-extensions/build.gradle.kts | 9 +++------ settings.gradle.kts | 9 ++------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/build-extensions/build.gradle.kts b/build-extensions/build.gradle.kts index ec09c718fe..05605f8a4a 100644 --- a/build-extensions/build.gradle.kts +++ b/build-extensions/build.gradle.kts @@ -25,14 +25,11 @@ kotlin.jvmToolchain(21) repositories { gradlePluginPortal() mavenCentral() - maven("https://repo.stellardrift.ca/repository/snapshots/") { - content { - includeGroup("net.kyori") - } - } + // TODO wait for indra to be configuration cache compatible + // maven("https://repo.stellardrift.ca/repository/snapshots/") { mavenLocal { content { - includeModule("eu.cloudnetservice.gradle", "juppiter") + includeGroup("net.kyori") } } } diff --git a/settings.gradle.kts b/settings.gradle.kts index ee04fc8a0a..a7e8940431 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,18 +21,13 @@ pluginManagement { includeBuild("build-extensions") repositories { gradlePluginPortal() -// maven("https://repo.stellardrift.ca/repository/snapshots/") { + // TODO wait for indra to be configuration cache compatible + // maven("https://repo.stellardrift.ca/repository/snapshots/") { mavenLocal { content { includeGroup("net.kyori") } } - mavenLocal { - content { - includeGroup("eu.cloudnetservice.juppiter") - includeGroup("eu.cloudnetservice.gradle") - } - } maven { name = "Fabric" url = uri("https://maven.fabricmc.net/") From 4d5727cf1ca7fcc0284de665677eb237e2a4c804 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 22:52:14 +0200 Subject: [PATCH 19/45] remove another withType() I missed --- ext/platform-inject-support/loader/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/platform-inject-support/loader/build.gradle.kts b/ext/platform-inject-support/loader/build.gradle.kts index b48781dd05..9d36e726f7 100644 --- a/ext/platform-inject-support/loader/build.gradle.kts +++ b/ext/platform-inject-support/loader/build.gradle.kts @@ -1,3 +1,5 @@ +import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin.Companion.shadowJar + /* * Copyright 2019-2024 CloudNetService team & contributors * @@ -24,7 +26,7 @@ val includeInJar = configurations.register("includeInJar") { isTransitive = false } -tasks.withType().configureEach { +tasks.jar { // copy over the final output file from(includeInJar) } From 115e11f731d9f6b48d69a540f58c3a78c5906405 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Wed, 30 Jul 2025 23:01:26 +0200 Subject: [PATCH 20/45] ignore .kotlin in build-extensions --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4204f0427f..98b97df15f 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ .gradle/ build/ /.kotlin +/build-extensions/.kotlin # gradle build scans /gradle.tos.agree From bf66f6c6a2ff2ac7d9d37e4e5548b9f369f11032 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Sat, 2 Aug 2025 01:01:42 +0200 Subject: [PATCH 21/45] idk a lot + gradle 9 cause we like gradle updates also a bunch of stuff left to do Seems to build at least so there's that --- bom/build.gradle.kts | 1 + build-extensions/build.gradle.kts | 35 ++- .../src/main/kotlin/CloudNetJavaApiPlugin.kt | 34 +++ .../src/main/kotlin/CloudNetJavaPlugin.kt | 275 ++++++++++++++++++ .../main/kotlin/CloudNetModulesApiPlugin.kt | 56 ++++ .../src/main/kotlin/CloudNetModulesPlugin.kt | 42 +++ .../src/main/kotlin/CloudNetPlugin.kt | 15 +- ...figuration.kt => CloudNetPluginsPlugin.kt} | 19 +- .../src/main/kotlin/CloudNetPublishPlugin.kt | 50 ++++ .../src/main/kotlin/CloudNetSettingsPlugin.kt | 10 +- build-extensions/src/main/kotlin/Versions.kt | 5 + .../cloudnet.parent-build-logic.gradle.kts | 2 +- .../src/main/kotlin/modules-configuration.kt | 71 ----- .../src/main/kotlin/publishing-extensions.kt | 22 +- .../src/main/kotlin/settings-plugin.kt | 201 +------------ build-extensions/src/main/kotlin/tasks.kt | 190 ++++++++---- build.gradle.kts | 19 +- driver/ap/build.gradle.kts | 4 + driver/api/build.gradle.kts | 4 + .../driver/service/ThreadSnapshot.java | 2 +- driver/impl/build.gradle.kts | 4 + ext/adventure-helper/build.gradle.kts | 4 + ext/bukkit-command/build.gradle.kts | 4 + ext/modlauncher/build.gradle.kts | 4 + .../api/build.gradle.kts | 4 + .../loader/build.gradle.kts | 4 + .../processor/build.gradle.kts | 4 + .../runtime/build.gradle.kts | 4 + ext/updater/build.gradle.kts | 3 + gradle.properties | 1 + gradle/wrapper/gradle-wrapper.properties | 4 +- launcher/build.gradle.kts | 15 - launcher/java22/build.gradle.kts | 1 + launcher/java8/build.gradle.kts | 7 +- launcher/patcher/build.gradle.kts | 4 + modules/bridge/api/build.gradle.kts | 5 + modules/bridge/impl/build.gradle.kts | 3 +- modules/build.gradle.kts | 15 - modules/cloudflare/api/build.gradle.kts | 4 + modules/cloudflare/build.gradle.kts | 15 - modules/cloudflare/impl/build.gradle.kts | 1 + .../database-mongodb/api}/build.gradle.kts | 6 +- modules/database-mongodb/build.gradle.kts | 15 - .../database-mongodb/impl/build.gradle.kts | 1 + modules/database-mysql/api/build.gradle.kts | 19 ++ modules/database-mysql/build.gradle.kts | 0 modules/database-mysql/impl/build.gradle.kts | 1 + .../dockerized-services/api/build.gradle.kts | 19 ++ modules/dockerized-services/build.gradle.kts | 0 .../dockerized-services/impl/build.gradle.kts | 1 + modules/influx/api/build.gradle.kts | 4 + modules/influx/build.gradle.kts | 15 - modules/influx/impl/build.gradle.kts | 1 + modules/labymod/api/build.gradle.kts | 4 + modules/labymod/build.gradle.kts | 15 - modules/labymod/impl/build.gradle.kts | 2 + modules/npcs/api/build.gradle.kts | 4 + modules/npcs/impl/build.gradle.kts | 2 +- modules/report/api/build.gradle.kts | 4 + modules/report/build.gradle.kts | 15 - modules/report/impl/build.gradle.kts | 1 + modules/signs/api/build.gradle.kts | 4 + modules/signs/impl/build.gradle.kts | 1 + .../smart/api}/build.gradle.kts | 5 +- modules/smart/build.gradle.kts | 0 modules/smart/impl/build.gradle.kts | 1 + modules/storage-s3/api/build.gradle.kts | 4 + modules/storage-s3/build.gradle.kts | 15 - modules/storage-s3/impl/build.gradle.kts | 1 + modules/storage-sftp/api/build.gradle.kts | 4 + modules/storage-sftp/build.gradle.kts | 15 - modules/storage-sftp/impl/build.gradle.kts | 1 + modules/syncproxy/api/build.gradle.kts | 5 + modules/syncproxy/build.gradle.kts | 15 - modules/syncproxy/impl/build.gradle.kts | 1 + node/api/build.gradle.kts | 4 + node/impl/build.gradle.kts | 3 +- plugins/luckperms/build.gradle.kts | 4 +- plugins/papi-expansion/build.gradle.kts | 4 + settings.gradle.kts | 2 +- utils/base/build.gradle.kts | 4 + utils/build.gradle.kts | 15 - wrapper-jvm/api/build.gradle.kts | 4 + wrapper-jvm/build.gradle.kts | 15 - wrapper-jvm/impl/build.gradle.kts | 19 +- 85 files changed, 884 insertions(+), 558 deletions(-) create mode 100644 build-extensions/src/main/kotlin/CloudNetJavaApiPlugin.kt create mode 100644 build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt create mode 100644 build-extensions/src/main/kotlin/CloudNetModulesApiPlugin.kt create mode 100644 build-extensions/src/main/kotlin/CloudNetModulesPlugin.kt rename ext/build.gradle.kts => build-extensions/src/main/kotlin/CloudNetPlugin.kt (56%) rename build-extensions/src/main/kotlin/{plugins-configuration.kt => CloudNetPluginsPlugin.kt} (70%) create mode 100644 build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt rename modules/bridge/build.gradle.kts => build-extensions/src/main/kotlin/CloudNetSettingsPlugin.kt (70%) delete mode 100644 build-extensions/src/main/kotlin/modules-configuration.kt delete mode 100644 launcher/build.gradle.kts delete mode 100644 modules/build.gradle.kts delete mode 100644 modules/cloudflare/build.gradle.kts rename {node => modules/database-mongodb/api}/build.gradle.kts (84%) delete mode 100644 modules/database-mongodb/build.gradle.kts delete mode 100644 modules/database-mysql/build.gradle.kts delete mode 100644 modules/dockerized-services/build.gradle.kts delete mode 100644 modules/influx/build.gradle.kts delete mode 100644 modules/labymod/build.gradle.kts delete mode 100644 modules/report/build.gradle.kts rename {ext/platform-inject-support => modules/smart/api}/build.gradle.kts (84%) delete mode 100644 modules/smart/build.gradle.kts delete mode 100644 modules/storage-s3/build.gradle.kts delete mode 100644 modules/storage-sftp/build.gradle.kts delete mode 100644 modules/syncproxy/build.gradle.kts delete mode 100644 utils/build.gradle.kts delete mode 100644 wrapper-jvm/build.gradle.kts diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index 14ca027072..34455b9977 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -16,6 +16,7 @@ plugins { id("java-platform") + id("cloudnet-publish") } dependencies { diff --git a/build-extensions/build.gradle.kts b/build-extensions/build.gradle.kts index 05605f8a4a..a619ec7822 100644 --- a/build-extensions/build.gradle.kts +++ b/build-extensions/build.gradle.kts @@ -35,6 +35,7 @@ repositories { } dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") implementation("net.kyori", "indra-git", "4.0.0-SNAPSHOT") implementation("com.google.code.gson", "gson", "2.13.1") @@ -45,9 +46,37 @@ dependencies { gradlePlugin { plugins { - register("settings-plugin") { - id = "settings-plugin" - implementationClass = "SettingsPlugin" + register("cloudnet") { + id = "cloudnet" + implementationClass = "CloudNetPlugin" + } + register("cloudnet-settings") { + id = "cloudnet-settings" + implementationClass = "CloudNetSettingsPlugin" + } + register("cloudnet-publish") { + id = "cloudnet-publish" + implementationClass = "CloudNetPublishPlugin" + } + register("cloudnet-java") { + id = "cloudnet-java" + implementationClass = "CloudNetJavaPlugin" + } + register("cloudnet-java-api") { + id = "cloudnet-java-api" + implementationClass = "CloudNetJavaApiPlugin" + } + register("cloudnet-modules") { + id = "cloudnet-modules" + implementationClass = "CloudNetModulesPlugin" + } + register("cloudnet-modules-api") { + id = "cloudnet-modules-api" + implementationClass = "CloudNetModulesApiPlugin" + } + register("cloudnet-plugins") { + id = "cloudnet-plugins" + implementationClass = "CloudNetPluginsPlugin" } } } diff --git a/build-extensions/src/main/kotlin/CloudNetJavaApiPlugin.kt b/build-extensions/src/main/kotlin/CloudNetJavaApiPlugin.kt new file mode 100644 index 0000000000..67b1143f0b --- /dev/null +++ b/build-extensions/src/main/kotlin/CloudNetJavaApiPlugin.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.withType + +class CloudNetJavaApiPlugin: Plugin { + override fun apply(project: Project) { + project.run { + apply() + + tasks.withType().configureEach { + sourceCompatibility = Versions.javaVersionApi.asInt().toString() + targetCompatibility = Versions.javaVersionApi.asInt().toString() + } + } + } +} diff --git a/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt b/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt new file mode 100644 index 0000000000..d8ca98a8bd --- /dev/null +++ b/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt @@ -0,0 +1,275 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.diffplug.gradle.spotless.SpotlessExtension +import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin +import org.apache.tools.ant.filters.ReplaceTokens +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.file.DuplicatesStrategy +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.plugins.quality.Checkstyle +import org.gradle.api.plugins.quality.CheckstyleExtension +import org.gradle.api.tasks.JavaExec +import org.gradle.api.tasks.Sync +import org.gradle.api.tasks.bundling.Jar +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.api.tasks.testing.Test +import org.gradle.jvm.toolchain.JavaLanguageVersion +import org.gradle.jvm.toolchain.JavaToolchainService +import org.gradle.jvm.toolchain.JavaToolchainSpec +import org.gradle.jvm.toolchain.JvmVendorSpec +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.assign +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.exclude +import org.gradle.kotlin.dsl.filter +import org.gradle.kotlin.dsl.getByType +import org.gradle.kotlin.dsl.hasPlugin +import org.gradle.kotlin.dsl.maven +import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.repositories +import org.gradle.kotlin.dsl.withType + +class CloudNetJavaPlugin : Plugin { + override fun apply(project: Project) { + project.run { + apply() + apply() + + apply(plugin = "checkstyle") + apply(plugin = "java-library") + apply(plugin = "com.diffplug.spotless") +// apply(plugin = "net.kyori.indra.git") + + // Add common repositories required in all projects + this.addDefaultRepositories() + // Add common dependencies required in all projects + this.addDefaultDependencies() + + this.includeLicenseInJar() + + // By default, all projects use the latest java version. + // This may be overwritten by API-projects + this.configureJavaVersion(Versions.javaVersion) + + this.configureTestTasks() + + this.configureCompileJava() + + afterEvaluate { + // Configure shadow after the subproject has been able to even apply it + this.configureShadow() + } + + this.configureCheckstyle() + + this.configureSpotless() + + // TODO find a better name + this.configureJavaVersionTasks() + } + } +} + +// We need the jvmArgs to run JVMs in multiple places +private val cloudNetJvmArgs = arrayOf( + "--enable-preview", + "-XX:+EnableDynamicAgentLoading", + "--enable-native-access=ALL-UNNAMED", + "--add-opens=java.base/java.lang.invoke=ALL-UNNAMED" +) + +private fun Project.addDefaultRepositories() { + repositories { + releasesOnly(mavenCentral()) + snapshotsOnly(maven("https://central.sonatype.com/repository/maven-snapshots/")) + + // ensure that we use these repositories for snapshots/releases only (improves lookup times) + releasesOnly(maven("https://repository.derklaro.dev/releases/")) + snapshotsOnly(maven("https://repository.derklaro.dev/snapshots/")) + + // must be after sonatype as sponge mirrors sonatype which leads to outdated dependencies + maven("https://repo.spongepowered.org/maven/") + } +} + +/** + * Adds default dependencies like annotation processors and testing + */ +private fun Project.addDefaultDependencies() { + val libs = this.libs + + afterEvaluate { + dependencies { + // lombok + "compileOnly"(libs.library("lombok")) + "annotationProcessor"(libs.library("lombok")) + // annotations + "compileOnly"(libs.library("annotations")) + // testing + "testImplementation"(libs.library("mockito")) + "testRuntimeOnly"(libs.library("junitLauncher")) + "testImplementation"(libs.bundle("junit")) + "testImplementation"(libs.bundle("testContainers")) + } + } + + configurations.configureEach { + // unsure why but every project loves them, and they literally have an import for every letter I type - beware + exclude("org.checkerframework", "checker-qual") + } +} + +private fun Project.includeLicenseInJar() { + tasks.withType().configureEach { + from(isolated.rootProject.projectDirectory.file("LICENSE")) + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } +} + +private fun Project.configureTestTasks() { + tasks.withType().configureEach { + useJUnitPlatform() + testLogging { + events("started", "passed", "skipped", "failed") + } + + // allow dynamic agent loading for mockito + jvmArgs(*cloudNetJvmArgs) + + // always pass down all given system properties + systemProperties(System.getProperties().mapKeys { it.key.toString() }) + } +} + +private fun Project.configureCompileJava() { + tasks.withType().configureEach { + options.encoding = "UTF-8" + options.isIncremental = true + + if (project.path != ":launcher:java8" && project.path != ":launcher:patcher" && !project.path.contains("api")) { + options.compilerArgs.add("--enable-preview") + options.compilerArgs.add("-Xlint:-deprecation,-unchecked,-preview") + options.compilerArgs.add("-proc:full") + } + } +} + +private fun Project.configureShadow() { + if (plugins.hasPlugin(ShadowJavaPlugin::class)) { + tasks.named("assemble").configure { + dependsOn(tasks.named("shadowJar")) + } + tasks.named("jar").configure { + // we use the shadow jar task, so move the jar into the task's temporary dir to avoid clutter + destinationDirectory = temporaryDir + } + } +} + +/** + * This may seem somewhat odd. + * When running JavaExec tasks from IntelliJ, sometimes to quickly run a snippet of code with a main() method, + * the JavaExec tasks will often have the wrong java version and fail. So we override them + */ +private fun Project.configureJavaVersionTasks() { + // This must be inside withPlugin("java-base") or else the extensions won't be registered yet + pluginManager.withPlugin("java-base") { + val extension = extensions.getByType() + val service = extensions.getByType() + val launcher = service.launcherFor(extension.toolchain) + val latestLauncher = service.launcherFor { this.configureFor(Versions.javaVersion) } + val javadoc = service.javadocToolFor { this.configureFor(Versions.javaVersion) } + + tasks.withType().configureEach { + javaLauncher = latestLauncher + } + + tasks.withType().configureEach { + javaLauncher = latestLauncher + } + + tasks.withType().configureEach { + javaLauncher = launcher + jvmArgs(*cloudNetJvmArgs) + } + + tasks.withType().configureEach { + javadocTool = javadoc + options.source = Versions.javaVersion.asInt().toString() + } + } +} + +private fun Project.configureCheckstyle() { + + tasks.withType().configureEach { + maxErrors = 0 + maxWarnings = 0 + configFile = project.isolated.rootProject.projectDirectory.file("checkstyle.xml").asFile + } + + // TODO investigate why this afterEvaluate exists + afterEvaluate { + extensions.configure { + toolVersion = libs.map { it.findVersion("checkstyleTools").orElseThrow().requiredVersion }.get() + } + } +} + +private fun Project.configureSpotless() { + extensions.configure { + java { + licenseHeaderFile(rootProject.file("LICENSE_HEADER")) + } + } +} + +// ---------------------------------------------------- +// - helpers used in other plugins - +// ---------------------------------------------------- + +internal fun Project.registerProcessSources() { + val processSources = tasks.register("processSources") { + inputs.property("version", project.version) + from(sourceSets().named("main").map { it.java }) + into(layout.buildDirectory.dir("src")) + filter(ReplaceTokens::class, mapOf("tokens" to mapOf("version" to project.version))) + } + tasks.named("compileJava") { + dependsOn(processSources) + setSource(processSources) + } +} + +// ---------------------------------------------------- +// - publicly visible api - +// ---------------------------------------------------- + +fun JavaToolchainSpec.configureFor(version: JavaLanguageVersion) { + this.languageVersion = version + this.vendor = JvmVendorSpec.ADOPTIUM +} + +fun Project.configureJavaVersion(version: JavaLanguageVersion) { + this.extensions.configure { + this.toolchain.configureFor(version) + } +} diff --git a/build-extensions/src/main/kotlin/CloudNetModulesApiPlugin.kt b/build-extensions/src/main/kotlin/CloudNetModulesApiPlugin.kt new file mode 100644 index 0000000000..13177cbbe0 --- /dev/null +++ b/build-extensions/src/main/kotlin/CloudNetModulesApiPlugin.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.* + +class CloudNetModulesApiPlugin : Plugin { + override fun apply(project: Project) { + project.run { + apply() + + configureModules() + } + } +} + +internal fun Project.configureModules() { + repositories { + maven("https://repo.waterdog.dev/releases/") + maven("https://repo.waterdog.dev/snapshots/") + maven("https://repo.loohpjames.com/repository") + maven("https://repo.md-5.net/repository/releases/") + maven("https://repo.md-5.net/repository/snapshots/") + maven("https://repo.opencollab.dev/maven-releases/") + maven("https://repo.opencollab.dev/maven-snapshots/") + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + } + + dependencies { + "compileOnly"(project(":node:node-api")) + "testImplementation"(project(":node:node-api")) + + // generation for platform main classes + "compileOnly"(project(":ext:platform-inject-support:platform-inject-api")) + "annotationProcessor"(project(":ext:platform-inject-support:platform-inject-processor")) + + "compileOnly"(libs.library("guava")) + } + + registerProcessSources() +} diff --git a/build-extensions/src/main/kotlin/CloudNetModulesPlugin.kt b/build-extensions/src/main/kotlin/CloudNetModulesPlugin.kt new file mode 100644 index 0000000000..a655e494a1 --- /dev/null +++ b/build-extensions/src/main/kotlin/CloudNetModulesPlugin.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import eu.cloudnetservice.gradle.juppiter.JuppiterPlugin +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.invoke +import org.gradle.kotlin.dsl.maven +import org.gradle.kotlin.dsl.project +import org.gradle.kotlin.dsl.repositories + +class CloudNetModulesPlugin : Plugin { + override fun apply(project: Project) { + project.run { + apply() + apply() + + configurations { + named("testImplementation").configure { + extendsFrom(getByName("moduleLibrary")) + } + } + + configureModules() + } + } +} diff --git a/ext/build.gradle.kts b/build-extensions/src/main/kotlin/CloudNetPlugin.kt similarity index 56% rename from ext/build.gradle.kts rename to build-extensions/src/main/kotlin/CloudNetPlugin.kt index d2d9f18709..e6e781d2d9 100644 --- a/ext/build.gradle.kts +++ b/build-extensions/src/main/kotlin/CloudNetPlugin.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 CloudNetService team & contributors + * Copyright 2019-2025 CloudNetService team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,3 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class CloudNetPlugin : Plugin { + override fun apply(project: Project) { + project.run { + this.version = Versions.cloudNet + this.group = "eu.cloudnetservice.cloudnet" + this.description = "A modern application that can dynamically and easily deliver Minecraft oriented software" + } + } +} diff --git a/build-extensions/src/main/kotlin/plugins-configuration.kt b/build-extensions/src/main/kotlin/CloudNetPluginsPlugin.kt similarity index 70% rename from build-extensions/src/main/kotlin/plugins-configuration.kt rename to build-extensions/src/main/kotlin/CloudNetPluginsPlugin.kt index ed29cbf8ca..c1d0060ade 100644 --- a/build-extensions/src/main/kotlin/plugins-configuration.kt +++ b/build-extensions/src/main/kotlin/CloudNetPluginsPlugin.kt @@ -14,16 +14,15 @@ * limitations under the License. */ -import org.apache.tools.ant.filters.ReplaceTokens import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.tasks.Sync -import org.gradle.api.tasks.compile.JavaCompile import org.gradle.kotlin.dsl.* -class PluginGradlePlugin : Plugin { +class CloudNetPluginsPlugin : Plugin { override fun apply(project: Project) { project.run { + apply() + repositories { maven("https://repo.waterdog.dev/releases/") maven("https://repo.waterdog.dev/snapshots/") @@ -43,17 +42,7 @@ class PluginGradlePlugin : Plugin { "annotationProcessor"(project(":ext:platform-inject-support:platform-inject-processor")) } - tasks.register("processSources") { - inputs.property("version", project.version) - from(sourceSets().getByName("main").java) - into(layout.buildDirectory.dir("src")) - filter(ReplaceTokens::class, mapOf("tokens" to mapOf("version" to rootProject.version))) - } - - tasks.named("compileJava") { - dependsOn(tasks.getByName("processSources")) - source = tasks.getByName("processSources").outputs.files.asFileTree - } + registerProcessSources() } } } diff --git a/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt b/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt new file mode 100644 index 0000000000..886e915b72 --- /dev/null +++ b/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.plugins.JavaPlugin +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.hasPlugin + +class CloudNetPublishPlugin : Plugin { + override fun apply(project: Project) { + project.run { + apply() + + // these are the plugins which we need to apply to all projects + apply(plugin = "signing") + apply(plugin = "maven-publish") + + // all these projects are publishing their java artifacts + // must happen after repository/dependency declaration + afterEvaluate { + if (plugins.hasPlugin(JavaBasePlugin::class)) { + configurePublishing("java") + + // create consumable artifacts for global javadoc + configurations.consumable(CustomConfigurations.GLOBAL_JAVADOC_SOURCES) { + outgoing.artifacts(sourceSets().named("main").map { it.allJava.srcDirs }) + } + configurations.consumable(CustomConfigurations.GLOBAL_JAVADOC_CLASSPATH) { + outgoing.artifacts(sourceSets().named("main").map { it.compileClasspath }) + } + } + } + } + } +} diff --git a/modules/bridge/build.gradle.kts b/build-extensions/src/main/kotlin/CloudNetSettingsPlugin.kt similarity index 70% rename from modules/bridge/build.gradle.kts rename to build-extensions/src/main/kotlin/CloudNetSettingsPlugin.kt index d2d9f18709..1459b96ff3 100644 --- a/modules/bridge/build.gradle.kts +++ b/build-extensions/src/main/kotlin/CloudNetSettingsPlugin.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 CloudNetService team & contributors + * Copyright 2019-2025 CloudNetService team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,3 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import org.gradle.api.Plugin +import org.gradle.api.initialization.Settings + +class CloudNetSettingsPlugin : Plugin { + override fun apply(target: Settings) { + } +} diff --git a/build-extensions/src/main/kotlin/Versions.kt b/build-extensions/src/main/kotlin/Versions.kt index 31844583e0..15b7f2d911 100644 --- a/build-extensions/src/main/kotlin/Versions.kt +++ b/build-extensions/src/main/kotlin/Versions.kt @@ -14,9 +14,14 @@ * limitations under the License. */ +import org.gradle.jvm.toolchain.JavaLanguageVersion + object Versions { // internal versions const val cloudNet = "4.0.0-RC14-SNAPSHOT" const val cloudNetCodeName = "Blizzard" + + val javaVersionApi = JavaLanguageVersion.of(17) + val javaVersion = JavaLanguageVersion.of(24) } diff --git a/build-extensions/src/main/kotlin/cloudnet.parent-build-logic.gradle.kts b/build-extensions/src/main/kotlin/cloudnet.parent-build-logic.gradle.kts index 495bcb1144..1cdc4873f8 100644 --- a/build-extensions/src/main/kotlin/cloudnet.parent-build-logic.gradle.kts +++ b/build-extensions/src/main/kotlin/cloudnet.parent-build-logic.gradle.kts @@ -15,5 +15,5 @@ */ plugins { - id("net.kyori.indra.git") +// id("net.kyori.indra.git") } diff --git a/build-extensions/src/main/kotlin/modules-configuration.kt b/build-extensions/src/main/kotlin/modules-configuration.kt deleted file mode 100644 index ec4dc50e74..0000000000 --- a/build-extensions/src/main/kotlin/modules-configuration.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019-2025 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.apache.tools.ant.filters.ReplaceTokens -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.tasks.Sync -import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.kotlin.dsl.* - -class ModuleGradlePlugin : Plugin { - override fun apply(project: Project) { - project.run { - if (name.endsWith("impl")) { - apply(plugin = "eu.cloudnetservice.juppiter") - - configurations { - getByName("testImplementation").extendsFrom(getByName("moduleLibrary")) - } - } - - repositories { - maven("https://repo.waterdog.dev/releases/") - maven("https://repo.waterdog.dev/snapshots/") - maven("https://repo.loohpjames.com/repository") - maven("https://repo.md-5.net/repository/releases/") - maven("https://repo.md-5.net/repository/snapshots/") - maven("https://repo.opencollab.dev/maven-releases/") - maven("https://repo.opencollab.dev/maven-snapshots/") - maven("https://repo.papermc.io/repository/maven-public/") - maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") - } - - dependencies { - "compileOnly"(project(":node:node-api")) - "testImplementation"(project(":node:node-api")) - - // generation for platform main classes - "compileOnly"(project(":ext:platform-inject-support:platform-inject-api")) - "annotationProcessor"(project(":ext:platform-inject-support:platform-inject-processor")) - - "compileOnly"(libs.library("guava")) - } - - tasks.register("processSources") { - inputs.property("version", project.version) - from(sourceSets().getByName("main").java) - into(layout.buildDirectory.dir("src")) - filter(ReplaceTokens::class, mapOf("tokens" to mapOf("version" to rootProject.version))) - } - - tasks.named("compileJava") { - dependsOn(tasks.getByName("processSources")) - source = tasks.getByName("processSources").outputs.files.asFileTree - } - } - } -} diff --git a/build-extensions/src/main/kotlin/publishing-extensions.kt b/build-extensions/src/main/kotlin/publishing-extensions.kt index 38cd0b5f4d..3148b8db61 100644 --- a/build-extensions/src/main/kotlin/publishing-extensions.kt +++ b/build-extensions/src/main/kotlin/publishing-extensions.kt @@ -16,11 +16,15 @@ import org.gradle.api.Project import org.gradle.api.artifacts.repositories.MavenArtifactRepository +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.javadoc.Javadoc import org.gradle.external.javadoc.JavadocMemberLevel import org.gradle.external.javadoc.StandardJavadocDocletOptions import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.hasPlugin import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.withType import org.gradle.plugins.signing.Sign @@ -115,19 +119,33 @@ fun Project.configurePublishing(publishedComponent: String) { } // pull this out because of configuration cache - val version = rootProject.version + val version = this.version tasks.withType().configureEach { onlyIf { !version.toString().endsWith("-SNAPSHOT") } } + + if (plugins.hasPlugin(JavaBasePlugin::class)) { + extensions.configure { + withSourcesJar() + withJavadocJar() + } + configureJavadoc() + } +} + +private fun Project.configureJavadoc() { + tasks.withType().configureEach { + val options = options as? StandardJavadocDocletOptions ?: return@configureEach + applyDefaultJavadocOptions(options) + } } fun applyDefaultJavadocOptions(options: StandardJavadocDocletOptions) { options.use() options.encoding = "UTF-8" options.memberLevel = JavadocMemberLevel.PRIVATE - options.addStringOption("source", "24") options.addBooleanOption("-enable-preview", true) options.addBooleanOption("Xdoclint:-missing", true) options.links( diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/settings-plugin.kt index b63cd602c7..f96a5b533b 100644 --- a/build-extensions/src/main/kotlin/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/settings-plugin.kt @@ -14,40 +14,13 @@ * limitations under the License. */ -import com.diffplug.gradle.spotless.SpotlessExtension -import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin -import org.gradle.api.JavaVersion -import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.ExternalModuleDependencyBundle import org.gradle.api.artifacts.MinimalExternalModuleDependency import org.gradle.api.artifacts.VersionCatalog import org.gradle.api.artifacts.VersionCatalogsExtension -import org.gradle.api.file.DuplicatesStrategy -import org.gradle.api.initialization.Settings -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.api.plugins.quality.Checkstyle -import org.gradle.api.plugins.quality.CheckstyleExtension import org.gradle.api.provider.Provider -import org.gradle.api.tasks.bundling.Jar -import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.api.tasks.javadoc.Javadoc -import org.gradle.api.tasks.testing.Test -import org.gradle.external.javadoc.StandardJavadocDocletOptions -import org.gradle.kotlin.dsl.* -import org.gradle.language.jvm.tasks.ProcessResources - -class SettingsPlugin : Plugin { - override fun apply(settings: Settings) { - settings.gradle.lifecycle.beforeProject { - plugins.apply(AllProjects::class) - if (this != this.rootProject && !isHelperProject(this.path)) { - println("configuring ${this.path}") // TODO remove, this is temporary to better debug any configuration done (configure-on-demand) - plugins.apply(JavaProjects::class) - } - } - } -} +import org.gradle.kotlin.dsl.getByName fun isJavaConfiguredProject(name: String, path: String): Boolean { if (isHelperProject(path)) return false @@ -56,7 +29,7 @@ fun isJavaConfiguredProject(name: String, path: String): Boolean { fun isHelperProject(path: String): Boolean { val guaranteedHelper = - path == ":modules" || path == ":plugins" || path == ":ext" || path == ":launcher" || path == ":node" || path == ":driver" || path == ":wrapper-jvm" + path == ":modules" || path == ":plugins" || path == ":ext" || path == ":launcher" || path == ":node" || path == ":driver" || path == ":wrapper-jvm" || path == ":utils" || path == ":ext:platform-inject-support" if (guaranteedHelper) return true val couldBeHelper = path.startsWith(":modules:") || path.startsWith(":node:") || path.startsWith(":wrapper-jvm:") val apiOrImpl = path.endsWith("-api") || path.endsWith("-impl") @@ -85,173 +58,3 @@ internal fun Provider.bundle(name: String): Provider get() = provider { extensions.getByName("versionCatalogs").named("libs") } - -class JavaProjects : Plugin { - override fun apply(project: Project) { - project.run { - // these are the plugins which we need to apply to all projects - apply(plugin = "signing") - apply(plugin = "maven-publish") - - // skip further applying to bom - this project is a bit special as we're not allowed to - // apply the java plugin to it (that's why we need to stop here, but we need to publish - // at well (that's why we're applying the publish plugin) - if (!isJavaConfiguredProject(name, path)) { - return@run - } - - apply(plugin = "checkstyle") - apply(plugin = "java-library") - apply(plugin = "com.diffplug.spotless") - apply(plugin = "net.kyori.indra.git") - - // declare repositories before plugins/modules sub-plugins - repositories { - releasesOnly(mavenCentral()) - snapshotsOnly(maven("https://central.sonatype.com/repository/maven-snapshots/")) - - // ensure that we use these repositories for snapshots/releases only (improves lookup times) - releasesOnly(maven("https://repository.derklaro.dev/releases/")) - snapshotsOnly(maven("https://repository.derklaro.dev/snapshots/")) - - // must be after sonatype as sponge mirrors sonatype which leads to outdated dependencies - maven("https://repo.spongepowered.org/maven/") - } - - if (path.startsWith(":plugins:")) { - apply() - } - if (path.startsWith(":modules:")) { - apply() - } - - val libs = this.libs - - afterEvaluate { - dependencies { - // the 'rootProject.libs.' prefix is needed here - see https://github.com/gradle/gradle/issues/16634 - // lombok - "compileOnly"(libs.library("lombok")) - "annotationProcessor"(libs.library("lombok")) - // annotations - "compileOnly"(libs.library("annotations")) - // testing - "testImplementation"(libs.library("mockito")) - "testRuntimeOnly"(libs.library("junitLauncher")) - "testImplementation"(libs.bundle("junit")) - "testImplementation"(libs.bundle("testContainers")) - } - } - - configurations.all { - // unsure why but every project loves them, and they literally have an import for every letter I type - beware - exclude("org.checkerframework", "checker-qual") - } - - tasks.withType().configureEach { - from(rootProject.file("LICENSE")) - duplicatesStrategy = DuplicatesStrategy.INCLUDE - } - - tasks.withType().configureEach { - useJUnitPlatform() - testLogging { - events("started", "passed", "skipped", "failed") - } - - // allow dynamic agent loading for mockito - jvmArgs( - "--enable-preview", - "-XX:+EnableDynamicAgentLoading", - "--enable-native-access=ALL-UNNAMED", - "--add-opens=java.base/java.lang.invoke=ALL-UNNAMED" - ) - - // always pass down all given system properties - systemProperties(System.getProperties().mapKeys { it.key.toString() }) - } - - tasks.withType().configureEach { - val javaVersion = if (project.path.contains("api")) JavaVersion.VERSION_17 else JavaVersion.VERSION_24 - sourceCompatibility = javaVersion.toString() - targetCompatibility = javaVersion.toString() - - options.encoding = "UTF-8" - options.isIncremental = true - - if (project.path != ":launcher:java8" && project.path != ":launcher:patcher" && !project.path.contains("api")) { - options.compilerArgs.add("--enable-preview") - options.compilerArgs.add("-Xlint:-deprecation,-unchecked,-preview") - options.compilerArgs.add("-proc:full") - } - } - - project.afterEvaluate { - if (project.plugins.hasPlugin(ShadowJavaPlugin::class)) { - tasks.named("assemble").configure { - dependsOn(project.tasks.named("shadowJar")) - } - tasks.named("jar").configure { - // we use the shadow jar task, so move the jar into the task's temporary dir to avoid clutter - destinationDirectory = temporaryDir - } - } - } - - tasks.withType().configureEach { - maxErrors = 0 - maxWarnings = 0 - configFile = rootProject.file("checkstyle.xml") - } - - afterEvaluate { - extensions.configure { - toolVersion = libs.map { it.findVersion("checkstyleTools").orElseThrow().requiredVersion }.get() - } - } - - extensions.configure { - java { - licenseHeaderFile(rootProject.file("LICENSE_HEADER")) - } - } - - val java = project.extensions.getByType() - java.withSourcesJar() - java.withJavadocJar() - - tasks.withType().configureEach { - val options = options as? StandardJavadocDocletOptions ?: return@configureEach - applyDefaultJavadocOptions(options) - } - - tasks.withType().configureEach { - dependsOn(tasks.withType()) - } - - // all these projects are publishing their java artifacts - // must happen after repository/dependency declaration - afterEvaluate { - configurePublishing("java") - } - - // create consumable artifacts for global javadoc - configurations.consumable(CustomConfigurations.GLOBAL_JAVADOC_SOURCES) { - outgoing.artifacts(sourceSets().named("main").map { it.allJava.srcDirs }) - } - configurations.consumable(CustomConfigurations.GLOBAL_JAVADOC_CLASSPATH) { - outgoing.artifacts(sourceSets().named("main").map { it.compileClasspath }) - } - } - } -} - -class AllProjects : Plugin { - override fun apply(project: Project) { - project.run { - this.version = Versions.cloudNet - this.group = "eu.cloudnetservice.cloudnet" - this.description = "A modern application that can dynamically and easily deliver Minecraft oriented software" - } - } -} diff --git a/build-extensions/src/main/kotlin/tasks.kt b/build-extensions/src/main/kotlin/tasks.kt index c3a13a5a55..bcb31b9b74 100644 --- a/build-extensions/src/main/kotlin/tasks.kt +++ b/build-extensions/src/main/kotlin/tasks.kt @@ -16,9 +16,18 @@ @file:Suppress("LeakingThis") +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.component.ComponentArtifactIdentifier +import org.gradle.api.artifacts.component.ModuleComponentIdentifier +import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.artifacts.repositories.MavenArtifactRepository +import org.gradle.api.artifacts.result.ResolvedVariantResult import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.ProjectLayout import org.gradle.api.file.RegularFileProperty @@ -26,10 +35,15 @@ import org.gradle.api.internal.artifacts.repositories.resolver.MavenUniqueSnapsh import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.* +import org.gradle.internal.component.external.model.DefaultModuleComponentArtifactIdentifier import org.gradle.kotlin.dsl.listProperty +import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.setProperty +import org.gradle.workers.WorkAction +import org.gradle.workers.WorkParameters import java.io.File import java.net.HttpURLConnection import java.net.URI @@ -50,43 +64,84 @@ abstract class ExportCnlFile : DefaultTask() { val outputFile: RegularFileProperty = objects.fileProperty() @Nested - val mavenRepositories: ListProperty = objects.listProperty() + val dependencies: ListProperty = objects.listProperty() @Nested - val resolvedArtifacts: SetProperty = objects.setProperty() + val mavenRepositories: ListProperty = objects.listProperty() + + @Input + val projectGroup: Property = objects.property() @get: Inject internal abstract val layout: ProjectLayout + private val repositoryComparator = + Comparator.comparing { it.name }.thenComparing { it.url } + init { + // Evaluate group lazily + projectGroup.set(project.provider { project.group.toString() }) outputFile.convention(layout.file(fileName.map { temporaryDir.resolve(it) })) mavenRepositories.convention(project.mavenRepositories().map { CacheableMavenRepository(it) }.toList()) } - fun setResolvedArtifacts(runtimeClasspath: Configuration) { - val artifacts = runtimeClasspath.resolvedConfiguration.resolvedArtifacts.map { - val group = it.moduleVersion.id.group - val name = it.moduleVersion.id.name - val version = it.moduleVersion.id.version + fun setResolvedArtifacts(runtimeClasspath: Provider) { + val resolved = runtimeClasspath.flatMap { it.incoming.artifacts.resolvedArtifacts } + + dependencies.set(resolved.map { set -> + set.map { + val file = it.file + val id = it.id + val variant = it.variant + CacheableResolvedArtifact(id, variant, file) + }.filter { + // Filter out all subprojects + it.id.componentIdentifier !is ProjectComponentIdentifier + } + }) + } + + @TaskAction + fun run() { +// this.dependencies.get().dependents.forEach { +// println(it) +// } + val resolvedArtifacts = ArrayList() + println("---------------------") + val projectGroup = projectGroup.get() + dependencies.get().forEach { it -> + val id = it.id + val componentIdentifier = id.componentIdentifier + + if (componentIdentifier !is ModuleComponentIdentifier) { + // Throw an error to make this future-proof. In case any weird unsupported new dependency is introduced, + // this will catch that. + error("Unexpected dependency type: $componentIdentifier: ${componentIdentifier.javaClass.name}") + } + + val group = componentIdentifier.moduleIdentifier.group + // Ignore all CloudNet projects + if (group == projectGroup) return@forEach + val name = componentIdentifier.moduleIdentifier.name + val version = componentIdentifier.version + val file = it.file + val timestampedVersion = - if (version.endsWith("-SNAPSHOT") && it.id.componentIdentifier is MavenUniqueSnapshotComponentIdentifier) { + if (version.endsWith("-SNAPSHOT") && componentIdentifier is MavenUniqueSnapshotComponentIdentifier) { // little hack to get the timestamped ("snapshot") version of the identifier - (it.id.componentIdentifier as MavenUniqueSnapshotComponentIdentifier).timestampedVersion + componentIdentifier.timestampedVersion } else version - val classifier = it.classifier - val file = it.file - CacheableResolvedArtifact(group, name, version, timestampedVersion, classifier, file) - }.filter { - it.group != project.group - }.toSet() - this.resolvedArtifacts.set(artifacts) - } + val classifier = if (id is DefaultModuleComponentArtifactIdentifier) { + // hack to get the classifier + id.name.classifier + } else "" + + resolvedArtifacts.add(ResolvedArtifact(group, name, version, timestampedVersion, classifier, file)) + } - @TaskAction - fun run() { val ignoredDependencyGroups = this.ignoredDependencyGroups.get() - val mavenRepositories = this.mavenRepositories.get() + val mavenRepositories = ArrayList(this.mavenRepositories.get()).apply { sortWith(repositoryComparator) } val stringBuilder = StringBuilder("# CloudNet ${Versions.cloudNetCodeName} ${Versions.cloudNet}\n\n").append("# repositories\n") @@ -97,26 +152,29 @@ abstract class ExportCnlFile : DefaultTask() { // add all dependencies stringBuilder.append("\n\n# dependencies\n") - resolvedArtifacts.get().forEach { - // get the module version from the artifact, stop if the dependency is ignored - if (ignoredDependencyGroups.contains(it.group)) { - return@forEach - } - // try to find the repository associated with the module - val path = "${it.group.replace('.', '/')}/${it.name}/${it.version}/${it.name}-${it.timestampedVersion}.jar" - val repository = resolveRepository( - path, mavenRepositories - ) ?: throw IllegalStateException( - "Unable to resolve repository for $it.\nSearched in ${ - mavenRepositories.joinToString( - separator = "\n" - ) { r -> r.url + path } - }") - - // add the repository - val cs = ChecksumHelper.fileShaSum(it.file) - stringBuilder.append("include ${repository.name} ${it.group} ${it.name} ${it.version} ${it.timestampedVersion} $cs ${it.classifier ?: ""}\n") + val deps = resolvedArtifacts.filter { !ignoredDependencyGroups.contains(it.group) } + + runBlocking { + deps.map { + async { + // try to find the repository associated with the module + val path = "${it.group.replace('.', '/')}/${it.name}/${it.version}/${it.name}-${it.timestampedVersion}.jar" + val repository = + resolveRepository(path, mavenRepositories) ?: throw IllegalStateException( + "Unable to resolve repository for $it.\nSearched in ${ + mavenRepositories.joinToString( + separator = "\n" + ) { r -> r.url + path } + }") + + // add the repository + val cs = ChecksumHelper.fileShaSum(it.file) + "include ${repository.name} ${it.group} ${it.name} ${it.version} ${it.timestampedVersion} $cs ${it.classifier ?: ""}\n" + } + }.awaitAll().forEach { + stringBuilder.append(it) + } } // write to the output file @@ -125,37 +183,49 @@ abstract class ExportCnlFile : DefaultTask() { } data class CacheableResolvedArtifact( - @Input val group: String, - @Input val name: String, - @Input val version: String, - @Input val timestampedVersion: String, - @Optional @Input val classifier: String?, + @Input val id: ComponentArtifactIdentifier, @Input val variant: ResolvedVariantResult, @InputFile @PathSensitive(PathSensitivity.RELATIVE) val file: File ) +data class ResolvedArtifact( + val group: String, + val name: String, + val version: String, + val timestampedVersion: String, + val classifier: String?, + val file: File +) + data class CacheableMavenRepository(@Input val name: String, @Input val url: String) { constructor(repository: MavenArtifactRepository) : this(repository.name, repository.url.toString()) } -private fun resolveRepository( + +abstract class ResolveRepository : WorkAction { + interface Params : WorkParameters {} +} + +private suspend fun resolveRepository( testUrlPath: String, repositories: Iterable ): CacheableMavenRepository? { - return repositories.firstOrNull { - val url = URI.create(it.url).resolve(testUrlPath).toURL() - with(url.openConnection() as HttpURLConnection) { - useCaches = false - readTimeout = 30000 - connectTimeout = 30000 - instanceFollowRedirects = true - - setRequestProperty( - "User-Agent", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11" - ) - - connect() - responseCode == 200 + return withContext(Dispatchers.IO) { + repositories.firstOrNull { + val url = URI.create(it.url).resolve(testUrlPath).toURL() + with(url.openConnection() as HttpURLConnection) { + useCaches = false + readTimeout = 30000 + connectTimeout = 30000 + instanceFollowRedirects = true + + setRequestProperty( + "User-Agent", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11" + ) + + connect() + responseCode == 200 + } } } } diff --git a/build.gradle.kts b/build.gradle.kts index 0ff58ed777..c6c278a21d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,6 +16,8 @@ plugins { id("cloudnet.parent-build-logic") + id("cloudnet") + id("java-base") alias(libs.plugins.nexusPublish) alias(libs.plugins.spotless) apply false alias(libs.plugins.shadow) apply false @@ -29,6 +31,8 @@ val globalJavadocClasspath = configurations.register("globalJavadocClasspath") tasks.register("globalJavaDoc", Javadoc::class) { val options = options as? StandardJavadocDocletOptions ?: return@register + javadocTool = javaToolchains.javadocToolFor { configureFor(Versions.javaVersion) } + options.source = Versions.javaVersion.asInt().toString() title = "CloudNet JavaDocs" setDestinationDir(layout.buildDirectory.dir("javadocs").get().asFile) @@ -57,12 +61,8 @@ nexusPublishing { dependencies { subprojects.map { it.isolated }.forEach { project -> if (!isJavaConfiguredProject(project.name, project.path)) return@forEach - globalJavadocSources(this.project(project.path)) { - targetConfiguration = CustomConfigurations.GLOBAL_JAVADOC_SOURCES - } - globalJavadocClasspath(this.project(project.path)) { - targetConfiguration = CustomConfigurations.GLOBAL_JAVADOC_CLASSPATH - } + globalJavadocSources(this.project(project.path, CustomConfigurations.GLOBAL_JAVADOC_SOURCES)) + globalJavadocClasspath(this.project(project.path, CustomConfigurations.GLOBAL_JAVADOC_CLASSPATH)) } } @@ -81,3 +81,10 @@ gradle.projectsEvaluated { } } } + +// Adapted from https://stackoverflow.com/a/75923728 to fix running inside IDE +gradle.taskGraph.whenReady { + allTasks.filterIsInstance().forEach { + it.setExecutable(it.javaLauncher.get().executablePath.asFile.absolutePath) + } +} diff --git a/driver/ap/build.gradle.kts b/driver/ap/build.gradle.kts index ba4ae65ad8..9790d6941c 100644 --- a/driver/ap/build.gradle.kts +++ b/driver/ap/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + dependencies { "implementation"(projects.driver.driverApi) } diff --git a/driver/api/build.gradle.kts b/driver/api/build.gradle.kts index 5c14a41368..c3d4767923 100644 --- a/driver/api/build.gradle.kts +++ b/driver/api/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java-api") +} + dependencies { "api"(libs.vavr) "api"(libs.slf4jApi) diff --git a/driver/api/src/main/java/eu/cloudnetservice/driver/service/ThreadSnapshot.java b/driver/api/src/main/java/eu/cloudnetservice/driver/service/ThreadSnapshot.java index 9d4dbc7093..66b422c09c 100644 --- a/driver/api/src/main/java/eu/cloudnetservice/driver/service/ThreadSnapshot.java +++ b/driver/api/src/main/java/eu/cloudnetservice/driver/service/ThreadSnapshot.java @@ -49,7 +49,7 @@ public record ThreadSnapshot( */ public static @NonNull ThreadSnapshot from(@NonNull Thread thread) { return new ThreadSnapshot( - thread.threadId(), + thread.getId(), thread.getPriority(), thread.isDaemon(), thread.getName(), diff --git a/driver/impl/build.gradle.kts b/driver/impl/build.gradle.kts index 4dfded9b06..a3412343a3 100644 --- a/driver/impl/build.gradle.kts +++ b/driver/impl/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + dependencies { "implementation"(projects.utils.utilsBase) "implementation"(projects.driver.driverApi) diff --git a/ext/adventure-helper/build.gradle.kts b/ext/adventure-helper/build.gradle.kts index 72b8132f82..99a6b250f3 100644 --- a/ext/adventure-helper/build.gradle.kts +++ b/ext/adventure-helper/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + dependencies { "compileOnly"(libs.adventureApi) "compileOnly"(libs.adventureSerializerLegacy) diff --git a/ext/bukkit-command/build.gradle.kts b/ext/bukkit-command/build.gradle.kts index 900a84c243..4ff8ce5d7b 100644 --- a/ext/bukkit-command/build.gradle.kts +++ b/ext/bukkit-command/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + repositories { maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") } diff --git a/ext/modlauncher/build.gradle.kts b/ext/modlauncher/build.gradle.kts index 3a0850e987..2fd95b1985 100644 --- a/ext/modlauncher/build.gradle.kts +++ b/ext/modlauncher/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + repositories { maven("https://repo.spongepowered.org/maven/") } diff --git a/ext/platform-inject-support/api/build.gradle.kts b/ext/platform-inject-support/api/build.gradle.kts index 4a49168f7e..893dbcca9d 100644 --- a/ext/platform-inject-support/api/build.gradle.kts +++ b/ext/platform-inject-support/api/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java-api") +} + dependencies { "compileOnlyApi"(projects.driver.driverApi) } diff --git a/ext/platform-inject-support/loader/build.gradle.kts b/ext/platform-inject-support/loader/build.gradle.kts index 9d36e726f7..25919b29c9 100644 --- a/ext/platform-inject-support/loader/build.gradle.kts +++ b/ext/platform-inject-support/loader/build.gradle.kts @@ -16,6 +16,10 @@ import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin.Companion.sha * limitations under the License. */ +plugins { + id("cloudnet-java") +} + dependencies { "api"(projects.ext.platformInjectSupport.platformInjectApi) "implementation"(projects.utils.utilsBase) diff --git a/ext/platform-inject-support/processor/build.gradle.kts b/ext/platform-inject-support/processor/build.gradle.kts index 7fd36d5b95..610d85b20d 100644 --- a/ext/platform-inject-support/processor/build.gradle.kts +++ b/ext/platform-inject-support/processor/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + dependencies { "implementation"(libs.javapoet) "implementation"(libs.bundles.nightConfig) diff --git a/ext/platform-inject-support/runtime/build.gradle.kts b/ext/platform-inject-support/runtime/build.gradle.kts index 4b58e37717..0db196b5e9 100644 --- a/ext/platform-inject-support/runtime/build.gradle.kts +++ b/ext/platform-inject-support/runtime/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + repositories { maven("https://repo.waterdog.dev/releases/") maven("https://repo.loohpjames.com/repository") diff --git a/ext/updater/build.gradle.kts b/ext/updater/build.gradle.kts index 860b693363..584d0b6d08 100644 --- a/ext/updater/build.gradle.kts +++ b/ext/updater/build.gradle.kts @@ -14,3 +14,6 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} diff --git a/gradle.properties b/gradle.properties index 509e2e5a90..009d0bbc75 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,6 +15,7 @@ # org.gradle.caching=true org.gradle.configuration-cache=true +org.gradle.configuration-cache.problems=warn org.gradle.configureondemand=true org.gradle.parallel=true #org.gradle.unsafe.isolated-projects=true # blocked on spotless https://github.com/diffplug/spotless/issues/1979 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 78cb6e16a4..3e781fbad9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionSha256Sum=8fad3d78296ca518113f3d29016617c7f9367dc005f932bd9d93bf45ba46072b +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/launcher/build.gradle.kts b/launcher/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/launcher/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/launcher/java22/build.gradle.kts b/launcher/java22/build.gradle.kts index e3e3ca7277..0be1e0152e 100644 --- a/launcher/java22/build.gradle.kts +++ b/launcher/java22/build.gradle.kts @@ -16,6 +16,7 @@ plugins { alias(libs.plugins.shadow) + id("cloudnet-java") } tasks.shadowJar.configure { diff --git a/launcher/java8/build.gradle.kts b/launcher/java8/build.gradle.kts index 090dcda321..1a6e2a8d02 100644 --- a/launcher/java8/build.gradle.kts +++ b/launcher/java8/build.gradle.kts @@ -14,7 +14,8 @@ * limitations under the License. */ -tasks.withType().configureEach { - sourceCompatibility = JavaVersion.VERSION_1_8.toString() - targetCompatibility = JavaVersion.VERSION_1_8.toString() +plugins { + id("cloudnet-java") } + +configureJavaVersion(JavaLanguageVersion.of(8)) diff --git a/launcher/patcher/build.gradle.kts b/launcher/patcher/build.gradle.kts index 3a05c63947..221290f1f6 100644 --- a/launcher/patcher/build.gradle.kts +++ b/launcher/patcher/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + tasks.jar.configure { archiveFileName.set(Files.launcherPatcher) } diff --git a/modules/bridge/api/build.gradle.kts b/modules/bridge/api/build.gradle.kts index 6f05c3f13c..f7a5bb341b 100644 --- a/modules/bridge/api/build.gradle.kts +++ b/modules/bridge/api/build.gradle.kts @@ -13,6 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +plugins { + id("cloudnet-modules-api") +} + dependencies { "api"(libs.adventureApi) "compileOnly"(projects.wrapperJvm.wrapperJvmApi) diff --git a/modules/bridge/impl/build.gradle.kts b/modules/bridge/impl/build.gradle.kts index fa72b54ee0..510590ddd5 100644 --- a/modules/bridge/impl/build.gradle.kts +++ b/modules/bridge/impl/build.gradle.kts @@ -14,10 +14,9 @@ * limitations under the License. */ -import net.fabricmc.loom.task.RemapJarTask - plugins { alias(libs.plugins.fabricLoom) + id("cloudnet-modules") } configurations { diff --git a/modules/build.gradle.kts b/modules/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/cloudflare/api/build.gradle.kts b/modules/cloudflare/api/build.gradle.kts index d2d9f18709..ad4cff563e 100644 --- a/modules/cloudflare/api/build.gradle.kts +++ b/modules/cloudflare/api/build.gradle.kts @@ -13,3 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +plugins { + id("cloudnet-modules-api") +} diff --git a/modules/cloudflare/build.gradle.kts b/modules/cloudflare/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/cloudflare/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/cloudflare/impl/build.gradle.kts b/modules/cloudflare/impl/build.gradle.kts index 9217375d21..6fdbb7b4e4 100644 --- a/modules/cloudflare/impl/build.gradle.kts +++ b/modules/cloudflare/impl/build.gradle.kts @@ -16,6 +16,7 @@ plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/node/build.gradle.kts b/modules/database-mongodb/api/build.gradle.kts similarity index 84% rename from node/build.gradle.kts rename to modules/database-mongodb/api/build.gradle.kts index 93e10be560..9ee0cdd790 100644 --- a/node/build.gradle.kts +++ b/modules/database-mongodb/api/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 CloudNetService team & contributors + * Copyright 2019-2025 CloudNetService team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,4 +14,6 @@ * limitations under the License. */ - +plugins { + id("cloudnet-modules-api") +} diff --git a/modules/database-mongodb/build.gradle.kts b/modules/database-mongodb/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/database-mongodb/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/database-mongodb/impl/build.gradle.kts b/modules/database-mongodb/impl/build.gradle.kts index be32eda410..1c0b3fbe8a 100644 --- a/modules/database-mongodb/impl/build.gradle.kts +++ b/modules/database-mongodb/impl/build.gradle.kts @@ -16,6 +16,7 @@ plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/database-mysql/api/build.gradle.kts b/modules/database-mysql/api/build.gradle.kts index e69de29bb2..9ee0cdd790 100644 --- a/modules/database-mysql/api/build.gradle.kts +++ b/modules/database-mysql/api/build.gradle.kts @@ -0,0 +1,19 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("cloudnet-modules-api") +} diff --git a/modules/database-mysql/build.gradle.kts b/modules/database-mysql/build.gradle.kts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/database-mysql/impl/build.gradle.kts b/modules/database-mysql/impl/build.gradle.kts index d3889cc7a9..ead5a53155 100644 --- a/modules/database-mysql/impl/build.gradle.kts +++ b/modules/database-mysql/impl/build.gradle.kts @@ -18,6 +18,7 @@ import java.util.* plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/dockerized-services/api/build.gradle.kts b/modules/dockerized-services/api/build.gradle.kts index e69de29bb2..9ee0cdd790 100644 --- a/modules/dockerized-services/api/build.gradle.kts +++ b/modules/dockerized-services/api/build.gradle.kts @@ -0,0 +1,19 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("cloudnet-modules-api") +} diff --git a/modules/dockerized-services/build.gradle.kts b/modules/dockerized-services/build.gradle.kts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/dockerized-services/impl/build.gradle.kts b/modules/dockerized-services/impl/build.gradle.kts index f882d8149f..0ae7b0aec0 100644 --- a/modules/dockerized-services/impl/build.gradle.kts +++ b/modules/dockerized-services/impl/build.gradle.kts @@ -16,6 +16,7 @@ plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/influx/api/build.gradle.kts b/modules/influx/api/build.gradle.kts index b5690fed80..a8bc87e851 100644 --- a/modules/influx/api/build.gradle.kts +++ b/modules/influx/api/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-modules-api") +} + dependencies { "compileOnly"(libs.influxClient) } diff --git a/modules/influx/build.gradle.kts b/modules/influx/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/influx/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/influx/impl/build.gradle.kts b/modules/influx/impl/build.gradle.kts index 7eb4a86dc3..e853591575 100644 --- a/modules/influx/impl/build.gradle.kts +++ b/modules/influx/impl/build.gradle.kts @@ -18,6 +18,7 @@ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/labymod/api/build.gradle.kts b/modules/labymod/api/build.gradle.kts index d8f4acb045..4c3003196f 100644 --- a/modules/labymod/api/build.gradle.kts +++ b/modules/labymod/api/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-modules-api") +} + dependencies { "compileOnly"(projects.modules.bridge.bridgeApi) } diff --git a/modules/labymod/build.gradle.kts b/modules/labymod/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/labymod/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/labymod/impl/build.gradle.kts b/modules/labymod/impl/build.gradle.kts index 049d91eb64..24996a7c61 100644 --- a/modules/labymod/impl/build.gradle.kts +++ b/modules/labymod/impl/build.gradle.kts @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/npcs/api/build.gradle.kts b/modules/npcs/api/build.gradle.kts index d8f4acb045..4c3003196f 100644 --- a/modules/npcs/api/build.gradle.kts +++ b/modules/npcs/api/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-modules-api") +} + dependencies { "compileOnly"(projects.modules.bridge.bridgeApi) } diff --git a/modules/npcs/impl/build.gradle.kts b/modules/npcs/impl/build.gradle.kts index 436ba94367..cbb3e78d98 100644 --- a/modules/npcs/impl/build.gradle.kts +++ b/modules/npcs/impl/build.gradle.kts @@ -14,11 +14,11 @@ * limitations under the License. */ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/report/api/build.gradle.kts b/modules/report/api/build.gradle.kts index d2d9f18709..ad4cff563e 100644 --- a/modules/report/api/build.gradle.kts +++ b/modules/report/api/build.gradle.kts @@ -13,3 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +plugins { + id("cloudnet-modules-api") +} diff --git a/modules/report/build.gradle.kts b/modules/report/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/report/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/report/impl/build.gradle.kts b/modules/report/impl/build.gradle.kts index 295befefb2..949bb06cbb 100644 --- a/modules/report/impl/build.gradle.kts +++ b/modules/report/impl/build.gradle.kts @@ -16,6 +16,7 @@ plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/signs/api/build.gradle.kts b/modules/signs/api/build.gradle.kts index d8f4acb045..4c3003196f 100644 --- a/modules/signs/api/build.gradle.kts +++ b/modules/signs/api/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-modules-api") +} + dependencies { "compileOnly"(projects.modules.bridge.bridgeApi) } diff --git a/modules/signs/impl/build.gradle.kts b/modules/signs/impl/build.gradle.kts index c2c175dcc7..377bbdaa5d 100644 --- a/modules/signs/impl/build.gradle.kts +++ b/modules/signs/impl/build.gradle.kts @@ -18,6 +18,7 @@ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/ext/platform-inject-support/build.gradle.kts b/modules/smart/api/build.gradle.kts similarity index 84% rename from ext/platform-inject-support/build.gradle.kts rename to modules/smart/api/build.gradle.kts index 860b693363..9ee0cdd790 100644 --- a/ext/platform-inject-support/build.gradle.kts +++ b/modules/smart/api/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 CloudNetService team & contributors + * Copyright 2019-2025 CloudNetService team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,3 +14,6 @@ * limitations under the License. */ +plugins { + id("cloudnet-modules-api") +} diff --git a/modules/smart/build.gradle.kts b/modules/smart/build.gradle.kts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/smart/impl/build.gradle.kts b/modules/smart/impl/build.gradle.kts index b50b179ecb..14f703df1e 100644 --- a/modules/smart/impl/build.gradle.kts +++ b/modules/smart/impl/build.gradle.kts @@ -18,6 +18,7 @@ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/storage-s3/api/build.gradle.kts b/modules/storage-s3/api/build.gradle.kts index d2d9f18709..ad4cff563e 100644 --- a/modules/storage-s3/api/build.gradle.kts +++ b/modules/storage-s3/api/build.gradle.kts @@ -13,3 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +plugins { + id("cloudnet-modules-api") +} diff --git a/modules/storage-s3/build.gradle.kts b/modules/storage-s3/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/storage-s3/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/storage-s3/impl/build.gradle.kts b/modules/storage-s3/impl/build.gradle.kts index b13ddc8f3b..fb65af11c5 100644 --- a/modules/storage-s3/impl/build.gradle.kts +++ b/modules/storage-s3/impl/build.gradle.kts @@ -16,6 +16,7 @@ plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/storage-sftp/api/build.gradle.kts b/modules/storage-sftp/api/build.gradle.kts index d2d9f18709..ad4cff563e 100644 --- a/modules/storage-sftp/api/build.gradle.kts +++ b/modules/storage-sftp/api/build.gradle.kts @@ -13,3 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +plugins { + id("cloudnet-modules-api") +} diff --git a/modules/storage-sftp/build.gradle.kts b/modules/storage-sftp/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/storage-sftp/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/storage-sftp/impl/build.gradle.kts b/modules/storage-sftp/impl/build.gradle.kts index cc26e6a14e..c1363653a2 100644 --- a/modules/storage-sftp/impl/build.gradle.kts +++ b/modules/storage-sftp/impl/build.gradle.kts @@ -16,6 +16,7 @@ plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/modules/syncproxy/api/build.gradle.kts b/modules/syncproxy/api/build.gradle.kts index 170f8b224f..4c3003196f 100644 --- a/modules/syncproxy/api/build.gradle.kts +++ b/modules/syncproxy/api/build.gradle.kts @@ -13,6 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +plugins { + id("cloudnet-modules-api") +} + dependencies { "compileOnly"(projects.modules.bridge.bridgeApi) } diff --git a/modules/syncproxy/build.gradle.kts b/modules/syncproxy/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/modules/syncproxy/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/modules/syncproxy/impl/build.gradle.kts b/modules/syncproxy/impl/build.gradle.kts index 7744946621..fdeb62a4a6 100644 --- a/modules/syncproxy/impl/build.gradle.kts +++ b/modules/syncproxy/impl/build.gradle.kts @@ -18,6 +18,7 @@ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration plugins { alias(libs.plugins.shadow) + id("cloudnet-modules") } tasks.shadowJar.configure { diff --git a/node/api/build.gradle.kts b/node/api/build.gradle.kts index acd9632218..02a987114c 100644 --- a/node/api/build.gradle.kts +++ b/node/api/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java-api") +} + dependencies { api(projects.driver.driverApi) compileOnlyApi(libs.bundles.cloud) diff --git a/node/impl/build.gradle.kts b/node/impl/build.gradle.kts index 289e7d5294..bde6e8d444 100644 --- a/node/impl/build.gradle.kts +++ b/node/impl/build.gradle.kts @@ -16,11 +16,12 @@ plugins { alias(libs.plugins.shadow) + id("cloudnet-java") } val exportCnlFile = tasks.register("exportCnlFile") { fileName = Files.nodeCnl - setResolvedArtifacts(configurations.runtimeClasspath.get()) + setResolvedArtifacts(configurations.runtimeClasspath) } val exportLanguageFileInformation = tasks.register("exportLanguageFileInformation") { languageFiles.from(project.projectDir.resolve("src/main/resources/lang").listFiles()) diff --git a/plugins/luckperms/build.gradle.kts b/plugins/luckperms/build.gradle.kts index 60908e3634..1c4055efb7 100644 --- a/plugins/luckperms/build.gradle.kts +++ b/plugins/luckperms/build.gradle.kts @@ -1,5 +1,3 @@ -import net.fabricmc.loom.task.RemapJarTask - /* * Copyright 2019-2023 CloudNetService team & contributors * @@ -18,9 +16,9 @@ import net.fabricmc.loom.task.RemapJarTask plugins { alias(libs.plugins.fabricLoom) + id("cloudnet-plugins") } - dependencies { "compileOnly"(libs.bundles.proxyPlatform) "compileOnly"(libs.bundles.serverPlatform) diff --git a/plugins/papi-expansion/build.gradle.kts b/plugins/papi-expansion/build.gradle.kts index 9df39b2368..56ed34da66 100644 --- a/plugins/papi-expansion/build.gradle.kts +++ b/plugins/papi-expansion/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-plugins") +} + tasks.jar.configure { archiveFileName.set(Files.papiExpansion) } diff --git a/settings.gradle.kts b/settings.gradle.kts index a7e8940431..90ffcb1830 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,7 +37,7 @@ pluginManagement { plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" id("com.gradle.develocity") version ("4.1") - id("settings-plugin") + id("cloudnet-settings") } rootProject.name = "cloudnet-root" diff --git a/utils/base/build.gradle.kts b/utils/base/build.gradle.kts index 96c680a333..dd8c5999f8 100644 --- a/utils/base/build.gradle.kts +++ b/utils/base/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java") +} + dependencies { "api"(libs.vavr) "implementation"(libs.guava) diff --git a/utils/build.gradle.kts b/utils/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/utils/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/wrapper-jvm/api/build.gradle.kts b/wrapper-jvm/api/build.gradle.kts index e92ef10f8a..75f96e6938 100644 --- a/wrapper-jvm/api/build.gradle.kts +++ b/wrapper-jvm/api/build.gradle.kts @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id("cloudnet-java-api") +} + dependencies { "api"(projects.driver.driverApi) } diff --git a/wrapper-jvm/build.gradle.kts b/wrapper-jvm/build.gradle.kts deleted file mode 100644 index d2d9f18709..0000000000 --- a/wrapper-jvm/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ diff --git a/wrapper-jvm/impl/build.gradle.kts b/wrapper-jvm/impl/build.gradle.kts index 37fa08ec26..90dda19f06 100644 --- a/wrapper-jvm/impl/build.gradle.kts +++ b/wrapper-jvm/impl/build.gradle.kts @@ -1,14 +1,29 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ plugins { alias(libs.plugins.shadow) + id("cloudnet-java") } val ignoredGroupIds = listOf("com.google.guava", "com.google.code.gson") val exportCnlFile = tasks.register("exportCnlFile") { fileName = "wrapper.cnl" ignoredDependencyGroups = ignoredGroupIds - setResolvedArtifacts(configurations.runtimeClasspath.get()) + setResolvedArtifacts(configurations.runtimeClasspath) } val exportLanguageFileInformation = tasks.register("exportLanguageFileInformation") { languageFiles.from(project.projectDir.resolve("src/main/resources/lang").listFiles()) From deac2ace5b4fcc8ca3ffda5510edfa7744b3978a Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Sat, 2 Aug 2025 01:13:51 +0200 Subject: [PATCH 22/45] remove the useless parent build logic plugin --- .../cloudnet.parent-build-logic.gradle.kts | 19 ------------------- build.gradle.kts | 1 - 2 files changed, 20 deletions(-) delete mode 100644 build-extensions/src/main/kotlin/cloudnet.parent-build-logic.gradle.kts diff --git a/build-extensions/src/main/kotlin/cloudnet.parent-build-logic.gradle.kts b/build-extensions/src/main/kotlin/cloudnet.parent-build-logic.gradle.kts deleted file mode 100644 index 1cdc4873f8..0000000000 --- a/build-extensions/src/main/kotlin/cloudnet.parent-build-logic.gradle.kts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -plugins { -// id("net.kyori.indra.git") -} diff --git a/build.gradle.kts b/build.gradle.kts index c6c278a21d..52fa1a83f0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,6 @@ */ plugins { - id("cloudnet.parent-build-logic") id("cloudnet") id("java-base") alias(libs.plugins.nexusPublish) From 85693df877837c96b00f68ed0cf50c1a7557db0c Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Sat, 2 Aug 2025 12:54:55 +0200 Subject: [PATCH 23/45] remove indra --- build-extensions/build.gradle.kts | 9 +- .../src/main/kotlin/CloudNetJavaPlugin.kt | 1 - .../src/main/kotlin/extensions.kt | 51 +++----- .../src/main/kotlin/git/GitPlugin.kt | 45 +++++++ .../src/main/kotlin/git/GitService.kt | 114 ++++++++++++++++++ settings.gradle.kts | 7 -- 6 files changed, 174 insertions(+), 53 deletions(-) create mode 100644 build-extensions/src/main/kotlin/git/GitPlugin.kt create mode 100644 build-extensions/src/main/kotlin/git/GitService.kt diff --git a/build-extensions/build.gradle.kts b/build-extensions/build.gradle.kts index a619ec7822..ea704e228e 100644 --- a/build-extensions/build.gradle.kts +++ b/build-extensions/build.gradle.kts @@ -25,18 +25,11 @@ kotlin.jvmToolchain(21) repositories { gradlePluginPortal() mavenCentral() - // TODO wait for indra to be configuration cache compatible - // maven("https://repo.stellardrift.ca/repository/snapshots/") { - mavenLocal { - content { - includeGroup("net.kyori") - } - } } dependencies { + implementation("org.eclipse.jgit:org.eclipse.jgit:7.3.0.202506031305-r") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") - implementation("net.kyori", "indra-git", "4.0.0-SNAPSHOT") implementation("com.google.code.gson", "gson", "2.13.1") implementation("com.diffplug.spotless", "spotless-plugin-gradle", libs.versions.spotless.get()) diff --git a/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt b/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt index d8ca98a8bd..8b864c095b 100644 --- a/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt +++ b/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt @@ -56,7 +56,6 @@ class CloudNetJavaPlugin : Plugin { apply(plugin = "checkstyle") apply(plugin = "java-library") apply(plugin = "com.diffplug.spotless") -// apply(plugin = "net.kyori.indra.git") // Add common repositories required in all projects this.addDefaultRepositories() diff --git a/build-extensions/src/main/kotlin/extensions.kt b/build-extensions/src/main/kotlin/extensions.kt index 0620a12e30..101d5e0331 100644 --- a/build-extensions/src/main/kotlin/extensions.kt +++ b/build-extensions/src/main/kotlin/extensions.kt @@ -14,26 +14,18 @@ * limitations under the License. */ -import net.kyori.indra.git.IndraGitExtension -import net.kyori.indra.git.RepositoryValueSource -import net.kyori.indra.git.internal.IndraGitExtensionImpl -import org.eclipse.jgit.api.Git -import org.eclipse.jgit.lib.Constants +import git.GitExtension +import git.GitService import org.gradle.api.Project -import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.artifacts.repositories.MavenArtifactRepository -import org.gradle.api.internal.artifacts.repositories.resolver.MavenUniqueSnapshotComponentIdentifier import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSetContainer import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.attributes import org.gradle.kotlin.dsl.findByType import org.gradle.kotlin.dsl.named import org.gradle.kotlin.dsl.the -import java.io.IOException -import java.net.HttpURLConnection -import java.util.logging.Level -import java.util.logging.Logger fun Project.applyJarMetadata(mainClass: String, module: String) { applyJarMetadata(mainClass, module, null) @@ -42,49 +34,34 @@ fun Project.applyJarMetadata(mainClass: String, module: String) { fun Project.applyJarMetadata(mainClass: String, module: String, preMain: String?) { if ("jar" in tasks.names) { tasks.named("jar") { + val service = git()?.service + service?.let { usesService(it) } + manifest.attributes( "Main-Class" to mainClass, "Automatic-Module-Name" to module, "Implementation-Vendor" to "CloudNetService", "Implementation-Title" to Versions.cloudNetCodeName, - "Implementation-Version" to project.version.toString() + "-${shortCommitHash()}") + "Implementation-Version" to project.version.toString() + "-${service.shortCommitHash()}" + ) // apply the pre-main class if given if (preMain != null) { manifest.attributes("Premain-Class" to preMain) } // apply git information to manifest - git()?.let { git -> - val commit = git.commit().map { it.name.substring(0, 8) } - val branchName = git.repositoryValue(BranchName::class.java) - if (commit.isPresent) manifest.attributes(IndraGitExtension.MANIFEST_ATTRIBUTE_GIT_COMMIT to commit.get()) - if (branchName.isPresent) manifest.attributes(IndraGitExtension.MANIFEST_ATTRIBUTE_GIT_BRANCH to branchName.get()) + service?.run { get() }?.let { service -> + service.commit?.name?.substring(0, 8)?.let { manifest.attributes("Git-Commit" to it) } + service.branchName?.let { manifest.attributes("Git-Branch" to it) } } } } } -/** - * Indra does not properly support configuration caching for #branchName yet - */ -private abstract class BranchName : RepositoryValueSource.Parameterless() { - override fun obtain(repository: Git): String? { - try { - val ref = repository.repository.exactRef(Constants.HEAD) - if (ref == null || !ref.isSymbolic) return null // no HEAD, or detached HEAD - - return ref.target.name - } catch (ex: IOException) { - Logger.getGlobal().log(Level.SEVERE, "Failed to query current branch name from git:", ex) - return null - } - } -} - -fun Project.shortCommitHash(): String { - return git()?.commit()?.get()?.name()?.substring(0, 8) ?: "unknown" +fun Provider?.shortCommitHash(): String { + return this?.get()?.commit?.name()?.substring(0, 8) ?: "unknown" } -fun Project.git(): IndraGitExtension? = extensions.findByType() +fun Project.git(): GitExtension? = extensions.findByType() fun Project.sourceSets(): SourceSetContainer = the().sourceSets diff --git a/build-extensions/src/main/kotlin/git/GitPlugin.kt b/build-extensions/src/main/kotlin/git/GitPlugin.kt new file mode 100644 index 0000000000..a7fbdaee1a --- /dev/null +++ b/build-extensions/src/main/kotlin/git/GitPlugin.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package git + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.provider.Provider +import javax.inject.Inject + +class GitPlugin : Plugin { + companion object { + private const val EXTENSION_NAME = "git" + private const val SERVICE_NAME = "gitService" + } + + override fun apply(project: Project) { + val rootDir = project.rootDir + val service = project.gradle.sharedServices.registerIfAbsent(SERVICE_NAME, GitService::class.java) { + parameters.projectDirectory.set(rootDir) + } + + project.extensions.create(GitExtension::class.java, EXTENSION_NAME, GitExtensionImpl::class.java, service) + } +} + +interface GitExtension { + val service: Provider +} + +internal abstract class GitExtensionImpl @Inject constructor(final override val service: Provider) : + GitExtension diff --git a/build-extensions/src/main/kotlin/git/GitService.kt b/build-extensions/src/main/kotlin/git/GitService.kt new file mode 100644 index 0000000000..4d03630c3a --- /dev/null +++ b/build-extensions/src/main/kotlin/git/GitService.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package git + +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.lib.* +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import java.io.Closeable +import java.lang.AutoCloseable +import java.nio.file.Path +import java.util.concurrent.atomic.AtomicBoolean +import kotlin.io.path.isDirectory +import kotlin.io.path.notExists +import kotlin.io.path.useLines + +abstract class GitService : BuildService, AutoCloseable { + private val git: GitInstance = GitInstance(parameters.projectDirectory.get().asFile.toPath()) + + override fun close() { + } + + interface Params : BuildServiceParameters { + val projectDirectory: DirectoryProperty + } + + val branchName: String? + get() = branch?.run { Repository.shortenRefName(this.name) } + + val commit: ObjectId? + get() = head?.run { this.objectId } + + val head: Ref? + get() = git.git?.repository?.run { exactRef(Constants.HEAD) } + + val branch: Ref? + get() = head?.run { if (!this.isSymbolic) null else this.target } + + /** + * Currently has no support for git submodules. + * We don't use them so it should be ok + */ + private class GitInstance(dir: Path) : Closeable { + companion object { + val logger: Logger = LoggerFactory.getLogger(GitInstance::class.java) + const val GIT_DIR = ".git" + const val GITDIR_PREFIX = "gitdir:" + } + + private val usable = AtomicBoolean(false) + val repository: Repository? + val git: Git? + + init { + var targetDir: Path? = dir + while (targetDir?.resolve(GIT_DIR)?.notExists() ?: false) { + targetDir = targetDir.parent + } + + val gitDir = targetDir?.let { resolveGitDirectory(it) } + if (targetDir == null || gitDir == null) { + logger.info("[Git] Unable to find repository for $dir") + repository = null + git = null + } else { + repository = + RepositoryBuilder().setWorkTree(dir.toFile()).setGitDir(gitDir.toFile()).setMustExist(true).build() + git = Git.wrap(repository) + } + } + + private fun resolveGitDirectory(projectDir: Path): Path? { + // https://git-scm.com/docs/gitrepository-layout + // .git file is allowed with 'gitdir:' reference + projectDir.run { + if (fileName.toString() == GIT_DIR) projectDir else projectDir.resolve(GIT_DIR) + }.run { + if (isDirectory()) return this + this.useLines { sequence -> + sequence.forEach { line -> + if (line.startsWith(GITDIR_PREFIX)) { + return parent.resolve(line.substring(GITDIR_PREFIX.length)) + } + } + } + logger.warn("[Git] Could not determine git directory for $projectDir") + return null + } + } + + override fun close() { + if (usable.compareAndSet(true, false)) { + repository!!.close() + } + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 90ffcb1830..5fc02a77bf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,13 +21,6 @@ pluginManagement { includeBuild("build-extensions") repositories { gradlePluginPortal() - // TODO wait for indra to be configuration cache compatible - // maven("https://repo.stellardrift.ca/repository/snapshots/") { - mavenLocal { - content { - includeGroup("net.kyori") - } - } maven { name = "Fabric" url = uri("https://maven.fabricmc.net/") From 24f58733469c255be1c0cc6c6f5665c3b04daf3a Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Sat, 2 Aug 2025 13:09:47 +0200 Subject: [PATCH 24/45] actually use the new git plugin --- build-extensions/build.gradle.kts | 4 ++ .../src/main/kotlin/extensions.kt | 47 ++++++++++--------- .../{GitPlugin.kt => CloudNetGitPlugin.kt} | 7 +-- launcher/java22/build.gradle.kts | 3 +- launcher/patcher/build.gradle.kts | 3 +- node/impl/build.gradle.kts | 3 +- wrapper-jvm/impl/build.gradle.kts | 3 +- 7 files changed, 41 insertions(+), 29 deletions(-) rename build-extensions/src/main/kotlin/git/{GitPlugin.kt => CloudNetGitPlugin.kt} (86%) diff --git a/build-extensions/build.gradle.kts b/build-extensions/build.gradle.kts index ea704e228e..230a71b947 100644 --- a/build-extensions/build.gradle.kts +++ b/build-extensions/build.gradle.kts @@ -43,6 +43,10 @@ gradlePlugin { id = "cloudnet" implementationClass = "CloudNetPlugin" } + register("cloudnet-git") { + id = "cloudnet-git" + implementationClass = "git.CloudNetGitPlugin" + } register("cloudnet-settings") { id = "cloudnet-settings" implementationClass = "CloudNetSettingsPlugin" diff --git a/build-extensions/src/main/kotlin/extensions.kt b/build-extensions/src/main/kotlin/extensions.kt index 101d5e0331..71c5275b65 100644 --- a/build-extensions/src/main/kotlin/extensions.kt +++ b/build-extensions/src/main/kotlin/extensions.kt @@ -27,31 +27,33 @@ import org.gradle.kotlin.dsl.findByType import org.gradle.kotlin.dsl.named import org.gradle.kotlin.dsl.the -fun Project.applyJarMetadata(mainClass: String, module: String) { +fun GitExtension.applyJarMetadata(mainClass: String, module: String) { applyJarMetadata(mainClass, module, null) } -fun Project.applyJarMetadata(mainClass: String, module: String, preMain: String?) { - if ("jar" in tasks.names) { - tasks.named("jar") { - val service = git()?.service - service?.let { usesService(it) } +fun GitExtension.applyJarMetadata(mainClass: String, module: String, preMain: String?) { + project.run { + if ("jar" in tasks.names) { + tasks.named("jar") { + val service = git()?.service + service?.let { usesService(it) } - manifest.attributes( - "Main-Class" to mainClass, - "Automatic-Module-Name" to module, - "Implementation-Vendor" to "CloudNetService", - "Implementation-Title" to Versions.cloudNetCodeName, - "Implementation-Version" to project.version.toString() + "-${service.shortCommitHash()}" - ) - // apply the pre-main class if given - if (preMain != null) { - manifest.attributes("Premain-Class" to preMain) - } - // apply git information to manifest - service?.run { get() }?.let { service -> - service.commit?.name?.substring(0, 8)?.let { manifest.attributes("Git-Commit" to it) } - service.branchName?.let { manifest.attributes("Git-Branch" to it) } + manifest.attributes( + "Main-Class" to mainClass, + "Automatic-Module-Name" to module, + "Implementation-Vendor" to "CloudNetService", + "Implementation-Title" to Versions.cloudNetCodeName, + "Implementation-Version" to project.version.toString() + "-${service.shortCommitHash()}" + ) + // apply the pre-main class if given + if (preMain != null) { + manifest.attributes("Premain-Class" to preMain) + } + // apply git information to manifest + service?.run { get() }?.let { service -> + service.commit?.name?.substring(0, 8)?.let { manifest.attributes("Git-Commit" to it) } + service.branchName?.let { manifest.attributes("Git-Branch" to it) } + } } } } @@ -65,7 +67,8 @@ fun Project.git(): GitExtension? = extensions.findByType() fun Project.sourceSets(): SourceSetContainer = the().sourceSets -fun Project.mavenRepositories(): Iterable = repositories.filterIsInstance() +fun Project.mavenRepositories(): Iterable = + repositories.filterIsInstance() fun releasesOnly(repository: MavenArtifactRepository) { repository.mavenContent { diff --git a/build-extensions/src/main/kotlin/git/GitPlugin.kt b/build-extensions/src/main/kotlin/git/CloudNetGitPlugin.kt similarity index 86% rename from build-extensions/src/main/kotlin/git/GitPlugin.kt rename to build-extensions/src/main/kotlin/git/CloudNetGitPlugin.kt index a7fbdaee1a..1c57c1bccc 100644 --- a/build-extensions/src/main/kotlin/git/GitPlugin.kt +++ b/build-extensions/src/main/kotlin/git/CloudNetGitPlugin.kt @@ -21,7 +21,7 @@ import org.gradle.api.Project import org.gradle.api.provider.Provider import javax.inject.Inject -class GitPlugin : Plugin { +class CloudNetGitPlugin : Plugin { companion object { private const val EXTENSION_NAME = "git" private const val SERVICE_NAME = "gitService" @@ -33,13 +33,14 @@ class GitPlugin : Plugin { parameters.projectDirectory.set(rootDir) } - project.extensions.create(GitExtension::class.java, EXTENSION_NAME, GitExtensionImpl::class.java, service) + project.extensions.create(GitExtension::class.java, EXTENSION_NAME, GitExtensionImpl::class.java, service, project) } } interface GitExtension { + val project: Project val service: Provider } -internal abstract class GitExtensionImpl @Inject constructor(final override val service: Provider) : +internal abstract class GitExtensionImpl @Inject constructor(final override val service: Provider, final override val project: Project) : GitExtension diff --git a/launcher/java22/build.gradle.kts b/launcher/java22/build.gradle.kts index 0be1e0152e..70f8d7483e 100644 --- a/launcher/java22/build.gradle.kts +++ b/launcher/java22/build.gradle.kts @@ -17,6 +17,7 @@ plugins { alias(libs.plugins.shadow) id("cloudnet-java") + id("cloudnet-git") } tasks.shadowJar.configure { @@ -28,4 +29,4 @@ dependencies { "implementation"(projects.launcher.java8) } -applyJarMetadata("eu.cloudnetservice.launcher.java8.Launcher", "eu.cloudnetservice.launcher") +git.applyJarMetadata("eu.cloudnetservice.launcher.java8.Launcher", "eu.cloudnetservice.launcher") diff --git a/launcher/patcher/build.gradle.kts b/launcher/patcher/build.gradle.kts index 221290f1f6..08f23610ab 100644 --- a/launcher/patcher/build.gradle.kts +++ b/launcher/patcher/build.gradle.kts @@ -16,6 +16,7 @@ plugins { id("cloudnet-java") + id("cloudnet-git") } tasks.jar.configure { @@ -27,4 +28,4 @@ tasks.withType().configureEach { targetCompatibility = JavaVersion.VERSION_17.toString() } -applyJarMetadata("eu.cloudnetservice.launcher.patcher.CloudNetLauncherPatcher", "eu.cloudnetservice.launcher") +git.applyJarMetadata("eu.cloudnetservice.launcher.patcher.CloudNetLauncherPatcher", "eu.cloudnetservice.launcher") diff --git a/node/impl/build.gradle.kts b/node/impl/build.gradle.kts index bde6e8d444..dd2854c7e8 100644 --- a/node/impl/build.gradle.kts +++ b/node/impl/build.gradle.kts @@ -17,6 +17,7 @@ plugins { alias(libs.plugins.shadow) id("cloudnet-java") + id("cloudnet-git") } val exportCnlFile = tasks.register("exportCnlFile") { @@ -91,4 +92,4 @@ dependencies { wrapperJar(projects.wrapperJvm.wrapperJvmImpl) { targetConfiguration = "shadow" } } -applyJarMetadata("eu.cloudnetservice.node.impl.boot.Bootstrap", "eu.cloudnetservice.node") +git.applyJarMetadata("eu.cloudnetservice.node.impl.boot.Bootstrap", "eu.cloudnetservice.node") diff --git a/wrapper-jvm/impl/build.gradle.kts b/wrapper-jvm/impl/build.gradle.kts index 90dda19f06..2ce30af8f2 100644 --- a/wrapper-jvm/impl/build.gradle.kts +++ b/wrapper-jvm/impl/build.gradle.kts @@ -17,6 +17,7 @@ plugins { alias(libs.plugins.shadow) id("cloudnet-java") + id("cloudnet-git") } val ignoredGroupIds = listOf("com.google.guava", "com.google.code.gson") @@ -74,7 +75,7 @@ dependencies { "annotationProcessor"(projects.driver.driverAp) } -applyJarMetadata( +git.applyJarMetadata( "eu.cloudnetservice.wrapper.impl.Main", "eu.cloudnetservice.wrapper", "eu.cloudnetservice.wrapper.impl.Premain") From d2bb8321afee4ae32304317c4824aa485369391d Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:38:27 +0200 Subject: [PATCH 25/45] cleanup --- .../src/main/kotlin/extensions.kt | 49 +++++++++---------- build-extensions/src/main/kotlin/tasks.kt | 2 +- gradle.properties | 1 + launcher/java22/build.gradle.kts | 2 +- launcher/patcher/build.gradle.kts | 4 +- node/impl/build.gradle.kts | 2 +- wrapper-jvm/impl/build.gradle.kts | 17 ++++++- 7 files changed, 44 insertions(+), 33 deletions(-) diff --git a/build-extensions/src/main/kotlin/extensions.kt b/build-extensions/src/main/kotlin/extensions.kt index 71c5275b65..e01d8a8f13 100644 --- a/build-extensions/src/main/kotlin/extensions.kt +++ b/build-extensions/src/main/kotlin/extensions.kt @@ -21,39 +21,37 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.TaskProvider import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.attributes import org.gradle.kotlin.dsl.findByType -import org.gradle.kotlin.dsl.named import org.gradle.kotlin.dsl.the -fun GitExtension.applyJarMetadata(mainClass: String, module: String) { - applyJarMetadata(mainClass, module, null) +fun GitExtension.applyJarMetadata(task: TaskProvider, mainClass: String, module: String) { + applyJarMetadata(task, mainClass, module, null) } -fun GitExtension.applyJarMetadata(mainClass: String, module: String, preMain: String?) { +fun GitExtension.applyJarMetadata(task: TaskProvider, mainClass: String, module: String, preMain: String?) { project.run { - if ("jar" in tasks.names) { - tasks.named("jar") { - val service = git()?.service - service?.let { usesService(it) } + task.configure { + val service = git()?.service + service?.let { usesService(it) } - manifest.attributes( - "Main-Class" to mainClass, - "Automatic-Module-Name" to module, - "Implementation-Vendor" to "CloudNetService", - "Implementation-Title" to Versions.cloudNetCodeName, - "Implementation-Version" to project.version.toString() + "-${service.shortCommitHash()}" - ) - // apply the pre-main class if given - if (preMain != null) { - manifest.attributes("Premain-Class" to preMain) - } - // apply git information to manifest - service?.run { get() }?.let { service -> - service.commit?.name?.substring(0, 8)?.let { manifest.attributes("Git-Commit" to it) } - service.branchName?.let { manifest.attributes("Git-Branch" to it) } - } + manifest.attributes( + "Main-Class" to mainClass, + "Automatic-Module-Name" to module, + "Implementation-Vendor" to "CloudNetService", + "Implementation-Title" to Versions.cloudNetCodeName, + "Implementation-Version" to project.version.toString() + "-${service.shortCommitHash()}" + ) + // apply the pre-main class if given + if (preMain != null) { + manifest.attributes("Premain-Class" to preMain) + } + // apply git information to manifest + service?.run { get() }?.let { service -> + service.commit?.name?.substring(0, 8)?.let { manifest.attributes("Git-Commit" to it) } + service.branchName?.let { manifest.attributes("Git-Branch" to it) } } } } @@ -67,9 +65,6 @@ fun Project.git(): GitExtension? = extensions.findByType() fun Project.sourceSets(): SourceSetContainer = the().sourceSets -fun Project.mavenRepositories(): Iterable = - repositories.filterIsInstance() - fun releasesOnly(repository: MavenArtifactRepository) { repository.mavenContent { releasesOnly() diff --git a/build-extensions/src/main/kotlin/tasks.kt b/build-extensions/src/main/kotlin/tasks.kt index bcb31b9b74..40c91a32ba 100644 --- a/build-extensions/src/main/kotlin/tasks.kt +++ b/build-extensions/src/main/kotlin/tasks.kt @@ -82,7 +82,7 @@ abstract class ExportCnlFile : DefaultTask() { // Evaluate group lazily projectGroup.set(project.provider { project.group.toString() }) outputFile.convention(layout.file(fileName.map { temporaryDir.resolve(it) })) - mavenRepositories.convention(project.mavenRepositories().map { CacheableMavenRepository(it) }.toList()) + mavenRepositories.convention(project.repositories.filterIsInstance().map { CacheableMavenRepository(it) }.toList()) } fun setResolvedArtifacts(runtimeClasspath: Provider) { diff --git a/gradle.properties b/gradle.properties index 009d0bbc75..2d9c0614c6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,6 +16,7 @@ org.gradle.caching=true org.gradle.configuration-cache=true org.gradle.configuration-cache.problems=warn +org.gradle.configuration-cache.integrity-check=true org.gradle.configureondemand=true org.gradle.parallel=true #org.gradle.unsafe.isolated-projects=true # blocked on spotless https://github.com/diffplug/spotless/issues/1979 diff --git a/launcher/java22/build.gradle.kts b/launcher/java22/build.gradle.kts index 70f8d7483e..00334445b1 100644 --- a/launcher/java22/build.gradle.kts +++ b/launcher/java22/build.gradle.kts @@ -29,4 +29,4 @@ dependencies { "implementation"(projects.launcher.java8) } -git.applyJarMetadata("eu.cloudnetservice.launcher.java8.Launcher", "eu.cloudnetservice.launcher") +git.applyJarMetadata(tasks.shadowJar, "eu.cloudnetservice.launcher.java8.Launcher", "eu.cloudnetservice.launcher") diff --git a/launcher/patcher/build.gradle.kts b/launcher/patcher/build.gradle.kts index 08f23610ab..bdc2d54be5 100644 --- a/launcher/patcher/build.gradle.kts +++ b/launcher/patcher/build.gradle.kts @@ -28,4 +28,6 @@ tasks.withType().configureEach { targetCompatibility = JavaVersion.VERSION_17.toString() } -git.applyJarMetadata("eu.cloudnetservice.launcher.patcher.CloudNetLauncherPatcher", "eu.cloudnetservice.launcher") +git.applyJarMetadata( + tasks.jar, "eu.cloudnetservice.launcher.patcher.CloudNetLauncherPatcher", "eu.cloudnetservice.launcher" +) diff --git a/node/impl/build.gradle.kts b/node/impl/build.gradle.kts index dd2854c7e8..878d880094 100644 --- a/node/impl/build.gradle.kts +++ b/node/impl/build.gradle.kts @@ -92,4 +92,4 @@ dependencies { wrapperJar(projects.wrapperJvm.wrapperJvmImpl) { targetConfiguration = "shadow" } } -git.applyJarMetadata("eu.cloudnetservice.node.impl.boot.Bootstrap", "eu.cloudnetservice.node") +git.applyJarMetadata(tasks.jar, "eu.cloudnetservice.node.impl.boot.Bootstrap", "eu.cloudnetservice.node") diff --git a/wrapper-jvm/impl/build.gradle.kts b/wrapper-jvm/impl/build.gradle.kts index 2ce30af8f2..db0de50558 100644 --- a/wrapper-jvm/impl/build.gradle.kts +++ b/wrapper-jvm/impl/build.gradle.kts @@ -1,3 +1,5 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + /* * Copyright 2019-2025 CloudNetService team & contributors * @@ -29,8 +31,10 @@ val exportCnlFile = tasks.register("exportCnlFile") { val exportLanguageFileInformation = tasks.register("exportLanguageFileInformation") { languageFiles.from(project.projectDir.resolve("src/main/resources/lang").listFiles()) } -tasks.shadowJar.configure { - archiveFileName.set(Files.wrapper) + +// intermediate task to take advantage of build cache when checking out another branch +val intermediateShadowJar = tasks.register("intermediateShadowJar") { + this.configurations.set(project.configurations.runtimeClasspath.map { setOf(it) }) // do not shade dependencies which we don't need to shade @@ -50,6 +54,14 @@ tasks.shadowJar.configure { from(exportLanguageFileInformation) from(exportCnlFile) + + destinationDirectory = temporaryDir +} +tasks.shadowJar.configure { + archiveFileName.set(Files.wrapper) + + configurations.empty() + from(intermediateShadowJar) } tasks.withType().configureEach { @@ -76,6 +88,7 @@ dependencies { } git.applyJarMetadata( + tasks.jar, "eu.cloudnetservice.wrapper.impl.Main", "eu.cloudnetservice.wrapper", "eu.cloudnetservice.wrapper.impl.Premain") From 37d2c9c48d1a398af0de8d9cbde518cb20aded58 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:51:33 +0200 Subject: [PATCH 26/45] fix conditional plugin logic --- build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt | 2 +- build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt | 2 +- build-extensions/src/main/kotlin/publishing-extensions.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt b/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt index 8b864c095b..cd2f29f46d 100644 --- a/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt +++ b/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt @@ -172,7 +172,7 @@ private fun Project.configureCompileJava() { } private fun Project.configureShadow() { - if (plugins.hasPlugin(ShadowJavaPlugin::class)) { + plugins.withId("com.gradleup.shadow") { tasks.named("assemble").configure { dependsOn(tasks.named("shadowJar")) } diff --git a/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt b/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt index 886e915b72..e6c4a90550 100644 --- a/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt +++ b/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt @@ -33,7 +33,7 @@ class CloudNetPublishPlugin : Plugin { // all these projects are publishing their java artifacts // must happen after repository/dependency declaration afterEvaluate { - if (plugins.hasPlugin(JavaBasePlugin::class)) { + plugins.withId("java") { configurePublishing("java") // create consumable artifacts for global javadoc diff --git a/build-extensions/src/main/kotlin/publishing-extensions.kt b/build-extensions/src/main/kotlin/publishing-extensions.kt index 3148b8db61..5df5c94df3 100644 --- a/build-extensions/src/main/kotlin/publishing-extensions.kt +++ b/build-extensions/src/main/kotlin/publishing-extensions.kt @@ -126,7 +126,7 @@ fun Project.configurePublishing(publishedComponent: String) { } } - if (plugins.hasPlugin(JavaBasePlugin::class)) { + plugins.withId("java") { extensions.configure { withSourcesJar() withJavadocJar() From fd5e9847c70454c3dfef9a83cb12ae0dead30f77 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:55:51 +0200 Subject: [PATCH 27/45] cleanup --- build-extensions/src/main/kotlin/tasks.kt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/build-extensions/src/main/kotlin/tasks.kt b/build-extensions/src/main/kotlin/tasks.kt index 40c91a32ba..dca5d65b86 100644 --- a/build-extensions/src/main/kotlin/tasks.kt +++ b/build-extensions/src/main/kotlin/tasks.kt @@ -103,11 +103,7 @@ abstract class ExportCnlFile : DefaultTask() { @TaskAction fun run() { -// this.dependencies.get().dependents.forEach { -// println(it) -// } val resolvedArtifacts = ArrayList() - println("---------------------") val projectGroup = projectGroup.get() dependencies.get().forEach { it -> val id = it.id @@ -201,11 +197,6 @@ data class CacheableMavenRepository(@Input val name: String, @Input val url: Str constructor(repository: MavenArtifactRepository) : this(repository.name, repository.url.toString()) } - -abstract class ResolveRepository : WorkAction { - interface Params : WorkParameters {} -} - private suspend fun resolveRepository( testUrlPath: String, repositories: Iterable ): CacheableMavenRepository? { From 39bb2359d2adb63e918dfac7f990b9f67ae35825 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Sat, 2 Aug 2025 15:23:00 +0200 Subject: [PATCH 28/45] start work on genUpdaterInformation --- build.gradle.kts | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 52fa1a83f0..472f61a80d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -65,19 +65,17 @@ dependencies { } } -gradle.projectsEvaluated { - tasks.register("genUpdaterInformation") { - subprojects.forEach { - // check if we need to depend on the plugin - // TODO this breaks isolated projects - if (!it.plugins.hasPlugin("java")) return@forEach - // depend this task on the build output of each subproject - dependsOn("${it.path}:build") - } - // generate the updater information - doLast { - generateUpdaterInformation() - } +tasks.register("genUpdaterInformation") { + subprojects.forEach { + // check if we need to depend on the plugin + // TODO this breaks isolated projects + if (!it.plugins.hasPlugin("java")) return@forEach + // depend this task on the build output of each subproject + dependsOn("${it.path}:build") + } + // generate the updater information + doLast { + generateUpdaterInformation() } } From 5220dbe0d56b6be63fd1a8283ac5a51947ffeafe Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 14:15:49 +0200 Subject: [PATCH 29/45] I think this works? --- .gitignore | 1 + bom/build.gradle.kts | 2 + build-extensions/build.gradle.kts | 22 ++- .../src/main/kotlin/CloudNetModulesPlugin.kt | 42 ----- .../cloudnet/gradle/ChecksumHelper.kt | 46 +++++ .../cloudnetservice/cloudnet/gradle}/Files.kt | 4 +- .../cloudnet/gradle}/Versions.kt | 4 +- .../cloudnet/gradle}/extensions.kt | 33 ++-- .../gradle/plugins}/CloudNetJavaApiPlugin.kt | 3 + .../gradle/plugins}/CloudNetJavaPlugin.kt | 31 ++-- .../plugins}/CloudNetModulesApiPlugin.kt | 4 + .../gradle/plugins/CloudNetModulesPlugin.kt | 78 +++++++++ .../gradle/plugins}/CloudNetPlugin.kt | 3 + .../gradle/plugins}/CloudNetPluginsPlugin.kt | 4 + .../gradle/plugins}/CloudNetPublishPlugin.kt | 8 +- .../gradle/plugins}/CloudNetSettingsPlugin.kt | 2 + .../gradle/plugins}/git/CloudNetGitPlugin.kt | 2 +- .../gradle/plugins}/git/GitService.kt | 64 ++++--- .../plugins/updater/CloudNetUpdaterPlugin.kt | 87 +++++++++ .../updater/GenerateUpdaterInformationTask.kt | 133 ++++++++++++++ .../cloudnet/gradle/plugins/updater/Meta.kt | 106 +++++++++++ .../plugins/updater/PrepareUpdaterDataTask.kt | 61 +++++++ .../cloudnet/gradle}/publishing-extensions.kt | 6 +- .../cloudnet/gradle}/settings-plugin.kt | 2 + .../cloudnetservice/cloudnet/gradle}/tasks.kt | 4 +- .../src/main/kotlin/updater-extensions.kt | 165 ------------------ build.gradle.kts | 23 +-- .../runtime/build.gradle.kts | 2 + gradle.properties | 1 - launcher/java22/build.gradle.kts | 12 ++ launcher/java8/build.gradle.kts | 2 + launcher/patcher/build.gradle.kts | 12 ++ modules/bridge/impl/build.gradle.kts | 2 + modules/cloudflare/impl/build.gradle.kts | 2 + .../database-mongodb/impl/build.gradle.kts | 2 + modules/database-mysql/impl/build.gradle.kts | 2 + .../dockerized-services/impl/build.gradle.kts | 2 + modules/influx/impl/build.gradle.kts | 1 + modules/labymod/impl/build.gradle.kts | 1 + modules/npcs/impl/build.gradle.kts | 1 + modules/report/impl/build.gradle.kts | 2 + modules/signs/impl/build.gradle.kts | 1 + modules/smart/impl/build.gradle.kts | 1 + modules/storage-s3/impl/build.gradle.kts | 2 + modules/storage-sftp/impl/build.gradle.kts | 2 + modules/syncproxy/impl/build.gradle.kts | 1 + node/impl/build.gradle.kts | 14 ++ plugins/luckperms/build.gradle.kts | 2 + plugins/papi-expansion/build.gradle.kts | 2 + settings.gradle.kts | 1 - wrapper-jvm/impl/build.gradle.kts | 8 +- 51 files changed, 718 insertions(+), 300 deletions(-) delete mode 100644 build-extensions/src/main/kotlin/CloudNetModulesPlugin.kt create mode 100644 build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/ChecksumHelper.kt rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle}/Files.kt (94%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle}/Versions.kt (89%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle}/extensions.kt (66%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/CloudNetJavaApiPlugin.kt (91%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/CloudNetJavaPlugin.kt (91%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/CloudNetModulesApiPlugin.kt (92%) create mode 100644 build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetModulesPlugin.kt rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/CloudNetPlugin.kt (90%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/CloudNetPluginsPlugin.kt (92%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/CloudNetPublishPlugin.kt (87%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/CloudNetSettingsPlugin.kt (93%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/git/CloudNetGitPlugin.kt (96%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle/plugins}/git/GitService.kt (58%) create mode 100644 build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt create mode 100644 build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt create mode 100644 build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/Meta.kt create mode 100644 build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/PrepareUpdaterDataTask.kt rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle}/publishing-extensions.kt (97%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle}/settings-plugin.kt (98%) rename build-extensions/src/main/kotlin/{ => eu/cloudnetservice/cloudnet/gradle}/tasks.kt (99%) delete mode 100644 build-extensions/src/main/kotlin/updater-extensions.kt diff --git a/.gitignore b/.gitignore index 98b97df15f..b38aae6044 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,5 @@ atlassian-ide-plugin.xml */src/main/lombok # CloudNet +.launchermeta-copy/ .launchermeta/ diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index 34455b9977..c6de1888e1 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.configurePublishing + plugins { id("java-platform") id("cloudnet-publish") diff --git a/build-extensions/build.gradle.kts b/build-extensions/build.gradle.kts index 230a71b947..966fb7f1f6 100644 --- a/build-extensions/build.gradle.kts +++ b/build-extensions/build.gradle.kts @@ -41,39 +41,43 @@ gradlePlugin { plugins { register("cloudnet") { id = "cloudnet" - implementationClass = "CloudNetPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetPlugin" } register("cloudnet-git") { id = "cloudnet-git" - implementationClass = "git.CloudNetGitPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.git.CloudNetGitPlugin" + } + register("cloudnet-updater") { + id = "cloudnet-updater" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.updater.CloudNetUpdaterPlugin" } register("cloudnet-settings") { id = "cloudnet-settings" - implementationClass = "CloudNetSettingsPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetSettingsPlugin" } register("cloudnet-publish") { id = "cloudnet-publish" - implementationClass = "CloudNetPublishPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetPublishPlugin" } register("cloudnet-java") { id = "cloudnet-java" - implementationClass = "CloudNetJavaPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetJavaPlugin" } register("cloudnet-java-api") { id = "cloudnet-java-api" - implementationClass = "CloudNetJavaApiPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetJavaApiPlugin" } register("cloudnet-modules") { id = "cloudnet-modules" - implementationClass = "CloudNetModulesPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetModulesPlugin" } register("cloudnet-modules-api") { id = "cloudnet-modules-api" - implementationClass = "CloudNetModulesApiPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetModulesApiPlugin" } register("cloudnet-plugins") { id = "cloudnet-plugins" - implementationClass = "CloudNetPluginsPlugin" + implementationClass = "eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetPluginsPlugin" } } } diff --git a/build-extensions/src/main/kotlin/CloudNetModulesPlugin.kt b/build-extensions/src/main/kotlin/CloudNetModulesPlugin.kt deleted file mode 100644 index a655e494a1..0000000000 --- a/build-extensions/src/main/kotlin/CloudNetModulesPlugin.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019-2025 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import eu.cloudnetservice.gradle.juppiter.JuppiterPlugin -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.invoke -import org.gradle.kotlin.dsl.maven -import org.gradle.kotlin.dsl.project -import org.gradle.kotlin.dsl.repositories - -class CloudNetModulesPlugin : Plugin { - override fun apply(project: Project) { - project.run { - apply() - apply() - - configurations { - named("testImplementation").configure { - extendsFrom(getByName("moduleLibrary")) - } - } - - configureModules() - } - } -} diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/ChecksumHelper.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/ChecksumHelper.kt new file mode 100644 index 0000000000..756919e72f --- /dev/null +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/ChecksumHelper.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.cloudnetservice.cloudnet.gradle + +import java.io.File +import java.io.IOException +import java.security.MessageDigest +import java.security.NoSuchAlgorithmException + +// Copies from the updater to keep consistent when generating checksums +object ChecksumHelper { + @Throws(IOException::class) + fun fileShaSum(path: File): String { + return newSha3256Digest().run { + update(path.readBytes()) + bytesToHex(digest()) + } + } + + @Throws(NoSuchAlgorithmException::class) + private fun newSha3256Digest(): MessageDigest = MessageDigest.getInstance("SHA3-256") + + private fun bytesToHex(input: ByteArray): String { + val buffer = StringBuilder() + for (b in input) { + buffer.append(Character.forDigit(b.toInt() shr 4 and 0xF, 16)) + buffer.append(Character.forDigit(b.toInt() and 0xF, 16)) + } + // convert to a string + return buffer.toString() + } +} diff --git a/build-extensions/src/main/kotlin/Files.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/Files.kt similarity index 94% rename from build-extensions/src/main/kotlin/Files.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/Files.kt index 42c60f7c59..6654dfae7b 100644 --- a/build-extensions/src/main/kotlin/Files.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/Files.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 CloudNetService team & contributors + * Copyright 2019-2025 CloudNetService team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,8 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle + object Files { const val driver = "driver.jar" diff --git a/build-extensions/src/main/kotlin/Versions.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/Versions.kt similarity index 89% rename from build-extensions/src/main/kotlin/Versions.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/Versions.kt index 15b7f2d911..1113c041a9 100644 --- a/build-extensions/src/main/kotlin/Versions.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/Versions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 CloudNetService team & contributors + * Copyright 2019-2025 CloudNetService team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,8 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle + import org.gradle.jvm.toolchain.JavaLanguageVersion object Versions { diff --git a/build-extensions/src/main/kotlin/extensions.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt similarity index 66% rename from build-extensions/src/main/kotlin/extensions.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt index e01d8a8f13..8eed270b45 100644 --- a/build-extensions/src/main/kotlin/extensions.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 CloudNetService team & contributors + * Copyright 2019-2025 CloudNetService team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,10 @@ * limitations under the License. */ -import git.GitExtension -import git.GitService +package eu.cloudnetservice.cloudnet.gradle + +import eu.cloudnetservice.cloudnet.gradle.plugins.git.GitExtension +import eu.cloudnetservice.cloudnet.gradle.plugins.git.GitService import org.gradle.api.Project import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.api.plugins.JavaPluginExtension @@ -26,6 +28,8 @@ import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.attributes import org.gradle.kotlin.dsl.findByType import org.gradle.kotlin.dsl.the +import java.util.* +import java.util.function.Function fun GitExtension.applyJarMetadata(task: TaskProvider, mainClass: String, module: String) { applyJarMetadata(task, mainClass, module, null) @@ -35,30 +39,33 @@ fun GitExtension.applyJarMetadata(task: TaskProvider, mainClass: String project.run { task.configure { val service = git()?.service + val serviceOrEmpty = (service?.map { Optional.of(it) }) ?: provider { Optional.empty() } service?.let { usesService(it) } + val projectVersion = project.version.toString() + manifest.attributes( "Main-Class" to mainClass, "Automatic-Module-Name" to module, "Implementation-Vendor" to "CloudNetService", "Implementation-Title" to Versions.cloudNetCodeName, - "Implementation-Version" to project.version.toString() + "-${service.shortCommitHash()}" + "Implementation-Version" to serviceOrEmpty.shortCommitHash().map { "$projectVersion-$it" }, + "Git-Commit" to serviceOrEmpty.shortCommitHash(), + "Git-Branch" to serviceOrEmpty.map("unknown") { it.branchName } ) // apply the pre-main class if given - if (preMain != null) { - manifest.attributes("Premain-Class" to preMain) - } - // apply git information to manifest - service?.run { get() }?.let { service -> - service.commit?.name?.substring(0, 8)?.let { manifest.attributes("Git-Commit" to it) } - service.branchName?.let { manifest.attributes("Git-Branch" to it) } + preMain?.let { + manifest.attributes("Premain-Class" to it) } } } } -fun Provider?.shortCommitHash(): String { - return this?.get()?.commit?.name()?.substring(0, 8) ?: "unknown" +fun Provider>.map(empty: String, function: Function) = + map { o -> o.map { function.apply(it) }.orElse(empty) } + +fun Provider>.shortCommitHash(): Provider { + return map("unknown") { it.commit?.name?.substring(0, 8) } } fun Project.git(): GitExtension? = extensions.findByType() diff --git a/build-extensions/src/main/kotlin/CloudNetJavaApiPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetJavaApiPlugin.kt similarity index 91% rename from build-extensions/src/main/kotlin/CloudNetJavaApiPlugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetJavaApiPlugin.kt index 67b1143f0b..413b7d0a3a 100644 --- a/build-extensions/src/main/kotlin/CloudNetJavaApiPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetJavaApiPlugin.kt @@ -14,6 +14,9 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle.plugins + +import eu.cloudnetservice.cloudnet.gradle.Versions import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.tasks.compile.JavaCompile diff --git a/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetJavaPlugin.kt similarity index 91% rename from build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetJavaPlugin.kt index cd2f29f46d..30b4080bff 100644 --- a/build-extensions/src/main/kotlin/CloudNetJavaPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetJavaPlugin.kt @@ -14,8 +14,16 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle.plugins + import com.diffplug.gradle.spotless.SpotlessExtension -import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin +import eu.cloudnetservice.cloudnet.gradle.Versions +import eu.cloudnetservice.cloudnet.gradle.bundle +import eu.cloudnetservice.cloudnet.gradle.library +import eu.cloudnetservice.cloudnet.gradle.libs +import eu.cloudnetservice.cloudnet.gradle.releasesOnly +import eu.cloudnetservice.cloudnet.gradle.snapshotsOnly +import eu.cloudnetservice.cloudnet.gradle.sourceSets import org.apache.tools.ant.filters.ReplaceTokens import org.gradle.api.Plugin import org.gradle.api.Project @@ -33,19 +41,7 @@ import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.jvm.toolchain.JavaToolchainService import org.gradle.jvm.toolchain.JavaToolchainSpec import org.gradle.jvm.toolchain.JvmVendorSpec -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.assign -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.exclude -import org.gradle.kotlin.dsl.filter -import org.gradle.kotlin.dsl.getByType -import org.gradle.kotlin.dsl.hasPlugin -import org.gradle.kotlin.dsl.maven -import org.gradle.kotlin.dsl.named -import org.gradle.kotlin.dsl.register -import org.gradle.kotlin.dsl.repositories -import org.gradle.kotlin.dsl.withType +import org.gradle.kotlin.dsl.* class CloudNetJavaPlugin : Plugin { override fun apply(project: Project) { @@ -72,10 +68,7 @@ class CloudNetJavaPlugin : Plugin { this.configureCompileJava() - afterEvaluate { - // Configure shadow after the subproject has been able to even apply it - this.configureShadow() - } + this.configureShadow() this.configureCheckstyle() @@ -178,7 +171,7 @@ private fun Project.configureShadow() { } tasks.named("jar").configure { // we use the shadow jar task, so move the jar into the task's temporary dir to avoid clutter - destinationDirectory = temporaryDir + destinationDirectory.convention(project.layout.dir(project.provider { temporaryDir })) } } } diff --git a/build-extensions/src/main/kotlin/CloudNetModulesApiPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetModulesApiPlugin.kt similarity index 92% rename from build-extensions/src/main/kotlin/CloudNetModulesApiPlugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetModulesApiPlugin.kt index 13177cbbe0..6a1669d954 100644 --- a/build-extensions/src/main/kotlin/CloudNetModulesApiPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetModulesApiPlugin.kt @@ -14,6 +14,10 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle.plugins + +import eu.cloudnetservice.cloudnet.gradle.library +import eu.cloudnetservice.cloudnet.gradle.libs import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.* diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetModulesPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetModulesPlugin.kt new file mode 100644 index 0000000000..1cbf034106 --- /dev/null +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetModulesPlugin.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.cloudnetservice.cloudnet.gradle.plugins + +import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.* +import eu.cloudnetservice.gradle.juppiter.GenerateModuleJson +import eu.cloudnetservice.gradle.juppiter.JuppiterPlugin +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.jvm.tasks.Jar +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.invoke +import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.property + +class CloudNetModulesPlugin : Plugin { + override fun apply(project: Project) { + project.run { + apply() + apply() + apply() + + configurations { + named("testImplementation").configure { + extendsFrom(getByName("moduleLibrary")) + } + } + + val generateModuleJson = tasks.named("genModuleJson") + + val archiveFileName = project.objects.property() + val prepareUpdaterData = tasks.named("prepareUpdaterData") { + dependsOn(generateModuleJson) + + from(generateModuleJson.flatMap { it.outputDirectory.file(it.fileName) }) + + val moduleJsonName = generateModuleJson.flatMap { it.fileName } + + meta.set(archiveFileName.flatMap { archiveName -> + moduleJsonName.map { moduleJsonName -> + Meta(Type.MODULE, Data.Module(archiveName, moduleJsonName)) + } + }) + } + + afterEvaluate { + val archiveProducer = (if (plugins.hasPlugin(ShadowJavaPlugin::class.java)) { + tasks.named("shadowJar") + } else if (plugins.hasPlugin("fabric-loom")) { + tasks.named("remapJar") + } else { + tasks.named("jar") + }) + + prepareUpdaterData.configure { + archiveFileName.convention(fromArchive(archiveProducer)) + } + } + + configureModules() + } + } +} diff --git a/build-extensions/src/main/kotlin/CloudNetPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPlugin.kt similarity index 90% rename from build-extensions/src/main/kotlin/CloudNetPlugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPlugin.kt index e6e781d2d9..f3f0fd750c 100644 --- a/build-extensions/src/main/kotlin/CloudNetPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPlugin.kt @@ -14,6 +14,9 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle.plugins + +import eu.cloudnetservice.cloudnet.gradle.Versions import org.gradle.api.Plugin import org.gradle.api.Project diff --git a/build-extensions/src/main/kotlin/CloudNetPluginsPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPluginsPlugin.kt similarity index 92% rename from build-extensions/src/main/kotlin/CloudNetPluginsPlugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPluginsPlugin.kt index c1d0060ade..8bbbe742c1 100644 --- a/build-extensions/src/main/kotlin/CloudNetPluginsPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPluginsPlugin.kt @@ -14,6 +14,10 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle.plugins + +import eu.cloudnetservice.cloudnet.gradle.library +import eu.cloudnetservice.cloudnet.gradle.libs import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.* diff --git a/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPublishPlugin.kt similarity index 87% rename from build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPublishPlugin.kt index e6c4a90550..6fa50688e2 100644 --- a/build-extensions/src/main/kotlin/CloudNetPublishPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetPublishPlugin.kt @@ -14,12 +14,14 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle.plugins + +import eu.cloudnetservice.cloudnet.gradle.CustomConfigurations +import eu.cloudnetservice.cloudnet.gradle.configurePublishing +import eu.cloudnetservice.cloudnet.gradle.sourceSets import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.plugins.JavaBasePlugin -import org.gradle.api.plugins.JavaPlugin import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.hasPlugin class CloudNetPublishPlugin : Plugin { override fun apply(project: Project) { diff --git a/build-extensions/src/main/kotlin/CloudNetSettingsPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetSettingsPlugin.kt similarity index 93% rename from build-extensions/src/main/kotlin/CloudNetSettingsPlugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetSettingsPlugin.kt index 1459b96ff3..b0a8f1eafc 100644 --- a/build-extensions/src/main/kotlin/CloudNetSettingsPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/CloudNetSettingsPlugin.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle.plugins + import org.gradle.api.Plugin import org.gradle.api.initialization.Settings diff --git a/build-extensions/src/main/kotlin/git/CloudNetGitPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/CloudNetGitPlugin.kt similarity index 96% rename from build-extensions/src/main/kotlin/git/CloudNetGitPlugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/CloudNetGitPlugin.kt index 1c57c1bccc..27550b9f66 100644 --- a/build-extensions/src/main/kotlin/git/CloudNetGitPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/CloudNetGitPlugin.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package git +package eu.cloudnetservice.cloudnet.gradle.plugins.git import org.gradle.api.Plugin import org.gradle.api.Project diff --git a/build-extensions/src/main/kotlin/git/GitService.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/GitService.kt similarity index 58% rename from build-extensions/src/main/kotlin/git/GitService.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/GitService.kt index 4d03630c3a..36095982e9 100644 --- a/build-extensions/src/main/kotlin/git/GitService.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/GitService.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package git +package eu.cloudnetservice.cloudnet.gradle.plugins.git import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.* @@ -27,6 +27,7 @@ import java.io.Closeable import java.lang.AutoCloseable import java.nio.file.Path import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicReference import kotlin.io.path.isDirectory import kotlin.io.path.notExists import kotlin.io.path.useLines @@ -54,41 +55,60 @@ abstract class GitService : BuildService, AutoCloseable { get() = head?.run { if (!this.isSymbolic) null else this.target } /** - * Currently has no support for git submodules. + * Currently has no support for eu.cloudnetservice.cloudnet.gradle.git submodules. * We don't use them so it should be ok */ - private class GitInstance(dir: Path) : Closeable { + private class GitInstance(private val dir: Path) : Closeable { companion object { val logger: Logger = LoggerFactory.getLogger(GitInstance::class.java) - const val GIT_DIR = ".git" + const val GIT_DIR = ".eu.cloudnetservice.cloudnet.gradle.git" const val GITDIR_PREFIX = "gitdir:" } private val usable = AtomicBoolean(false) - val repository: Repository? + private val closed = AtomicBoolean(false) + private val wrapper = AtomicReference() + val git: Git? + get() = resolve()?.git + + private fun resolve(): Wrapper? { + if (closed.get()) return null + if (usable.compareAndSet(false, true)) { + var targetDir: Path? = dir + while (targetDir?.resolve(GIT_DIR)?.notExists() ?: false) { + targetDir = targetDir.parent + } - init { - var targetDir: Path? = dir - while (targetDir?.resolve(GIT_DIR)?.notExists() ?: false) { - targetDir = targetDir.parent + val gitDir = targetDir?.let { resolveGitDirectory(it) } + if (targetDir == null || gitDir == null) { + logger.info("[Git] Unable to find repository for $dir") + } else { + val repository = + RepositoryBuilder().setWorkTree(dir.toFile()).setGitDir(gitDir.toFile()).setMustExist(true).build() + val git = Git.wrap(repository) + val wrapper = Wrapper(git, repository) + if (this.wrapper.compareAndSet(null, wrapper)) { + return wrapper + } else { + wrapper.close() + return this.wrapper.get() + } + } } + return wrapper.get() + } - val gitDir = targetDir?.let { resolveGitDirectory(it) } - if (targetDir == null || gitDir == null) { - logger.info("[Git] Unable to find repository for $dir") - repository = null - git = null - } else { - repository = - RepositoryBuilder().setWorkTree(dir.toFile()).setGitDir(gitDir.toFile()).setMustExist(true).build() - git = Git.wrap(repository) + private data class Wrapper(val git: Git, val repository: Repository) : Closeable { + override fun close() { + git.close() + repository.close() } } private fun resolveGitDirectory(projectDir: Path): Path? { // https://git-scm.com/docs/gitrepository-layout - // .git file is allowed with 'gitdir:' reference + // .eu.cloudnetservice.cloudnet.gradle.git file is allowed with 'gitdir:' reference projectDir.run { if (fileName.toString() == GIT_DIR) projectDir else projectDir.resolve(GIT_DIR) }.run { @@ -100,14 +120,14 @@ abstract class GitService : BuildService, AutoCloseable { } } } - logger.warn("[Git] Could not determine git directory for $projectDir") + logger.warn("[Git] Could not determine eu.cloudnetservice.cloudnet.gradle.git directory for $projectDir") return null } } override fun close() { - if (usable.compareAndSet(true, false)) { - repository!!.close() + if (closed.compareAndSet(false, true)) { + wrapper.getAndSet(null)?.close() } } } diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt new file mode 100644 index 0000000000..2630d7a3b8 --- /dev/null +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.cloudnetservice.cloudnet.gradle.plugins.updater + +import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin +import eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetJavaPlugin +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.attributes.Category +import org.gradle.api.attributes.LibraryElements +import org.gradle.api.attributes.Usage +import org.gradle.jvm.tasks.Jar +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.project +import org.gradle.kotlin.dsl.register + +class CloudNetUpdaterPlugin : Plugin { + companion object { + const val UPDATER_DATA = "updater-data" + } + + override fun apply(project: Project) { + if (project.rootProject == project) { + project.configureRootProject() + } else { + project.configureSubProject() + } + } + + fun Project.configureSubProject() { + apply() + + val updaterData = configurations.register("updaterData") { + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY)) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(UPDATER_DATA)) + } + } + + val prepareUpdaterData = tasks.register("prepareUpdaterData") { + into(temporaryDir) + } + + artifacts.add(updaterData.name, prepareUpdaterData) + } + + fun Project.configureRootProject() { + val updaterDependencies = configurations.register("updaterDependencies") { + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY)) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(UPDATER_DATA)) + } + } + + + subprojects.map { it.isolated }.forEach { + println(it.name) + dependencies.add( + updaterDependencies.name, dependencies.project(path = it.path) + ) + } + + val view = updaterDependencies.map { it.incoming.artifactView { isLenient = true } } + val artifacts = view.flatMap { it.artifacts.resolvedArtifacts } + val genUpdaterInformation = tasks.register("genUpdaterInformation", artifacts) + genUpdaterInformation.configure { + this.destinationDirectory.set(project.layout.projectDirectory.dir(".launchermeta")) + } + } +} diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt new file mode 100644 index 0000000000..051b6a9d1f --- /dev/null +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.cloudnetservice.cloudnet.gradle.plugins.updater + +import com.google.gson.Gson +import com.google.gson.JsonArray +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import eu.cloudnetservice.cloudnet.gradle.ChecksumHelper +import eu.cloudnetservice.cloudnet.gradle.Versions +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.result.ResolvedArtifactResult +import org.gradle.api.file.ArchiveOperations +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import java.util.Properties +import javax.inject.Inject + +abstract class GenerateUpdaterInformationTask @Inject constructor(private val artifacts: Provider>) : + DefaultTask() { + + @get:OutputDirectory + abstract val destinationDirectory: DirectoryProperty + + @get:InputFile + abstract val initialModules: RegularFileProperty + + init { + initialModules.convention(project.layout.file(project.provider { project.file("modules.json") })) + dependsOn(artifacts) + } + + @TaskAction + fun run() { + val artifacts = artifacts.get() + val destination = destinationDirectory.get().asFile + destination.deleteRecursively() + destination.mkdirs() + val modulesDirectory = destination.resolve("modules") + modulesDirectory.mkdirs() + + val moduleJsonArray = initialModules.get().asFile.bufferedReader().use { + JsonParser.parseReader(it).asJsonObject.get("entries").asJsonArray + } + + val checksums = Properties() + + artifacts.map { it.file }.forEach { directory -> + val meta = directory.resolve("meta.json").readText().run { Meta.gson.fromJson(this, Meta::class.java) } + val data = meta.data + when (meta.type) { + Type.MODULE -> { + data as Data.Module + val moduleJson = directory.resolve(data.moduleJsonName).bufferedReader().use { + JsonParser.parseReader(it).asJsonObject + } + val moduleFile = directory.resolve(data.archiveName) + moduleJsonArray.add(JsonObject().apply { + addProperty("official", true) + addProperty("name", moduleJson.get("name").asString) + addProperty("website", moduleJson.get("website").asString) + addProperty("version", moduleJson.get("version").asString) + addProperty("sha3256", ChecksumHelper.fileShaSum(moduleFile)) + addProperty("description", moduleJson.get("description").asString) + + add("maintainers", JsonArray(1).apply { add(moduleJson.get("author").asString) }) + add("releaseNotes", JsonArray(1).apply { add("Working with CloudNet ${Versions.cloudNet}") }) + + add("dependingModules", JsonArray().apply { + val dependencies = moduleJson.get("dependencies")?.asJsonArray ?: JsonArray() + dependencies.map { it.asJsonObject }.filter { !it.has("repo") }.map { it.get("name").asString } + .forEach { add(it) } + }) + }) + moduleFile.copyTo(modulesDirectory.resolve(moduleFile.name)) + } + + Type.NODE -> { + data as Data.Node + val nodeFile = directory.resolve(data.archiveName) + nodeFile.copyTo(destination.resolve(nodeFile.name)) + checksums.setProperty("node", ChecksumHelper.fileShaSum(nodeFile)) + } + + Type.LAUNCHER -> { + data as Data.Launcher + val launcherFile = directory.resolve(data.archiveName) + launcherFile.copyTo(destination.resolve(launcherFile.name)) + checksums.setProperty("launcher", ChecksumHelper.fileShaSum(launcherFile)) + } + + Type.LAUNCHER_PATCHER -> { + data as Data.LauncherPatcher + val launcherPatcherFile = directory.resolve(data.archiveName) + launcherPatcherFile.copyTo(destination.resolve(launcherPatcherFile.name)) + checksums.setProperty("launcher-patcher", ChecksumHelper.fileShaSum(launcherPatcherFile)) + } + + Type.EMPTY -> { + logger.error("Detected empty metadata dependency. Please fix your configuration!") + } + } + } + + val modulesJsonFile = destination.resolve("modules.json") + modulesJsonFile.writeText(Gson().toJson(JsonObject().apply { + add("entries", moduleJsonArray) + })) + checksums.setProperty("modules-json", ChecksumHelper.fileShaSum(modulesJsonFile)) + + destination.resolve("checksums.properties").bufferedWriter().use { + checksums.store(it, "Checksums for CloudNet ${Versions.cloudNet}-${Versions.cloudNetCodeName}") + } + } +} diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/Meta.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/Meta.kt new file mode 100644 index 0000000000..11244ef059 --- /dev/null +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/Meta.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.cloudnetservice.cloudnet.gradle.plugins.updater + +import com.google.gson.GsonBuilder +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer +import java.io.Serializable + +data class Meta( + val type: Type, + val data: Data +) : Serializable { + companion object { + val gson = GsonBuilder().registerTypeHierarchyAdapter(Meta::class.java, MetaAdapter).create() + } + + /** + * Custom serializer to support the Data interface + */ + object MetaAdapter : JsonSerializer, JsonDeserializer { + override fun serialize( + src: Meta, + typeOfSrc: java.lang.reflect.Type, + context: JsonSerializationContext + ): JsonElement { + val json = JsonObject() + json.add("type", context.serialize(src.type)) + json.add("data", context.serialize(src.data)) + return json + } + + override fun deserialize( + json: JsonElement, + typeOfT: java.lang.reflect.Type, + context: JsonDeserializationContext + ): Meta { + val json = json.asJsonObject + val type = context.deserialize(json.get("type"), Type::class.java) + val dataClass = when (type) { + Type.MODULE -> Data.Module::class + Type.NODE -> Data.Node::class + Type.LAUNCHER -> Data.Launcher::class + Type.LAUNCHER_PATCHER -> Data.LauncherPatcher::class + Type.EMPTY -> Data.Empty::class + } + val data = context.deserialize(json.get("data"), dataClass.java) + return Meta(type, data) + } + } +} + +enum class Type : Serializable { + MODULE, + NODE, + LAUNCHER, + LAUNCHER_PATCHER, + + /** + * Empty type. Should in reality never be used and will print a warning when detected. + * This is useful because it allows for nice conventions and better initial setup/troubleshooting. + */ + EMPTY +} + +sealed interface Data : Serializable { + data class Module( + val archiveName: String, + val moduleJsonName: String + ) : Data + + data class Node( + val archiveName: String, + ) : Data + + data class Launcher( + val archiveName: String + ) : Data + + data class LauncherPatcher( + val archiveName: String + ) : Data + + object Empty : Data { + @Suppress("unused") // kotlin wants this + private fun readResolve(): Any = Empty + } +} diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/PrepareUpdaterDataTask.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/PrepareUpdaterDataTask.kt new file mode 100644 index 0000000000..d0a0354b9c --- /dev/null +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/PrepareUpdaterDataTask.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2019-2025 CloudNetService team & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.cloudnetservice.cloudnet.gradle.plugins.updater + +import org.gradle.api.Task +import org.gradle.api.file.RegularFile +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.* +import org.gradle.api.tasks.bundling.AbstractArchiveTask + +@CacheableTask +abstract class PrepareUpdaterDataTask : Sync() { + @get:Input + abstract val meta: Property + + init { + meta.convention(project.provider { Meta(Type.EMPTY, Data.Empty) }) + + val metaResource = meta.map { + project.resources.text.fromString(Meta.gson.toJson(it)) + } + + from(metaResource) { rename { "meta.json" } } + } + + fun fromArchive(task: Provider, archiveName: Provider? = null): Provider { + // We create an extra property to work around a gradle limitation + // https://github.com/gradle/gradle/issues/16777#issuecomment-1424863032 + val property = project.objects.fileProperty() + property.convention(task.flatMap { it.archiveFile }) + + val archiveName = archiveName ?: property.locationOnly.map { it.asFile.name } + from(property) { rename { archiveName.get() } } + return archiveName + } + + @TaskAction + override fun copy() { + val meta = meta.get() + if (meta.type == Type.EMPTY) { + logger.error("[{}] Found updater metadata with EMPTY type. Please configure this task.", path) + } + super.copy() + } +} diff --git a/build-extensions/src/main/kotlin/publishing-extensions.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/publishing-extensions.kt similarity index 97% rename from build-extensions/src/main/kotlin/publishing-extensions.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/publishing-extensions.kt index 5df5c94df3..3f3629a441 100644 --- a/build-extensions/src/main/kotlin/publishing-extensions.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/publishing-extensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 CloudNetService team & contributors + * Copyright 2019-2025 CloudNetService team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle + import org.gradle.api.Project import org.gradle.api.artifacts.repositories.MavenArtifactRepository -import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication @@ -24,7 +25,6 @@ import org.gradle.api.tasks.javadoc.Javadoc import org.gradle.external.javadoc.JavadocMemberLevel import org.gradle.external.javadoc.StandardJavadocDocletOptions import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.hasPlugin import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.withType import org.gradle.plugins.signing.Sign diff --git a/build-extensions/src/main/kotlin/settings-plugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/settings-plugin.kt similarity index 98% rename from build-extensions/src/main/kotlin/settings-plugin.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/settings-plugin.kt index f96a5b533b..8317c9c122 100644 --- a/build-extensions/src/main/kotlin/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/settings-plugin.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +package eu.cloudnetservice.cloudnet.gradle + import org.gradle.api.Project import org.gradle.api.artifacts.ExternalModuleDependencyBundle import org.gradle.api.artifacts.MinimalExternalModuleDependency diff --git a/build-extensions/src/main/kotlin/tasks.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks.kt similarity index 99% rename from build-extensions/src/main/kotlin/tasks.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks.kt index dca5d65b86..f3b8356b66 100644 --- a/build-extensions/src/main/kotlin/tasks.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks.kt @@ -16,6 +16,8 @@ @file:Suppress("LeakingThis") +package eu.cloudnetservice.cloudnet.gradle + import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -42,8 +44,6 @@ import org.gradle.internal.component.external.model.DefaultModuleComponentArtifa import org.gradle.kotlin.dsl.listProperty import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.setProperty -import org.gradle.workers.WorkAction -import org.gradle.workers.WorkParameters import java.io.File import java.net.HttpURLConnection import java.net.URI diff --git a/build-extensions/src/main/kotlin/updater-extensions.kt b/build-extensions/src/main/kotlin/updater-extensions.kt deleted file mode 100644 index 8ee1981c3d..0000000000 --- a/build-extensions/src/main/kotlin/updater-extensions.kt +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2019-2024 CloudNetService team & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import com.google.gson.Gson -import com.google.gson.JsonArray -import com.google.gson.JsonObject -import com.google.gson.JsonParser -import java.io.File -import java.io.FileReader -import java.io.FileWriter -import java.io.IOException -import java.security.MessageDigest -import java.security.NoSuchAlgorithmException -import java.util.* - -fun generateUpdaterInformation() { - UpdaterFiles.targetDirectory.deleteRecursively() - UpdaterFiles.targetDirectory.mkdir() - // module information - updateModuleInformation() - // node & launcher - prepareNodeAndLauncherInfo() -} - -@Throws(IOException::class) -private fun prepareNodeAndLauncherInfo() { - // first copy the node and launcher to the target directory - val nodeOut = UpdaterFiles.nodeFile.copyTo(UpdaterFiles.updaterOutputFile("node"), true) - val launcherOut = UpdaterFiles.launcherFile.copyTo(UpdaterFiles.updaterOutputFile("launcher"), true) - val launcherPatcherOut = UpdaterFiles.launcherPatcherFile.copyTo(UpdaterFiles.updaterOutputFile("launcher-patcher"), true) - // generate the checksums for those files - val nodeChecksum = ChecksumHelper.fileShaSum(nodeOut) - val launcherChecksum = ChecksumHelper.fileShaSum(launcherOut) - val launcherPatcherChecksum = ChecksumHelper.fileShaSum(launcherPatcherOut) - val modulesJsonChecksum = ChecksumHelper.fileShaSum(UpdaterFiles.modulesJson) - // set the checksums - val checksums = Properties().apply { - setProperty("node", nodeChecksum) - setProperty("launcher", launcherChecksum) - setProperty("modules-json", modulesJsonChecksum) - setProperty("launcher-patcher", launcherPatcherChecksum) - } - // write the checksums - FileWriter(UpdaterFiles.updaterOutputFile("checksums", "properties")).use { - checksums.store(it, "Checksums for CloudNet ${Versions.cloudNet}-${Versions.cloudNetCodeName}") - } -} - -private fun updateModuleInformation() { - // parse the current module file - val moduleJsonFile = FileReader(File("modules.json")).use { - JsonParser.parseReader(it).asJsonObject.get("entries").asJsonArray - } - // read all modules - val internalModules = collectModuleInformation() - // append the information of all internal modules to the object - internalModules.forEach { - moduleJsonFile.add(JsonObject().apply { - addProperty("official", true) - addProperty("name", it.second.get("name").asString) - addProperty("website", it.second.get("website").asString) - addProperty("version", it.second.get("version").asString) - addProperty("sha3256", ChecksumHelper.fileShaSum(it.first)) - addProperty("description", it.second.get("description").asString) - addProperty("url", "https://github.com/%updateRepo%/raw/%updateBranch%/modules/${it.first.name}") - - add("maintainers", stringJsonArray(it.second.get("author").asString)) - add("releaseNotes", stringJsonArray("Working with CloudNet ${Versions.cloudNet}")) - - add("dependingModules", JsonArray().apply { - val dependencies = it.second.get("dependencies")?.asJsonArray ?: JsonArray() - dependencies - .map { it.asJsonObject } - .filter { it.get("repo") == null } - .map { it.get("name").asString } - .forEach { add(it) } - }) - }) - } - // write the file - FileWriter(UpdaterFiles.modulesJson).use { - Gson().toJson(JsonObject().apply { add("entries", moduleJsonFile) }, it) - } - - // copy all module files - internalModules.map { it.first }.forEach { - it.copyTo(UpdaterFiles.moduleTargetDirectory.resolve(it.name)) - } -} - -private fun collectModuleInformation(): List> { - return UpdaterFiles.modulesDirectory.walkTopDown() - .filter { it.name != "src" } - .filter { it.name.startsWith("cloudnet-") && it.name.endsWith(".jar") } - .map { - // a module is located in build/libs - it's json is located in build/generated/module-json - FileReader(it.parentFile.parentFile.resolve("generated/module-json/module.json")).use { reader -> - Pair(it, JsonParser.parseReader(reader).asJsonObject) - } - } - .toList() -} - -private fun stringJsonArray(entry: String): JsonArray { - return JsonArray(1).apply { add(entry) } -} - -object UpdaterFiles { - - val modulesDirectory: File = File("modules") - val targetDirectory: File = File(".launchermeta") - - val modulesJson: File = targetDirectory.resolve("modules.json") - val moduleTargetDirectory: File = targetDirectory.resolve("modules") - - val nodeFile: File = gradleOutputJar("node/impl", "cloudnet") - val launcherFile: File = gradleOutputJar("launcher/java22", "launcher") - val launcherPatcherFile: File = gradleOutputJar("launcher/patcher", "launcher-patcher") - - fun updaterOutputFile(filename: String, fileExtension: String = "jar", subdirectory: String? = null): File { - return targetDirectory.resolve("${subdirectory?.plus("/") ?: ""}$filename.$fileExtension") - } - - private fun gradleOutputJar(projectName: String, outputFile: String): File { - return File("$projectName/build/libs/$outputFile.jar") - } -} - -// Copies from the updater to keep consistent when generating checksums -object ChecksumHelper { - - @Throws(IOException::class) - fun fileShaSum(path: File): String { - return newSha3256Digest().run { - update(path.readBytes()) - bytesToHex(digest()) - } - } - - @Throws(NoSuchAlgorithmException::class) - private fun newSha3256Digest(): MessageDigest = MessageDigest.getInstance("SHA3-256") - - private fun bytesToHex(input: ByteArray): String { - val buffer = StringBuilder() - for (b in input) { - buffer.append(Character.forDigit(b.toInt() shr 4 and 0xF, 16)) - buffer.append(Character.forDigit(b.toInt() and 0xF, 16)) - } - // convert to a string - return buffer.toString() - } -} diff --git a/build.gradle.kts b/build.gradle.kts index 472f61a80d..6fa569729e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,8 +14,15 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.plugins.configureFor +import eu.cloudnetservice.cloudnet.gradle.Versions +import eu.cloudnetservice.cloudnet.gradle.applyDefaultJavadocOptions +import eu.cloudnetservice.cloudnet.gradle.isJavaConfiguredProject +import eu.cloudnetservice.cloudnet.gradle.CustomConfigurations + plugins { id("cloudnet") + id("cloudnet-updater") id("java-base") alias(libs.plugins.nexusPublish) alias(libs.plugins.spotless) apply false @@ -34,7 +41,7 @@ tasks.register("globalJavaDoc", Javadoc::class) { options.source = Versions.javaVersion.asInt().toString() title = "CloudNet JavaDocs" - setDestinationDir(layout.buildDirectory.dir("javadocs").get().asFile) + destinationDir = layout.buildDirectory.dir("javadocs").get().asFile // options applyDefaultJavadocOptions(options) options.windowTitle = "CloudNet JavaDocs" @@ -65,20 +72,6 @@ dependencies { } } -tasks.register("genUpdaterInformation") { - subprojects.forEach { - // check if we need to depend on the plugin - // TODO this breaks isolated projects - if (!it.plugins.hasPlugin("java")) return@forEach - // depend this task on the build output of each subproject - dependsOn("${it.path}:build") - } - // generate the updater information - doLast { - generateUpdaterInformation() - } -} - // Adapted from https://stackoverflow.com/a/75923728 to fix running inside IDE gradle.taskGraph.whenReady { allTasks.filterIsInstance().forEach { diff --git a/ext/platform-inject-support/runtime/build.gradle.kts b/ext/platform-inject-support/runtime/build.gradle.kts index 0db196b5e9..30927332e4 100644 --- a/ext/platform-inject-support/runtime/build.gradle.kts +++ b/ext/platform-inject-support/runtime/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { id("cloudnet-java") } diff --git a/gradle.properties b/gradle.properties index 2d9c0614c6..29917c236f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,7 +15,6 @@ # org.gradle.caching=true org.gradle.configuration-cache=true -org.gradle.configuration-cache.problems=warn org.gradle.configuration-cache.integrity-check=true org.gradle.configureondemand=true org.gradle.parallel=true diff --git a/launcher/java22/build.gradle.kts b/launcher/java22/build.gradle.kts index 00334445b1..ae8d256685 100644 --- a/launcher/java22/build.gradle.kts +++ b/launcher/java22/build.gradle.kts @@ -14,16 +14,28 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files +import eu.cloudnetservice.cloudnet.gradle.applyJarMetadata +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Data +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Meta +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Type + plugins { alias(libs.plugins.shadow) id("cloudnet-java") id("cloudnet-git") + id("cloudnet-updater") } tasks.shadowJar.configure { archiveFileName.set(Files.launcher) } +tasks.prepareUpdaterData { + val archiveName = fromArchive(tasks.shadowJar) + meta.set(archiveName.map { Meta(Type.LAUNCHER, Data.Node(it)) }) +} + dependencies { "implementation"(projects.ext.updater) "implementation"(projects.launcher.java8) diff --git a/launcher/java8/build.gradle.kts b/launcher/java8/build.gradle.kts index 1a6e2a8d02..5f5967a3a1 100644 --- a/launcher/java8/build.gradle.kts +++ b/launcher/java8/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.plugins.configureJavaVersion + plugins { id("cloudnet-java") } diff --git a/launcher/patcher/build.gradle.kts b/launcher/patcher/build.gradle.kts index bdc2d54be5..388c97c255 100644 --- a/launcher/patcher/build.gradle.kts +++ b/launcher/patcher/build.gradle.kts @@ -14,15 +14,27 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files +import eu.cloudnetservice.cloudnet.gradle.applyJarMetadata +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Data +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Meta +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Type + plugins { id("cloudnet-java") id("cloudnet-git") + id("cloudnet-updater") } tasks.jar.configure { archiveFileName.set(Files.launcherPatcher) } +tasks.prepareUpdaterData { + val archiveName = fromArchive(tasks.jar) + meta.set(archiveName.map { Meta(Type.LAUNCHER_PATCHER, Data.Node(it)) }) +} + tasks.withType().configureEach { sourceCompatibility = JavaVersion.VERSION_17.toString() targetCompatibility = JavaVersion.VERSION_17.toString() diff --git a/modules/bridge/impl/build.gradle.kts b/modules/bridge/impl/build.gradle.kts index 510590ddd5..1fabe8d78d 100644 --- a/modules/bridge/impl/build.gradle.kts +++ b/modules/bridge/impl/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.fabricLoom) id("cloudnet-modules") diff --git a/modules/cloudflare/impl/build.gradle.kts b/modules/cloudflare/impl/build.gradle.kts index 6fdbb7b4e4..a45b5bd3e8 100644 --- a/modules/cloudflare/impl/build.gradle.kts +++ b/modules/cloudflare/impl/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.shadow) id("cloudnet-modules") diff --git a/modules/database-mongodb/impl/build.gradle.kts b/modules/database-mongodb/impl/build.gradle.kts index 1c0b3fbe8a..90ec172747 100644 --- a/modules/database-mongodb/impl/build.gradle.kts +++ b/modules/database-mongodb/impl/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.shadow) id("cloudnet-modules") diff --git a/modules/database-mysql/impl/build.gradle.kts b/modules/database-mysql/impl/build.gradle.kts index ead5a53155..3f7af6c5bf 100644 --- a/modules/database-mysql/impl/build.gradle.kts +++ b/modules/database-mysql/impl/build.gradle.kts @@ -16,6 +16,8 @@ import java.util.* * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.shadow) id("cloudnet-modules") diff --git a/modules/dockerized-services/impl/build.gradle.kts b/modules/dockerized-services/impl/build.gradle.kts index 0ae7b0aec0..81b16dc68d 100644 --- a/modules/dockerized-services/impl/build.gradle.kts +++ b/modules/dockerized-services/impl/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.shadow) id("cloudnet-modules") diff --git a/modules/influx/impl/build.gradle.kts b/modules/influx/impl/build.gradle.kts index e853591575..5eafd1ac8e 100644 --- a/modules/influx/impl/build.gradle.kts +++ b/modules/influx/impl/build.gradle.kts @@ -15,6 +15,7 @@ */ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration +import eu.cloudnetservice.cloudnet.gradle.Files plugins { alias(libs.plugins.shadow) diff --git a/modules/labymod/impl/build.gradle.kts b/modules/labymod/impl/build.gradle.kts index 24996a7c61..fdf69e4e14 100644 --- a/modules/labymod/impl/build.gradle.kts +++ b/modules/labymod/impl/build.gradle.kts @@ -15,6 +15,7 @@ */ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration +import eu.cloudnetservice.cloudnet.gradle.Files plugins { alias(libs.plugins.shadow) diff --git a/modules/npcs/impl/build.gradle.kts b/modules/npcs/impl/build.gradle.kts index cbb3e78d98..3fb359e8d1 100644 --- a/modules/npcs/impl/build.gradle.kts +++ b/modules/npcs/impl/build.gradle.kts @@ -15,6 +15,7 @@ */ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration +import eu.cloudnetservice.cloudnet.gradle.Files plugins { alias(libs.plugins.shadow) diff --git a/modules/report/impl/build.gradle.kts b/modules/report/impl/build.gradle.kts index 949bb06cbb..894a64d764 100644 --- a/modules/report/impl/build.gradle.kts +++ b/modules/report/impl/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.shadow) id("cloudnet-modules") diff --git a/modules/signs/impl/build.gradle.kts b/modules/signs/impl/build.gradle.kts index 377bbdaa5d..a3b03bba5b 100644 --- a/modules/signs/impl/build.gradle.kts +++ b/modules/signs/impl/build.gradle.kts @@ -15,6 +15,7 @@ */ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration +import eu.cloudnetservice.cloudnet.gradle.Files plugins { alias(libs.plugins.shadow) diff --git a/modules/smart/impl/build.gradle.kts b/modules/smart/impl/build.gradle.kts index 14f703df1e..6631edb976 100644 --- a/modules/smart/impl/build.gradle.kts +++ b/modules/smart/impl/build.gradle.kts @@ -15,6 +15,7 @@ */ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration +import eu.cloudnetservice.cloudnet.gradle.Files plugins { alias(libs.plugins.shadow) diff --git a/modules/storage-s3/impl/build.gradle.kts b/modules/storage-s3/impl/build.gradle.kts index fb65af11c5..4ac7b18dfd 100644 --- a/modules/storage-s3/impl/build.gradle.kts +++ b/modules/storage-s3/impl/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.shadow) id("cloudnet-modules") diff --git a/modules/storage-sftp/impl/build.gradle.kts b/modules/storage-sftp/impl/build.gradle.kts index c1363653a2..be2d5ae57f 100644 --- a/modules/storage-sftp/impl/build.gradle.kts +++ b/modules/storage-sftp/impl/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.shadow) id("cloudnet-modules") diff --git a/modules/syncproxy/impl/build.gradle.kts b/modules/syncproxy/impl/build.gradle.kts index fdeb62a4a6..90e8545bbc 100644 --- a/modules/syncproxy/impl/build.gradle.kts +++ b/modules/syncproxy/impl/build.gradle.kts @@ -15,6 +15,7 @@ */ import eu.cloudnetservice.gradle.juppiter.ModuleConfiguration +import eu.cloudnetservice.cloudnet.gradle.Files plugins { alias(libs.plugins.shadow) diff --git a/node/impl/build.gradle.kts b/node/impl/build.gradle.kts index 878d880094..7d933f3ff2 100644 --- a/node/impl/build.gradle.kts +++ b/node/impl/build.gradle.kts @@ -14,10 +14,19 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.ExportCnlFile +import eu.cloudnetservice.cloudnet.gradle.ExportLanguageFileInformation +import eu.cloudnetservice.cloudnet.gradle.Files +import eu.cloudnetservice.cloudnet.gradle.applyJarMetadata +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Data +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Meta +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.Type + plugins { alias(libs.plugins.shadow) id("cloudnet-java") id("cloudnet-git") + id("cloudnet-updater") } val exportCnlFile = tasks.register("exportCnlFile") { @@ -44,6 +53,11 @@ tasks.shadowJar { from(exportLanguageFileInformation) } +tasks.prepareUpdaterData { + val archiveName = fromArchive(tasks.shadowJar) + meta.set(archiveName.map { Meta(Type.NODE, Data.Node(it)) }) +} + tasks.withType().configureEach { options.compilerArgs.add("-AaerogelAutoFileName=autoconfigure/node.aero") } diff --git a/plugins/luckperms/build.gradle.kts b/plugins/luckperms/build.gradle.kts index 1c4055efb7..f999d57284 100644 --- a/plugins/luckperms/build.gradle.kts +++ b/plugins/luckperms/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { alias(libs.plugins.fabricLoom) id("cloudnet-plugins") diff --git a/plugins/papi-expansion/build.gradle.kts b/plugins/papi-expansion/build.gradle.kts index 56ed34da66..bbe2dc345e 100644 --- a/plugins/papi-expansion/build.gradle.kts +++ b/plugins/papi-expansion/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +import eu.cloudnetservice.cloudnet.gradle.Files + plugins { id("cloudnet-plugins") } diff --git a/settings.gradle.kts b/settings.gradle.kts index 5fc02a77bf..c0434af881 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,7 +14,6 @@ * limitations under the License. */ -enableFeaturePreview("STABLE_CONFIGURATION_CACHE") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") pluginManagement { diff --git a/wrapper-jvm/impl/build.gradle.kts b/wrapper-jvm/impl/build.gradle.kts index db0de50558..bd8d601a39 100644 --- a/wrapper-jvm/impl/build.gradle.kts +++ b/wrapper-jvm/impl/build.gradle.kts @@ -1,5 +1,3 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - /* * Copyright 2019-2025 CloudNetService team & contributors * @@ -16,6 +14,12 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar * limitations under the License. */ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import eu.cloudnetservice.cloudnet.gradle.Files +import eu.cloudnetservice.cloudnet.gradle.ExportCnlFile +import eu.cloudnetservice.cloudnet.gradle.ExportLanguageFileInformation +import eu.cloudnetservice.cloudnet.gradle.applyJarMetadata + plugins { alias(libs.plugins.shadow) id("cloudnet-java") From 2c40293affb4a36f3fe6076d468bd560be165cd4 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:28:41 +0200 Subject: [PATCH 30/45] fix GitService --- .../cloudnet/gradle/plugins/git/GitService.kt | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/GitService.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/GitService.kt index 36095982e9..44a7976cfb 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/GitService.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/git/GitService.kt @@ -26,8 +26,8 @@ import org.slf4j.LoggerFactory import java.io.Closeable import java.lang.AutoCloseable import java.nio.file.Path -import java.util.concurrent.atomic.AtomicBoolean -import java.util.concurrent.atomic.AtomicReference +import java.util.concurrent.locks.ReentrantLock +import kotlin.concurrent.withLock import kotlin.io.path.isDirectory import kotlin.io.path.notExists import kotlin.io.path.useLines @@ -61,20 +61,24 @@ abstract class GitService : BuildService, AutoCloseable { private class GitInstance(private val dir: Path) : Closeable { companion object { val logger: Logger = LoggerFactory.getLogger(GitInstance::class.java) - const val GIT_DIR = ".eu.cloudnetservice.cloudnet.gradle.git" + const val GIT_DIR = ".git" const val GITDIR_PREFIX = "gitdir:" } - private val usable = AtomicBoolean(false) - private val closed = AtomicBoolean(false) - private val wrapper = AtomicReference() + private val lock = ReentrantLock() + private var opened = false + private var closed = false + private var wrapper: Wrapper? = null val git: Git? get() = resolve()?.git private fun resolve(): Wrapper? { - if (closed.get()) return null - if (usable.compareAndSet(false, true)) { + lock.withLock { + if (closed) return null + if (opened) return wrapper + opened = true + var targetDir: Path? = dir while (targetDir?.resolve(GIT_DIR)?.notExists() ?: false) { targetDir = targetDir.parent @@ -82,21 +86,16 @@ abstract class GitService : BuildService, AutoCloseable { val gitDir = targetDir?.let { resolveGitDirectory(it) } if (targetDir == null || gitDir == null) { - logger.info("[Git] Unable to find repository for $dir") + logger.warn("[Git] Unable to find repository for $dir") + return null } else { val repository = RepositoryBuilder().setWorkTree(dir.toFile()).setGitDir(gitDir.toFile()).setMustExist(true).build() val git = Git.wrap(repository) - val wrapper = Wrapper(git, repository) - if (this.wrapper.compareAndSet(null, wrapper)) { - return wrapper - } else { - wrapper.close() - return this.wrapper.get() - } + this.wrapper = Wrapper(git, repository) + return this.wrapper } } - return wrapper.get() } private data class Wrapper(val git: Git, val repository: Repository) : Closeable { @@ -126,8 +125,11 @@ abstract class GitService : BuildService, AutoCloseable { } override fun close() { - if (closed.compareAndSet(false, true)) { - wrapper.getAndSet(null)?.close() + lock.withLock { + if (closed) return + closed = true + wrapper?.close() + wrapper = null } } } From d9ffd3d8aac05527f3d7ad535d32bac40c5d25cf Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:31:57 +0200 Subject: [PATCH 31/45] use long commit hash in Git-Commit manifest entry --- .../kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt index 8eed270b45..c5745a2034 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt @@ -50,7 +50,7 @@ fun GitExtension.applyJarMetadata(task: TaskProvider, mainClass: String "Implementation-Vendor" to "CloudNetService", "Implementation-Title" to Versions.cloudNetCodeName, "Implementation-Version" to serviceOrEmpty.shortCommitHash().map { "$projectVersion-$it" }, - "Git-Commit" to serviceOrEmpty.shortCommitHash(), + "Git-Commit" to serviceOrEmpty.map("unknown") { it.commit?.name }, "Git-Branch" to serviceOrEmpty.map("unknown") { it.branchName } ) // apply the pre-main class if given From 103ed5ffaf3e92e64af782f72c88ff250a883961 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:45:39 +0200 Subject: [PATCH 32/45] register commit and branch as proper task inputs --- .../eu/cloudnetservice/cloudnet/gradle/extensions.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt index c5745a2034..58f748ec7b 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt @@ -44,14 +44,19 @@ fun GitExtension.applyJarMetadata(task: TaskProvider, mainClass: String val projectVersion = project.version.toString() + val commit = serviceOrEmpty.map("unknown") { it.commit?.name } + val branch = serviceOrEmpty.map("unknown") { it.branchName } + inputs.property("commit", commit) + inputs.property("branch", branch) + manifest.attributes( "Main-Class" to mainClass, "Automatic-Module-Name" to module, "Implementation-Vendor" to "CloudNetService", "Implementation-Title" to Versions.cloudNetCodeName, "Implementation-Version" to serviceOrEmpty.shortCommitHash().map { "$projectVersion-$it" }, - "Git-Commit" to serviceOrEmpty.map("unknown") { it.commit?.name }, - "Git-Branch" to serviceOrEmpty.map("unknown") { it.branchName } + "Git-Commit" to commit, + "Git-Branch" to branch ) // apply the pre-main class if given preMain?.let { From 1a661129fe621716aeef57d4c64199f57b62938f Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:46:10 +0200 Subject: [PATCH 33/45] register project version as input --- .../main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt index 58f748ec7b..f7e471b585 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt @@ -46,6 +46,7 @@ fun GitExtension.applyJarMetadata(task: TaskProvider, mainClass: String val commit = serviceOrEmpty.map("unknown") { it.commit?.name } val branch = serviceOrEmpty.map("unknown") { it.branchName } + inputs.property("projectVersion", projectVersion) inputs.property("commit", commit) inputs.property("branch", branch) From 0c0cd3336d08e8b77e89c319bfe6521626833057 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 16:27:05 +0200 Subject: [PATCH 34/45] fix artifact inputs not recognized on update --- .../plugins/updater/CloudNetUpdaterPlugin.kt | 9 ++++---- .../updater/GenerateUpdaterInformationTask.kt | 23 +++++++++---------- .../plugins/updater/PrepareUpdaterDataTask.kt | 8 +++---- wrapper-jvm/impl/build.gradle.kts | 8 +++++-- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt index 2630d7a3b8..834a98869b 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt @@ -69,18 +69,19 @@ class CloudNetUpdaterPlugin : Plugin { } } - subprojects.map { it.isolated }.forEach { - println(it.name) dependencies.add( updaterDependencies.name, dependencies.project(path = it.path) ) } val view = updaterDependencies.map { it.incoming.artifactView { isLenient = true } } - val artifacts = view.flatMap { it.artifacts.resolvedArtifacts } - val genUpdaterInformation = tasks.register("genUpdaterInformation", artifacts) + val artifacts = view.flatMap { it.artifacts.resolvedArtifacts }.map { artifacts -> + artifacts.map { it.file } + } + val genUpdaterInformation = tasks.register("genUpdaterInformation") genUpdaterInformation.configure { + this.artifacts.from(artifacts) this.destinationDirectory.set(project.layout.projectDirectory.dir(".launchermeta")) } } diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt index 051b6a9d1f..f13c207b46 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt @@ -23,19 +23,19 @@ import com.google.gson.JsonParser import eu.cloudnetservice.cloudnet.gradle.ChecksumHelper import eu.cloudnetservice.cloudnet.gradle.Versions import org.gradle.api.DefaultTask -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.file.ArchiveOperations +import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.Provider import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction -import java.util.Properties -import javax.inject.Inject +import java.util.* -abstract class GenerateUpdaterInformationTask @Inject constructor(private val artifacts: Provider>) : - DefaultTask() { +abstract class GenerateUpdaterInformationTask : DefaultTask() { + + @get:InputFiles + abstract val artifacts: ConfigurableFileCollection @get:OutputDirectory abstract val destinationDirectory: DirectoryProperty @@ -50,7 +50,6 @@ abstract class GenerateUpdaterInformationTask @Inject constructor(private val ar @TaskAction fun run() { - val artifacts = artifacts.get() val destination = destinationDirectory.get().asFile destination.deleteRecursively() destination.mkdirs() @@ -63,7 +62,7 @@ abstract class GenerateUpdaterInformationTask @Inject constructor(private val ar val checksums = Properties() - artifacts.map { it.file }.forEach { directory -> + artifacts.forEach { directory -> val meta = directory.resolve("meta.json").readText().run { Meta.gson.fromJson(this, Meta::class.java) } val data = meta.data when (meta.type) { @@ -96,21 +95,21 @@ abstract class GenerateUpdaterInformationTask @Inject constructor(private val ar Type.NODE -> { data as Data.Node val nodeFile = directory.resolve(data.archiveName) - nodeFile.copyTo(destination.resolve(nodeFile.name)) + nodeFile.copyTo(destination.resolve("node.jar")) checksums.setProperty("node", ChecksumHelper.fileShaSum(nodeFile)) } Type.LAUNCHER -> { data as Data.Launcher val launcherFile = directory.resolve(data.archiveName) - launcherFile.copyTo(destination.resolve(launcherFile.name)) + launcherFile.copyTo(destination.resolve("launcher.jar")) checksums.setProperty("launcher", ChecksumHelper.fileShaSum(launcherFile)) } Type.LAUNCHER_PATCHER -> { data as Data.LauncherPatcher val launcherPatcherFile = directory.resolve(data.archiveName) - launcherPatcherFile.copyTo(destination.resolve(launcherPatcherFile.name)) + launcherPatcherFile.copyTo(destination.resolve("launcher-patcher.jar")) checksums.setProperty("launcher-patcher", ChecksumHelper.fileShaSum(launcherPatcherFile)) } diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/PrepareUpdaterDataTask.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/PrepareUpdaterDataTask.kt index d0a0354b9c..a57590d035 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/PrepareUpdaterDataTask.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/PrepareUpdaterDataTask.kt @@ -16,12 +16,12 @@ package eu.cloudnetservice.cloudnet.gradle.plugins.updater -import org.gradle.api.Task -import org.gradle.api.file.RegularFile -import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider -import org.gradle.api.tasks.* +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Sync +import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.bundling.AbstractArchiveTask @CacheableTask diff --git a/wrapper-jvm/impl/build.gradle.kts b/wrapper-jvm/impl/build.gradle.kts index bd8d601a39..88a3a3d529 100644 --- a/wrapper-jvm/impl/build.gradle.kts +++ b/wrapper-jvm/impl/build.gradle.kts @@ -36,7 +36,8 @@ val exportLanguageFileInformation = tasks.register("intermediateShadowJar") { this.configurations.set(project.configurations.runtimeClasspath.map { setOf(it) }) @@ -61,11 +62,14 @@ val intermediateShadowJar = tasks.register("intermediateShadowJar") { destinationDirectory = temporaryDir } + tasks.shadowJar.configure { archiveFileName.set(Files.wrapper) configurations.empty() - from(intermediateShadowJar) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + dependsOn(intermediateShadowJar) + from(intermediateShadowJar.map { zipTree(it.archiveFile) }) } tasks.withType().configureEach { From ee3ccbbba9d5f5ba6daaa0eb8d1fea0f3e9af798 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 16:33:10 +0200 Subject: [PATCH 35/45] revert threadId change --- .../java/eu/cloudnetservice/driver/service/ThreadSnapshot.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/api/src/main/java/eu/cloudnetservice/driver/service/ThreadSnapshot.java b/driver/api/src/main/java/eu/cloudnetservice/driver/service/ThreadSnapshot.java index 66b422c09c..9d4dbc7093 100644 --- a/driver/api/src/main/java/eu/cloudnetservice/driver/service/ThreadSnapshot.java +++ b/driver/api/src/main/java/eu/cloudnetservice/driver/service/ThreadSnapshot.java @@ -49,7 +49,7 @@ public record ThreadSnapshot( */ public static @NonNull ThreadSnapshot from(@NonNull Thread thread) { return new ThreadSnapshot( - thread.getId(), + thread.threadId(), thread.getPriority(), thread.isDaemon(), thread.getName(), From 7af4e7f7b670d7b3960b33edfc766b630aa819c4 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 16:47:03 +0200 Subject: [PATCH 36/45] update shadow to rc3 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 39b9482901..89cf78a7b4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] # plugins -shadow = "9.0.0-rc1" +shadow = "9.0.0-rc3" juppiter = "0.5.0-beta.2" spotless = "7.2.1" fabricLoom = "1.11.4" From 84b6cfe647be14784300ffee4067b2738ecf54ea Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 16:54:00 +0200 Subject: [PATCH 37/45] correct manifest order --- .../eu/cloudnetservice/cloudnet/gradle/extensions.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt index f7e471b585..6a62f641be 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/extensions.kt @@ -55,14 +55,15 @@ fun GitExtension.applyJarMetadata(task: TaskProvider, mainClass: String "Automatic-Module-Name" to module, "Implementation-Vendor" to "CloudNetService", "Implementation-Title" to Versions.cloudNetCodeName, - "Implementation-Version" to serviceOrEmpty.shortCommitHash().map { "$projectVersion-$it" }, - "Git-Commit" to commit, - "Git-Branch" to branch + "Implementation-Version" to serviceOrEmpty.shortCommitHash().map { "$projectVersion-$it" } ) // apply the pre-main class if given preMain?.let { manifest.attributes("Premain-Class" to it) } + + // add git information + manifest.attributes("Git-Commit" to commit, "Git-Branch" to branch) } } } From 09bd4728b731a0ec7237f404ba4b36a0ca0c05df Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:28:41 +0200 Subject: [PATCH 38/45] add logback-test.xml to wrapper-jvm-impl. Don't know why that wasn't there yet --- .../impl/src/test/resources/logback-test.xml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 wrapper-jvm/impl/src/test/resources/logback-test.xml diff --git a/wrapper-jvm/impl/src/test/resources/logback-test.xml b/wrapper-jvm/impl/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..78dd636580 --- /dev/null +++ b/wrapper-jvm/impl/src/test/resources/logback-test.xml @@ -0,0 +1,32 @@ + + + + + + [%d{dd.MM HH:mm:ss.SSS}] %-5level: %msg%n + + + + + + + + + + + + From d0573410957204e5a721aececfbad8f365ef3925 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:29:29 +0200 Subject: [PATCH 39/45] remove launchermeta copy from gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index b38aae6044..98b97df15f 100644 --- a/.gitignore +++ b/.gitignore @@ -76,5 +76,4 @@ atlassian-ide-plugin.xml */src/main/lombok # CloudNet -.launchermeta-copy/ .launchermeta/ From aab574aa653bc6ab3ae9e5e152a48387a3f0f799 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:48:07 +0200 Subject: [PATCH 40/45] forgot URL in updater meta --- .../gradle/plugins/updater/CloudNetUpdaterPlugin.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt index 834a98869b..4244a221bd 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/CloudNetUpdaterPlugin.kt @@ -16,14 +16,13 @@ package eu.cloudnetservice.cloudnet.gradle.plugins.updater -import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin import eu.cloudnetservice.cloudnet.gradle.plugins.CloudNetJavaPlugin import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration import org.gradle.api.attributes.Category import org.gradle.api.attributes.LibraryElements import org.gradle.api.attributes.Usage -import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.named import org.gradle.kotlin.dsl.project @@ -75,10 +74,8 @@ class CloudNetUpdaterPlugin : Plugin { ) } - val view = updaterDependencies.map { it.incoming.artifactView { isLenient = true } } - val artifacts = view.flatMap { it.artifacts.resolvedArtifacts }.map { artifacts -> - artifacts.map { it.file } - } + val view = updaterDependencies.map { it.lenientView } + val artifacts = view.map { it.files } val genUpdaterInformation = tasks.register("genUpdaterInformation") genUpdaterInformation.configure { this.artifacts.from(artifacts) @@ -86,3 +83,6 @@ class CloudNetUpdaterPlugin : Plugin { } } } + +val Configuration.lenientView + get() = this.incoming.artifactView { isLenient = true } From eb9c22de74c05958e80871c506c1910ddc371b69 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:54:59 +0200 Subject: [PATCH 41/45] globalJavaDoc --- .../updater/GenerateUpdaterInformationTask.kt | 1 + .../cloudnet/gradle/settings-plugin.kt | 14 -------------- build.gradle.kts | 13 ++++++------- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt index f13c207b46..8422d387c1 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt @@ -79,6 +79,7 @@ abstract class GenerateUpdaterInformationTask : DefaultTask() { addProperty("version", moduleJson.get("version").asString) addProperty("sha3256", ChecksumHelper.fileShaSum(moduleFile)) addProperty("description", moduleJson.get("description").asString) + addProperty("url", "https://github.com/%updateRepo%/raw/%updateBranch%/modules/${data.archiveName}") add("maintainers", JsonArray(1).apply { add(moduleJson.get("author").asString) }) add("releaseNotes", JsonArray(1).apply { add("Working with CloudNet ${Versions.cloudNet}") }) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/settings-plugin.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/settings-plugin.kt index 8317c9c122..80dea1fbe0 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/settings-plugin.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/settings-plugin.kt @@ -24,20 +24,6 @@ import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.api.provider.Provider import org.gradle.kotlin.dsl.getByName -fun isJavaConfiguredProject(name: String, path: String): Boolean { - if (isHelperProject(path)) return false - return name != "bom" -} - -fun isHelperProject(path: String): Boolean { - val guaranteedHelper = - path == ":modules" || path == ":plugins" || path == ":ext" || path == ":launcher" || path == ":node" || path == ":driver" || path == ":wrapper-jvm" || path == ":utils" || path == ":ext:platform-inject-support" - if (guaranteedHelper) return true - val couldBeHelper = path.startsWith(":modules:") || path.startsWith(":node:") || path.startsWith(":wrapper-jvm:") - val apiOrImpl = path.endsWith("-api") || path.endsWith("-impl") - return couldBeHelper && !apiOrImpl -} - object CustomConfigurations { const val GLOBAL_JAVADOC_SOURCES = "globalJavadocSources" const val GLOBAL_JAVADOC_CLASSPATH = "globalJavadocClasspath" diff --git a/build.gradle.kts b/build.gradle.kts index 6fa569729e..05c94a10b2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,11 +14,11 @@ * limitations under the License. */ -import eu.cloudnetservice.cloudnet.gradle.plugins.configureFor +import eu.cloudnetservice.cloudnet.gradle.CustomConfigurations import eu.cloudnetservice.cloudnet.gradle.Versions import eu.cloudnetservice.cloudnet.gradle.applyDefaultJavadocOptions -import eu.cloudnetservice.cloudnet.gradle.isJavaConfiguredProject -import eu.cloudnetservice.cloudnet.gradle.CustomConfigurations +import eu.cloudnetservice.cloudnet.gradle.plugins.configureFor +import eu.cloudnetservice.cloudnet.gradle.plugins.updater.lenientView plugins { id("cloudnet") @@ -45,9 +45,9 @@ tasks.register("globalJavaDoc", Javadoc::class) { // options applyDefaultJavadocOptions(options) options.windowTitle = "CloudNet JavaDocs" - // set the sources - source(globalJavadocSources) - classpath = globalJavadocClasspath.get() + // set the sources. We are using lenientView to ignore subprojects that shouldn't be included + source(globalJavadocSources.map { it.lenientView.files }) + classpath = globalJavadocClasspath.map { it.lenientView.files }.get() } nexusPublishing { @@ -66,7 +66,6 @@ nexusPublishing { dependencies { subprojects.map { it.isolated }.forEach { project -> - if (!isJavaConfiguredProject(project.name, project.path)) return@forEach globalJavadocSources(this.project(project.path, CustomConfigurations.GLOBAL_JAVADOC_SOURCES)) globalJavadocClasspath(this.project(project.path, CustomConfigurations.GLOBAL_JAVADOC_CLASSPATH)) } From 2c7fd6090cb61ba3f59b742a19498dbde5b28e23 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:56:34 +0200 Subject: [PATCH 42/45] move ChecksumHelper --- .../gradle/plugins/updater/GenerateUpdaterInformationTask.kt | 2 +- .../src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks.kt | 1 + .../cloudnet/gradle/{ => util}/ChecksumHelper.kt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/{ => util}/ChecksumHelper.kt (96%) diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt index 8422d387c1..4436beb80b 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/plugins/updater/GenerateUpdaterInformationTask.kt @@ -20,7 +20,7 @@ import com.google.gson.Gson import com.google.gson.JsonArray import com.google.gson.JsonObject import com.google.gson.JsonParser -import eu.cloudnetservice.cloudnet.gradle.ChecksumHelper +import eu.cloudnetservice.cloudnet.gradle.util.ChecksumHelper import eu.cloudnetservice.cloudnet.gradle.Versions import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks.kt index f3b8356b66..a06923dcfb 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks.kt @@ -18,6 +18,7 @@ package eu.cloudnetservice.cloudnet.gradle +import eu.cloudnetservice.cloudnet.gradle.util.ChecksumHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll diff --git a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/ChecksumHelper.kt b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/util/ChecksumHelper.kt similarity index 96% rename from build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/ChecksumHelper.kt rename to build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/util/ChecksumHelper.kt index 756919e72f..46454574f4 100644 --- a/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/ChecksumHelper.kt +++ b/build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/util/ChecksumHelper.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package eu.cloudnetservice.cloudnet.gradle +package eu.cloudnetservice.cloudnet.gradle.util import java.io.File import java.io.IOException From 984166155ca139fa948c13aa26c454df650f5788 Mon Sep 17 00:00:00 2001 From: Lorenz Wrobel <43410952+DasBabyPixel@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:19:00 +0200 Subject: [PATCH 43/45] more refactoring --- .idea/codeStyles/Project.xml | 4 + .../cloudnet/gradle/extensions.kt | 48 ++++---- .../gradle/plugins/CloudNetJavaApiPlugin.kt | 2 +- .../gradle/plugins/CloudNetJavaPlugin.kt | 15 ++- .../plugins/CloudNetModulesApiPlugin.kt | 6 +- .../gradle/plugins/CloudNetModulesPlugin.kt | 6 +- .../cloudnet/gradle/plugins/CloudNetPlugin.kt | 2 +- .../gradle/plugins/CloudNetPluginsPlugin.kt | 6 +- .../gradle/plugins/CloudNetPublishPlugin.kt | 2 +- .../gradle/plugins/git/CloudNetGitPlugin.kt | 5 +- .../cloudnet/gradle/plugins/git/GitService.kt | 6 +- .../plugins/updater/CloudNetUpdaterPlugin.kt | 2 + .../cloudnet/gradle/settings-plugin.kt | 5 +- .../{tasks.kt => tasks/ExportCnlFile.kt} | 114 ++++++++---------- .../tasks/ExportLanguageFileInformation.kt | 46 +++++++ .../GenerateUpdaterInformationTask.kt | 9 +- .../PrepareUpdaterDataTask.kt | 11 +- .../gradle/util/CustomConfigurations.kt | 22 ++++ .../cloudnet/gradle/{ => util}/Files.kt | 2 +- .../updater/Meta.kt => util/UpdaterMeta.kt} | 78 ++++++------ .../cloudnet/gradle/{ => util}/Versions.kt | 2 +- build.gradle.kts | 4 +- .../runtime/build.gradle.kts | 2 +- launcher/java22/build.gradle.kts | 10 +- launcher/patcher/build.gradle.kts | 10 +- modules/bridge/impl/build.gradle.kts | 2 +- modules/cloudflare/impl/build.gradle.kts | 2 +- .../database-mongodb/impl/build.gradle.kts | 2 +- modules/database-mysql/impl/build.gradle.kts | 4 +- .../dockerized-services/impl/build.gradle.kts | 2 +- modules/influx/impl/build.gradle.kts | 2 +- modules/labymod/impl/build.gradle.kts | 2 +- modules/npcs/impl/build.gradle.kts | 2 +- modules/report/impl/build.gradle.kts | 2 +- modules/signs/impl/build.gradle.kts | 2 +- modules/smart/impl/build.gradle.kts | 2 +- modules/storage-s3/impl/build.gradle.kts | 2 +- modules/storage-sftp/impl/build.gradle.kts | 2 +- modules/syncproxy/impl/build.gradle.kts | 2 +- node/impl/build.gradle.kts | 14 +-- plugins/luckperms/build.gradle.kts | 2 +- plugins/papi-expansion/build.gradle.kts | 2 +- wrapper-jvm/impl/build.gradle.kts | 6 +- 43 files changed, 279 insertions(+), 194 deletions(-) rename build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/{tasks.kt => tasks/ExportCnlFile.kt} (76%) create mode 100644 build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/tasks/ExportLanguageFileInformation.kt rename build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/{plugins/updater => tasks}/GenerateUpdaterInformationTask.kt (93%) rename build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/{plugins/updater => tasks}/PrepareUpdaterDataTask.kt (81%) create mode 100644 build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/util/CustomConfigurations.kt rename build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/{ => util}/Files.kt (97%) rename build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/{plugins/updater/Meta.kt => util/UpdaterMeta.kt} (60%) rename build-extensions/src/main/kotlin/eu/cloudnetservice/cloudnet/gradle/{ => util}/Versions.kt (94%) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 55df1a1108..19d618074c 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -68,6 +68,10 @@ + +