From 95a4237d1bdac17d8a5363aa485306ca3c0a00d3 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Sun, 3 Nov 2024 17:44:16 -0500 Subject: [PATCH 01/35] fix caching for CompressJarTask --- build.gradle.kts | 27 +++++---- .../dev/nolij/zumegradle/JarCompressing.kt | 60 +++++++++++-------- gradle.properties | 2 +- 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index dd5148c..dd16f31 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -101,13 +101,15 @@ val patchHistory = releaseTags .map { name -> name.substring(minorTagPrefix.length) } val maxPatch = patchHistory.maxOfOrNull { it.substringBefore('-').toInt() } -val patch = - maxPatch?.plus( - if (patchHistory.contains(maxPatch.toString())) - releaseIncrement - else - 0 - ) ?: 0 +val patch = maxPatch.let { + if (it != null) { + if (patchHistory.contains(it.toString())) { + it + releaseIncrement + } else { + it + } + } else 0 +} var patchAndSuffix = patch.toString() if (releaseChannel.suffix != null) { @@ -175,11 +177,6 @@ allprojects { apply(plugin = "maven-publish") repositories { - mavenCentral { - content { - excludeGroup("ca.weblite") - } - } maven("https://repo.spongepowered.org/maven") maven("https://jitpack.io/") exclusiveContent { @@ -200,6 +197,7 @@ allprojects { languageVersion = JavaLanguageVersion.of(21) } options.compilerArgs.addAll(arrayOf("-Xplugin:Manifold no-bootstrap", "-Xplugin:jabel")) + options.forkOptions.jvmArgs?.add("-XX:+EnableDynamicAgentLoading") } } @@ -397,7 +395,7 @@ tasks.shadowJar { exclude("LICENSE_zson") configurations = immutableListOf(shade) - archiveClassifier = null + archiveClassifier = "deobfuscated" isPreserveFileTimestamps = false isReproducibleFileOrder = true @@ -451,6 +449,9 @@ val compressJar = tasks.register("compressJar") { val shadowJar = tasks.shadowJar.get() inputJar = shadowJar.archiveFile.get().asFile + outputJar = shadowJar.archiveFile.get().asFile.let { + it.parentFile.resolve("${it.nameWithoutExtension.removeSuffix("-deobfuscated")}.jar") + } deflateAlgorithm = releaseChannel.deflation jsonShrinkingType = releaseChannel.json diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt index e3d7a42..981cc99 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt @@ -7,11 +7,8 @@ import net.fabricmc.mappingio.format.MappingFormat import net.fabricmc.mappingio.tree.MappingTree.ClassMapping import net.fabricmc.mappingio.tree.MemoryMappingTree import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.* import org.gradle.api.tasks.options.Option import org.gradle.kotlin.dsl.support.uppercaseFirstChar import org.objectweb.asm.ClassReader @@ -82,7 +79,7 @@ fun squishJar(jar: File, jsonProcessing: JsonShrinkingType, mappingsFile: File?) } if (name.endsWith(".class")) { - bytes = processClassFile(bytes, mappings!!) + bytes = processClassFile(bytes, mappings) } out.putNextEntry(JarEntry(name)) @@ -97,7 +94,7 @@ fun squishJar(jar: File, jsonProcessing: JsonShrinkingType, mappingsFile: File?) private fun remapMixinConfig(bytes: ByteArray, mappings: MemoryMappingTree): ByteArray { val json = (JsonSlurper().parse(bytes) as Map).toMutableMap() val old = json["plugin"] as String - val obf = mappings.obfuscate(old) + val obf = mappings.map(old) json["plugin"] = obf json["package"] = "zume.mixin" @@ -105,17 +102,19 @@ private fun remapMixinConfig(bytes: ByteArray, mappings: MemoryMappingTree): Byt return JsonOutput.toJson(json).toByteArray() } -private fun processClassFile(bytes: ByteArray, mappings: MemoryMappingTree): ByteArray { +private fun processClassFile(bytes: ByteArray, mappings: MemoryMappingTree?): ByteArray { val classNode = ClassNode() ClassReader(bytes).accept(classNode, 0) - for (annotation in classNode.visibleAnnotations ?: emptyList()) { - if (annotation.desc.endsWith("fml/common/Mod;")) { - for (i in 0 until annotation.values.size step 2) { - if (annotation.values[i] == "guiFactory") { - val old = annotation.values[i + 1] as String - annotation.values[i + 1] = mappings.obfuscate(old) - println("Remapped guiFactory: $old -> ${annotation.values[i + 1]}") + if(mappings != null) { + for (annotation in classNode.visibleAnnotations ?: emptyList()) { + if (annotation.desc.endsWith("fml/common/Mod;")) { + for (i in 0 until annotation.values.size step 2) { + if (annotation.values[i] == "guiFactory") { + val old = annotation.values[i + 1] as String + annotation.values[i + 1] = mappings.map(old) + println("Remapped guiFactory: $old -> ${annotation.values[i + 1]}") + } } } } @@ -262,9 +261,10 @@ fun applyProguard(jar: File, minecraftConfigs: List, configDir: } } -open class CompressJarTask : DefaultTask() { - @InputFile - lateinit var inputJar: File +abstract class CompressJarTask : DefaultTask() { + @get:InputFile + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val inputJar: RegularFileProperty @Input var deflateAlgorithm = DeflateAlgorithm.LIBDEFLATE @@ -278,13 +278,15 @@ open class CompressJarTask : DefaultTask() { private var minecraftConfigs: List = emptyList() @get:OutputFile - val outputJar get() = inputJar // compressed jar will replace the input jar + abstract val outputJar: RegularFileProperty @get:OutputFile @get:Optional val mappingsFile get() = if (useProguard) - inputJar.parentFile.resolve("${inputJar.nameWithoutExtension}-mappings.txt") + inputJar.get().asFile.let { + it.parentFile.resolve("${it.nameWithoutExtension}-mappings.txt") + } else null @Option(option = "compression-type", description = "How to recompress the jar") @@ -306,10 +308,18 @@ open class CompressJarTask : DefaultTask() { @TaskAction fun compressJar() { - if (useProguard) - applyProguard(inputJar, minecraftConfigs, project.rootDir) - squishJar(inputJar, jsonShrinkingType, mappingsFile) - deflate(outputJar, deflateAlgorithm) +// if (useProguard) +// applyProguard(inputJar, minecraftConfigs, project.rootDir) +// squishJar(inputJar, jsonShrinkingType, mappingsFile) +// deflate(outputJar, deflateAlgorithm) + val jar = inputJar.get().asFile + val temp = jar.copyTo(temporaryDir.resolve("temp.jar"), true) + if(useProguard) { + applyProguard(temp, minecraftConfigs, project.rootDir) + } + squishJar(temp, jsonShrinkingType, mappingsFile) + deflate(temp, deflateAlgorithm) + temp.copyTo(outputJar.get().asFile, true) } } @@ -324,7 +334,7 @@ fun mappings(file: File, format: MappingFormat = MappingFormat.PROGUARD): Memory } @Suppress("INACCESSIBLE_TYPE", "NAME_SHADOWING") -fun MemoryMappingTree.obfuscate(src: String): String { +fun MemoryMappingTree.map(src: String): String { val src = src.replace('.', '/') val dstNamespaceIndex = getNamespaceId(dstNamespaces[0]) val classMapping: ClassMapping? = getClass(src) diff --git a/gradle.properties b/gradle.properties index dd3577a..4874537 100644 --- a/gradle.properties +++ b/gradle.properties @@ -117,7 +117,7 @@ mixin_version = 0.8.5 # https://central.sonatype.com/artifact/org.jetbrains/annotations jetbrains_annotations_version = 24.1.0 # https://github.com/manifold-systems/manifold -manifold_version = 2024.1.30 +manifold_version = 2024.1.39 # Gradle Plugins # https://maven.fabricmc.net/net/fabricmc/mapping-io/ From f243a7142c817de29f8ac60a608b71b5baf287d8 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Sun, 3 Nov 2024 20:53:13 -0500 Subject: [PATCH 02/35] remove old comments --- .../src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt index 981cc99..08b4f9f 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt @@ -308,10 +308,6 @@ abstract class CompressJarTask : DefaultTask() { @TaskAction fun compressJar() { -// if (useProguard) -// applyProguard(inputJar, minecraftConfigs, project.rootDir) -// squishJar(inputJar, jsonShrinkingType, mappingsFile) -// deflate(outputJar, deflateAlgorithm) val jar = inputJar.get().asFile val temp = jar.copyTo(temporaryDir.resolve("temp.jar"), true) if(useProguard) { From d9fb8f9bc41e532d4265afb89dad382be8cc54cf Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Sun, 3 Nov 2024 20:54:03 -0500 Subject: [PATCH 03/35] remove old comments --- .../src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt index 981cc99..08b4f9f 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt @@ -308,10 +308,6 @@ abstract class CompressJarTask : DefaultTask() { @TaskAction fun compressJar() { -// if (useProguard) -// applyProguard(inputJar, minecraftConfigs, project.rootDir) -// squishJar(inputJar, jsonShrinkingType, mappingsFile) -// deflate(outputJar, deflateAlgorithm) val jar = inputJar.get().asFile val temp = jar.copyTo(temporaryDir.resolve("temp.jar"), true) if(useProguard) { From 744cd624011d4aca559ff6adf6ca6bb4d16f366b Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Sun, 3 Nov 2024 20:53:45 -0500 Subject: [PATCH 04/35] the great rework --- build.gradle.kts | 95 ++++- buildSrc/build.gradle.kts | 6 + .../dev/nolij/zumegradle/DeflateAlgorithm.kt | 33 ++ .../dev/nolij/zumegradle/JarCompressing.kt | 342 ------------------ .../dev/nolij/zumegradle/JsonShrinkingType.kt | 5 + .../entryprocessing/EntryProcessors.kt | 118 ++++++ .../dev/nolij/zumegradle/task/AdvzipTask.kt | 44 +++ .../dev/nolij/zumegradle/task/CopyJarTask.kt | 7 + .../task/JarEntryModificationTask.kt | 54 +++ .../nolij/zumegradle/task/ProcessJarTask.kt | 35 ++ .../dev/nolij/zumegradle/task/ProguardTask.kt | 87 +++++ .../dev/nolij/zumegradle/util/AsmHelper.kt | 17 + .../nolij/zumegradle/util/MappingsHelper.kt | 29 ++ 13 files changed, 512 insertions(+), 360 deletions(-) create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/DeflateAlgorithm.kt delete mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/JsonShrinkingType.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/entryprocessing/EntryProcessors.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/AdvzipTask.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/CopyJarTask.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/JarEntryModificationTask.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/ProcessJarTask.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/ProguardTask.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/util/AsmHelper.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/util/MappingsHelper.kt diff --git a/build.gradle.kts b/build.gradle.kts index dd16f31..dbd5100 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,11 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import dev.nolij.zumegradle.DeflateAlgorithm import dev.nolij.zumegradle.JsonShrinkingType import dev.nolij.zumegradle.MixinConfigMergingTransformer -import dev.nolij.zumegradle.CompressJarTask +import dev.nolij.zumegradle.entryprocessing.EntryProcessors +import dev.nolij.zumegradle.task.AdvzipTask +import dev.nolij.zumegradle.task.CopyJarTask +import dev.nolij.zumegradle.task.JarEntryModificationTask +import dev.nolij.zumegradle.task.ProguardTask import kotlinx.serialization.encodeToString import me.modmuss50.mpp.HttpUtils import me.modmuss50.mpp.PublishModTask @@ -38,13 +42,13 @@ operator fun String.invoke(): String = rootProject.properties[this] as? String ? enum class ReleaseChannel( val suffix: String? = null, val releaseType: ReleaseType? = null, - val deflation: DeflateAlgorithm = DeflateAlgorithm.ZOPFLI, - val json: JsonShrinkingType = JsonShrinkingType.MINIFY, + val deflation: DeflateAlgorithm = DeflateAlgorithm.INSANE, + val json: JsonShrinkingType? = JsonShrinkingType.MINIFY, val proguard: Boolean = true, ) { DEV_BUILD( suffix = "dev", - deflation = DeflateAlgorithm.SEVENZIP, + deflation = DeflateAlgorithm.EXTRA, json = JsonShrinkingType.PRETTY_PRINT ), PRE_RELEASE("pre"), @@ -364,8 +368,8 @@ val sourcesJar = tasks.register("sourcesJar") { } if (releaseChannel.proguard) { - dependsOn(compressJar) - from(compressJar.get().mappingsFile!!) { + dependsOn(proguardJar) + from(proguardJar.get().mappingsFile) { rename { "mappings.txt" } } } @@ -443,23 +447,78 @@ tasks.shadowJar { } } -val compressJar = tasks.register("compressJar") { +//region compressJar +val cjTempDir = layout.buildDirectory.dir("compressJar") +val proguardJar by tasks.registering(ProguardTask::class) { dependsOn(tasks.shadowJar) - group = "build" + inputJar = tasks.shadowJar.get().archiveFile + destinationDirectory = cjTempDir + run = releaseChannel.proguard - val shadowJar = tasks.shadowJar.get() - inputJar = shadowJar.archiveFile.get().asFile - outputJar = shadowJar.archiveFile.get().asFile.let { - it.parentFile.resolve("${it.nameWithoutExtension.removeSuffix("-deobfuscated")}.jar") - } + config(file("proguard.pro")) - deflateAlgorithm = releaseChannel.deflation - jsonShrinkingType = releaseChannel.json + mappingsFile = destinationDirectory.get().asFile + .resolve("${archiveFile.get().asFile.nameWithoutExtension}-mappings.txt") + + jmod("java.base") + jmod("java.desktop") + + classpath.addAll( + uniminedImpls.flatMap { implName -> project(":$implName").unimined.minecrafts.values }.flatMap { mc -> + val prodNamespace = mc.mcPatcher.prodNamespace + + val minecrafts = listOf( + mc.sourceSet.compileClasspath.files, + mc.sourceSet.runtimeClasspath.files + ) + .flatten() + .filter { !mc.isMinecraftJar(it.toPath()) } + .toHashSet() + + mc.mods.getClasspathAs(prodNamespace, prodNamespace, minecrafts) + .filter { it.extension == "jar" && !it.name.startsWith("zume") } + .plus(mc.getMinecraft(prodNamespace, prodNamespace).toFile()) + } + ) + + archiveClassifier = "proguard" +} + +val minifyJar by tasks.registering(JarEntryModificationTask::class) { + dependsOn(proguardJar) + inputJar = proguardJar.get().archiveFile + destinationDirectory = cjTempDir + + archiveClassifier = "minified" + json(releaseChannel.json) { + it.endsWith(".json") || it.endsWith(".mcmeta") || it == "mcmod.info" + } + + process(EntryProcessors.minifyClass { it.desc.startsWith("Ldev/nolij/zumegradle/proguard/") }) + if (releaseChannel.proguard) { - useProguard(uniminedImpls.flatMap { implName -> project(":$implName").unimined.minecrafts.values }) + process(EntryProcessors.obfuscationFixer(proguardJar.get().mappingsFile.get().asFile)) } } +val advzip by tasks.registering(AdvzipTask::class) { + dependsOn(minifyJar) + inputJar = minifyJar.get().archiveFile + destinationDirectory = cjTempDir + + archiveClassifier = "advzip" + level = releaseChannel.deflation +} + +val compressJar by tasks.registering(CopyJarTask::class) { + dependsOn(advzip) + group = "build" + inputJar = advzip.get().archiveFile + + archiveClassifier = null +} +//endregion + tasks.assemble { dependsOn(compressJar, sourcesJar) } @@ -473,7 +532,7 @@ afterEvaluate { publications { create("mod_id"()) { - artifact(compressJar.get().outputJar) + artifact(compressJar.get().archiveFile) artifact(sourcesJar) } } @@ -488,7 +547,7 @@ afterEvaluate { } publishMods { - file = compressJar.get().outputJar + file = compressJar.get().archiveFile additionalFiles.from(sourcesJar.get().archiveFile) type = releaseChannel.releaseType ?: ALPHA displayName = Zume.version diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 675a30f..4629987 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -18,6 +18,12 @@ repositories { } } +kotlin { + jvmToolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + fun DependencyHandler.plugin(id: String, version: String) { this.implementation(group = id, name = "$id.gradle.plugin", version = version) } diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/DeflateAlgorithm.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/DeflateAlgorithm.kt new file mode 100644 index 0000000..255f6f7 --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/DeflateAlgorithm.kt @@ -0,0 +1,33 @@ +package dev.nolij.zumegradle + +import org.gradle.kotlin.dsl.support.uppercaseFirstChar + +enum class DeflateAlgorithm(val id: Int?) { + + /** + * Entries are stored without compression + */ + STORE(0), + + /** + * Entries are stored with Zlib + */ + FAST(1), + + /** + * Entries are stored with libdeflate + */ + NORMAL(2), + + /** + * Entries are stored with 7zip + */ + EXTRA(3), + + /** + * Entries are stored with Zopfli + */ + INSANE(4); + + override fun toString() = name.lowercase().uppercaseFirstChar() +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt deleted file mode 100644 index 08b4f9f..0000000 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt +++ /dev/null @@ -1,342 +0,0 @@ -package dev.nolij.zumegradle - -import groovy.json.JsonOutput -import groovy.json.JsonSlurper -import net.fabricmc.mappingio.MappingReader -import net.fabricmc.mappingio.format.MappingFormat -import net.fabricmc.mappingio.tree.MappingTree.ClassMapping -import net.fabricmc.mappingio.tree.MemoryMappingTree -import org.gradle.api.DefaultTask -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.tasks.* -import org.gradle.api.tasks.options.Option -import org.gradle.kotlin.dsl.support.uppercaseFirstChar -import org.objectweb.asm.ClassReader -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.tree.AnnotationNode -import org.objectweb.asm.tree.ClassNode -import proguard.Configuration -import proguard.ConfigurationParser -import proguard.ProGuard -import xyz.wagyourtail.unimined.api.minecraft.MinecraftConfig -import java.io.File -import java.util.Properties -import java.util.jar.JarEntry -import java.util.jar.JarFile -import java.util.jar.JarOutputStream -import java.util.zip.Deflater -import kotlin.collections.HashSet - -enum class DeflateAlgorithm(val id: Int?) { - NONE(null), - LIBDEFLATE(2), - SEVENZIP(3), - ZOPFLI(4), // too slow - ; - - override fun toString() = name.lowercase().uppercaseFirstChar() -} - -enum class JsonShrinkingType { - NONE, MINIFY, PRETTY_PRINT -} - -fun squishJar(jar: File, jsonProcessing: JsonShrinkingType, mappingsFile: File?) { - val contents = linkedMapOf() - JarFile(jar).use { - it.entries().asIterator().forEach { entry -> - if (!entry.isDirectory) { - contents[entry.name] = it.getInputStream(entry).readAllBytes() - } - } - } - - jar.delete() - - val json = JsonSlurper() - - val isObfuscating = mappingsFile?.exists() == true - val mappings = if (isObfuscating) mappings(mappingsFile!!) else null - - JarOutputStream(jar.outputStream()).use { out -> - out.setLevel(Deflater.BEST_COMPRESSION) - contents.forEach { var (name, bytes) = it - - if (name.endsWith("mixins.json") && isObfuscating) { - bytes = remapMixinConfig(bytes, mappings!!) - } - - if (jsonProcessing != JsonShrinkingType.NONE && - name.endsWith(".json") || name.endsWith(".mcmeta") || name == "mcmod.info" - ) { - bytes = when (jsonProcessing) { - JsonShrinkingType.MINIFY -> JsonOutput.toJson(json.parse(bytes)).toByteArray() - JsonShrinkingType.PRETTY_PRINT -> JsonOutput.prettyPrint(JsonOutput.toJson(json.parse(bytes))) - .toByteArray() - - else -> throw AssertionError() - } - } - - if (name.endsWith(".class")) { - bytes = processClassFile(bytes, mappings) - } - - out.putNextEntry(JarEntry(name)) - out.write(bytes) - out.closeEntry() - } - out.finish() - } -} - -@Suppress("UNCHECKED_CAST") -private fun remapMixinConfig(bytes: ByteArray, mappings: MemoryMappingTree): ByteArray { - val json = (JsonSlurper().parse(bytes) as Map).toMutableMap() - val old = json["plugin"] as String - val obf = mappings.map(old) - json["plugin"] = obf - - json["package"] = "zume.mixin" - - return JsonOutput.toJson(json).toByteArray() -} - -private fun processClassFile(bytes: ByteArray, mappings: MemoryMappingTree?): ByteArray { - val classNode = ClassNode() - ClassReader(bytes).accept(classNode, 0) - - if(mappings != null) { - for (annotation in classNode.visibleAnnotations ?: emptyList()) { - if (annotation.desc.endsWith("fml/common/Mod;")) { - for (i in 0 until annotation.values.size step 2) { - if (annotation.values[i] == "guiFactory") { - val old = annotation.values[i + 1] as String - annotation.values[i + 1] = mappings.map(old) - println("Remapped guiFactory: $old -> ${annotation.values[i + 1]}") - } - } - } - } - } - - val strippableAnnotations = setOf( - "Lorg/spongepowered/asm/mixin/Dynamic;", - "Lorg/spongepowered/asm/mixin/Final;", - "Ljava/lang/SafeVarargs;", - ) - val canStripAnnotation = { annotationNode: AnnotationNode -> - annotationNode.desc.startsWith("Ldev/nolij/zumegradle/proguard/") || - annotationNode.desc.startsWith("Lorg/jetbrains/annotations/") || - strippableAnnotations.contains(annotationNode.desc) - } - - classNode.invisibleAnnotations?.removeIf(canStripAnnotation) - classNode.visibleAnnotations?.removeIf(canStripAnnotation) - classNode.invisibleTypeAnnotations?.removeIf(canStripAnnotation) - classNode.visibleTypeAnnotations?.removeIf(canStripAnnotation) - classNode.fields.forEach { fieldNode -> - fieldNode.invisibleAnnotations?.removeIf(canStripAnnotation) - fieldNode.visibleAnnotations?.removeIf(canStripAnnotation) - fieldNode.invisibleTypeAnnotations?.removeIf(canStripAnnotation) - fieldNode.visibleTypeAnnotations?.removeIf(canStripAnnotation) - } - classNode.methods.forEach { methodNode -> - methodNode.invisibleAnnotations?.removeIf(canStripAnnotation) - methodNode.visibleAnnotations?.removeIf(canStripAnnotation) - methodNode.invisibleTypeAnnotations?.removeIf(canStripAnnotation) - methodNode.visibleTypeAnnotations?.removeIf(canStripAnnotation) - methodNode.invisibleLocalVariableAnnotations?.removeIf(canStripAnnotation) - methodNode.visibleLocalVariableAnnotations?.removeIf(canStripAnnotation) - methodNode.invisibleParameterAnnotations?.forEach { parameterAnnotations -> - parameterAnnotations?.removeIf(canStripAnnotation) - } - methodNode.visibleParameterAnnotations?.forEach { parameterAnnotations -> - parameterAnnotations?.removeIf(canStripAnnotation) - } - } - - if (classNode.invisibleAnnotations?.any { it.desc == "Lorg/spongepowered/asm/mixin/Mixin;" } == true) { - classNode.methods.removeAll { it.name == "" && it.instructions.size() <= 3 } // ALOAD, super(), RETURN - } - - val writer = ClassWriter(0) - classNode.accept(writer) - return writer.toByteArray() -} - -val advzipInstalled = try { - ProcessBuilder("advzip", "-V").start().waitFor() == 0 -} catch (e: Exception) { - false -} - -fun deflate(zip: File, type: DeflateAlgorithm) { - if (type == DeflateAlgorithm.NONE) return - if (!advzipInstalled) { - println("advzip is not installed; skipping re-deflation of $zip") - return - } - - try { - val process = ProcessBuilder("advzip", "-z", "-${type.id}", zip.absolutePath).start() - val exitCode = process.waitFor() - if (exitCode != 0) { - error("Failed to compress $zip with $type") - } - } catch (e: Exception) { - error("Failed to compress $zip with $type: ${e.message}") - } -} - -val JAVA_HOME = System.getProperty("java.home") - -@Suppress("UnstableApiUsage") -fun applyProguard(jar: File, minecraftConfigs: List, configDir: File) { - val inputJar = jar.copyTo( - jar.parentFile.resolve(".${jar.nameWithoutExtension}_proguardRunning.jar"), true - ).also { - it.deleteOnExit() - } - - val config = configDir.resolve("proguard.pro") - if (!config.exists()) { - error("proguard.pro not found") - } - val proguardCommand = mutableListOf( - "@${config.absolutePath}", - "-printmapping", jar.parentFile.resolve("${jar.nameWithoutExtension}-mappings.txt").absolutePath, - "-injars", inputJar.absolutePath, - "-outjars", jar.absolutePath, - ) - - val libraries = HashSet() - libraries.add("${JAVA_HOME}/jmods/java.base.jmod") - libraries.add("${JAVA_HOME}/jmods/java.desktop.jmod") - - for (minecraftConfig in minecraftConfigs) { - val prodNamespace = minecraftConfig.mcPatcher.prodNamespace - - libraries.add(minecraftConfig.getMinecraft(prodNamespace, prodNamespace).toFile().absolutePath) - - val minecrafts = listOf( - minecraftConfig.sourceSet.compileClasspath.files, - minecraftConfig.sourceSet.runtimeClasspath.files - ) - .flatten() - .filter { it: File -> !minecraftConfig.isMinecraftJar(it.toPath()) } - .toHashSet() - - libraries += minecraftConfig.mods.getClasspathAs(prodNamespace, prodNamespace, minecrafts) - .filter { it.extension == "jar" && !it.name.startsWith("zume") } - .map { it.absolutePath } - } - - val debug = Properties().apply { - val gradleproperties = configDir.resolve("gradle.properties") - if (gradleproperties.exists()) { - load(gradleproperties.inputStream()) - } - }.getProperty("zumegradle.proguard.keepAttrs").toBoolean() - - if (debug) { - proguardCommand.add("-keepattributes") - proguardCommand.add("*Annotation*,SourceFile,MethodParameters,L*Table") - proguardCommand.add("-dontobfuscate") - } - - proguardCommand.add("-libraryjars") - proguardCommand.add(libraries.joinToString(File.pathSeparator) { "\"$it\"" }) - - val configuration = Configuration() - ConfigurationParser(proguardCommand.toTypedArray(), System.getProperties()) - .parse(configuration) - - try { - ProGuard(configuration).execute() - } catch (ex: Exception) { - throw IllegalStateException("ProGuard failed for $jar", ex) - } finally { - inputJar.delete() - } -} - -abstract class CompressJarTask : DefaultTask() { - @get:InputFile - @get:PathSensitive(PathSensitivity.RELATIVE) - abstract val inputJar: RegularFileProperty - - @Input - var deflateAlgorithm = DeflateAlgorithm.LIBDEFLATE - - @Input - var jsonShrinkingType = JsonShrinkingType.NONE - - @get:Input - val useProguard get() = this.minecraftConfigs.isNotEmpty() - - private var minecraftConfigs: List = emptyList() - - @get:OutputFile - abstract val outputJar: RegularFileProperty - - @get:OutputFile - @get:Optional - val mappingsFile - get() = if (useProguard) - inputJar.get().asFile.let { - it.parentFile.resolve("${it.nameWithoutExtension}-mappings.txt") - } - else null - - @Option(option = "compression-type", description = "How to recompress the jar") - fun setDeflateAlgorithm(value: String) { - deflateAlgorithm = value.uppercase().let { - if (it.matches(Regex("7Z(?:IP)?"))) DeflateAlgorithm.SEVENZIP - else DeflateAlgorithm.valueOf(it) - } - } - - @Option(option = "json-processing", description = "How to process json files") - fun setJsonShrinkingType(value: String) { - jsonShrinkingType = JsonShrinkingType.valueOf(value.uppercase()) - } - - fun useProguard(minecraftConfigs: List) { - this.minecraftConfigs = minecraftConfigs - } - - @TaskAction - fun compressJar() { - val jar = inputJar.get().asFile - val temp = jar.copyTo(temporaryDir.resolve("temp.jar"), true) - if(useProguard) { - applyProguard(temp, minecraftConfigs, project.rootDir) - } - squishJar(temp, jsonShrinkingType, mappingsFile) - deflate(temp, deflateAlgorithm) - temp.copyTo(outputJar.get().asFile, true) - } -} - -fun mappings(file: File, format: MappingFormat = MappingFormat.PROGUARD): MemoryMappingTree { - if (!file.exists()) { - error("Mappings file $file does not exist") - } - - val mappingTree = MemoryMappingTree() - MappingReader.read(file.toPath(), format, mappingTree) - return mappingTree -} - -@Suppress("INACCESSIBLE_TYPE", "NAME_SHADOWING") -fun MemoryMappingTree.map(src: String): String { - val src = src.replace('.', '/') - val dstNamespaceIndex = getNamespaceId(dstNamespaces[0]) - val classMapping: ClassMapping? = getClass(src) - if (classMapping == null) { - println("Class $src not found in mappings") - return src - } - return classMapping.getDstName(dstNamespaceIndex).replace('/', '.') -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JsonShrinkingType.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JsonShrinkingType.kt new file mode 100644 index 0000000..d05cea7 --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/JsonShrinkingType.kt @@ -0,0 +1,5 @@ +package dev.nolij.zumegradle + +enum class JsonShrinkingType { + MINIFY, PRETTY_PRINT +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/entryprocessing/EntryProcessors.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/entryprocessing/EntryProcessors.kt new file mode 100644 index 0000000..8f85d5c --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/entryprocessing/EntryProcessors.kt @@ -0,0 +1,118 @@ +package dev.nolij.zumegradle.entryprocessing + +import dev.nolij.zumegradle.util.map +import dev.nolij.zumegradle.util.mappings +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +import net.fabricmc.mappingio.format.MappingFormat +import org.objectweb.asm.tree.AnnotationNode +import java.io.File + +import dev.nolij.zumegradle.util.toBytes +import dev.nolij.zumegradle.util.ClassNode + +typealias EntryProcessor = (String, ByteArray) -> ByteArray + +object EntryProcessors { + val PASS: EntryProcessor = { _, bytes -> bytes } + + fun jsonMinifier(shouldRun: (String) -> Boolean = { it.endsWith(".json") }): EntryProcessor = { name, bytes -> + if (shouldRun(name)) { + val json = String(bytes) + val minified = JsonSlurper().parseText(json).toString() + minified.toByteArray() + } else { + bytes + } + } + + fun jsonPrettyPrinter(shouldRun: (String) -> Boolean = { it.endsWith(".json") }): EntryProcessor = { name, bytes -> + if (shouldRun(name)) { + JsonOutput.prettyPrint(String(bytes)).toByteArray() + } else { + bytes + } + } + + @Suppress("UNCHECKED_CAST") + fun obfuscationFixer(mappingsFile: File, format: MappingFormat = MappingFormat.PROGUARD): EntryProcessor = { name, bytes -> + val mappings = mappings(mappingsFile, format) + if (name.endsWith("mixins.json")) { + val json = (JsonSlurper().parse(bytes) as Map).toMutableMap() + json["plugin"] = mappings.map(json["plugin"] as String) + + json["package"] = "zume.mixin" // TODO: make this configurable + + JsonOutput.toJson(json).toByteArray() + } else if (name.endsWith(".class")) { + val classNode = ClassNode(bytes) + + for (annotation in classNode.visibleAnnotations ?: emptyList()) { + if (annotation.desc.endsWith("fml/common/Mod;")) { + for (i in 0 until annotation.values.size step 2) { + if (annotation.values[i] == "guiFactory") { + val old = annotation.values[i + 1] as String + annotation.values[i + 1] = mappings.map(old) + println("Remapped guiFactory: $old -> ${annotation.values[i + 1]}") + } + } + } + } + + classNode.toBytes() + } else { + bytes + } + } + + fun minifyClass(runOnEverything: Boolean = false, extraAnnotationsToStrip: (AnnotationNode) -> Boolean): EntryProcessor = a@{ name, bytes -> + if(!name.endsWith(".class") && !runOnEverything) { + return@a bytes + } + + val shouldStripAnnotation: (AnnotationNode) -> Boolean = { + setOf( + "Lorg/spongepowered/asm/mixin/Dynamic;", + "Lorg/spongepowered/asm/mixin/Final;", + "Ljava/lang/SafeVarargs;", + ).contains(it.desc) + || it.desc.startsWith("Lorg/jetbrains/annotations/") + || extraAnnotationsToStrip(it) + } + val classNode = ClassNode(bytes) + + classNode.invisibleAnnotations?.removeIf(shouldStripAnnotation) + classNode.visibleAnnotations?.removeIf(shouldStripAnnotation) + classNode.invisibleTypeAnnotations?.removeIf(shouldStripAnnotation) + classNode.visibleTypeAnnotations?.removeIf(shouldStripAnnotation) + classNode.fields.forEach { + it.invisibleAnnotations?.removeIf(shouldStripAnnotation) + it.visibleAnnotations?.removeIf(shouldStripAnnotation) + it.invisibleTypeAnnotations?.removeIf(shouldStripAnnotation) + it.visibleTypeAnnotations?.removeIf(shouldStripAnnotation) + } + classNode.methods.forEach { + it.invisibleAnnotations?.removeIf(shouldStripAnnotation) + it.visibleAnnotations?.removeIf(shouldStripAnnotation) + it.invisibleTypeAnnotations?.removeIf(shouldStripAnnotation) + it.visibleTypeAnnotations?.removeIf(shouldStripAnnotation) + it.invisibleLocalVariableAnnotations?.removeIf(shouldStripAnnotation) + it.visibleLocalVariableAnnotations?.removeIf(shouldStripAnnotation) + it.invisibleParameterAnnotations?.forEach { parameterAnnotations -> + parameterAnnotations?.removeIf(shouldStripAnnotation) + } + it.visibleParameterAnnotations?.forEach { parameterAnnotations -> + parameterAnnotations?.removeIf(shouldStripAnnotation) + } + } + + if (classNode.invisibleAnnotations?.any { it.desc == "Lorg/spongepowered/asm/mixin/Mixin;" } == true) { + // remove any empty constructors that just call super() + // since these classes are never loaded, they are not needed + // 3 instructions are ALOAD + call to super() + RETURN + classNode.methods.removeAll { it.name == "" && it.instructions.size() <= 3 } + } + + classNode.toBytes() + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/AdvzipTask.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/AdvzipTask.kt new file mode 100644 index 0000000..fcf8a96 --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/AdvzipTask.kt @@ -0,0 +1,44 @@ +package dev.nolij.zumegradle.task + +import dev.nolij.zumegradle.DeflateAlgorithm +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input + +@Suppress("LeakingThis") +abstract class AdvzipTask : ProcessJarTask() { + @get:Input + abstract val level: Property + + @get:Input + abstract val throwIfNotInstalled: Property + + init { + throwIfNotInstalled.convention(false) + } + + override fun process() { + if(try { + ProcessBuilder("advzip", "-V").start().waitFor() != 0 + } catch (e: Exception) { true }) { + if(throwIfNotInstalled.get()) { + throw IllegalStateException("advzip is not installed") + } + + println("advzip is not installed, skipping ${this.name}") + return + } + + val jar = inputJar.get().asFile.copyTo(archiveFile.get().asFile, true) + val type = level.get() + + try { + val process = ProcessBuilder("advzip", "-z", "-${type.id}", jar.absolutePath).start() + val exitCode = process.waitFor() + if (exitCode != 0) { + error("Failed to compress $jar with $type") + } + } catch (e: Exception) { + error("Failed to compress $jar with $type: ${e.message}") + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/CopyJarTask.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/CopyJarTask.kt new file mode 100644 index 0000000..04fe607 --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/CopyJarTask.kt @@ -0,0 +1,7 @@ +package dev.nolij.zumegradle.task + +abstract class CopyJarTask : ProcessJarTask() { + override fun process() { + inputJar.get().asFile.copyTo(archiveFile.get().asFile, true) + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/JarEntryModificationTask.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/JarEntryModificationTask.kt new file mode 100644 index 0000000..8e2089a --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/JarEntryModificationTask.kt @@ -0,0 +1,54 @@ +package dev.nolij.zumegradle.task + +import dev.nolij.zumegradle.JsonShrinkingType +import org.gradle.api.tasks.Input +import dev.nolij.zumegradle.entryprocessing.EntryProcessor +import dev.nolij.zumegradle.entryprocessing.EntryProcessors +import org.gradle.api.provider.ListProperty +import java.util.jar.JarEntry +import java.util.jar.JarFile +import java.util.jar.JarOutputStream +import java.util.zip.Deflater + +abstract class JarEntryModificationTask : ProcessJarTask() { + @get:Input + protected abstract val processors: ListProperty + + fun process(processor: EntryProcessor) { + processors.add(processor) + } + + fun json(type: JsonShrinkingType?, shouldRun: (String) -> Boolean = { it.endsWith(".json") }) { + processors.add(when(type) { + null -> EntryProcessors.PASS + JsonShrinkingType.MINIFY -> EntryProcessors.jsonMinifier(shouldRun) + JsonShrinkingType.PRETTY_PRINT -> EntryProcessors.jsonPrettyPrinter(shouldRun) + }) + } + + override fun process() { + val contents = linkedMapOf() + JarFile(inputJar.get().asFile).use { + it.entries().asIterator().forEach { entry -> + if (!entry.isDirectory) { + contents[entry.name] = it.getInputStream(entry).readAllBytes() + } + } + } + + JarOutputStream(archiveFile.get().asFile.outputStream()).use { out -> + out.setLevel(Deflater.BEST_COMPRESSION) + contents.forEach { var (name, bytes) = it + + processors.get().forEach { processor -> + bytes = processor(name, bytes) + } + + out.putNextEntry(JarEntry(name)) + out.write(bytes) + out.closeEntry() + } + out.finish() + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/ProcessJarTask.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/ProcessJarTask.kt new file mode 100644 index 0000000..3cc11cb --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/ProcessJarTask.kt @@ -0,0 +1,35 @@ +package dev.nolij.zumegradle.task + +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.jvm.tasks.Jar + +@Suppress("LeakingThis") +abstract class ProcessJarTask : Jar() { + @get:InputFile + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val inputJar: RegularFileProperty + + @get:Input + abstract val ignoreSameInputOutput: Property + + init { + ignoreSameInputOutput.convention(false) + + group = "processing" + } + + override fun copy() { + if(!ignoreSameInputOutput.get() && inputJar.get().asFile.equals(archiveFile.get().asFile)) { + throw IllegalStateException("Input jar and output jar are the same file; this breaks caching" + + "\nTo ignore this, set ignoreSameInputOutput to true") + } + process() + } + + protected abstract fun process() +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/ProguardTask.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/ProguardTask.kt new file mode 100644 index 0000000..51e35c1 --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/ProguardTask.kt @@ -0,0 +1,87 @@ +package dev.nolij.zumegradle.task + +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.* +import org.gradle.api.tasks.Optional +import proguard.Configuration +import proguard.ConfigurationParser +import proguard.ProGuard +import java.io.File +import java.util.* + +private val javaHome = System.getProperty("java.home")!! + +abstract class ProguardTask : ProcessJarTask() { + + @get:InputFiles + @get:Classpath + abstract val classpath: ListProperty + + @get:Input + abstract val options: ListProperty + + @get:Input + abstract val run: Property + + @get:OutputFile + @get:Optional + abstract val mappingsFile: RegularFileProperty + + fun config(config: File) { + options.add("@${config.relativeTo(project.rootDir)}") + } + + fun jmod(jmod: String) { + classpath.add(File("$javaHome/jmods/$jmod.jmod")) + } + + override fun process() { + if(!run.get()) { + inputJar.get().asFile.copyTo(archiveFile.get().asFile, true) + return + } + + val cmd = this.options.get().toMutableSet() + + cmd.addAll(arrayOf( + "-injars", inputJar.get().asFile.absolutePath, + "-outjars", archiveFile.get().asFile.absolutePath + )) + + if (mappingsFile.isPresent) { + cmd.add("-printmapping") + cmd.add(mappingsFile.get().asFile.absolutePath) + } + + cmd.addAll(arrayOf( + "-libraryjars", classpath.get().toSet().joinToString(File.pathSeparator) { "\"$it\"" } + )) + + val debug = Properties().apply { + val gradleproperties = project.rootDir.resolve("gradle.properties") + if (gradleproperties.exists()) { + load(gradleproperties.inputStream()) + } + }.getProperty("zumegradle.proguard.keepAttrs")?.toBoolean() ?: false + + if (debug) { + cmd.add("-keepattributes") + cmd.add("*Annotation*,SourceFile,MethodParameters,L*Table") + cmd.add("-dontobfuscate") + } + + project.logger.debug("Proguard command: {}", cmd) + + val configuration = Configuration() + ConfigurationParser(cmd.toTypedArray(), System.getProperties()) + .parse(configuration) + + try { + ProGuard(configuration).execute() + } catch (ex: Exception) { + throw IllegalStateException("ProGuard failed for task ${this.name}", ex) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/util/AsmHelper.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/util/AsmHelper.kt new file mode 100644 index 0000000..b425276 --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/util/AsmHelper.kt @@ -0,0 +1,17 @@ +package dev.nolij.zumegradle.util + +import org.objectweb.asm.ClassReader +import org.objectweb.asm.ClassWriter +import org.objectweb.asm.tree.ClassNode + +fun ClassNode.toBytes(flags: Int = 0): ByteArray { + val writer = ClassWriter(flags) + this.accept(writer) + return writer.toByteArray() +} + +fun ClassNode(bytes: ByteArray): ClassNode { + val node = ClassNode() + ClassReader(bytes).accept(node, 0) + return node +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/util/MappingsHelper.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/util/MappingsHelper.kt new file mode 100644 index 0000000..5c6540a --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/util/MappingsHelper.kt @@ -0,0 +1,29 @@ +package dev.nolij.zumegradle.util + +import net.fabricmc.mappingio.MappingReader +import net.fabricmc.mappingio.format.MappingFormat +import net.fabricmc.mappingio.tree.MappingTree.ClassMapping +import net.fabricmc.mappingio.tree.MemoryMappingTree +import java.io.File + +fun mappings(file: File, format: MappingFormat = MappingFormat.PROGUARD): MemoryMappingTree { + if (!file.exists()) { + error("Mappings file $file does not exist") + } + + val mappingTree = MemoryMappingTree() + MappingReader.read(file.toPath(), format, mappingTree) + return mappingTree +} + +@Suppress("INACCESSIBLE_TYPE", "NAME_SHADOWING") +fun MemoryMappingTree.map(src: String): String { + val src = src.replace('.', '/') + val dstNamespaceIndex = getNamespaceId(dstNamespaces[0]) + val classMapping: ClassMapping? = getClass(src) + if (classMapping == null) { + println("Class $src not found in mappings") + return src + } + return classMapping.getDstName(dstNamespaceIndex).replace('/', '.') +} \ No newline at end of file From a9bede0bb40597df4194966d1f8d5c2706e08d5f Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Sun, 3 Nov 2024 23:56:02 -0500 Subject: [PATCH 05/35] no daemon in ci --- .github/workflows/build.yml | 2 +- .github/workflows/pull_request.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/release_dev.yml | 2 +- .github/workflows/release_pre.yml | 2 +- .github/workflows/release_rc.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3ba9992..4a426b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} - name: :build - run: ./gradlew build --stacktrace + run: ./gradlew build --stacktrace --no-daemon - name: Upload artifacts uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 4b3f255..a2fd8bf 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -18,7 +18,7 @@ jobs: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY_PR }} cache-read-only: true - name: :build - run: ./gradlew build + run: ./gradlew build --no-daemon - name: Upload artifacts uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8b72948..2dfc6d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} cache-read-only: true - name: :publishMods - run: ./gradlew publishMods -Prelease_channel=RELEASE + run: ./gradlew publishMods -Prelease_channel=RELEASE --no-daemon env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} diff --git a/.github/workflows/release_dev.yml b/.github/workflows/release_dev.yml index 29231c8..223b104 100644 --- a/.github/workflows/release_dev.yml +++ b/.github/workflows/release_dev.yml @@ -21,7 +21,7 @@ jobs: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} cache-read-only: true - name: :publishMods - run: ./gradlew publishMods -Prelease_channel=DEV_BUILD --stacktrace + run: ./gradlew publishMods -Prelease_channel=DEV_BUILD --stacktrace --no-daemon env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_DEV_WEBHOOK }} \ No newline at end of file diff --git a/.github/workflows/release_pre.yml b/.github/workflows/release_pre.yml index c5e0045..16466e8 100644 --- a/.github/workflows/release_pre.yml +++ b/.github/workflows/release_pre.yml @@ -21,7 +21,7 @@ jobs: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} cache-read-only: true - name: :publishMods - run: ./gradlew publishMods -Prelease_channel=PRE_RELEASE + run: ./gradlew publishMods -Prelease_channel=PRE_RELEASE --no-daemon env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_DEV_WEBHOOK }} \ No newline at end of file diff --git a/.github/workflows/release_rc.yml b/.github/workflows/release_rc.yml index 4e3e3a9..9dce8ec 100644 --- a/.github/workflows/release_rc.yml +++ b/.github/workflows/release_rc.yml @@ -21,7 +21,7 @@ jobs: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} cache-read-only: true - name: :publishMods - run: ./gradlew publishMods -Prelease_channel=RELEASE_CANDIDATE + run: ./gradlew publishMods -Prelease_channel=RELEASE_CANDIDATE --no-daemon env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_DEV_WEBHOOK }} \ No newline at end of file From 6aea3164c002742ce4be9eeb15e0721df41eb705 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Mon, 4 Nov 2024 13:03:58 +0800 Subject: [PATCH 06/35] better caching i hope --- .github/workflows/build.yml | 1 + .github/workflows/pull_request.yml | 1 + .github/workflows/release.yml | 1 + .github/workflows/release_dev.yml | 1 + .github/workflows/release_pre.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4a426b9..d554098 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,6 +12,7 @@ jobs: with: distribution: temurin java-version: 21 + cache: 'gradle' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index a2fd8bf..592f776 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -12,6 +12,7 @@ jobs: with: distribution: temurin java-version: 21 + cache: 'gradle' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2dfc6d9..7359caa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,7 @@ jobs: with: distribution: temurin java-version: 21 + cache: 'gradle' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release_dev.yml b/.github/workflows/release_dev.yml index 223b104..d97fe37 100644 --- a/.github/workflows/release_dev.yml +++ b/.github/workflows/release_dev.yml @@ -15,6 +15,7 @@ jobs: with: distribution: temurin java-version: 21 + cache: 'gradle' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release_pre.yml b/.github/workflows/release_pre.yml index 16466e8..b4286c7 100644 --- a/.github/workflows/release_pre.yml +++ b/.github/workflows/release_pre.yml @@ -15,6 +15,7 @@ jobs: with: distribution: temurin java-version: 21 + cache: 'gradle' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: From 474191e37b922fcbe69c78c9fd6dacdfdbd63c6e Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Mon, 4 Nov 2024 13:14:17 +0800 Subject: [PATCH 07/35] cache `build` folders --- .github/workflows/build.yml | 1 + .github/workflows/pull_request.yml | 1 + .github/workflows/release.yml | 1 + .github/workflows/release_dev.yml | 1 + .github/workflows/release_pre.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d554098..0186ff6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,6 +13,7 @@ jobs: distribution: temurin java-version: 21 cache: 'gradle' + cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 592f776..12d899f 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -13,6 +13,7 @@ jobs: distribution: temurin java-version: 21 cache: 'gradle' + cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7359caa..e7f8f49 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,6 +16,7 @@ jobs: distribution: temurin java-version: 21 cache: 'gradle' + cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release_dev.yml b/.github/workflows/release_dev.yml index d97fe37..bebb441 100644 --- a/.github/workflows/release_dev.yml +++ b/.github/workflows/release_dev.yml @@ -16,6 +16,7 @@ jobs: distribution: temurin java-version: 21 cache: 'gradle' + cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release_pre.yml b/.github/workflows/release_pre.yml index b4286c7..1915af7 100644 --- a/.github/workflows/release_pre.yml +++ b/.github/workflows/release_pre.yml @@ -16,6 +16,7 @@ jobs: distribution: temurin java-version: 21 cache: 'gradle' + cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: From cdda047a43017e8a704d2f160f64fbe28a2a79fb Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:50:20 -0500 Subject: [PATCH 08/35] undo the patch thing --- build.gradle.kts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index dd16f31..b140935 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -101,15 +101,13 @@ val patchHistory = releaseTags .map { name -> name.substring(minorTagPrefix.length) } val maxPatch = patchHistory.maxOfOrNull { it.substringBefore('-').toInt() } -val patch = maxPatch.let { - if (it != null) { - if (patchHistory.contains(it.toString())) { - it + releaseIncrement - } else { - it - } - } else 0 -} +val patch = + maxPatch?.plus( + if (patchHistory.contains(maxPatch.toString())) + releaseIncrement + else + 0 + ) ?: 0 var patchAndSuffix = patch.toString() if (releaseChannel.suffix != null) { From 2fa2c0e49e40fc15740b50646dfc8c66749b0f30 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:15:14 +0700 Subject: [PATCH 09/35] only cache regular builds, and maybe make it actually work --- .github/workflows/build.yml | 4 +++- .github/workflows/pull_request.yml | 2 -- .github/workflows/release.yml | 2 -- .github/workflows/release_dev.yml | 2 -- .github/workflows/release_pre.yml | 2 -- 5 files changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0186ff6..046bceb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,9 @@ jobs: distribution: temurin java-version: 21 cache: 'gradle' - cache-dependency-path: '**/build/**' + cache-dependency-path: | + **/.gradle/ + **/build/ - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 12d899f..a2fd8bf 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -12,8 +12,6 @@ jobs: with: distribution: temurin java-version: 21 - cache: 'gradle' - cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e7f8f49..2dfc6d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,8 +15,6 @@ jobs: with: distribution: temurin java-version: 21 - cache: 'gradle' - cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release_dev.yml b/.github/workflows/release_dev.yml index bebb441..223b104 100644 --- a/.github/workflows/release_dev.yml +++ b/.github/workflows/release_dev.yml @@ -15,8 +15,6 @@ jobs: with: distribution: temurin java-version: 21 - cache: 'gradle' - cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: diff --git a/.github/workflows/release_pre.yml b/.github/workflows/release_pre.yml index 1915af7..16466e8 100644 --- a/.github/workflows/release_pre.yml +++ b/.github/workflows/release_pre.yml @@ -15,8 +15,6 @@ jobs: with: distribution: temurin java-version: 21 - cache: 'gradle' - cache-dependency-path: '**/build/**' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: From b1577a099cf9f18395fc486117900593ad2fdb02 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:25:20 +0700 Subject: [PATCH 10/35] hmm maybe don't setup-java caching --- .github/workflows/build.yml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 046bceb..7fb09a5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,22 +6,31 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 + - name: Install Packages run: sudo apt-get install -y advancecomp + + # cache local gradle files, global ones will be taken care of by the setup-gradle action + - uses: actions/cache@v4 + with: + path: | + **/.gradle/ + **/build/ + key: ${{ runner.os }}-gradlelocal-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 21 - cache: 'gradle' - cache-dependency-path: | - **/.gradle/ - **/build/ + - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + - name: :build run: ./gradlew build --stacktrace --no-daemon + - name: Upload artifacts uses: actions/upload-artifact@v3 with: From 9bab11f3a7699c4b90f8044bb940387af5e9568e Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:21:08 -0500 Subject: [PATCH 11/35] change artifact globs --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c5faf53..a2a0ff3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,5 +41,5 @@ jobs: with: name: zume path: | - **/zume-*.jar - **/*mappings.txt + **/build/libs/zume*.jar + build/libs/*mappings.txt From ac017fbf994e5bd0412cf77759c6db25ccafbaa9 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:25:34 -0500 Subject: [PATCH 12/35] post merge fixes and stuff --- build.gradle.kts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index bc16a6a..ab72daf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,7 +28,7 @@ import ru.vyarus.gradle.plugin.python.PythonExtension import xyz.wagyourtail.unimined.api.minecraft.task.RemapJarTask import xyz.wagyourtail.unimined.api.unimined import java.io.FileOutputStream -import java.net.URL +import java.net.URI import java.nio.file.Files import java.time.ZonedDateTime import kotlin.io.path.* @@ -277,7 +277,7 @@ subprojects { defaultRemapJar = true } - val outputJar = tasks.register("outputJar") { + val outputJar by tasks.registering(ShadowJar::class) { group = "build" val remapJarTasks = tasks.withType() @@ -367,7 +367,7 @@ tasks.jar { enabled = false } -val sourcesJar = tasks.register("sourcesJar") { +val sourcesJar by tasks.registering(Jar::class) { group = "build" archiveClassifier = "sources" @@ -674,13 +674,13 @@ val smokeTest = tasks.register("smokeTest") { } config.dependencies?.forEach { (name, urlString) -> - URL(urlString).openStream().use { inputStream -> + URI(urlString).toURL().openStream().use { inputStream -> FileOutputStream("${modsDir}/${name}.jar").use(inputStream::transferTo) } } copy { - from(compressJar.get().outputJar) + from(compressJar.get().archiveFile) into(modsDir) } From cbd422b414cae1986b1d3294f3a7de4b2b512bed Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:27:16 -0500 Subject: [PATCH 13/35] cache based on gradle.properties --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a2a0ff3..818b6db 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: path: | **/.gradle/ **/build/ - key: ${{ runner.os }}-gradlelocal-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + key: ${{ runner.os }}-gradlelocal-${{ hashFiles('gradle.properties', '**/gradle-wrapper.properties') }} - uses: actions/setup-java@v4 with: From 3344803a2e4a472a052cde2c13a1b8d2f085d9d9 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:20:07 -0500 Subject: [PATCH 14/35] bump to upload-artifact v4 --- .github/workflows/build.yml | 2 +- .github/workflows/pull_request.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 818b6db..a139b3b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ jobs: run: ./gradlew :smokeTest --no-daemon - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: zume path: | diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ea127da..f004af8 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -24,7 +24,7 @@ jobs: with: run: ./gradlew :smokeTest --no-daemon - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: zume path: | From ddf649f502fd2a53beacd6bda7e90039c5025bad Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:14:54 -0500 Subject: [PATCH 15/35] merge but correct --- build.gradle.kts | 138 +---------------------------------------------- 1 file changed, 2 insertions(+), 136 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 434248a..65cb9b0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,6 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import dev.nolij.zumegradle.DeflateAlgorithm import dev.nolij.zumegradle.JsonShrinkingType import dev.nolij.zumegradle.MixinConfigMergingTransformer +import dev.nolij.zumegradle.SmokeTest import dev.nolij.zumegradle.entryprocessing.EntryProcessors import dev.nolij.zumegradle.task.AdvzipTask import dev.nolij.zumegradle.task.CopyJarTask @@ -26,8 +27,6 @@ import org.objectweb.asm.tree.ClassNode import ru.vyarus.gradle.plugin.python.PythonExtension import xyz.wagyourtail.unimined.api.minecraft.task.RemapJarTask import xyz.wagyourtail.unimined.api.unimined -import java.io.FileOutputStream -import java.net.URI import java.nio.file.Files import java.time.ZonedDateTime import kotlin.math.max @@ -547,7 +546,7 @@ val smokeTest = tasks.register("smokeTest") { SmokeTest( logger, "${project.rootDir}/.gradle/python/bin/portablemc", - compressJar.get().outputJar.asFile.get(), + compressJar.get().archiveFile.get().asFile, "${project.rootDir}/.gradle/portablemc", "${project.layout.buildDirectory.get()}/smoke_test", max(2, Runtime.getRuntime().availableProcessors() / 5), @@ -619,139 +618,6 @@ val smokeTest = tasks.register("smokeTest") { SmokeTest.Config("forge", "1.7.10", dependencies = listOf( "unimixins" to "https://github.com/LegacyModdingMC/UniMixins/releases/download/0.1.19/+unimixins-all-1.7.10-0.1.19.jar" )), - override fun toString(): String { - val result = StringBuilder() - - result.appendLine("modLoader=${modLoader}") - result.appendLine("mcVersion=${mcVersion}") - result.appendLine("loaderVersion=${loaderVersion}") - result.appendLine("jvmVersion=${jvmVersion}") - result.appendLine("extraArgs=[${extraArgs?.joinToString(", ") ?: ""}]") - result.appendLine("mods=[${dependencies?.joinToString(", ") { (name, _) -> name } ?: ""}]") - - return result.toString() - } -} - -val smokeTestConfigs = arrayOf( - SmokeTestConfig("fabric", "snapshot", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.4/fabric-api-0.107.0+1.21.4.jar", - )), - SmokeTestConfig("fabric", "release", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.3/fabric-api-0.107.0+1.21.3.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v11.0.3/modmenu-11.0.3.jar", - )), - SmokeTestConfig("fabric", "1.21.1", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.1/fabric-api-0.107.0+1.21.1.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v11.0.3/modmenu-11.0.3.jar", - )), - SmokeTestConfig("fabric", "1.20.6", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.100.8%2B1.20.6/fabric-api-0.100.8+1.20.6.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v10.0.0/modmenu-10.0.0.jar", - )), - SmokeTestConfig("fabric", "1.20.1", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.92.2%2B1.20.1/fabric-api-0.92.2+1.20.1.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v7.2.2/modmenu-7.2.2.jar", - )), - SmokeTestConfig("fabric", "1.18.2", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.77.0%2B1.18.2/fabric-api-0.77.0+1.18.2.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v3.2.5/modmenu-3.2.5.jar", - ), extraArgs = listOf("--lwjgl=3.2.3")), - SmokeTestConfig("fabric", "1.16.5", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.42.0%2B1.16/fabric-api-0.42.0+1.16.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v1.16.23/modmenu-1.16.23.jar", - )), - SmokeTestConfig("fabric", "1.14.4", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.28.5%2B1.14/fabric-api-0.28.5+1.14.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v1.7.11/modmenu-1.7.11+build.121.jar", - )), - SmokeTestConfig("legacyfabric", "1.12.2", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), - SmokeTestConfig("legacyfabric", "1.8.9", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), - SmokeTestConfig("legacyfabric", "1.7.10", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), -// SmokeTestConfig("legacyfabric", "1.6.4", dependencies = listOf( -// "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", -// )), - SmokeTestConfig("babric", "b1.7.3", jvmVersion = 17, dependencies = listOf( - "station-api" to "https://cdn.modrinth.com/data/472oW63Q/versions/W3QVtn6S/StationAPI-2.0-alpha.2.4.jar", - ), extraArgs = listOf("--exclude-lib=asm-all")), - SmokeTestConfig("neoforge", "release"), - SmokeTestConfig("neoforge", "1.21.1"), - SmokeTestConfig("neoforge", "1.20.4"), - SmokeTestConfig("forge", "1.20.4"), - SmokeTestConfig("forge", "1.20.1"), - SmokeTestConfig("forge", "1.19.2"), - SmokeTestConfig("forge", "1.18.2", extraArgs = listOf("--lwjgl=3.2.3")), - SmokeTestConfig("forge", "1.16.5", extraArgs = listOf("--lwjgl=3.2.3")), - SmokeTestConfig("forge", "1.14.4", dependencies = listOf( - "mixinbootstrap" to "https://github.com/LXGaming/MixinBootstrap/releases/download/v1.1.0/_MixinBootstrap-1.1.0.jar" - ), extraArgs = listOf("--lwjgl=3.2.3")), - SmokeTestConfig("forge", "1.12.2", dependencies = listOf( - "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" - )), - SmokeTestConfig("forge", "1.8.9", dependencies = listOf( - "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" - )), - SmokeTestConfig("forge", "1.7.10", dependencies = listOf( - "unimixins" to "https://github.com/LegacyModdingMC/UniMixins/releases/download/0.1.19/+unimixins-all-1.7.10-0.1.19.jar" - )), -) - -@OptIn(ExperimentalPathApi::class) -val smokeTest = tasks.register("smokeTest") { - group = "verification" - dependsOn(tasks.checkPython, tasks.pipInstall, compressJar) - - val mainDir = "${project.rootDir}/.gradle/portablemc" - - doFirst { - val failures = ArrayList() - smokeTestConfigs.forEach { config -> - val name = config.hashCode().toHexString() - val workDir = "${project.layout.buildDirectory.get()}/smoke_test/${name}" - val modsDir = "${workDir}/mods" - val latestLog = "${workDir}/logs/latest.log" - - Path(workDir).also { workPath -> - if (!workPath.exists()) - workPath.createDirectories() - } - Path(modsDir).also { modsPath -> - if (modsPath.exists()) - modsPath.deleteRecursively() - - modsPath.createDirectories() - } - Path(latestLog).also { logPath -> - logPath.deleteIfExists() - logPath.parent.also { logsPath -> - if (!logsPath.exists()) - logsPath.createDirectories() - } - } - - config.dependencies?.forEach { (name, urlString) -> - URI(urlString).toURL().openStream().use { inputStream -> - FileOutputStream("${modsDir}/${name}.jar").use(inputStream::transferTo) - } - } - - copy { - from(compressJar.get().archiveFile) - into(modsDir) - } - - val extraArgs = arrayListOf() - - val jvmVersionMap = mapOf( - 17 to "java-runtime-gamma", - 21 to "java-runtime-delta", - 8 to "jre-legacy" ) ).test() } From ff8b6e34d4af175d53bf569df6d8cc91e2b62a97 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:44:19 -0500 Subject: [PATCH 16/35] make smoke testing a real task --- build.gradle.kts | 168 +++++++------ .../kotlin/dev/nolij/zumegradle/SmokeTest.kt | 229 ------------------ .../dev/nolij/zumegradle/smoketest/Config.kt | 29 +++ .../nolij/zumegradle/smoketest/SmokeTest.kt | 59 +++++ .../dev/nolij/zumegradle/smoketest/Thread.kt | 146 +++++++++++ .../nolij/zumegradle/task/SmokeTestTask.kt | 65 +++++ 6 files changed, 380 insertions(+), 316 deletions(-) delete mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/SmokeTest.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt create mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt diff --git a/build.gradle.kts b/build.gradle.kts index 65cb9b0..dfcbcec 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,12 +3,10 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import dev.nolij.zumegradle.DeflateAlgorithm import dev.nolij.zumegradle.JsonShrinkingType import dev.nolij.zumegradle.MixinConfigMergingTransformer -import dev.nolij.zumegradle.SmokeTest import dev.nolij.zumegradle.entryprocessing.EntryProcessors -import dev.nolij.zumegradle.task.AdvzipTask -import dev.nolij.zumegradle.task.CopyJarTask -import dev.nolij.zumegradle.task.JarEntryModificationTask -import dev.nolij.zumegradle.task.ProguardTask +import dev.nolij.zumegradle.smoketest.Config +import dev.nolij.zumegradle.smoketest.SmokeTest +import dev.nolij.zumegradle.task.* import kotlinx.serialization.encodeToString import me.modmuss50.mpp.HttpUtils import me.modmuss50.mpp.PublishModTask @@ -47,7 +45,7 @@ enum class ReleaseChannel( val suffix: String? = null, val releaseType: ReleaseType? = null, val deflation: DeflateAlgorithm = DeflateAlgorithm.INSANE, - val json: JsonShrinkingType? = JsonShrinkingType.MINIFY, + val json: JsonShrinkingType = JsonShrinkingType.MINIFY, val proguard: Boolean = true, ) { DEV_BUILD( @@ -538,89 +536,85 @@ python { pip("portablemc:${"portablemc_version"()}") } -val smokeTest = tasks.register("smokeTest") { - group = "verification" +val smokeTest by tasks.registering(SmokeTestTask::class) { dependsOn(tasks.checkPython, tasks.pipInstall, compressJar) - doFirst { - SmokeTest( - logger, - "${project.rootDir}/.gradle/python/bin/portablemc", - compressJar.get().archiveFile.get().asFile, - "${project.rootDir}/.gradle/portablemc", - "${project.layout.buildDirectory.get()}/smoke_test", - max(2, Runtime.getRuntime().availableProcessors() / 5), - TimeUnit.SECONDS.toNanos(60), - listOf( - SmokeTest.Config("fabric", "snapshot", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.4/fabric-api-0.107.0+1.21.4.jar", - )), - SmokeTest.Config("fabric", "release", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.3/fabric-api-0.107.0+1.21.3.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v11.0.3/modmenu-11.0.3.jar", - )), - SmokeTest.Config("fabric", "1.21.1", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.1/fabric-api-0.107.0+1.21.1.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v11.0.3/modmenu-11.0.3.jar", - )), - SmokeTest.Config("fabric", "1.20.6", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.100.8%2B1.20.6/fabric-api-0.100.8+1.20.6.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v10.0.0/modmenu-10.0.0.jar", - )), - SmokeTest.Config("fabric", "1.20.1", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.92.2%2B1.20.1/fabric-api-0.92.2+1.20.1.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v7.2.2/modmenu-7.2.2.jar", - )), - SmokeTest.Config("fabric", "1.18.2", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.77.0%2B1.18.2/fabric-api-0.77.0+1.18.2.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v3.2.5/modmenu-3.2.5.jar", - ), extraArgs = listOf("--lwjgl=3.2.3")), - SmokeTest.Config("fabric", "1.16.5", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.42.0%2B1.16/fabric-api-0.42.0+1.16.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v1.16.23/modmenu-1.16.23.jar", - )), - SmokeTest.Config("fabric", "1.14.4", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.28.5%2B1.14/fabric-api-0.28.5+1.14.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v1.7.11/modmenu-1.7.11+build.121.jar", - )), - SmokeTest.Config("legacyfabric", "1.12.2", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), - SmokeTest.Config("legacyfabric", "1.8.9", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), - SmokeTest.Config("legacyfabric", "1.7.10", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), -// SmokeTest.Config("legacyfabric", "1.6.4", dependencies = listOf( -// "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", -// )), - SmokeTest.Config("babric", "b1.7.3", jvmVersion = 17, dependencies = listOf( - "station-api" to "https://cdn.modrinth.com/data/472oW63Q/versions/W3QVtn6S/StationAPI-2.0-alpha.2.4.jar", - ), extraArgs = listOf("--exclude-lib=asm-all")), - SmokeTest.Config("neoforge", "release"), - SmokeTest.Config("neoforge", "1.21.1"), - SmokeTest.Config("neoforge", "1.20.4"), - SmokeTest.Config("forge", "1.20.4"), - SmokeTest.Config("forge", "1.20.1"), - SmokeTest.Config("forge", "1.19.2"), - SmokeTest.Config("forge", "1.18.2", extraArgs = listOf("--lwjgl=3.2.3")), - SmokeTest.Config("forge", "1.16.5", extraArgs = listOf("--lwjgl=3.2.3")), - SmokeTest.Config("forge", "1.14.4", dependencies = listOf( - "mixinbootstrap" to "https://github.com/LXGaming/MixinBootstrap/releases/download/v1.1.0/_MixinBootstrap-1.1.0.jar" - ), extraArgs = listOf("--lwjgl=3.2.3")), - SmokeTest.Config("forge", "1.12.2", dependencies = listOf( - "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" - )), - SmokeTest.Config("forge", "1.8.9", dependencies = listOf( - "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" - )), - SmokeTest.Config("forge", "1.7.10", dependencies = listOf( - "unimixins" to "https://github.com/LegacyModdingMC/UniMixins/releases/download/0.1.19/+unimixins-all-1.7.10-0.1.19.jar" - )), - ) - ).test() - } + inputTask = compressJar + portableMCBinary = "${python.envPath}/bin/portablemc" + mainDir = file("${project.rootDir}/.gradle/portablemc") + workDir = file("${project.layout.buildDirectory.get()}/smoke_test") + maxThreads = max(2, Runtime.getRuntime().availableProcessors() / 5) + threadTimeout = TimeUnit.SECONDS.toNanos(60) + + configs( + Config("fabric", "snapshot", dependencies = listOf( + "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.4/fabric-api-0.107.0+1.21.4.jar", + )), + Config("fabric", "release", dependencies = listOf( + "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.3/fabric-api-0.107.0+1.21.3.jar", + "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v11.0.3/modmenu-11.0.3.jar", + )), + Config("fabric", "1.21.1", dependencies = listOf( + "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.1/fabric-api-0.107.0+1.21.1.jar", + "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v11.0.3/modmenu-11.0.3.jar", + )), + Config("fabric", "1.20.6", dependencies = listOf( + "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.100.8%2B1.20.6/fabric-api-0.100.8+1.20.6.jar", + "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v10.0.0/modmenu-10.0.0.jar", + )), + Config( + "fabric", "1.20.1", dependencies = listOf( + "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.92.2%2B1.20.1/fabric-api-0.92.2+1.20.1.jar", + "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v7.2.2/modmenu-7.2.2.jar", + )), + Config("fabric", "1.18.2", dependencies = listOf( + "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.77.0%2B1.18.2/fabric-api-0.77.0+1.18.2.jar", + "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v3.2.5/modmenu-3.2.5.jar", + ), extraArgs = listOf("--lwjgl=3.2.3")), + Config("fabric", "1.16.5", dependencies = listOf( + "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.42.0%2B1.16/fabric-api-0.42.0+1.16.jar", + "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v1.16.23/modmenu-1.16.23.jar", + )), + Config("fabric", "1.14.4", dependencies = listOf( + "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.28.5%2B1.14/fabric-api-0.28.5+1.14.jar", + "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v1.7.11/modmenu-1.7.11+build.121.jar", + )), + Config("legacyfabric", "1.12.2", dependencies = listOf( + "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", + )), + Config("legacyfabric", "1.8.9", dependencies = listOf( + "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", + )), + Config("legacyfabric", "1.7.10", dependencies = listOf( + "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", + )), + Config("legacyfabric", "1.6.4", dependencies = listOf( + "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", + )), + Config("babric", "b1.7.3", jvmVersion = 17, dependencies = listOf( + "station-api" to "https://cdn.modrinth.com/data/472oW63Q/versions/W3QVtn6S/StationAPI-2.0-alpha.2.4.jar", + ), extraArgs = listOf("--exclude-lib=asm-all")), + Config("neoforge", "release"), + Config("neoforge", "1.21.1"), + Config("neoforge", "1.20.4"), + Config("forge", "1.20.4"), + Config("forge", "1.20.1"), + Config("forge", "1.19.2"), + Config("forge", "1.18.2", extraArgs = listOf("--lwjgl=3.2.3")), + Config("forge", "1.16.5", extraArgs = listOf("--lwjgl=3.2.3")), + Config("forge", "1.14.4", dependencies = listOf( + "mixinbootstrap" to "https://github.com/LXGaming/MixinBootstrap/releases/download/v1.1.0/_MixinBootstrap-1.1.0.jar" + ), extraArgs = listOf("--lwjgl=3.2.3")), + Config("forge", "1.12.2", dependencies = listOf( + "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" + )), + Config("forge", "1.8.9", dependencies = listOf( + "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" + )), + Config("forge", "1.7.10", dependencies = listOf( + "unimixins" to "https://github.com/LegacyModdingMC/UniMixins/releases/download/0.1.19/+unimixins-all-1.7.10-0.1.19.jar" + )), + ) } //endregion diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/SmokeTest.kt deleted file mode 100644 index 69a0ed9..0000000 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/SmokeTest.kt +++ /dev/null @@ -1,229 +0,0 @@ -@file:OptIn(ExperimentalPathApi::class) - -package dev.nolij.zumegradle - -import org.gradle.api.logging.Logger -import java.io.File -import java.io.FileOutputStream -import java.net.URL -import java.nio.file.Files -import java.util.* -import kotlin.io.path.* - -fun sleep(millis: Long) { - Thread.sleep(millis) -} - -class SmokeTest( - private val logger: Logger, - private val portableMCBinary: String, - private val modFile: File, - private val mainDir: String, - private val workDir: String, - private val maxThreads: Int, - private val threadTimeout: Long, - private val configs: List -) { - - data class Config( - val modLoader: String, - val mcVersion: String, - val loaderVersion: String? = null, - val jvmVersion: Int? = null, - val extraArgs: List? = null, - val dependencies: List>? = null, - ) { - val versionString: String get() = - if (loaderVersion != null) - "${modLoader}:${mcVersion}:${loaderVersion}" - else - "${modLoader}:${mcVersion}" - - override fun toString(): String { - val result = StringBuilder() - - result.appendLine("modLoader=${modLoader}") - result.appendLine("mcVersion=${mcVersion}") - result.appendLine("loaderVersion=${loaderVersion}") - result.appendLine("jvmVersion=${jvmVersion}") - result.appendLine("extraArgs=[${extraArgs?.joinToString(", ") ?: ""}]") - result.appendLine("mods=[${dependencies?.joinToString(", ") { (name, _) -> name } ?: ""}]") - - return result.toString() - } - } - - private enum class ThreadState { - PENDING, - RUNNING, - TIMED_OUT, - READY, - PASSED, - FAILED, - } - - private inner class Thread(val config: Config) { - private val name: String = config.hashCode().toUInt().toString(16) - private val instanceDir = "${workDir}/${name}" - private val modsDir = "${instanceDir}/mods" - private val logDir = "${instanceDir}/logs/latest.log" - private val logFile = File(logDir) - private val command: Array - - private var process: Process? = null - - private var startTimestamp: Long? = null - - val isAlive: Boolean get() = process?.isAlive == true - private val isTimedOut: Boolean get() = - if (isAlive) - System.nanoTime() - startTimestamp!! > threadTimeout - else - false - - private var finalState: ThreadState? = null - val finished: Boolean get() = finalState != null - val state: ThreadState - get() { - return finalState ?: - if (startTimestamp == null) ThreadState.PENDING - else if (isTimedOut) ThreadState.TIMED_OUT - else if (isAlive) ThreadState.RUNNING - else ThreadState.READY - } - - init { - Path(instanceDir).also { path -> - if (!path.exists()) - path.createDirectories() - } - - Path(modsDir).also { modsPath -> - if (modsPath.exists()) - modsPath.deleteRecursively() - modsPath.createDirectories() - } - - Path(logDir).also { logPath -> - logPath.deleteIfExists() - logPath.parent.also { logsPath -> - if (!logsPath.exists()) - logsPath.createDirectories() - } - } - - config.dependencies?.forEach { (name, urlString) -> - URL(urlString).openStream().use { inputStream -> - FileOutputStream("${modsDir}/${name}.jar").use(inputStream::transferTo) - } - } - - Files.copy(modFile.toPath(), Path("${modsDir}/${modFile.name}")) - - val extraArgs = arrayListOf() - - val jvmVersionMap = mapOf( - 17 to "java-runtime-gamma", - 21 to "java-runtime-delta", - 8 to "jre-legacy" - ) - if (config.jvmVersion != null) - extraArgs.add("--jvm=${mainDir}/jvm/${jvmVersionMap[config.jvmVersion]!!}/bin/java") - - if (config.extraArgs != null) - extraArgs.addAll(config.extraArgs) - - command = arrayOf( - portableMCBinary, - "--main-dir", mainDir, - "--work-dir", instanceDir, - "start", config.versionString, - *extraArgs.toTypedArray(), - "--jvm-args=-DzumeGradle.auditAndExit=true", - ) - - ProcessBuilder(*command, "--dry") - .inheritIO() - .start() - .waitFor() - } - - fun start() { - if (state != ThreadState.PENDING) - error("Thread already started!") - - startTimestamp = System.nanoTime() - process = ProcessBuilder(*command) - .inheritIO() - .start() - } - - fun update() { - var passed = false - - when (state) { - ThreadState.TIMED_OUT -> process!!.destroyForcibly() - ThreadState.READY -> { - if (logFile.exists()) { - logFile.reader().use { reader -> - reader.forEachLine { line -> - if (line.endsWith("ZumeGradle audit passed")) - passed = true - } - } - } - } - else -> return - } - - if (passed) { - println("Smoke test passed for config:\n${config}") - finalState = ThreadState.PASSED - } else { - logger.error("Smoke test failed for config:\n${config}") - finalState = ThreadState.FAILED - } - - printThreads() - } - } - - private val threads = ArrayList() - - private fun printThreads() { - println(""" - > TOTAL: ${threads.filter { thread -> thread.finished }.size}/${configs.size} - > RUNNING: ${threads.filter { thread -> thread.state == ThreadState.RUNNING }.size}/${maxThreads} - > PASSED: ${threads.filter { thread -> thread.state == ThreadState.PASSED }.size} - > FAILED: ${threads.filter { thread -> thread.state == ThreadState.FAILED }.size} - """.trimIndent()) - } - - fun test() { - println("Setting up instances...") - configs.forEach { config -> - threads.add(Thread(config)) - } - - printThreads() - - do { - while (threads.count { thread -> thread.isAlive } < maxThreads) - threads.firstOrNull { thread -> thread.state == ThreadState.PENDING }?.start() ?: break - sleep(500L) - threads.forEach(Thread::update) - } while (threads.any { thread -> !thread.finished }) - - val failedConfigs = threads - .filter { thread -> thread.state == ThreadState.FAILED } - .map { thread -> thread.config } - - if (failedConfigs.isNotEmpty()) { - logger.error("[{\n${failedConfigs.joinToString("}, {\n")}}]") - error("One or more tests failed. See logs for more details.") - } - - println("All tests passed.") - } - -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt new file mode 100644 index 0000000..9897339 --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt @@ -0,0 +1,29 @@ +package dev.nolij.zumegradle.smoketest + +data class Config( + val modLoader: String, + val mcVersion: String, + val loaderVersion: String? = null, + val jvmVersion: Int? = null, + val extraArgs: List? = null, + val dependencies: List>? = null, +) { + val versionString: String get() = + if (loaderVersion != null) + "${modLoader}:${mcVersion}:${loaderVersion}" + else + "${modLoader}:${mcVersion}" + + override fun toString(): String { + val result = StringBuilder() + + result.appendLine("modLoader=${modLoader}") + result.appendLine("mcVersion=${mcVersion}") + result.appendLine("loaderVersion=${loaderVersion}") + result.appendLine("jvmVersion=${jvmVersion}") + result.appendLine("extraArgs=[${extraArgs?.joinToString(", ") ?: ""}]") + result.appendLine("mods=[${dependencies?.joinToString(", ") { (name, _) -> name } ?: ""}]") + + return result.toString() + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt new file mode 100644 index 0000000..05bbd23 --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt @@ -0,0 +1,59 @@ +package dev.nolij.zumegradle.smoketest + +import org.gradle.api.logging.Logger +import java.io.File +import java.util.* +import kotlin.io.path.* + +import dev.nolij.zumegradle.smoketest.Thread.ThreadState + +class SmokeTest( + internal val logger: Logger, + internal val portableMCBinary: String, + internal val modFile: File, + internal val mainDir: String, + internal val workDir: String, + internal val maxThreads: Int, + internal val threadTimeout: Long, + internal val configs: List +) { + + private val threads = ArrayList() + + internal fun printThreads() { + println(""" + > TOTAL: ${threads.filter { thread -> thread.finished }.size}/${configs.size} + > RUNNING: ${threads.filter { thread -> thread.state == ThreadState.RUNNING }.size}/${maxThreads} + > PASSED: ${threads.filter { thread -> thread.state == ThreadState.PASSED }.size} + > FAILED: ${threads.filter { thread -> thread.state == ThreadState.FAILED }.size} + """.trimIndent()) + } + + fun test() { + println("Setting up instances...") + configs.forEach { config -> + threads.add(Thread(this, config)) + } + + printThreads() + + do { + while (threads.count { thread -> thread.isAlive } < maxThreads) + threads.firstOrNull { thread -> thread.state == ThreadState.PENDING }?.start() ?: break + java.lang.Thread.sleep(500L) + threads.forEach(Thread::update) + } while (threads.any { thread -> !thread.finished }) + + val failedConfigs = threads + .filter { thread -> thread.state == ThreadState.FAILED } + .map { thread -> thread.config } + + if (failedConfigs.isNotEmpty()) { + logger.error("[{\n${failedConfigs.joinToString("}, {\n")}}]") + error("One or more tests failed. See logs for more details.") + } + + println("All tests passed.") + } + +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt new file mode 100644 index 0000000..3d37dbc --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt @@ -0,0 +1,146 @@ +package dev.nolij.zumegradle.smoketest + +import java.io.File +import java.io.FileOutputStream +import java.net.URL +import java.nio.file.Files +import kotlin.io.path.* + +@OptIn(ExperimentalPathApi::class) +internal class Thread( + private val smokeTest: SmokeTest, + val config: Config +) { + private val name: String = config.hashCode().toUInt().toString(16) + private val instanceDir = "${smokeTest.workDir}/${name}" + private val modsDir = "${instanceDir}/mods" + private val logDir = "${instanceDir}/logs/latest.log" + private val logFile = File(logDir) + private val command: Array + + private var process: Process? = null + + private var startTimestamp: Long? = null + + val isAlive: Boolean get() = process?.isAlive == true + private val isTimedOut: Boolean get() = + if (isAlive) + System.nanoTime() - startTimestamp!! > smokeTest.threadTimeout + else + false + + private var finalState: ThreadState? = null + val finished: Boolean get() = finalState != null + val state: ThreadState + get() { + return finalState ?: + if (startTimestamp == null) ThreadState.PENDING + else if (isTimedOut) ThreadState.TIMED_OUT + else if (isAlive) ThreadState.RUNNING + else ThreadState.READY + } + + init { + Path(instanceDir).also { path -> + if (!path.exists()) + path.createDirectories() + } + + Path(modsDir).also { modsPath -> + if (modsPath.exists()) + modsPath.deleteRecursively() + modsPath.createDirectories() + } + + Path(logDir).also { logPath -> + logPath.deleteIfExists() + logPath.parent.also { logsPath -> + if (!logsPath.exists()) + logsPath.createDirectories() + } + } + + config.dependencies?.forEach { (name, urlString) -> + URL(urlString).openStream().use { inputStream -> + FileOutputStream("${modsDir}/${name}.jar").use(inputStream::transferTo) + } + } + + Files.copy(smokeTest.modFile.toPath(), Path("${modsDir}/${smokeTest.modFile.name}")) + + val extraArgs = arrayListOf() + + val jvmVersionMap = mapOf( + 17 to "java-runtime-gamma", + 21 to "java-runtime-delta", + 8 to "jre-legacy" + ) + if (config.jvmVersion != null) + extraArgs.add("--jvm=${smokeTest.mainDir}/jvm/${jvmVersionMap[config.jvmVersion]!!}/bin/java") + + if (config.extraArgs != null) + extraArgs.addAll(config.extraArgs) + + command = arrayOf( + smokeTest.portableMCBinary, + "--main-dir", smokeTest.mainDir, + "--work-dir", instanceDir, + "start", config.versionString, + *extraArgs.toTypedArray(), + "--jvm-args=-DzumeGradle.auditAndExit=true", + ) + + ProcessBuilder(*command, "--dry") + .inheritIO() + .start() + .waitFor() + } + + fun start() { + if (state != ThreadState.PENDING) + error("Thread already started!") + + startTimestamp = System.nanoTime() + process = ProcessBuilder(*command) + .inheritIO() + .start() + } + + fun update() { + var passed = false + + when (state) { + ThreadState.TIMED_OUT -> process!!.destroyForcibly() + ThreadState.READY -> { + if (logFile.exists()) { + logFile.reader().use { reader -> + reader.forEachLine { line -> + if (line.endsWith("ZumeGradle audit passed")) + passed = true + } + } + } + } + else -> return + } + + if (passed) { + println("Smoke test passed for config:\n${config}") + finalState = ThreadState.PASSED + } else { + smokeTest.logger.error("Smoke test failed for config:\n${config}") + finalState = ThreadState.FAILED + } + + smokeTest.printThreads() + } + + internal enum class ThreadState { + PENDING, + RUNNING, + TIMED_OUT, + READY, + PASSED, + FAILED, + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt new file mode 100644 index 0000000..abb032a --- /dev/null +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt @@ -0,0 +1,65 @@ +package dev.nolij.zumegradle.task + +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory +import org.gradle.jvm.tasks.Jar +import org.gradle.api.tasks.TaskAction + +import dev.nolij.zumegradle.smoketest.Config +import dev.nolij.zumegradle.smoketest.SmokeTest + +abstract class SmokeTestTask : DefaultTask() { + init { + group = "verification" + } + + /** + * The task that provides the input jar file. + */ + @get:Input + abstract val inputTask: Property + + @get:InputDirectory + abstract val mainDir: RegularFileProperty + + @get:InputDirectory + abstract val workDir: RegularFileProperty + + @get:Input + abstract val maxThreads: Property + + @get:Input + abstract val threadTimeout: Property + + @get:Input + abstract val configs: ListProperty + + @get:Input + abstract val portableMCBinary: Property + + fun config(config: Config) { + configs.add(config) + } + + fun configs(vararg configs: Config) { + this.configs.addAll(configs.asList()) + } + + @TaskAction + fun runSmokeTest() { + SmokeTest( + logger = logger, + portableMCBinary = portableMCBinary.get(), + modFile = inputTask.get().archiveFile.get().asFile, + mainDir = mainDir.get().asFile.absolutePath, + workDir = workDir.get().asFile.absolutePath, + maxThreads = maxThreads.get(), + threadTimeout = threadTimeout.get(), + configs = configs.get() + ).test() + } +} \ No newline at end of file From a9e54e73bb4f3053378f8c6573e8105c934d4699 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 00:23:05 -0500 Subject: [PATCH 17/35] use gradle dependencies I sincerely hope this works --- build.gradle.kts | 100 ++++++++++-------- .../dev/nolij/zumegradle/smoketest/Config.kt | 4 +- .../nolij/zumegradle/smoketest/SmokeTest.kt | 10 +- .../dev/nolij/zumegradle/smoketest/Thread.kt | 22 ++-- .../nolij/zumegradle/task/SmokeTestTask.kt | 24 ++--- 5 files changed, 90 insertions(+), 70 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index dfcbcec..058c6f1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,6 @@ import dev.nolij.zumegradle.JsonShrinkingType import dev.nolij.zumegradle.MixinConfigMergingTransformer import dev.nolij.zumegradle.entryprocessing.EntryProcessors import dev.nolij.zumegradle.smoketest.Config -import dev.nolij.zumegradle.smoketest.SmokeTest import dev.nolij.zumegradle.task.* import kotlinx.serialization.encodeToString import me.modmuss50.mpp.HttpUtils @@ -536,64 +535,69 @@ python { pip("portablemc:${"portablemc_version"()}") } +repositories { + maven("https://maven.terraformersmc.com/releases") + maven("https://maven.legacyfabric.net") + maven("https://maven.cleanroommc.com/") +} + val smokeTest by tasks.registering(SmokeTestTask::class) { dependsOn(tasks.checkPython, tasks.pipInstall, compressJar) inputTask = compressJar portableMCBinary = "${python.envPath}/bin/portablemc" - mainDir = file("${project.rootDir}/.gradle/portablemc") - workDir = file("${project.layout.buildDirectory.get()}/smoke_test") + mainDir = "${project.rootDir}/.gradle/portablemc" + workDir = "${project.layout.buildDirectory.get()}/smoke_test" maxThreads = max(2, Runtime.getRuntime().availableProcessors() / 5) threadTimeout = TimeUnit.SECONDS.toNanos(60) configs( Config("fabric", "snapshot", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.4/fabric-api-0.107.0+1.21.4.jar", - )), + "net.fabricmc.fabric-api:fabric-api:0.107.0+1.21.4", + )), Config("fabric", "release", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.3/fabric-api-0.107.0+1.21.3.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v11.0.3/modmenu-11.0.3.jar", - )), + "net.fabricmc.fabric-api:fabric-api:0.107.0+1.21.3", + "com.terraformersmc:modmenu:11.0.3", + )), Config("fabric", "1.21.1", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.107.0%2B1.21.1/fabric-api-0.107.0+1.21.1.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v11.0.3/modmenu-11.0.3.jar", - )), + "net.fabricmc.fabric-api:fabric-api:0.107.0+1.21.1", + "com.terraformersmc:modmenu:11.0.3", + )), Config("fabric", "1.20.6", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.100.8%2B1.20.6/fabric-api-0.100.8+1.20.6.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v10.0.0/modmenu-10.0.0.jar", - )), - Config( - "fabric", "1.20.1", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.92.2%2B1.20.1/fabric-api-0.92.2+1.20.1.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v7.2.2/modmenu-7.2.2.jar", - )), + "net.fabricmc.fabric-api:fabric-api:0.100.8+1.20.6", + "com.terraformersmc:modmenu:10.0.0", + )), + Config("fabric", "1.20.1", dependencies = listOf( + "net.fabricmc.fabric-api:fabric-api:0.92.2+1.20.1", + "com.terraformersmc:modmenu:7.2.2", + )), Config("fabric", "1.18.2", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.77.0%2B1.18.2/fabric-api-0.77.0+1.18.2.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v3.2.5/modmenu-3.2.5.jar", - ), extraArgs = listOf("--lwjgl=3.2.3")), + "net.fabricmc.fabric-api:fabric-api:0.77.0+1.18.2", + "com.terraformersmc:modmenu:3.2.5", + ), extraArgs = listOf("--lwjgl=3.2.3")), Config("fabric", "1.16.5", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.42.0%2B1.16/fabric-api-0.42.0+1.16.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v1.16.23/modmenu-1.16.23.jar", - )), + "net.fabricmc.fabric-api:fabric-api:0.42.0+1.16", + "com.terraformersmc:modmenu:1.16.23", + )), Config("fabric", "1.14.4", dependencies = listOf( - "fabric-api" to "https://github.com/FabricMC/fabric/releases/download/0.28.5%2B1.14/fabric-api-0.28.5+1.14.jar", - "modmenu" to "https://github.com/TerraformersMC/ModMenu/releases/download/v1.7.11/modmenu-1.7.11+build.121.jar", - )), + "net.fabricmc.fabric-api:fabric-api:0.28.5+1.14", + "maven.modrinth:modmenu:1.7.17", + )), Config("legacyfabric", "1.12.2", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), + "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.12.2", + )), Config("legacyfabric", "1.8.9", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), + "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.8.9", + )), Config("legacyfabric", "1.7.10", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), + "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.7.10", + )), Config("legacyfabric", "1.6.4", dependencies = listOf( - "legacy-fabric-api" to "https://github.com/Legacy-Fabric/fabric/releases/download/1.10.2/legacy-fabric-api-1.10.2.jar", - )), + "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.6.4", + )), Config("babric", "b1.7.3", jvmVersion = 17, dependencies = listOf( - "station-api" to "https://cdn.modrinth.com/data/472oW63Q/versions/W3QVtn6S/StationAPI-2.0-alpha.2.4.jar", - ), extraArgs = listOf("--exclude-lib=asm-all")), + "maven.modrinth:stationapi:2.0-alpha.2.4", + ), extraArgs = listOf("--exclude-lib=asm-all")), Config("neoforge", "release"), Config("neoforge", "1.21.1"), Config("neoforge", "1.20.4"), @@ -603,17 +607,21 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { Config("forge", "1.18.2", extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.16.5", extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.14.4", dependencies = listOf( - "mixinbootstrap" to "https://github.com/LXGaming/MixinBootstrap/releases/download/v1.1.0/_MixinBootstrap-1.1.0.jar" - ), extraArgs = listOf("--lwjgl=3.2.3")), +// "mixinbootstrap" to "https://github.com/LXGaming/MixinBootstrap/releases/download/v1.1.0/_MixinBootstrap-1.1.0.jar" + "maven.modrinth:mixinbootstrap:1.1.0" + ), extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.12.2", dependencies = listOf( - "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" - )), +// "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" + "zone.rong:mixinbooter:9.3" + )), Config("forge", "1.8.9", dependencies = listOf( - "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" - )), +// "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" + "zone.rong:mixinbooter:9.3" + )), Config("forge", "1.7.10", dependencies = listOf( - "unimixins" to "https://github.com/LegacyModdingMC/UniMixins/releases/download/0.1.19/+unimixins-all-1.7.10-0.1.19.jar" - )), +// "unimixins" to "https://github.com/LegacyModdingMC/UniMixins/releases/download/0.1.19/+unimixins-all-1.7.10-0.1.19.jar" + "com.github.LegacyModdingMC.UniMixins:unimixins-all-1.7.10:0.1.19" + )), ) } //endregion diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt index 9897339..3e5db73 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt @@ -6,7 +6,7 @@ data class Config( val loaderVersion: String? = null, val jvmVersion: Int? = null, val extraArgs: List? = null, - val dependencies: List>? = null, + val dependencies: List? = null, ) { val versionString: String get() = if (loaderVersion != null) @@ -22,7 +22,7 @@ data class Config( result.appendLine("loaderVersion=${loaderVersion}") result.appendLine("jvmVersion=${jvmVersion}") result.appendLine("extraArgs=[${extraArgs?.joinToString(", ") ?: ""}]") - result.appendLine("mods=[${dependencies?.joinToString(", ") { (name, _) -> name } ?: ""}]") + result.appendLine("mods=[${dependencies?.joinToString(", ") { it.split(":")[1] } ?: ""}]") return result.toString() } diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt index 05bbd23..c102088 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt @@ -3,21 +3,23 @@ package dev.nolij.zumegradle.smoketest import org.gradle.api.logging.Logger import java.io.File import java.util.* -import kotlin.io.path.* import dev.nolij.zumegradle.smoketest.Thread.ThreadState +import org.gradle.api.Project class SmokeTest( - internal val logger: Logger, + internal val project: Project, internal val portableMCBinary: String, internal val modFile: File, internal val mainDir: String, internal val workDir: String, - internal val maxThreads: Int, + private val maxThreads: Int, internal val threadTimeout: Long, - internal val configs: List + private val configs: List ) { + internal val logger: Logger = project.logger + private val threads = ArrayList() internal fun printThreads() { diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt index 3d37dbc..40bfbca 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt @@ -1,8 +1,6 @@ package dev.nolij.zumegradle.smoketest import java.io.File -import java.io.FileOutputStream -import java.net.URL import java.nio.file.Files import kotlin.io.path.* @@ -59,12 +57,24 @@ internal class Thread( logsPath.createDirectories() } } - - config.dependencies?.forEach { (name, urlString) -> - URL(urlString).openStream().use { inputStream -> - FileOutputStream("${modsDir}/${name}.jar").use(inputStream::transferTo) + +// config.dependencies?.forEach { (name, urlString) -> +// URL(urlString).openStream().use { inputStream -> +// FileOutputStream("${modsDir}/${name}.jar").use(inputStream::transferTo) +// } +// } + + if(config.dependencies != null) { + val files = smokeTest.project.configurations.detachedConfiguration( + *config.dependencies.map { + smokeTest.project.dependencies.create(it) + }.toTypedArray() + ).resolve() + files.forEach { file -> + Files.copy(file.toPath(), Path("${modsDir}/${file.name}")) } } + Files.copy(smokeTest.modFile.toPath(), Path("${modsDir}/${smokeTest.modFile.name}")) diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt index abb032a..11f8fef 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt @@ -23,11 +23,11 @@ abstract class SmokeTestTask : DefaultTask() { @get:Input abstract val inputTask: Property - @get:InputDirectory - abstract val mainDir: RegularFileProperty + @get:Input + abstract val mainDir: Property - @get:InputDirectory - abstract val workDir: RegularFileProperty + @get:Input + abstract val workDir: Property @get:Input abstract val maxThreads: Property @@ -52,14 +52,14 @@ abstract class SmokeTestTask : DefaultTask() { @TaskAction fun runSmokeTest() { SmokeTest( - logger = logger, - portableMCBinary = portableMCBinary.get(), - modFile = inputTask.get().archiveFile.get().asFile, - mainDir = mainDir.get().asFile.absolutePath, - workDir = workDir.get().asFile.absolutePath, - maxThreads = maxThreads.get(), - threadTimeout = threadTimeout.get(), - configs = configs.get() + project, + portableMCBinary.get(), + inputTask.get().archiveFile.get().asFile, + mainDir.get(), + workDir.get(), + maxThreads.get(), + threadTimeout.get(), + configs.get() ).test() } } \ No newline at end of file From dde44f01cd56fc221ed3be1bde4bbf01f1ec3ea9 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 07:46:01 -0500 Subject: [PATCH 18/35] upload test results if they fail and upload jars anyways --- .github/workflows/build.yml | 9 +++++++++ build.gradle.kts | 4 ---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a139b3b..97e5e24 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,14 +32,23 @@ jobs: run: ./gradlew build --stacktrace --no-daemon - name: :smokeTest + id: smokeTest uses: coactions/setup-xvfb@v1 with: run: ./gradlew :smokeTest --no-daemon - name: Upload artifacts + if: always() uses: actions/upload-artifact@v4 with: name: zume path: | **/build/libs/zume*.jar build/libs/*mappings.txt + + - name: Upload test results + if: steps.smokeTest.conclusion == 'failure' + uses: actions/upload-artifact@v4 + with: + name: smokeTest + path: build/smokeTest/**/logs/** diff --git a/build.gradle.kts b/build.gradle.kts index 058c6f1..8a5516a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -607,19 +607,15 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { Config("forge", "1.18.2", extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.16.5", extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.14.4", dependencies = listOf( -// "mixinbootstrap" to "https://github.com/LXGaming/MixinBootstrap/releases/download/v1.1.0/_MixinBootstrap-1.1.0.jar" "maven.modrinth:mixinbootstrap:1.1.0" ), extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.12.2", dependencies = listOf( -// "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" "zone.rong:mixinbooter:9.3" )), Config("forge", "1.8.9", dependencies = listOf( -// "mixinbooter" to "https://github.com/CleanroomMC/MixinBooter/releases/download/9.3/mixinbooter-9.3.jar" "zone.rong:mixinbooter:9.3" )), Config("forge", "1.7.10", dependencies = listOf( -// "unimixins" to "https://github.com/LegacyModdingMC/UniMixins/releases/download/0.1.19/+unimixins-all-1.7.10-0.1.19.jar" "com.github.LegacyModdingMC.UniMixins:unimixins-all-1.7.10:0.1.19" )), ) From 38349ebc9b38fe9d19bf354c08e8fe19387b82e1 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:30:06 -0500 Subject: [PATCH 19/35] use modrinth maven for now since legfab is down --- build.gradle.kts | 14 +++++++++----- .../dev/nolij/zumegradle/smoketest/Thread.kt | 6 ------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8a5516a..e6fcf3c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -537,7 +537,7 @@ python { repositories { maven("https://maven.terraformersmc.com/releases") - maven("https://maven.legacyfabric.net") +// maven("https://maven.legacyfabric.net") maven("https://maven.cleanroommc.com/") } @@ -584,16 +584,20 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { "maven.modrinth:modmenu:1.7.17", )), Config("legacyfabric", "1.12.2", dependencies = listOf( - "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.12.2", +// "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.12.2", + "maven.modrinth:legacy-fabric-api:1.10.2", )), Config("legacyfabric", "1.8.9", dependencies = listOf( - "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.8.9", +// "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.8.9", + "maven.modrinth:legacy-fabric-api:1.10.2", )), Config("legacyfabric", "1.7.10", dependencies = listOf( - "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.7.10", +// "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.7.10", + "maven.modrinth:legacy-fabric-api:1.10.2", )), Config("legacyfabric", "1.6.4", dependencies = listOf( - "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.6.4", +// "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.6.4", + "maven.modrinth:legacy-fabric-api:1.10.2", )), Config("babric", "b1.7.3", jvmVersion = 17, dependencies = listOf( "maven.modrinth:stationapi:2.0-alpha.2.4", diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt index 40bfbca..fa8c555 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt @@ -58,12 +58,6 @@ internal class Thread( } } -// config.dependencies?.forEach { (name, urlString) -> -// URL(urlString).openStream().use { inputStream -> -// FileOutputStream("${modsDir}/${name}.jar").use(inputStream::transferTo) -// } -// } - if(config.dependencies != null) { val files = smokeTest.project.configurations.detachedConfiguration( *config.dependencies.map { From 463d4d85767ba4f12f16c8ac7f9085985b624980 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:35:51 -0500 Subject: [PATCH 20/35] indent failed tests --- .../kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt index c102088..f8f6c61 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt @@ -1,8 +1,6 @@ package dev.nolij.zumegradle.smoketest -import org.gradle.api.logging.Logger import java.io.File -import java.util.* import dev.nolij.zumegradle.smoketest.Thread.ThreadState import org.gradle.api.Project @@ -18,9 +16,9 @@ class SmokeTest( private val configs: List ) { - internal val logger: Logger = project.logger + internal val logger = project.logger - private val threads = ArrayList() + private val threads = mutableListOf() internal fun printThreads() { println(""" @@ -51,7 +49,7 @@ class SmokeTest( .map { thread -> thread.config } if (failedConfigs.isNotEmpty()) { - logger.error("[{\n${failedConfigs.joinToString("}, {\n")}}]") + logger.error("[{\n${failedConfigs.joinToString("}, {\n") { it.toString().indent(4) }}]") error("One or more tests failed. See logs for more details.") } From ee76889f1387beab20e803d105c6c488845e7acc Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:58:34 -0500 Subject: [PATCH 21/35] no --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 97e5e24..dad6d12 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,7 +47,7 @@ jobs: build/libs/*mappings.txt - name: Upload test results - if: steps.smokeTest.conclusion == 'failure' + if: ${{ steps.smokeTest.outcome == 'failure' }} uses: actions/upload-artifact@v4 with: name: smokeTest From e01acb400b5df81d8ee2ead1d4c049fd6f7b6efe Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 19:42:04 -0500 Subject: [PATCH 22/35] back to single file sadness --- build.gradle.kts | 2 +- .../dev/nolij/zumegradle/smoketest/Config.kt | 29 -- .../nolij/zumegradle/smoketest/SmokeTest.kt | 255 ++++++++++++++++-- .../dev/nolij/zumegradle/smoketest/Thread.kt | 150 ----------- .../nolij/zumegradle/task/SmokeTestTask.kt | 7 +- 5 files changed, 230 insertions(+), 213 deletions(-) delete mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt delete mode 100644 buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt diff --git a/build.gradle.kts b/build.gradle.kts index e6fcf3c..6eeeb0d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ import dev.nolij.zumegradle.DeflateAlgorithm import dev.nolij.zumegradle.JsonShrinkingType import dev.nolij.zumegradle.MixinConfigMergingTransformer import dev.nolij.zumegradle.entryprocessing.EntryProcessors -import dev.nolij.zumegradle.smoketest.Config +import dev.nolij.zumegradle.smoketest.SmokeTest.Config import dev.nolij.zumegradle.task.* import kotlinx.serialization.encodeToString import me.modmuss50.mpp.HttpUtils diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt deleted file mode 100644 index 3e5db73..0000000 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Config.kt +++ /dev/null @@ -1,29 +0,0 @@ -package dev.nolij.zumegradle.smoketest - -data class Config( - val modLoader: String, - val mcVersion: String, - val loaderVersion: String? = null, - val jvmVersion: Int? = null, - val extraArgs: List? = null, - val dependencies: List? = null, -) { - val versionString: String get() = - if (loaderVersion != null) - "${modLoader}:${mcVersion}:${loaderVersion}" - else - "${modLoader}:${mcVersion}" - - override fun toString(): String { - val result = StringBuilder() - - result.appendLine("modLoader=${modLoader}") - result.appendLine("mcVersion=${mcVersion}") - result.appendLine("loaderVersion=${loaderVersion}") - result.appendLine("jvmVersion=${jvmVersion}") - result.appendLine("extraArgs=[${extraArgs?.joinToString(", ") ?: ""}]") - result.appendLine("mods=[${dependencies?.joinToString(", ") { it.split(":")[1] } ?: ""}]") - - return result.toString() - } -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt index f8f6c61..c711139 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt @@ -1,56 +1,255 @@ +@file:OptIn(ExperimentalPathApi::class) + package dev.nolij.zumegradle.smoketest +import org.gradle.api.Project import java.io.File +import java.nio.file.Files +import java.util.* +import kotlin.io.path.* +import kotlin.math.max -import dev.nolij.zumegradle.smoketest.Thread.ThreadState -import org.gradle.api.Project +fun sleep(millis: Long) { + Thread.sleep(millis) +} class SmokeTest( - internal val project: Project, - internal val portableMCBinary: String, - internal val modFile: File, - internal val mainDir: String, - internal val workDir: String, + private val project: Project, + private val portableMCBinary: String, + private val modFile: File, + private val mainDir: String, + private val workDir: String, private val maxThreads: Int, - internal val threadTimeout: Long, + private val threadTimeout: Long, private val configs: List ) { + + data class Config( + val modLoader: String, + val mcVersion: String, + val loaderVersion: String? = null, + val jvmVersion: Int? = null, + val extraArgs: List? = null, + val dependencies: List? = null, + ) { + val name: String = hashCode().toUInt().toString(16) + + val versionString: String get() = + if (loaderVersion != null) + "${modLoader}:${mcVersion}:${loaderVersion}" + else + "${modLoader}:${mcVersion}" + + override fun toString(): String { + val result = StringBuilder() + + result.appendLine("name=${name}") + result.appendLine("modLoader=${modLoader}") + result.appendLine("mcVersion=${mcVersion}") + result.appendLine("loaderVersion=${loaderVersion}") + result.appendLine("jvmVersion=${jvmVersion}") + result.appendLine("extraArgs=[${extraArgs?.joinToString(", ") ?: ""}]") + result.appendLine("mods=[${dependencies?.joinToString(", ") { it.split(":")[1] } ?: ""}]") + + return result.toString() + } + } + + private enum class ThreadStage { + SETUP, + TESTING, + COMPLETED, + } - internal val logger = project.logger + private enum class FailureReason { + SETUP_NONZERO_EXIT_CODE, + TIMED_OUT, + TESTING_NONZERO_EXIT_CODE, + SUCCESS_LOG_MISSING, + } + + private inner class Thread(val config: Config) { + val instancePath = "${workDir}/${config.name}" + val modsPath = "${instancePath}/mods" + val command: Array + val setupLogFile = File("${instancePath}/setup.log") + val testLogFile = File("${instancePath}/test.log") + val gameLogFile = File("${instancePath}/logs/latest.log") + + private var process: Process? = null + private var startTimestamp: Long? = null + + val alive: Boolean get() = process?.isAlive == true + private val isTimedOut: Boolean get() = + if (alive) + System.nanoTime() - startTimestamp!! > threadTimeout + else + false + + var stage: ThreadStage = ThreadStage.SETUP + private set + var failureReason: FailureReason? = null + private set + val failed: Boolean get() = failureReason != null + + val ready: Boolean get() = !failed && stage == ThreadStage.SETUP + val done: Boolean get() = failed || stage == ThreadStage.COMPLETED + + init { + Path(instancePath).also { path -> + if (!path.exists()) + path.createDirectories() + } + + Path(modsPath).also { modsPath -> + if (modsPath.exists()) + modsPath.deleteRecursively() + modsPath.createDirectories() + } + + if (gameLogFile.exists()) + gameLogFile.delete() + + if(config.dependencies != null) { + val files = project.configurations.detachedConfiguration( + *config.dependencies.map { + project.dependencies.create(it) + }.toTypedArray() + ).resolve() + files.forEach { file -> + Files.copy(file.toPath(), Path("${modsPath}/${file.name}")) + } + } + + Files.copy(modFile.toPath(), Path("${modsPath}/${modFile.name}")) + + val extraArgs = arrayListOf() + + val jvmVersionMap = mapOf( + 17 to "java-runtime-gamma", + 21 to "java-runtime-delta", + 8 to "jre-legacy" + ) + if (config.jvmVersion != null) + extraArgs.add("--jvm=${mainDir}/jvm/${jvmVersionMap[config.jvmVersion]!!}/bin/java") + + if (config.extraArgs != null) + extraArgs.addAll(config.extraArgs) + + command = arrayOf( + portableMCBinary, + "--main-dir", mainDir, + "--work-dir", instancePath, + "start", config.versionString, + *extraArgs.toTypedArray(), + "--jvm-args=-DzumeGradle.auditAndExit=true -Xmx1G", + ) + + if (ProcessBuilder(*command, "--dry") + .redirectOutput(setupLogFile) + .start() + .waitFor() != 0) { + failureReason = FailureReason.SETUP_NONZERO_EXIT_CODE + } + } + + private fun start() { + if (stage != ThreadStage.SETUP) + error("Thread already started") + else if (failed) + error("Cannot start thread which failed setup") + + stage = ThreadStage.TESTING + + startTimestamp = System.nanoTime() + process = ProcessBuilder(*command) + .redirectOutput(testLogFile) + .start() + } + + fun step() { + var passed = false + + if (stage == ThreadStage.SETUP && ready && anyAvailableThreads) { + return start() + } else if (stage == ThreadStage.TESTING && isTimedOut) { + failureReason = FailureReason.TIMED_OUT + process!!.destroyForcibly() + } else if (stage == ThreadStage.TESTING && !alive) { + if (process!!.exitValue() == 0) { + (if (gameLogFile.exists()) gameLogFile else testLogFile).reader().use { reader -> + reader.forEachLine { line -> + if (line.endsWith("ZumeGradle audit passed")) { + passed = true + } + } + } + + if (!passed) { + failureReason = FailureReason.SUCCESS_LOG_MISSING + } + } else { + failureReason = FailureReason.TESTING_NONZERO_EXIT_CODE + } + } else { + return + } + + stage = ThreadStage.COMPLETED + + if (passed) { + println("Smoke test passed for config:\n${config}") + } else { + project.logger.error("Smoke test failed for config:\n${config}") + } + + printThreads() + } + } - private val threads = mutableListOf() + private val threads = ArrayList() + private val runningThreads: List get() = threads.filter(Thread::alive) + private val pendingThreads: List get() = threads.filter { thread -> !thread.done } + private val finishedThreads: List get() = threads.filter(Thread::done) + private val passedThreads: List get() = finishedThreads.filter { thread -> !thread.failed } + private val failedThreads: List get() = threads.filter(Thread::failed) + private val availableThreads: Int get() = max(0, maxThreads - runningThreads.size) + private val anyAvailableThreads: Boolean get() = runningThreads.size < maxThreads - internal fun printThreads() { + private fun printThreads() { println(""" - > TOTAL: ${threads.filter { thread -> thread.finished }.size}/${configs.size} - > RUNNING: ${threads.filter { thread -> thread.state == ThreadState.RUNNING }.size}/${maxThreads} - > PASSED: ${threads.filter { thread -> thread.state == ThreadState.PASSED }.size} - > FAILED: ${threads.filter { thread -> thread.state == ThreadState.FAILED }.size} + > TOTAL: ${finishedThreads.size}/${configs.size} + > RUNNING: ${runningThreads.size}/${maxThreads} + > PASSED: ${passedThreads.size} + > FAILED: ${failedThreads.size} """.trimIndent()) } fun test() { println("Setting up instances...") configs.forEach { config -> - threads.add(Thread(this, config)) + threads.add(Thread(config)) } printThreads() do { - while (threads.count { thread -> thread.isAlive } < maxThreads) - threads.firstOrNull { thread -> thread.state == ThreadState.PENDING }?.start() ?: break - java.lang.Thread.sleep(500L) - threads.forEach(Thread::update) - } while (threads.any { thread -> !thread.finished }) - - val failedConfigs = threads - .filter { thread -> thread.state == ThreadState.FAILED } - .map { thread -> thread.config } + threads.forEach(Thread::step) + sleep(500L) + } while (threads.any { thread -> !thread.done }) - if (failedConfigs.isNotEmpty()) { - logger.error("[{\n${failedConfigs.joinToString("}, {\n") { it.toString().indent(4) }}]") - error("One or more tests failed. See logs for more details.") + if (failedThreads.isNotEmpty()) { + failedThreads.forEach { thread -> + project.logger.error( + "Config ${thread.config.name} failed!\n" + + "> STAGE: ${thread.stage}\n" + + "> CONFIG: {\n${thread.config}}\n" + + "> COMMAND: [${thread.command.joinToString(", ")}]\n" + + "> FAILURE REASON: ${thread.failureReason}\n" + + "> INSTANCE PATH: ${thread.instancePath}\n" + ) + } + error("${failedThreads.size} smoke test config(s) failed. See logs for more details.") } println("All tests passed.") diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt deleted file mode 100644 index fa8c555..0000000 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/Thread.kt +++ /dev/null @@ -1,150 +0,0 @@ -package dev.nolij.zumegradle.smoketest - -import java.io.File -import java.nio.file.Files -import kotlin.io.path.* - -@OptIn(ExperimentalPathApi::class) -internal class Thread( - private val smokeTest: SmokeTest, - val config: Config -) { - private val name: String = config.hashCode().toUInt().toString(16) - private val instanceDir = "${smokeTest.workDir}/${name}" - private val modsDir = "${instanceDir}/mods" - private val logDir = "${instanceDir}/logs/latest.log" - private val logFile = File(logDir) - private val command: Array - - private var process: Process? = null - - private var startTimestamp: Long? = null - - val isAlive: Boolean get() = process?.isAlive == true - private val isTimedOut: Boolean get() = - if (isAlive) - System.nanoTime() - startTimestamp!! > smokeTest.threadTimeout - else - false - - private var finalState: ThreadState? = null - val finished: Boolean get() = finalState != null - val state: ThreadState - get() { - return finalState ?: - if (startTimestamp == null) ThreadState.PENDING - else if (isTimedOut) ThreadState.TIMED_OUT - else if (isAlive) ThreadState.RUNNING - else ThreadState.READY - } - - init { - Path(instanceDir).also { path -> - if (!path.exists()) - path.createDirectories() - } - - Path(modsDir).also { modsPath -> - if (modsPath.exists()) - modsPath.deleteRecursively() - modsPath.createDirectories() - } - - Path(logDir).also { logPath -> - logPath.deleteIfExists() - logPath.parent.also { logsPath -> - if (!logsPath.exists()) - logsPath.createDirectories() - } - } - - if(config.dependencies != null) { - val files = smokeTest.project.configurations.detachedConfiguration( - *config.dependencies.map { - smokeTest.project.dependencies.create(it) - }.toTypedArray() - ).resolve() - files.forEach { file -> - Files.copy(file.toPath(), Path("${modsDir}/${file.name}")) - } - } - - - Files.copy(smokeTest.modFile.toPath(), Path("${modsDir}/${smokeTest.modFile.name}")) - - val extraArgs = arrayListOf() - - val jvmVersionMap = mapOf( - 17 to "java-runtime-gamma", - 21 to "java-runtime-delta", - 8 to "jre-legacy" - ) - if (config.jvmVersion != null) - extraArgs.add("--jvm=${smokeTest.mainDir}/jvm/${jvmVersionMap[config.jvmVersion]!!}/bin/java") - - if (config.extraArgs != null) - extraArgs.addAll(config.extraArgs) - - command = arrayOf( - smokeTest.portableMCBinary, - "--main-dir", smokeTest.mainDir, - "--work-dir", instanceDir, - "start", config.versionString, - *extraArgs.toTypedArray(), - "--jvm-args=-DzumeGradle.auditAndExit=true", - ) - - ProcessBuilder(*command, "--dry") - .inheritIO() - .start() - .waitFor() - } - - fun start() { - if (state != ThreadState.PENDING) - error("Thread already started!") - - startTimestamp = System.nanoTime() - process = ProcessBuilder(*command) - .inheritIO() - .start() - } - - fun update() { - var passed = false - - when (state) { - ThreadState.TIMED_OUT -> process!!.destroyForcibly() - ThreadState.READY -> { - if (logFile.exists()) { - logFile.reader().use { reader -> - reader.forEachLine { line -> - if (line.endsWith("ZumeGradle audit passed")) - passed = true - } - } - } - } - else -> return - } - - if (passed) { - println("Smoke test passed for config:\n${config}") - finalState = ThreadState.PASSED - } else { - smokeTest.logger.error("Smoke test failed for config:\n${config}") - finalState = ThreadState.FAILED - } - - smokeTest.printThreads() - } - - internal enum class ThreadState { - PENDING, - RUNNING, - TIMED_OUT, - READY, - PASSED, - FAILED, - } -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt index 11f8fef..5f659b7 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/task/SmokeTestTask.kt @@ -1,17 +1,14 @@ package dev.nolij.zumegradle.task +import dev.nolij.zumegradle.smoketest.SmokeTest +import dev.nolij.zumegradle.smoketest.SmokeTest.Config import org.gradle.api.DefaultTask -import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputDirectory import org.gradle.jvm.tasks.Jar import org.gradle.api.tasks.TaskAction -import dev.nolij.zumegradle.smoketest.Config -import dev.nolij.zumegradle.smoketest.SmokeTest - abstract class SmokeTestTask : DefaultTask() { init { group = "verification" From 24b867d603606092ca3503c5e34c7acfbf9471b6 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:14:48 -0500 Subject: [PATCH 23/35] use modrinth for everything --- build.gradle.kts | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6eeeb0d..a1dea47 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -535,12 +535,6 @@ python { pip("portablemc:${"portablemc_version"()}") } -repositories { - maven("https://maven.terraformersmc.com/releases") -// maven("https://maven.legacyfabric.net") - maven("https://maven.cleanroommc.com/") -} - val smokeTest by tasks.registering(SmokeTestTask::class) { dependsOn(tasks.checkPython, tasks.pipInstall, compressJar) @@ -553,50 +547,46 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { configs( Config("fabric", "snapshot", dependencies = listOf( - "net.fabricmc.fabric-api:fabric-api:0.107.0+1.21.4", + "maven.modrinth:fabric-api:0.107.0+1.21.4", )), Config("fabric", "release", dependencies = listOf( - "net.fabricmc.fabric-api:fabric-api:0.107.0+1.21.3", - "com.terraformersmc:modmenu:11.0.3", + "maven.modrinth:fabric-api:0.107.0+1.21.3", + "maven.modrinth:modmenu:11.0.3", )), Config("fabric", "1.21.1", dependencies = listOf( - "net.fabricmc.fabric-api:fabric-api:0.107.0+1.21.1", - "com.terraformersmc:modmenu:11.0.3", + "maven.modrinth:fabric-api:0.107.0+1.21.1", + "maven.modrinth:modmenu:11.0.3", )), Config("fabric", "1.20.6", dependencies = listOf( - "net.fabricmc.fabric-api:fabric-api:0.100.8+1.20.6", - "com.terraformersmc:modmenu:10.0.0", + "maven.modrinth:fabric-api:0.100.8+1.20.6", + "maven.modrinth:modmenu:10.0.0", )), Config("fabric", "1.20.1", dependencies = listOf( - "net.fabricmc.fabric-api:fabric-api:0.92.2+1.20.1", - "com.terraformersmc:modmenu:7.2.2", + "maven.modrinth:fabric-api:0.92.2+1.20.1", + "maven.modrinth:modmenu:7.2.2", )), Config("fabric", "1.18.2", dependencies = listOf( - "net.fabricmc.fabric-api:fabric-api:0.77.0+1.18.2", - "com.terraformersmc:modmenu:3.2.5", + "maven.modrinth:fabric-api:0.77.0+1.18.2", + "maven.modrinth:modmenu:3.2.5", ), extraArgs = listOf("--lwjgl=3.2.3")), Config("fabric", "1.16.5", dependencies = listOf( - "net.fabricmc.fabric-api:fabric-api:0.42.0+1.16", - "com.terraformersmc:modmenu:1.16.23", + "maven.modrinth:fabric-api:0.42.0+1.16", + "maven.modrinth:modmenu:1.16.23", )), Config("fabric", "1.14.4", dependencies = listOf( - "net.fabricmc.fabric-api:fabric-api:0.28.5+1.14", + "maven.modrinth:fabric-api:0.28.5+1.14", "maven.modrinth:modmenu:1.7.17", )), Config("legacyfabric", "1.12.2", dependencies = listOf( -// "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.12.2", "maven.modrinth:legacy-fabric-api:1.10.2", )), Config("legacyfabric", "1.8.9", dependencies = listOf( -// "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.8.9", "maven.modrinth:legacy-fabric-api:1.10.2", )), Config("legacyfabric", "1.7.10", dependencies = listOf( -// "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.7.10", "maven.modrinth:legacy-fabric-api:1.10.2", )), Config("legacyfabric", "1.6.4", dependencies = listOf( -// "net.legacyfabric.legacy-fabric-api:legacy-fabric-api:1.10.2+1.6.4", "maven.modrinth:legacy-fabric-api:1.10.2", )), Config("babric", "b1.7.3", jvmVersion = 17, dependencies = listOf( @@ -614,13 +604,13 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { "maven.modrinth:mixinbootstrap:1.1.0" ), extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.12.2", dependencies = listOf( - "zone.rong:mixinbooter:9.3" + "maven.modrinth:mixinbooter:9.3" )), Config("forge", "1.8.9", dependencies = listOf( - "zone.rong:mixinbooter:9.3" + "maven.modrinth:mixinbooter:9.3" )), Config("forge", "1.7.10", dependencies = listOf( - "com.github.LegacyModdingMC.UniMixins:unimixins-all-1.7.10:0.1.19" + "maven.modrinth:unimixins:1.7.10-0.1.19" )), ) } From 31f0dc7798cd0304a6f0d510337661f488d04c82 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:34:57 -0500 Subject: [PATCH 24/35] =?UTF-8?q?allow=20url=20downloads=20too=20old=20mc?= =?UTF-8?q?=20=F0=9F=92=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nolij/zumegradle/smoketest/SmokeTest.kt | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt index c711139..736c442 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt @@ -3,9 +3,9 @@ package dev.nolij.zumegradle.smoketest import org.gradle.api.Project +import xyz.wagyourtail.unimined.util.cachingDownload import java.io.File import java.nio.file.Files -import java.util.* import kotlin.io.path.* import kotlin.math.max @@ -29,8 +29,8 @@ class SmokeTest( val mcVersion: String, val loaderVersion: String? = null, val jvmVersion: Int? = null, - val extraArgs: List? = null, - val dependencies: List? = null, + val extraArgs: List = emptyList(), + val dependencies: Set = emptySet(), ) { val name: String = hashCode().toUInt().toString(16) @@ -48,8 +48,8 @@ class SmokeTest( result.appendLine("mcVersion=${mcVersion}") result.appendLine("loaderVersion=${loaderVersion}") result.appendLine("jvmVersion=${jvmVersion}") - result.appendLine("extraArgs=[${extraArgs?.joinToString(", ") ?: ""}]") - result.appendLine("mods=[${dependencies?.joinToString(", ") { it.split(":")[1] } ?: ""}]") + result.appendLine("extraArgs=[${extraArgs.joinToString(", ")}]") + result.appendLine("mods=[${dependencies.joinToString(", ") { it.split(":")[1] }}]") return result.toString() } @@ -110,20 +110,21 @@ class SmokeTest( if (gameLogFile.exists()) gameLogFile.delete() - if(config.dependencies != null) { - val files = project.configurations.detachedConfiguration( - *config.dependencies.map { - project.dependencies.create(it) - }.toTypedArray() - ).resolve() - files.forEach { file -> - Files.copy(file.toPath(), Path("${modsPath}/${file.name}")) - } + val urlDeps = config.dependencies.filter { it.matches(Regex("https?://.*")) }.toSet() + val mavenDeps = (config.dependencies - urlDeps).toSet() + + val files = project.configurations.detachedConfiguration( + *mavenDeps.map { project.dependencies.create(it) } + .toTypedArray() + ).resolve() + urlDeps.map { project.cachingDownload(it).toFile() } + + files.forEach { file -> + Files.copy(file.toPath(), Path("${modsPath}/${file.name}")) } Files.copy(modFile.toPath(), Path("${modsPath}/${modFile.name}")) - val extraArgs = arrayListOf() + val extraArgs = mutableListOf() val jvmVersionMap = mapOf( 17 to "java-runtime-gamma", @@ -133,8 +134,7 @@ class SmokeTest( if (config.jvmVersion != null) extraArgs.add("--jvm=${mainDir}/jvm/${jvmVersionMap[config.jvmVersion]!!}/bin/java") - if (config.extraArgs != null) - extraArgs.addAll(config.extraArgs) + extraArgs.addAll(config.extraArgs) command = arrayOf( portableMCBinary, From 6c79eddca56e021e81297ebaae25f8227925a51c Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:36:46 -0500 Subject: [PATCH 25/35] cache based on branch name --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dad6d12..eb0ae67 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: path: | **/.gradle/ **/build/ - key: ${{ runner.os }}-gradlelocal-${{ hashFiles('gradle.properties', '**/gradle-wrapper.properties') }} + key: ${{ runner.os }}-gradlelocal-${{ github.ref }} - uses: actions/setup-java@v4 with: From 8acc1c5c33c7ac9ea05afda210ced36889502eb3 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Wed, 6 Nov 2024 23:37:48 -0500 Subject: [PATCH 26/35] oops --- build.gradle.kts | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a1dea47..2b398c4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -546,50 +546,50 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { threadTimeout = TimeUnit.SECONDS.toNanos(60) configs( - Config("fabric", "snapshot", dependencies = listOf( + Config("fabric", "snapshot", dependencies = setOf( "maven.modrinth:fabric-api:0.107.0+1.21.4", )), - Config("fabric", "release", dependencies = listOf( + Config("fabric", "release", dependencies = setOf( "maven.modrinth:fabric-api:0.107.0+1.21.3", "maven.modrinth:modmenu:11.0.3", )), - Config("fabric", "1.21.1", dependencies = listOf( + Config("fabric", "1.21.1", dependencies = setOf( "maven.modrinth:fabric-api:0.107.0+1.21.1", "maven.modrinth:modmenu:11.0.3", )), - Config("fabric", "1.20.6", dependencies = listOf( + Config("fabric", "1.20.6", dependencies = setOf( "maven.modrinth:fabric-api:0.100.8+1.20.6", "maven.modrinth:modmenu:10.0.0", )), - Config("fabric", "1.20.1", dependencies = listOf( + Config("fabric", "1.20.1", dependencies = setOf( "maven.modrinth:fabric-api:0.92.2+1.20.1", "maven.modrinth:modmenu:7.2.2", )), - Config("fabric", "1.18.2", dependencies = listOf( + Config("fabric", "1.18.2", dependencies = setOf( "maven.modrinth:fabric-api:0.77.0+1.18.2", "maven.modrinth:modmenu:3.2.5", ), extraArgs = listOf("--lwjgl=3.2.3")), - Config("fabric", "1.16.5", dependencies = listOf( + Config("fabric", "1.16.5", dependencies = setOf( "maven.modrinth:fabric-api:0.42.0+1.16", "maven.modrinth:modmenu:1.16.23", )), - Config("fabric", "1.14.4", dependencies = listOf( + Config("fabric", "1.14.4", dependencies = setOf( "maven.modrinth:fabric-api:0.28.5+1.14", "maven.modrinth:modmenu:1.7.17", )), - Config("legacyfabric", "1.12.2", dependencies = listOf( + Config("legacyfabric", "1.12.2", dependencies = setOf( "maven.modrinth:legacy-fabric-api:1.10.2", )), - Config("legacyfabric", "1.8.9", dependencies = listOf( + Config("legacyfabric", "1.8.9", dependencies = setOf( "maven.modrinth:legacy-fabric-api:1.10.2", )), - Config("legacyfabric", "1.7.10", dependencies = listOf( + Config("legacyfabric", "1.7.10", dependencies = setOf( "maven.modrinth:legacy-fabric-api:1.10.2", )), - Config("legacyfabric", "1.6.4", dependencies = listOf( + Config("legacyfabric", "1.6.4", dependencies = setOf( "maven.modrinth:legacy-fabric-api:1.10.2", )), - Config("babric", "b1.7.3", jvmVersion = 17, dependencies = listOf( + Config("babric", "b1.7.3", jvmVersion = 17, dependencies = setOf( "maven.modrinth:stationapi:2.0-alpha.2.4", ), extraArgs = listOf("--exclude-lib=asm-all")), Config("neoforge", "release"), @@ -600,16 +600,16 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { Config("forge", "1.19.2"), Config("forge", "1.18.2", extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.16.5", extraArgs = listOf("--lwjgl=3.2.3")), - Config("forge", "1.14.4", dependencies = listOf( + Config("forge", "1.14.4", dependencies = setOf( "maven.modrinth:mixinbootstrap:1.1.0" ), extraArgs = listOf("--lwjgl=3.2.3")), - Config("forge", "1.12.2", dependencies = listOf( + Config("forge", "1.12.2", dependencies = setOf( "maven.modrinth:mixinbooter:9.3" )), - Config("forge", "1.8.9", dependencies = listOf( + Config("forge", "1.8.9", dependencies = setOf( "maven.modrinth:mixinbooter:9.3" )), - Config("forge", "1.7.10", dependencies = listOf( + Config("forge", "1.7.10", dependencies = setOf( "maven.modrinth:unimixins:1.7.10-0.1.19" )), ) From a4948d03dc3f34918e5e38e3a1e72c005eec68d9 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Thu, 7 Nov 2024 00:10:48 -0500 Subject: [PATCH 27/35] bump fapi --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2b398c4..76f1265 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -547,7 +547,7 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { configs( Config("fabric", "snapshot", dependencies = setOf( - "maven.modrinth:fabric-api:0.107.0+1.21.4", + "maven.modrinth:fabric-api:0.107.2+1.21.4", )), Config("fabric", "release", dependencies = setOf( "maven.modrinth:fabric-api:0.107.0+1.21.3", From d665e7422f7af26460473e07032175561e2b52e1 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Thu, 7 Nov 2024 08:40:48 -0500 Subject: [PATCH 28/35] what --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eb0ae67..4d0b475 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,8 +46,11 @@ jobs: **/build/libs/zume*.jar build/libs/*mappings.txt + - name: test + run: echo ${{ steps.smokeTest.outcome }} + - name: Upload test results - if: ${{ steps.smokeTest.outcome == 'failure' }} + if: steps.smokeTest.outcome != 'success' uses: actions/upload-artifact@v4 with: name: smokeTest From 6a6076cd13aac58efb0127d9f2b87e49658e2e47 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Thu, 7 Nov 2024 09:07:56 -0500 Subject: [PATCH 29/35] use new path apis --- .github/workflows/build.yml | 13 ++++--- .../nolij/zumegradle/smoketest/SmokeTest.kt | 39 ++++++++----------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4d0b475..a8f3031 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,12 +31,6 @@ jobs: - name: :build run: ./gradlew build --stacktrace --no-daemon - - name: :smokeTest - id: smokeTest - uses: coactions/setup-xvfb@v1 - with: - run: ./gradlew :smokeTest --no-daemon - - name: Upload artifacts if: always() uses: actions/upload-artifact@v4 @@ -45,8 +39,15 @@ jobs: path: | **/build/libs/zume*.jar build/libs/*mappings.txt + + - name: :smokeTest + id: smokeTest + uses: coactions/setup-xvfb@v1 + with: + run: ./gradlew :smokeTest --no-daemon - name: test + if: always() run: echo ${{ steps.smokeTest.outcome }} - name: Upload test results diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt index 736c442..6b598c4 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt @@ -1,12 +1,8 @@ -@file:OptIn(ExperimentalPathApi::class) - package dev.nolij.zumegradle.smoketest import org.gradle.api.Project import xyz.wagyourtail.unimined.util.cachingDownload import java.io.File -import java.nio.file.Files -import kotlin.io.path.* import kotlin.math.max fun sleep(millis: Long) { @@ -69,12 +65,12 @@ class SmokeTest( } private inner class Thread(val config: Config) { - val instancePath = "${workDir}/${config.name}" - val modsPath = "${instancePath}/mods" + val instancePath = File(workDir, config.name) + val modsPath = instancePath.resolve("mods") val command: Array - val setupLogFile = File("${instancePath}/setup.log") - val testLogFile = File("${instancePath}/test.log") - val gameLogFile = File("${instancePath}/logs/latest.log") + val setupLogFile = instancePath.resolve("setup.log") + val testLogFile = instancePath.resolve("test.log") + val gameLogFile = instancePath.resolve("logs/latest.log") private var process: Process? = null private var startTimestamp: Long? = null @@ -96,16 +92,13 @@ class SmokeTest( val done: Boolean get() = failed || stage == ThreadStage.COMPLETED init { - Path(instancePath).also { path -> - if (!path.exists()) - path.createDirectories() + if (!instancePath.exists()) { + instancePath.mkdirs() } - Path(modsPath).also { modsPath -> - if (modsPath.exists()) - modsPath.deleteRecursively() - modsPath.createDirectories() - } + if (modsPath.exists()) + modsPath.deleteRecursively() + modsPath.mkdirs() if (gameLogFile.exists()) gameLogFile.delete() @@ -119,10 +112,10 @@ class SmokeTest( ).resolve() + urlDeps.map { project.cachingDownload(it).toFile() } files.forEach { file -> - Files.copy(file.toPath(), Path("${modsPath}/${file.name}")) + file.copyTo(modsPath.resolve(file.name), overwrite = true) } - Files.copy(modFile.toPath(), Path("${modsPath}/${modFile.name}")) + modFile.copyTo(modsPath.resolve(modFile.name), overwrite = true) val extraArgs = mutableListOf() @@ -131,15 +124,17 @@ class SmokeTest( 21 to "java-runtime-delta", 8 to "jre-legacy" ) - if (config.jvmVersion != null) - extraArgs.add("--jvm=${mainDir}/jvm/${jvmVersionMap[config.jvmVersion]!!}/bin/java") + if (config.jvmVersion != null) { + val vmName = jvmVersionMap[config.jvmVersion] ?: error("Invalid JVM version: ${config.jvmVersion}") + extraArgs.add("--jvm=${mainDir}/jvm/${vmName}/bin/java") + } extraArgs.addAll(config.extraArgs) command = arrayOf( portableMCBinary, "--main-dir", mainDir, - "--work-dir", instancePath, + "--work-dir", instancePath.absolutePath, "start", config.versionString, *extraArgs.toTypedArray(), "--jvm-args=-DzumeGradle.auditAndExit=true -Xmx1G", From 81f0ad38cbc1aadc9cd5537540c025d6801823f2 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Thu, 7 Nov 2024 09:25:44 -0500 Subject: [PATCH 30/35] maybe this will work idk --- .github/workflows/build.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a8f3031..fbb932c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,12 +46,8 @@ jobs: with: run: ./gradlew :smokeTest --no-daemon - - name: test - if: always() - run: echo ${{ steps.smokeTest.outcome }} - - name: Upload test results - if: steps.smokeTest.outcome != 'success' + if: failure() uses: actions/upload-artifact@v4 with: name: smokeTest From 7fa1245e7a5479456eaa2864edff1eb4894e7f5a Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:49:22 -0500 Subject: [PATCH 31/35] fix log path --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fbb932c..daa0cd1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,4 +51,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: smokeTest - path: build/smokeTest/**/logs/** + path: build/smoke_test/**/logs/** From 644160488bf8da683625ad63d993384eee4430d6 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:25:29 -0500 Subject: [PATCH 32/35] upload setup logs too --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index daa0cd1..4d9c624 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,4 +51,6 @@ jobs: uses: actions/upload-artifact@v4 with: name: smokeTest - path: build/smoke_test/**/logs/** + path: | + build/smoke_test/**/logs/** + build/smoke_test/**/setup.log From 8904dc9f6d7b6c9d1a54c25f33e3efa67a66b414 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Thu, 7 Nov 2024 20:36:59 -0500 Subject: [PATCH 33/35] lazydfu! --- build.gradle.kts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 76f1265..2e36c5f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -188,6 +188,12 @@ allprojects { includeGroup("maven.modrinth") } } + exclusiveContent { + forRepository { maven("https://cursemaven.com") } + filter { + includeGroup("curse.maven") + } + } maven("https://maven.blamejared.com") maven("https://maven.taumc.org/releases") } @@ -568,14 +574,17 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { Config("fabric", "1.18.2", dependencies = setOf( "maven.modrinth:fabric-api:0.77.0+1.18.2", "maven.modrinth:modmenu:3.2.5", + "maven.modrinth:lazydfu:0.1.2", ), extraArgs = listOf("--lwjgl=3.2.3")), Config("fabric", "1.16.5", dependencies = setOf( "maven.modrinth:fabric-api:0.42.0+1.16", "maven.modrinth:modmenu:1.16.23", + "maven.modrinth:lazydfu:0.1.2", )), Config("fabric", "1.14.4", dependencies = setOf( "maven.modrinth:fabric-api:0.28.5+1.14", "maven.modrinth:modmenu:1.7.17", + "maven.modrinth:lazydfu:0.1.2", )), Config("legacyfabric", "1.12.2", dependencies = setOf( "maven.modrinth:legacy-fabric-api:1.10.2", @@ -597,9 +606,15 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { Config("neoforge", "1.20.4"), Config("forge", "1.20.4"), Config("forge", "1.20.1"), - Config("forge", "1.19.2"), - Config("forge", "1.18.2", extraArgs = listOf("--lwjgl=3.2.3")), - Config("forge", "1.16.5", extraArgs = listOf("--lwjgl=3.2.3")), + Config("forge", "1.19.2", dependencies = setOf( + "curse.maven:lazydfu-460819:4327266" + )), + Config("forge", "1.18.2", dependencies = setOf( + "curse.maven:lazuyfu-460819:3544496" + ), extraArgs = listOf("--lwjgl=3.2.3")), + Config("forge", "1.16.5", dependencies = setOf( + "curse.maven:lazydfu-460819:3249059" + ), extraArgs = listOf("--lwjgl=3.2.3")), Config("forge", "1.14.4", dependencies = setOf( "maven.modrinth:mixinbootstrap:1.1.0" ), extraArgs = listOf("--lwjgl=3.2.3")), From 88f6623b500d13e6e6bffaff177389f5d5d797a9 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Fri, 8 Nov 2024 08:49:19 -0500 Subject: [PATCH 34/35] make this one thing look nicer --- .../nolij/zumegradle/smoketest/SmokeTest.kt | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt index 6b598c4..ef4046d 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt @@ -45,7 +45,7 @@ class SmokeTest( result.appendLine("loaderVersion=${loaderVersion}") result.appendLine("jvmVersion=${jvmVersion}") result.appendLine("extraArgs=[${extraArgs.joinToString(", ")}]") - result.appendLine("mods=[${dependencies.joinToString(", ") { it.split(":")[1] }}]") + result.append("mods=[${dependencies.joinToString(", ") { it.split(":")[1] }}]") return result.toString() } @@ -235,14 +235,16 @@ class SmokeTest( if (failedThreads.isNotEmpty()) { failedThreads.forEach { thread -> - project.logger.error( - "Config ${thread.config.name} failed!\n" + - "> STAGE: ${thread.stage}\n" + - "> CONFIG: {\n${thread.config}}\n" + - "> COMMAND: [${thread.command.joinToString(", ")}]\n" + - "> FAILURE REASON: ${thread.failureReason}\n" + - "> INSTANCE PATH: ${thread.instancePath}\n" - ) + project.logger.error(listOf( + "Config ${thread.config.name} failed!", + "> STAGE: ${thread.stage}", + "> CONFIG: {", + thread.config.toString().prependIndent("\t"), + "}", + "> COMMAND: [${thread.command.joinToString(", ")}]", + "> FAILURE REASON: ${thread.failureReason}", + "> INSTANCE PATH: ${thread.instancePath}" + ).joinToString("\n")) } error("${failedThreads.size} smoke test config(s) failed. See logs for more details.") } From 07a4359f9d5db90feb622fdbd04786c83d7cedd7 Mon Sep 17 00:00:00 2001 From: Rhys <98863820+rhysdh540@users.noreply.github.com> Date: Sun, 10 Nov 2024 17:40:23 -0500 Subject: [PATCH 35/35] remove one tab and comment out smoke test for fabric 1.6.4 --- build.gradle.kts | 6 +++--- .../main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2e36c5f..a142d2a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -595,9 +595,9 @@ val smokeTest by tasks.registering(SmokeTestTask::class) { Config("legacyfabric", "1.7.10", dependencies = setOf( "maven.modrinth:legacy-fabric-api:1.10.2", )), - Config("legacyfabric", "1.6.4", dependencies = setOf( - "maven.modrinth:legacy-fabric-api:1.10.2", - )), +// Config("legacyfabric", "1.6.4", dependencies = setOf( +// "maven.modrinth:legacy-fabric-api:1.10.2", +// )), Config("babric", "b1.7.3", jvmVersion = 17, dependencies = setOf( "maven.modrinth:stationapi:2.0-alpha.2.4", ), extraArgs = listOf("--exclude-lib=asm-all")), diff --git a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt index ef4046d..8990ff3 100644 --- a/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt +++ b/buildSrc/src/main/kotlin/dev/nolij/zumegradle/smoketest/SmokeTest.kt @@ -242,7 +242,7 @@ class SmokeTest( thread.config.toString().prependIndent("\t"), "}", "> COMMAND: [${thread.command.joinToString(", ")}]", - "> FAILURE REASON: ${thread.failureReason}", + "> FAILURE REASON: ${thread.failureReason}", "> INSTANCE PATH: ${thread.instancePath}" ).joinToString("\n")) }