diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 6fbd357d97..7478b47449 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -15,18 +15,27 @@ repositories { name = "MinecraftForge" url = uri("https://maven.minecraftforge.net/") } + maven { + name = "EngineHub" + url = uri("https://repo.enginehub.org/libs-release/") + } mavenCentral() gradlePluginPortal() } dependencies { implementation(gradleApi()) + implementation(libs.crankcase.java) + implementation(libs.crankcase.javaLibrary) + implementation(libs.crankcase.checkstyle) + implementation(libs.crankcase.common) + implementation(libs.crankcase.licensing) + implementation(libs.crankcase.git) + implementation(libs.crankcase.japicmp) + implementation(libs.crankcase.publishing) implementation(libs.levelHeadered) - implementation(libs.japicmp) implementation(libs.shadow) - implementation(libs.jfrog.buildinfo) implementation(libs.paperweight) - implementation(libs.errorprone.gradle.plugin) implementation(libs.gson) implementation(libs.sponge.vanillagradle) diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts index 338b917c26..7506ab52c6 100644 --- a/build-logic/settings.gradle.kts +++ b/build-logic/settings.gradle.kts @@ -1,4 +1,35 @@ -apply(from = "../gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts") +pluginManagement { + // pluginManagement repositories resolve plugins before the repo-reconfiguration plugin can + // apply, so they must point at EngineHub mirrors directly rather than upstream URLs. + repositories { + maven { + name = "EngineHub" + url = uri("https://repo.enginehub.org/libs-release/") + mavenContent { + releasesOnly() + includeGroupAndSubgroups("com.sk89q") + includeGroupAndSubgroups("org.enginehub") + } + } + maven { + name = "EngineHub Maven Central Mirror" + url = uri("https://repo.enginehub.org/internal/maven-central-proxy/") + mavenContent { + releasesOnly() + } + } + maven { + name = "EngineHub Gradle Plugin Portal Mirror" + url = uri("https://repo.enginehub.org/internal/plugin-portal-proxy/") + mavenContent { + releasesOnly() + } + } + } +} +plugins { + id("org.enginehub.crankcase.repo-reconfiguration") version "0.1.0" +} dependencyResolutionManagement { versionCatalogs { diff --git a/build-logic/src/main/kotlin/buildlogic.adapter-mojmap.gradle.kts b/build-logic/src/main/kotlin/buildlogic.adapter-mojmap.gradle.kts index e6352b36d3..190de14e9a 100644 --- a/build-logic/src/main/kotlin/buildlogic.adapter-mojmap.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.adapter-mojmap.gradle.kts @@ -1,5 +1,4 @@ import io.papermc.paperweight.userdev.ReobfArtifactConfiguration -import org.gradle.kotlin.dsl.named plugins { id("buildlogic.adapter") @@ -8,10 +7,3 @@ plugins { paperweight { reobfArtifactConfiguration = ReobfArtifactConfiguration.MOJANG_PRODUCTION } - -tasks - .withType() - .matching { it.name == "compileJava" || it.name == "compileTestJava" } - .configureEach { - options.release.set(25) - } diff --git a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts index e04931c417..079d15b786 100644 --- a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts @@ -3,9 +3,7 @@ import buildlogic.stringyLibs import buildlogic.getVersion plugins { - `java-library` - id("buildlogic.common") - id("buildlogic.common-java") + id("buildlogic.common-java-library") id("io.papermc.paperweight.userdev") } diff --git a/build-logic/src/main/kotlin/buildlogic.artifactory-root.gradle.kts b/build-logic/src/main/kotlin/buildlogic.artifactory-root.gradle.kts deleted file mode 100644 index c3b4f8310d..0000000000 --- a/build-logic/src/main/kotlin/buildlogic.artifactory-root.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.gradle.api.Project -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.named -import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention -import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask - -plugins { - id("com.jfrog.artifactory") -} - -val ARTIFACTORY_CONTEXT_URL = "artifactory_contextUrl" -val ARTIFACTORY_USER = "artifactory_user" -val ARTIFACTORY_PASSWORD = "artifactory_password" - -if (!project.hasProperty(ARTIFACTORY_CONTEXT_URL)) ext[ARTIFACTORY_CONTEXT_URL] = "http://localhost" -if (!project.hasProperty(ARTIFACTORY_USER)) ext[ARTIFACTORY_USER] = "guest" -if (!project.hasProperty(ARTIFACTORY_PASSWORD)) ext[ARTIFACTORY_PASSWORD] = "" - -configure { - setContextUrl("${project.property(ARTIFACTORY_CONTEXT_URL)}") - clientConfig.publisher.run { - repoKey = when { - "${project.version}".contains("SNAPSHOT") -> "libs-snapshot-local" - else -> "libs-release-local" - } - username = "${project.property(ARTIFACTORY_USER)}" - password = "${project.property(ARTIFACTORY_PASSWORD)}" - isMaven = true - isIvy = false - } -} - -tasks.named("artifactoryPublish") { - isSkip = true -} diff --git a/build-logic/src/main/kotlin/buildlogic.artifactory-sub.gradle.kts b/build-logic/src/main/kotlin/buildlogic.artifactory-sub.gradle.kts deleted file mode 100644 index 966409761f..0000000000 --- a/build-logic/src/main/kotlin/buildlogic.artifactory-sub.gradle.kts +++ /dev/null @@ -1,10 +0,0 @@ -plugins { - id("com.jfrog.artifactory") -} - -// Artifactory eagerly evaluates publications, so this must run after all changes to artifacts are done -afterEvaluate { - tasks.named("artifactoryPublish") { - publications("maven") - } -} diff --git a/build-logic/src/main/kotlin/buildlogic.common-java-library.gradle.kts b/build-logic/src/main/kotlin/buildlogic.common-java-library.gradle.kts new file mode 100644 index 0000000000..ba52d8cbf7 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.common-java-library.gradle.kts @@ -0,0 +1,11 @@ +import buildlogic.stringyLibs +import buildlogic.getLibrary + +plugins { + id("org.enginehub.crankcase.java-library") + id("buildlogic.common-java") +} + +dependencies { + "compileOnlyApi"(stringyLibs.getLibrary("errorprone-annotations")) +} diff --git a/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts b/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts index cbd66a4965..c80538f874 100644 --- a/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts @@ -1,46 +1,30 @@ import buildlogic.stringyLibs import buildlogic.getLibrary -import net.ltgt.gradle.errorprone.errorprone plugins { id("eclipse") id("idea") - id("checkstyle") - id("net.ltgt.errorprone") + id("org.enginehub.crankcase.java") + id("org.enginehub.crankcase.checkstyle") id("buildlogic.common") } -tasks - .withType() - .matching { it.name == "compileJava" || it.name == "compileTestJava" } - .configureEach { - val disabledLint = listOf( - "processing", "path", "fallthrough", "serial", "overloads", - ) - options.release.set(25) - options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" }) - options.isDeprecation = true - options.encoding = "UTF-8" - options.compilerArgs.add("-parameters") - options.compilerArgs.add("-Werror") - options.errorprone { - // We use -Werror, so we don't need errorprone to fail the build separately - allErrorsAsWarnings = true - // Obviously we don't need to fix generated code - disableWarningsInGeneratedCode = true - // We use reference equality intentionally in several places - // Perhaps we should consider testing the performance impact of using .equals() instead? - // Especially for the types that are only compared by reference equality, we could consider - // removing their .equals() implementations to avoid confusion. - disable("ReferenceEquality") - // We're on JDK 21, so System.console() can still be null - disable("SystemConsoleNull") - } - } +crankcaseJava { + javaRelease = 25 + disabledLints = listOf("processing", "path", "fallthrough", "serial", "overloads") + disabledErrorprone = listOf( + // We use reference equality intentionally in several places + // Perhaps we should consider testing the performance impact of using .equals() instead? + // Especially for the types that are only compared by reference equality, we could consider + // removing their .equals() implementations to avoid confusion. + "ReferenceEquality", + // We're on JDK 21, so System.console() can still be null + "SystemConsoleNull", + ) +} -configure { - configFile = rootProject.file("config/checkstyle/checkstyle.xml") - toolVersion = "13.3.0" +crankcaseCheckstyle { + suppressionsFile = rootDir.resolve("config/checkstyle/checkstyle-suppression.xml") } tasks.withType().configureEach { @@ -51,39 +35,8 @@ tasks.withType().configureEach { dependencies { "compileOnly"(stringyLibs.getLibrary("jsr305")) - "compileOnlyApi"(stringyLibs.getLibrary("errorprone-annotations")) - "errorprone"(stringyLibs.getLibrary("errorprone-core")) - "testImplementation"(platform(stringyLibs.getLibrary("junit-bom"))) - "testImplementation"(stringyLibs.getLibrary("junit-jupiter-api")) - "testImplementation"(stringyLibs.getLibrary("junit-jupiter-params")) "testImplementation"(stringyLibs.getLibrary("jqwik")) "testImplementation"(platform(stringyLibs.getLibrary("mockito-bom"))) "testImplementation"(stringyLibs.getLibrary("mockito-core")) "testImplementation"(stringyLibs.getLibrary("mockito-junit-jupiter")) - "testRuntimeOnly"(stringyLibs.getLibrary("junit-jupiter-engine")) - "testRuntimeOnly"(stringyLibs.getLibrary("junit-platform-launcher")) -} - -// Java 8 turns on doclint which we fail -tasks.withType().configureEach { - options.encoding = "UTF-8" - (options as StandardJavadocDocletOptions).apply { - addBooleanOption("Werror", true) - addBooleanOption("Xdoclint:all", true) - addBooleanOption("Xdoclint:-missing", true) - tags( - "apiNote:a:API Note:", - "implSpec:a:Implementation Requirements:", - "implNote:a:Implementation Note:" - ) - } -} - -configure { - withJavadocJar() - withSourcesJar() -} - -tasks.named("check").configure { - dependsOn("checkstyleMain", "checkstyleTest") } diff --git a/build-logic/src/main/kotlin/buildlogic.common.gradle.kts b/build-logic/src/main/kotlin/buildlogic.common.gradle.kts index 1af6cf684f..f88fa774ba 100644 --- a/build-logic/src/main/kotlin/buildlogic.common.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.common.gradle.kts @@ -1,26 +1,15 @@ import buildlogic.getLibrary import buildlogic.stringyLibs -import org.gradle.plugins.ide.idea.model.IdeaModel plugins { - id("net.octyl.level-headered") + id("org.enginehub.crankcase.common") + id("org.enginehub.crankcase.licensing") + id("org.enginehub.crankcase.git") } group = rootProject.group version = rootProject.version -configurations.all { - resolutionStrategy { - cacheChangingModulesFor(1, TimeUnit.DAYS) - } -} - -plugins.withId("java") { - the().toolchain { - languageVersion.set(JavaLanguageVersion.of(25)) - } -} - dependencies { for (conf in listOf("implementation", "api")) { if (!configurations.names.contains(conf)) { @@ -46,19 +35,8 @@ dependencies { } levelHeadered { - headerTemplate(rootProject.file("HEADER.txt")) - sourceMatchPatterns { // Exclude overrides for text formatting exclude("com/sk89q/worldedit/util/formatting/text/") } } - -plugins.withId("idea") { - configure { - module { - isDownloadSources = true - isDownloadJavadoc = true - } - } -} diff --git a/build-logic/src/main/kotlin/buildlogic.core-and-platform.gradle.kts b/build-logic/src/main/kotlin/buildlogic.core-and-platform.gradle.kts index 1128a7531b..771ea95677 100644 --- a/build-logic/src/main/kotlin/buildlogic.core-and-platform.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.core-and-platform.gradle.kts @@ -1,8 +1,7 @@ plugins { - id("java") id("maven-publish") - id("buildlogic.common-java") - id("buildlogic.artifactory-sub") + id("buildlogic.common-java-library") + id("org.enginehub.crankcase.publishing") } publishing { diff --git a/build-logic/src/main/kotlin/buildlogic.libs.gradle.kts b/build-logic/src/main/kotlin/buildlogic.libs.gradle.kts index e9ab197658..94e0ff490f 100644 --- a/build-logic/src/main/kotlin/buildlogic.libs.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.libs.gradle.kts @@ -2,9 +2,8 @@ plugins { id("java-base") id("maven-publish") id("com.gradleup.shadow") - id("com.jfrog.artifactory") id("buildlogic.common") - id("buildlogic.artifactory-sub") + id("org.enginehub.crankcase.publishing") } // A horrible hack because `softwareComponentFactory` has to be gotten via plugin diff --git a/build-logic/src/main/kotlin/buildlogic/GitBuildService.kt b/build-logic/src/main/kotlin/buildlogic/GitBuildService.kt deleted file mode 100644 index a64edc74ca..0000000000 --- a/build-logic/src/main/kotlin/buildlogic/GitBuildService.kt +++ /dev/null @@ -1,25 +0,0 @@ -package buildlogic - -import org.gradle.api.provider.Provider -import org.gradle.api.provider.ProviderFactory -import org.gradle.api.services.BuildService -import org.gradle.api.services.BuildServiceParameters -import javax.inject.Inject - -/** - * Git-related extension. - */ -internal abstract class GitBuildService @Inject constructor( - private val providers: ProviderFactory, -) : BuildService { - private val gitCommitHash by lazy { - val probedCommitHash = providers.exec { - commandLine("git", "rev-parse", "--short", "HEAD") - }.standardOutput.asText.map { it.trim() } - - providers.gradleProperty("gitCommitHash").orElse(probedCommitHash) - } - - fun computeInternalVersion(version: String): Provider = - gitCommitHash.map { hash -> "$version+$hash" } -} diff --git a/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt b/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt index d559c716cb..d825c472ad 100644 --- a/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt +++ b/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt @@ -7,9 +7,10 @@ import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.api.artifacts.VersionConstraint import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.plugins.ExtraPropertiesExtension +import org.enginehub.crankcase.git.GitExtension import org.gradle.api.provider.Provider import org.gradle.kotlin.dsl.getByType -import org.gradle.kotlin.dsl.registerIfAbsent +import org.gradle.kotlin.dsl.the import java.net.URI val Project.ext: ExtraPropertiesExtension @@ -19,8 +20,10 @@ val Project.stringyLibs: VersionCatalog get() = extensions.getByType().named("libs") val Project.internalVersion: Provider - get() = gradle.sharedServices.registerIfAbsent("git", GitBuildService::class) {} - .flatMap { service -> service.computeInternalVersion(project.version as String) } + get() { + val version = version.toString() + return the().commitHash.map { "$version+$it" } + } fun VersionCatalog.getLibrary(name: String): Provider = findLibrary(name).orElseThrow { error("Library $name not found in version catalog") diff --git a/build-logic/src/main/kotlin/japicmp/accept/AbstractAcceptingRule.kt b/build-logic/src/main/kotlin/japicmp/accept/AbstractAcceptingRule.kt deleted file mode 100644 index a0a72439c3..0000000000 --- a/build-logic/src/main/kotlin/japicmp/accept/AbstractAcceptingRule.kt +++ /dev/null @@ -1,52 +0,0 @@ -package japicmp.accept - -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken -import com.google.gson.stream.JsonWriter -import japicmp.model.JApiCompatibility -import me.champeau.gradle.japicmp.report.AbstractContextAwareViolationRule -import me.champeau.gradle.japicmp.report.Violation -import java.io.StringWriter - -abstract class AbstractAcceptingRule : AbstractContextAwareViolationRule() { - fun checkAcceptance( - member: JApiCompatibility, - changes: List, - rejection: Violation - ): Violation { - val changeParams = context.changeParams - val seenApiChanges = context.seenApiChanges - val change = ApiChange( - context.className, - Violation.describe(member), - changes - ) - val reason = changeParams.changeToReason.get(change) - if (reason != null) { - seenApiChanges.add(change) - return Violation.accept( - member, - "${rejection.humanExplanation}. Reason for accepting this: $reason" - ) - } - return Violation.error( - member, - rejection.humanExplanation + """. -
-

- In order to accept this change add the following to verification/src/changes/${changeParams.changeFileName}: -

${prettyPrintJson(mapOf("[REASON CHANGE IS OKAY]" to listOf(change)))}
-

- """.trimIndent() - ) - } - - private fun prettyPrintJson(acceptanceJson: Any): String { - val stringWriter = StringWriter() - JsonWriter(stringWriter).use { - it.setIndent(" ") - Gson().toJson(acceptanceJson, object : TypeToken() {}.type, it) - } - return stringWriter.toString() - } -} diff --git a/build-logic/src/main/kotlin/japicmp/accept/AcceptedRegressionsRulePostProcess.kt b/build-logic/src/main/kotlin/japicmp/accept/AcceptedRegressionsRulePostProcess.kt deleted file mode 100644 index e909c7dcc7..0000000000 --- a/build-logic/src/main/kotlin/japicmp/accept/AcceptedRegressionsRulePostProcess.kt +++ /dev/null @@ -1,17 +0,0 @@ -package japicmp.accept - -import me.champeau.gradle.japicmp.report.PostProcessViolationsRule -import me.champeau.gradle.japicmp.report.ViolationCheckContextWithViolations - -class AcceptedRegressionsRulePostProcess : PostProcessViolationsRule { - override fun execute(context: ViolationCheckContextWithViolations) { - val changeParams = context.changeParams - val seenApiChanges = context.seenApiChanges - val left = HashSet(changeParams.changeToReason.keys) - left.removeAll(seenApiChanges) - if (!left.isEmpty()) { - val formattedLeft: String = left.joinToString(separator = "\n") { it.toString() } - throw RuntimeException("The following regressions are declared as accepted, but didn't match any rule:\n\n$formattedLeft") - } - } -} diff --git a/build-logic/src/main/kotlin/japicmp/accept/AcceptingSetupRule.kt b/build-logic/src/main/kotlin/japicmp/accept/AcceptingSetupRule.kt deleted file mode 100644 index c76c54b8d8..0000000000 --- a/build-logic/src/main/kotlin/japicmp/accept/AcceptingSetupRule.kt +++ /dev/null @@ -1,28 +0,0 @@ -package japicmp.accept - -import me.champeau.gradle.japicmp.report.SetupRule -import me.champeau.gradle.japicmp.report.ViolationCheckContext -import java.nio.file.Path -import java.nio.file.Paths - -class AcceptingSetupRule(private val params: Map) : SetupRule { - companion object { - fun createParams(changeFile: Path): Map { - return mapOf( - "changeFile" to changeFile.toAbsolutePath().toString(), - "fileName" to changeFile.fileName.toString() - ) - } - } - - override fun execute(t: ViolationCheckContext) { - @Suppress("UNCHECKED_CAST") - val userData = t.userData as MutableMap - userData["changeParams"] = ChangeParams( - changeToReason = loadAcceptedApiChanges(Paths.get(params["changeFile"]!!)), - changeFileName = params["fileName"]!!, - ) - userData["seenApiChanges"] = HashSet() - } - -} diff --git a/build-logic/src/main/kotlin/japicmp/accept/BinaryCompatRule.kt b/build-logic/src/main/kotlin/japicmp/accept/BinaryCompatRule.kt deleted file mode 100644 index 16887cbf2b..0000000000 --- a/build-logic/src/main/kotlin/japicmp/accept/BinaryCompatRule.kt +++ /dev/null @@ -1,39 +0,0 @@ -package japicmp.accept - -import japicmp.model.* -import me.champeau.gradle.japicmp.report.Violation - - -class BinaryCompatRule() : AbstractAcceptingRule() { - private val IGNORED_CHANGE_TYPES: List = listOf( - JApiCompatibilityChangeType.METHOD_REMOVED_IN_SUPERCLASS, // the removal of the method will be reported - JApiCompatibilityChangeType.INTERFACE_REMOVED, // the removed methods will be reported - JApiCompatibilityChangeType.INTERFACE_ADDED, // the added methods will be reported - JApiCompatibilityChangeType.ANNOTATION_DEPRECATED_ADDED, // semver detection is broken - ) - - override fun maybeViolation(member: JApiCompatibility): Violation? { - if (member.isBinaryCompatible) { - return null - } - if (member is JApiClass && member.compatibilityChanges.isEmpty()) { - // A member of the class breaks binary compatibility. - // That will be handled when the member is passed to `maybeViolation`. - return null - } - if (member is JApiImplementedInterface) { - // The changes about the interface's methods will be reported already - return null - } - for (change in member.compatibilityChanges) { - if (IGNORED_CHANGE_TYPES.contains(change.getType())) { - return null - } - } - return checkAcceptance( - member, - member.compatibilityChanges.map { it.getType().name }, - Violation.notBinaryCompatible(member), - ) - } -} diff --git a/build-logic/src/main/kotlin/japicmp/accept/ChangeParams.kt b/build-logic/src/main/kotlin/japicmp/accept/ChangeParams.kt deleted file mode 100644 index b0dc551901..0000000000 --- a/build-logic/src/main/kotlin/japicmp/accept/ChangeParams.kt +++ /dev/null @@ -1,6 +0,0 @@ -package japicmp.accept - -data class ChangeParams( - val changeToReason: Map, - val changeFileName: String, -) diff --git a/build-logic/src/main/kotlin/japicmp/accept/LICENSE.md b/build-logic/src/main/kotlin/japicmp/accept/LICENSE.md deleted file mode 100644 index 6a59db912e..0000000000 --- a/build-logic/src/main/kotlin/japicmp/accept/LICENSE.md +++ /dev/null @@ -1,3 +0,0 @@ -Code in this package is mostly taken and adapted from -[Gradle's binary compat checking](https://github.com/gradle/gradle/blob/master/build-logic/binary-compatibility), -which is licensed under the Apache License 2.0. diff --git a/build-logic/src/main/kotlin/japicmp/accept/apichanges.kt b/build-logic/src/main/kotlin/japicmp/accept/apichanges.kt deleted file mode 100644 index 5d88cb67b4..0000000000 --- a/build-logic/src/main/kotlin/japicmp/accept/apichanges.kt +++ /dev/null @@ -1,22 +0,0 @@ -package japicmp.accept - -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken -import java.nio.file.Files -import java.nio.file.Path - -typealias ApiChangesDiskFormat = Map>; -fun loadAcceptedApiChanges(path: Path): Map { - val fromDisk: ApiChangesDiskFormat = Files.newBufferedReader(path).use { - Gson().fromJson(it, object : TypeToken() {}.type) - } - return fromDisk.asSequence().flatMap { (key, value) -> - value.asSequence().map { it to key } - }.toMap() -} - -data class ApiChange( - val type: String, - val member: String, - val changes: List, -) diff --git a/build-logic/src/main/kotlin/japicmp/accept/userdata.kt b/build-logic/src/main/kotlin/japicmp/accept/userdata.kt deleted file mode 100644 index ac65d4e7c2..0000000000 --- a/build-logic/src/main/kotlin/japicmp/accept/userdata.kt +++ /dev/null @@ -1,10 +0,0 @@ -package japicmp.accept - -import me.champeau.gradle.japicmp.report.ViolationCheckContext - -val ViolationCheckContext.changeParams - get() = userData["changeParams"] as ChangeParams - -@Suppress("UNCHECKED_CAST") -val ViolationCheckContext.seenApiChanges - get() = userData["seenApiChanges"] as MutableSet diff --git a/build.gradle.kts b/build.gradle.kts index b156052388..26686e17dd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,6 @@ plugins { jacoco id("buildlogic.common") - id("buildlogic.artifactory-root") } val totalReport = tasks.register("jacocoTotalReport") { diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml deleted file mode 100644 index 5960a38037..0000000000 --- a/config/checkstyle/checkstyle.xml +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9d4f627907..185cb5840d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,6 +13,8 @@ cuiProtocol = "4.0.3" errorprone = "2.48.0" +crankcase = "0.1.0" + fabric-api = "0.154.0+26.2" neogradle = "7.1.38" @@ -38,6 +40,15 @@ lang-version = "2233" neogradle-neoform = { module = "net.neoforged.gradle:neoform", version.ref = "neogradle" } sponge-vanillagradle = { module = "org.spongepowered:vanillagradle", version.ref = "sponge-vanillagradle" } +crankcase-java = { module = "org.enginehub.crankcase:java", version.ref = "crankcase" } +crankcase-javaLibrary = { module = "org.enginehub.crankcase:java-library", version.ref = "crankcase" } +crankcase-checkstyle = { module = "org.enginehub.crankcase:checkstyle", version.ref = "crankcase" } +crankcase-common = { module = "org.enginehub.crankcase:common", version.ref = "crankcase" } +crankcase-licensing = { module = "org.enginehub.crankcase:licensing", version.ref = "crankcase" } +crankcase-git = { module = "org.enginehub.crankcase:git", version.ref = "crankcase" } +crankcase-japicmp = { module = "org.enginehub.crankcase:japicmp", version.ref = "crankcase" } +crankcase-publishing = { module = "org.enginehub.crankcase:publishing", version.ref = "crankcase" } + levelHeadered = "net.octyl.level-headered:plugin:0.1.1" japicmp = "me.champeau.gradle:japicmp-gradle-plugin:0.4.6" shadow = "com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.3.2" diff --git a/gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts b/gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts deleted file mode 100644 index 35faef4553..0000000000 --- a/gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts +++ /dev/null @@ -1,164 +0,0 @@ -// This file is responsible for reconfiguring repositories to use EngineHub's mirrors -// In addition, it configures content filtering to speed up dependency resolution - -import java.net.URI - -data class RepositoryReconfiguration( - val newUri: URI, - val contentConfiguration: (MavenArtifactRepository.() -> Unit)? = null, -) { - constructor(newUri: String, contentConfiguration: (MavenArtifactRepository.() -> Unit)? = null) : - this(URI.create(newUri), contentConfiguration) -} - -data class ModuleDeclaration( - val group: String, - val name: String, - val version: String? = null, -) - -// Isolate everything from the buildscript so it's serializable -object Isolated { - private val ALLOWED_PREFIXES = listOf( - "https://repo.enginehub.org", - "file:", - ) - - private val REPO_RECONFIGURATIONS = listOf( - "https://repo.maven.apache.org/maven2/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/maven-central-proxy/") { - mavenContent { - releasesOnly() - } - }, - "https://plugins.gradle.org/m2" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/plugin-portal-proxy/") { - mavenContent { - releasesOnly() - } - }, - "https://libraries.minecraft.net/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/minecraft/") { - mavenContent { - releasesOnly() - } - }, - "https://maven.neoforged.net/releases/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/neoforged/") { - mavenContent { - releasesOnly() - includeGroupAndSubgroups("net.minecraftforge") - includeGroupAndSubgroups("net.neoforged") - } - }, - "https://maven.minecraftforge.net/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/forge/") { - mavenContent { - releasesOnly() - includeGroupAndSubgroups("net.minecraftforge") - } - }, - "https://maven.parchmentmc.org/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/parchment/") { - mavenContent { - releasesOnly() - includeGroup("org.parchmentmc.data") - } - }, - "https://repo.papermc.io/repository/maven-public/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/papermc-proxy/") { - mavenContent { - includeGroupAndSubgroups("io.papermc") - includeGroupAndSubgroups("com.velocitypowered") - includeGroupAndSubgroups("ca.spottedleaf") - includeGroupAndSubgroups("me.lucko") - includeModule("net.md-5", "bungeecord-chat") - } - }, - "https://maven.fabricmc.net/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/fabricmc/") { - mavenContent { - releasesOnly() - includeGroupAndSubgroups("fabric-loom") - includeGroupAndSubgroups("net.fabricmc") - excludeModule("net.fabricmc", "yarn") - } - }, - "https://maven.fabricmc.net/#yarn-only" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/fabricmc-yarn/") { - mavenContent { - releasesOnly() - includeModule("net.fabricmc", "yarn") - } - }, - "https://repo.spongepowered.org/repository/maven-releases/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/spongepowered-releases/") { - mavenContent { - releasesOnly() - includeGroupAndSubgroups("org.spongepowered") - } - }, - "https://repo.spongepowered.org/repository/maven-snapshots/" to - RepositoryReconfiguration("https://repo.enginehub.org/internal/spongepowered-snapshots/") { - mavenContent { - snapshotsOnly() - includeGroupAndSubgroups("org.spongepowered") - } - }, - "https://repo.enginehub.org/libs-release/" to - RepositoryReconfiguration("https://repo.enginehub.org/libs-release/") { - mavenContent { - releasesOnly() - includeGroupAndSubgroups("com.sk89q") - includeGroupAndSubgroups("org.enginehub") - } - - metadataSources { - gradleMetadata() - mavenPom() - artifact() - } - }, - ).associate { (k, v) -> URI.create(k) to v } - private val LOGGER = Logging.getLogger("enginehub-reconfiguring-repositories") - - fun RepositoryHandler.mirrorNonEngineHubRepositories() { - configureEach { - val repo = this - if (!(repo is UrlArtifactRepository)) { - return@configureEach - } - val reconfiguration = REPO_RECONFIGURATIONS[repo.url] - val mustReplaceUrl = !ALLOWED_PREFIXES.any { repo.url.toString().startsWith(it) } - if (mustReplaceUrl) { - check(reconfiguration != null) { - "No replacement found for non-EngineHub repository: ${repo.name} ${repo.url}" - } - LOGGER.info( - "Replacing non-EngineHub repository: {} {} -> {}", - repo.name, - repo.url, - reconfiguration.newUri - ) - repo.url = reconfiguration.newUri - } - if (reconfiguration?.contentConfiguration != null) { - if (!(repo is MavenArtifactRepository)) { - error("Cannot configure content on non-Maven repository: ${repo.name} ${repo.url}") - } - repo.run(reconfiguration.contentConfiguration) - } - } - } -} - -with(Isolated) { - gradle.lifecycle.beforeProject { - buildscript.repositories.mirrorNonEngineHubRepositories() - repositories.mirrorNonEngineHubRepositories() - } - - settings.buildscript.repositories.mirrorNonEngineHubRepositories() - settings.pluginManagement.repositories.mirrorNonEngineHubRepositories() - settings.dependencyResolutionManagement.repositories.mirrorNonEngineHubRepositories() -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 19861879f9..f7f43333a1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,30 +1,72 @@ import java.net.URI -apply(from = "gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts") pluginManagement { + // pluginManagement repositories resolve plugins before the repo-reconfiguration plugin can + // apply, so they must point at EngineHub mirrors directly rather than upstream URLs. repositories { maven { - name = "FabricMC" - url = uri("https://maven.fabricmc.net/") + name = "EngineHub" + url = uri("https://repo.enginehub.org/libs-release/") + mavenContent { + releasesOnly() + includeGroupAndSubgroups("com.sk89q") + includeGroupAndSubgroups("org.enginehub") + } } maven { - name = "SpongePowered" - url = uri("https://repo.spongepowered.org/repository/maven-releases/") + name = "EngineHub FabricMC Mirror" + url = uri("https://repo.enginehub.org/internal/fabricmc/") + mavenContent { + releasesOnly() + includeGroupAndSubgroups("fabric-loom") + includeGroupAndSubgroups("net.fabricmc") + excludeModule("net.fabricmc", "yarn") + } } maven { - name = "NeoForged" - url = uri("https://maven.neoforged.net/releases/") + name = "EngineHub SpongePowered Mirror" + url = uri("https://repo.enginehub.org/internal/spongepowered-releases/") + mavenContent { + releasesOnly() + includeGroupAndSubgroups("org.spongepowered") + } } maven { - name = "MinecraftForge" - url = uri("https://maven.minecraftforge.net/") + name = "EngineHub NeoForged Mirror" + url = uri("https://repo.enginehub.org/internal/neoforged/") + mavenContent { + releasesOnly() + includeGroupAndSubgroups("net.minecraftforge") + includeGroupAndSubgroups("net.neoforged") + } + } + maven { + name = "EngineHub MinecraftForge Mirror" + url = uri("https://repo.enginehub.org/internal/forge/") + mavenContent { + releasesOnly() + includeGroupAndSubgroups("net.minecraftforge") + } + } + maven { + name = "EngineHub Maven Central Mirror" + url = uri("https://repo.enginehub.org/internal/maven-central-proxy/") + mavenContent { + releasesOnly() + } + } + maven { + name = "EngineHub Gradle Plugin Portal Mirror" + url = uri("https://repo.enginehub.org/internal/plugin-portal-proxy/") + mavenContent { + releasesOnly() + } } - mavenCentral() - gradlePluginPortal() } } plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" + id("org.enginehub.crankcase.repo-reconfiguration") version "0.1.0" } dependencyResolutionManagement { repositories { diff --git a/verification/build.gradle.kts b/verification/build.gradle.kts index c5e1e2436d..83a0a41ce1 100644 --- a/verification/build.gradle.kts +++ b/verification/build.gradle.kts @@ -1,129 +1,43 @@ -import japicmp.accept.AcceptingSetupRule -import japicmp.accept.BinaryCompatRule import me.champeau.gradle.japicmp.JapicmpTask -import org.gradle.internal.resolve.ModuleVersionNotFoundException -import java.nio.charset.StandardCharsets -import java.nio.file.Files -import java.util.* +import java.util.Locale plugins { base - id("me.champeau.gradle.japicmp") + id("org.enginehub.crankcase.japicmp") } -val resetAcceptedApiChangesFiles by tasks.registering { - group = "API Compatibility" - description = "Resets ALL the accepted API changes files" -} - -val checkApiCompatibility by tasks.registering { - group = "API Compatibility" - description = "Checks ALL API compatibility" -} - -tasks.check { - dependsOn(checkApiCompatibility) -} - -// Generic setup for all tasks // Pull the version before our current version. val baseVersion = "(,${rootProject.version.toString().substringBefore("-SNAPSHOT")}[" + // TODO Re-add neoforge when it's fixed for (projectFragment in listOf("bukkit", "core", "fabric", "sponge")) { - val capitalizedFragment = - projectFragment.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() } - val changeFile = project.file("src/changes/accepted-$projectFragment-public-api-changes.json").toPath() - - val resetChangeFileTask = tasks.register("reset${capitalizedFragment}AcceptedApiChangesFile") { - group = "API Compatibility" - description = "Reset the accepted API changes file for $projectFragment" - outputs.file(changeFile) - - doFirst { - Files.newBufferedWriter(changeFile, StandardCharsets.UTF_8).use { - it.write("{\n}") + japicmp.addCheck(projectFragment) { + // Skip the check when there is no prior published jar to compare against + skipWhenOldClasspathMissing = true + dependencies { + oldClasspath("com.sk89q.worldedit:worldedit-$projectFragment:$baseVersion") { + isTransitive = false } - } - } - resetAcceptedApiChangesFiles { - dependsOn(resetChangeFileTask) - } - - val oldJarScope = configurations.dependencyScope("${projectFragment}OldJarScope") - val oldJarConf = configurations.resolvable("${projectFragment}OldJar") { - extendsFrom(oldJarScope.get()) - } - val newJarScope = configurations.dependencyScope("${projectFragment}NewJarScope") - val newJarConf = configurations.resolvable("${projectFragment}NewJar") { - extendsFrom(newJarScope.get()) - } - dependencies { - (oldJarScope.name)("com.sk89q.worldedit:worldedit-$projectFragment:$baseVersion") { - isTransitive = false - } - (newJarScope.name)(dependencies.project(":worldedit-$projectFragment")) { - isTransitive = false - } - } - val resolvedOldJar = files({ - try { - val confRealized = oldJarConf.get() - confRealized.resolvedConfiguration.rethrowFailure() - confRealized - } catch (e: ResolveException) { - if (e.cause is ModuleVersionNotFoundException) { - logger.warn("Skipping check for $projectFragment API compatibility because there is no jar to compare against") - logger.info("API compatibility exception details: ", e) - setOf() - } else { - throw e + newClasspath(project(":worldedit-$projectFragment")) { + isTransitive = false } } - }) - val checkApi = tasks.register("check${capitalizedFragment}ApiCompatibility") { - group = "API Compatibility" - description = "Check API compatibility for $capitalizedFragment API" - inputs.file(changeFile) - richReport { - addSetupRule( - AcceptingSetupRule::class.java, AcceptingSetupRule.createParams( - changeFile, - ) - ) - addRule(BinaryCompatRule::class.java) - reportName.set("api-compatibility-$projectFragment.html") - } - - onlyIf { - // Only check if we have a jar to compare against - !resolvedOldJar.isEmpty - } - - oldClasspath.from(resolvedOldJar) - newClasspath.from(newJarConf) - onlyModified.set(false) - failOnModification.set(false) // report does the failing (so we can accept) - ignoreMissingClasses.set(true) - // Internals are not API packageExcludes.add("com.sk89q.worldedit*.internal*") // Mixins are not API packageExcludes.add("com.sk89q.worldedit*.mixin*") // Experimental is not API packageExcludes.add("com.sk89q.worldedit*.experimental*") + when (projectFragment) { + // Commands are not API + "core" -> packageExcludes.add("com.sk89q.worldedit.command*") + // Internal Adapters are not API + "bukkit" -> packageExcludes.add("com.sk89q.worldedit.bukkit.adapter*") + } } - checkApiCompatibility { - dependsOn(checkApi) + val capitalizedFragment = projectFragment.replaceFirstChar { it.titlecase(Locale.ROOT) } + tasks.named("check${capitalizedFragment}ApiCompatibility") { + ignoreMissingClasses = true } } - -// Specific project overrides -tasks.named("checkCoreApiCompatibility") { - // Commands are not API - packageExcludes.add("com.sk89q.worldedit.command*") -} -tasks.named("checkBukkitApiCompatibility") { - // Internal Adapters are not API - packageExcludes.add("com.sk89q.worldedit.bukkit.adapter*") -} diff --git a/verification/src/changes/accepted-bukkit-public-api-changes.json b/verification/src/changes/accepted-bukkit-public-api-changes.json index fd21c268d8..2c63c08510 100644 --- a/verification/src/changes/accepted-bukkit-public-api-changes.json +++ b/verification/src/changes/accepted-bukkit-public-api-changes.json @@ -1,12 +1,2 @@ { - "Not API": [ - { - "type": "com.sk89q.worldedit.bukkit.WorldEditListener", - "member": "Method com.sk89q.worldedit.bukkit.WorldEditListener.onPlayerCommandSend(org.bukkit.event.player.PlayerCommandSendEvent)", - "changes": [ - "METHOD_REMOVED", - "ANNOTATION_REMOVED" - ] - } - ] } diff --git a/verification/src/changes/accepted-core-public-api-changes.json b/verification/src/changes/accepted-core-public-api-changes.json index 4876c13d16..2c63c08510 100644 --- a/verification/src/changes/accepted-core-public-api-changes.json +++ b/verification/src/changes/accepted-core-public-api-changes.json @@ -1,27 +1,2 @@ { - "Constructor was not useful": [ - { - "type": "com.sk89q.worldedit.registry.Registries", - "member": "Constructor com.sk89q.worldedit.registry.Registries()", - "changes": [ - "CONSTRUCTOR_LESS_ACCESSIBLE" - ] - } - ], - "Experimental API may change freely": [ - { - "type": "com.sk89q.worldedit.LocalSession", - "member": "Method com.sk89q.worldedit.LocalSession.getSnapshotExperimental()", - "changes": [ - "METHOD_RETURN_TYPE_CHANGED" - ] - }, - { - "type": "com.sk89q.worldedit.LocalSession", - "member": "Method com.sk89q.worldedit.LocalSession.setSnapshotExperimental(com.sk89q.worldedit.world.snapshot.experimental.Snapshot)", - "changes": [ - "METHOD_REMOVED" - ] - } - ] } diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index 2eaa7a887e..cca9e099d3 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -3,7 +3,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import io.papermc.paperweight.userdev.attribute.Obfuscation plugins { - `java-library` id("buildlogic.platform") } diff --git a/worldedit-cli/build.gradle.kts b/worldedit-cli/build.gradle.kts index 22f21f4714..0bcf0e3f80 100644 --- a/worldedit-cli/build.gradle.kts +++ b/worldedit-cli/build.gradle.kts @@ -1,7 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { - `java-library` id("buildlogic.platform") } diff --git a/worldedit-core-mc/build.gradle.kts b/worldedit-core-mc/build.gradle.kts index 26a25440ea..3ca8523105 100644 --- a/worldedit-core-mc/build.gradle.kts +++ b/worldedit-core-mc/build.gradle.kts @@ -3,7 +3,6 @@ import buildlogic.addEngineHubRepository plugins { alias(libs.plugins.fabric.loom) - `java-library` id("buildlogic.core-and-platform") id("buildlogic.expose-resources") } diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index 1d69bf7a09..3d4817b59e 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -1,7 +1,6 @@ import org.gradle.plugins.ide.idea.model.IdeaModel plugins { - `java-library` antlr id("buildlogic.core-and-platform") id("buildlogic.expose-resources") diff --git a/worldedit-core/doctools/build.gradle.kts b/worldedit-core/doctools/build.gradle.kts index 0a074c3474..58d26736e9 100644 --- a/worldedit-core/doctools/build.gradle.kts +++ b/worldedit-core/doctools/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("jvm") version "2.3.10" application - id("buildlogic.common") + id("buildlogic.common-java") } application.mainClass.set("com.sk89q.worldedit.internal.util.DocumentationPrinter") diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 49df120495..8268027302 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -8,7 +8,6 @@ import java.net.URI plugins { alias(libs.plugins.fabric.loom) - `java-library` id("buildlogic.platform") } diff --git a/worldedit-neoforge/build.gradle.kts b/worldedit-neoforge/build.gradle.kts index 70fe733073..cce1516446 100644 --- a/worldedit-neoforge/build.gradle.kts +++ b/worldedit-neoforge/build.gradle.kts @@ -6,7 +6,6 @@ import net.neoforged.gradle.dsl.common.runs.run.Run plugins { alias(libs.plugins.neogradle.userdev) - `java-library` id("buildlogic.platform") } diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index 77184c34c3..7d54635d41 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -6,7 +6,6 @@ import org.spongepowered.plugin.metadata.model.PluginDependency plugins { alias(libs.plugins.sponge.spongegradle) id("org.spongepowered.gradle.vanilla") - `java-library` id("buildlogic.platform") }