Skip to content

Commit

Permalink
Use XVFB on Linux CI, allows running the client prod tasks on a headl…
Browse files Browse the repository at this point in the history
…ess OS (#1243)
  • Loading branch information
modmuss50 authored Jan 2, 2025
1 parent 8b6658c commit 52a19b3
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ test {
maxRetries = 3
}
}

testLogging {
// Log everything to the console
setEvents(TestLogEvent.values().toList())
}
}

// Workaround https://github.com/gradle/gradle/issues/25898
Expand All @@ -283,7 +288,7 @@ tasks.withType(Test).configureEach {
}


import org.gradle.api.internal.artifacts.configurations.ConfigurationRoles
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.gradle.util.GradleVersion
import org.w3c.dom.Document
import org.w3c.dom.Element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@
*/
@ApiStatus.Experimental
public abstract non-sealed class ClientProductionRunTask extends AbstractProductionRunTask {
/**
* Whether to use XVFB to run the game, using a virtual framebuffer. This is useful for CI environments that don't have a display server.
*
* <p>Defaults to true only on Linux and when the "CI" environment variable is set.
*
* <p>XVFB must be installed, on Debian-based systems you can install it with: <code>apt install -y xvfb</code>
*/
@Input
public abstract Property<Boolean> getUseXVFB();

// Internal options
@Input
protected abstract Property<String> getAssetsIndex();
Expand All @@ -52,6 +62,11 @@ public abstract non-sealed class ClientProductionRunTask extends AbstractProduct

@Inject
public ClientProductionRunTask() {
getUseXVFB().convention(getProject().getProviders().environmentVariable("CI")
.map(value -> Platform.CURRENT.getOperatingSystem().isLinux())
.orElse(false)
);

getAssetsIndex().set(getExtension().getMinecraftVersion()
.map(minecraftVersion -> getExtension()
.getMinecraftProvider()
Expand All @@ -71,6 +86,22 @@ public ClientProductionRunTask() {
dependsOn("downloadAssets");
}

@Override
protected void configureCommand(ExecSpec exec) {
if (getUseXVFB().get()) {
if (!Platform.CURRENT.getOperatingSystem().isLinux()) {
throw new UnsupportedOperationException("XVFB is only supported on Linux");
}

exec.commandLine("/usr/bin/xvfb-run");
exec.args("-a", getJavaLauncher().get().getExecutablePath());

return;
}

super.configureCommand(exec);
}

@Override
protected void configureJvmArgs(ExecSpec exec) {
super.configureJvmArgs(exec);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@

package net.fabricmc.loom.test.integration

import java.util.concurrent.TimeUnit

import spock.lang.IgnoreIf
import spock.lang.Specification
import spock.lang.Timeout
import spock.lang.Unroll
import spock.util.environment.RestoreSystemProperties

Expand Down Expand Up @@ -157,19 +160,30 @@ class RunConfigTest extends Specification implements GradleProjectTestTrait {
version << STANDARD_TEST_VERSIONS
}
@Timeout(value = 10, unit = TimeUnit.MINUTES)
@Unroll
@IgnoreIf({ System.getenv("CI") != null }) // This test is disabled on CI because it launches a real client and cannot run headless.
@IgnoreIf({ !os.linux }) // XVFB is installed on the CI for this test
def "prod client (gradle #version)"() {
setup:
def gradle = gradleProject(project: "minimalBase", version: version)
gradle.buildGradle << '''
configurations {
productionMods
}
dependencies {
minecraft "com.mojang:minecraft:1.21.4"
mappings "net.fabricmc:yarn:1.21.4+build.4:v2"
modImplementation "net.fabricmc:fabric-loader:0.16.9"
modImplementation "net.fabricmc.fabric-api:fabric-api:0.114.0+1.21.4"
productionMods "net.fabricmc.fabric-api:fabric-api:0.114.0+1.21.4"
}
tasks.register("prodClient", net.fabricmc.loom.task.prod.ClientProductionRunTask)
tasks.register("prodClient", net.fabricmc.loom.task.prod.ClientProductionRunTask) {
mods.from(configurations.productionMods)
jvmArgs.add("-Dfabric.client.gametest")
}
'''
when:
def result = gradle.run(task: "prodClient")
Expand Down

0 comments on commit 52a19b3

Please sign in to comment.