Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,41 @@ and then registers the `gtnhGradle` extension object which can be used to activa
`test` tests make sure that applying the plugin works correctly in a simple Gradle setup.
Bulk of the testing is done in `functionalTest` which uses [Gradle TestKit](https://docs.gradle.org/8.1.1/userguide/test_kit.html) to test entire workflows in sandboxed Gradle environments.

## Running against the complete modpack

Build and run the current mod in a full GTNH client with:

```shell
./gradlew runFullPack
```

`runFullPack` runs `prepareFullPackClient` automatically. Downloaded files are shared between projects under
`<GRADLE_USER_HOME>/caches/gtnh/fullpack`.

Private GitHub assets use the token from the `GITHUB_TOKEN` environment variable.

To test a local dependency, publish it to Maven Local:

```shell
./gradlew publishToMavenLocal
```

Then use that version in the project and enable Maven Local overrides:

```kotlin
repositories {
mavenLocal()
}

dependencies {
api("com.github.GTNewHorizons:OtherMod:1.2.3-local:dev")
}

fullPack {
preferMavenLocal.set(true)
}
```

## Updating from the previous buildscript

0. Make sure you're on the latest `master` commit and you pulled the recent repository changes ;-)
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ dependencies {
implementation("org.jdom:jdom2:2.0.6.1")
// Maven artifact for version comparison
implementation("org.apache.maven:maven-artifact:3.9.9")
// Full-pack manifest parsing
implementation("com.google.code.gson:gson:2.13.2")

// All these plugins will be present in the classpath of the project using our plugin, but not activated until explicitly applied
api(pluginDep("com.gtnewhorizons.retrofuturagradle","2.0.2"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package com.gtnewhorizons.gtnhgradle;

import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import com.gtnewhorizons.retrofuturagradle.shadow.com.google.common.collect.ImmutableMap;

class FullPackModuleFunctionalTest {

@TempDir
Path projectDirectory;

@Test
void conventionPluginRegistersFullPackTasksWithoutProjectConfiguration() throws IOException {
setupProject();

BuildResult result = createRunner("tasks", "--all").build();

assertTrue(
result.getOutput()
.contains("prepareFullPackClient"));
assertTrue(
result.getOutput()
.contains("runFullPack"));
}

@Test
void runFullPackBuildsAndPreparesTheLocalProductionJar() throws IOException {
setupProject();

BuildResult result = createRunner("runFullPack", "--dry-run", "--configuration-cache").build();

assertTrue(
result.getOutput()
.contains(":reobfJar SKIPPED"));
assertTrue(
result.getOutput()
.contains(":prepareFullPackClient SKIPPED"));
assertTrue(
result.getOutput()
.contains(":runFullPack SKIPPED"));
}

@Test
void runFullPackUsesProductionLauncherWithoutDevelopmentMixinValidation() throws IOException {
setupProject();
Files.writeString(projectDirectory.resolve("gradle.properties"), """
usesMixins = true
usesMixinDebug = true
mixinsPackage = mixin.mixins
""", StandardOpenOption.APPEND);
Files.createDirectories(projectDirectory.resolve("src/main/java/com/myname/mymodid/mixin/mixins"));
Path launcherPatch = projectDirectory.resolve("build/fullpack/lwjgl3ify-forgePatches.jar");
Files.createDirectories(launcherPatch.getParent());
Files.writeString(launcherPatch, "launcher");
Path runtimePathFile = projectDirectory.resolve("build/fullpack/client-runtime.path");
Files.createDirectories(runtimePathFile.getParent());
Files.writeString(
runtimePathFile,
projectDirectory.resolve("fake-runtime")
.toString());
Files.writeString(projectDirectory.resolve("build.gradle.kts"), """

tasks.register("verifyRunFullPackLauncher") {
doLast {
val run = tasks.named<com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask>(
"runFullPack"
).get()
check(run.lwjglVersion.get() == 3) { "runFullPack must use LWJGL 3" }
check(run.javaLauncher.get().metadata.languageVersion.asInt() == 17) {
"runFullPack must use Java 17"
}
check(
run.mainClass.get() ==
"com.gtnewhorizons.retrofuturabootstrap.MainStartOnFirstThread"
) { "runFullPack must enter through RetroFuturaBootstrap" }
check(
run.extraJvmArgs.get().contains(
"-Djava.system.class.loader=" +
"com.gtnewhorizons.retrofuturabootstrap.RfbSystemClassLoader"
)
) { "runFullPack must install the RFB system class loader" }
check(
!run.calculateJvmArgs().contains("-Dmixin.debug.countInjections=true")
) { "runFullPack must not enable development-only Mixin injection validation" }
check(
run.classpath.files.first().canonicalFile ==
file("build/fullpack/lwjgl3ify-forgePatches.jar").canonicalFile
) { "lwjgl3ify forgePatches must be first on the launch classpath" }
}
}
""", StandardOpenOption.APPEND);

BuildResult result = createRunner("verifyRunFullPackLauncher").build();

assertTrue(
result.getOutput()
.contains("BUILD SUCCESSFUL"));
}

@Test
void devDependencyIsMirroredAsAnSrgProductionArtifactWithoutAClassifier() throws IOException {
setupProject();
Files.writeString(projectDirectory.resolve("build.gradle.kts"), """

dependencies {
api("com.github.GTNewHorizons:ModularUI2:2.3.85-1.7.10:dev")
}

tasks.register("verifyFullPackProductionDependencies") {
doLast {
val production = configurations.getByName("fullPackProductionMods")
val dependency = production.dependencies.single {
it.group == "com.github.GTNewHorizons" && it.name == "ModularUI2"
} as ExternalModuleDependency
check(dependency.artifacts.isEmpty())
check(
production.attributes.getAttribute(
com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute.OBFUSCATION_ATTRIBUTE
)?.name == "srg"
)
}
}
""", StandardOpenOption.APPEND);

BuildResult result = createRunner("verifyFullPackProductionDependencies").build();

assertTrue(
result.getOutput()
.contains("BUILD SUCCESSFUL"));
}

private void setupProject() throws IOException {
Files.writeString(projectDirectory.resolve("settings.gradle.kts"), """
pluginManagement {
repositories {
maven {
name = "GTNH Maven"
url = uri("https://nexus.gtnewhorizons.com/repository/public/")
}
gradlePluginPortal()
mavenCentral()
mavenLocal()
}
}
plugins {
id("com.gtnewhorizons.gtnhsettingsconvention")
}
""");
Files.writeString(projectDirectory.resolve("build.gradle.kts"), """
plugins {
id("com.gtnewhorizons.gtnhconvention")
}
""");
Files.writeString(projectDirectory.resolve("gradle.properties"), """
modName = MyMod
modId = mymodid
modGroup = com.myname.mymodid
enableModernJavaSyntax = true
enableGenericInjection = true
""");
Files.createDirectories(projectDirectory.resolve("src/main/java/com/myname/mymodid"));
}

private GradleRunner createRunner(String... arguments) {
return GradleRunner.create()
.withEnvironment(ImmutableMap.of("VERSION", "1.0.0"))
.withArguments(arguments)
.forwardOutput()
.withPluginClasspath()
.withProjectDir(projectDirectory.toFile());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.gtnewhorizons.retrofuturagradle.shadow.com.google.common.collect.ImmutableMap;
import com.gtnewhorizons.gtnhgradle.modules.AccessTransformerModule;
import com.gtnewhorizons.gtnhgradle.modules.CodeStyleModule;
import com.gtnewhorizons.gtnhgradle.modules.FullPackModule;
import com.gtnewhorizons.gtnhgradle.modules.GitVersionModule;
import com.gtnewhorizons.gtnhgradle.modules.IdeIntegrationModule;
import com.gtnewhorizons.gtnhgradle.modules.JVMDowngraderModule;
Expand Down Expand Up @@ -101,6 +102,7 @@ public static abstract class GTNHExtension implements ExtensionAware {
GitVersionModule.class,
CodeStyleModule.class,
ToolchainModule.class,
FullPackModule.class,
ScalaModule.class,
StructureCheckModule.class,
AccessTransformerModule.class,
Expand Down
Loading