From 14feb26f66489221f34bb3df56314ac625e6b500 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Thu, 23 Oct 2025 22:37:58 -0700 Subject: [PATCH 01/16] test matrix parallel actions --- .github/workflows/java-21-builds.yml | 5 ++++- build.gradle | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index 24fecb17aff..d45056736ac 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -11,6 +11,9 @@ jobs: build: if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" runs-on: ubuntu-latest + strategy: + matrix: + minecraft-version: [1.20.6, 1.21.3, 1.21.4, 1.21.5, 1.21.8, 1.21.10] steps: - uses: actions/checkout@v5 with: @@ -26,7 +29,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build Skript and run test scripts - run: ./gradlew clean skriptTestJava21 + run: ./gradlew clean specificTest -PtestEnv=java21/${{ matrix.minecraft-version }} -PtestEnvJavaVersion=21 - name: Upload Nightly Build uses: actions/upload-artifact@v4 if: success() diff --git a/build.gradle b/build.gradle index adff0ed54e4..603adb0d700 100644 --- a/build.gradle +++ b/build.gradle @@ -268,6 +268,7 @@ compileTestJava.options.encoding = 'UTF-8' String environments = 'src/test/skript/environments/'; int envJava = project.property('testEnvJavaVersion') == null ? latestJava : Integer.parseInt(project.property('testEnvJavaVersion') as String) createTestTask('quickTest', 'Runs tests on one environment being the latest supported Java and Minecraft.', environments + env, latestJava, 0) +createTestTask('specificTest', 'Runs tests on a specific environment defined in \'testEnv\' project property using the java version defined in the \'testEnvJavaVersion\' property.', environments + env, envJava, 0) createTestTask('skriptTestJava21', 'Runs tests on all Java 21 environments.', environments + 'java21', java21, 0) createTestTask('skriptTestJava17', 'Runs tests on all Java 17 environments.', environments + 'java17', java17, 0) createTestTask('skriptTestDev', 'Runs testing server and uses \'system.in\' for command input, stop server to finish.', environments + env, envJava, 0, Modifiers.DEV_MODE, Modifiers.DEBUG) From 678b58ff85d2ed538e6e0fd5b24bbbe6d9eb7e65 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Thu, 23 Oct 2025 22:40:43 -0700 Subject: [PATCH 02/16] Update java-21-builds.yml --- .github/workflows/java-21-builds.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index d45056736ac..cd8a0d872ab 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -29,7 +29,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build Skript and run test scripts - run: ./gradlew clean specificTest -PtestEnv=java21/${{ matrix.minecraft-version }} -PtestEnvJavaVersion=21 + run: ./gradlew clean specificTest -PtestEnv=java21/paper-${{ matrix.minecraft-version }} -PtestEnvJavaVersion=21 - name: Upload Nightly Build uses: actions/upload-artifact@v4 if: success() From d676bcb0ed9146956421d650780698cb9f707ad1 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Thu, 23 Oct 2025 22:48:38 -0700 Subject: [PATCH 03/16] Update java-21-builds.yml --- .github/workflows/java-21-builds.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index cd8a0d872ab..a5469c0c675 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -30,6 +30,10 @@ jobs: run: chmod +x gradlew - name: Build Skript and run test scripts run: ./gradlew clean specificTest -PtestEnv=java21/paper-${{ matrix.minecraft-version }} -PtestEnvJavaVersion=21 + upload: + needs: build + runs-on: ubuntu-latest + steps: - name: Upload Nightly Build uses: actions/upload-artifact@v4 if: success() From a1d593145efc4146f9f7a9c619a1bb85e2f1fe54 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 00:20:26 -0700 Subject: [PATCH 04/16] parallelize within skript instead of in actions --- .github/workflows/java-17-builds.yml | 2 +- .github/workflows/java-21-builds.yml | 9 +- .github/workflows/junit-17-builds.yml | 2 +- .github/workflows/junit-21-builds.yml | 2 +- build.gradle | 20 +-- gradle.properties | 1 + .../skript/test/platform/Environment.java | 63 ++++++++-- .../skript/test/platform/PlatformMain.java | 116 ++++++++++-------- .../runner_data/server.properties.generic | 2 +- 9 files changed, 136 insertions(+), 81 deletions(-) diff --git a/.github/workflows/java-17-builds.yml b/.github/workflows/java-17-builds.yml index 7aded923f67..37326275392 100644 --- a/.github/workflows/java-17-builds.yml +++ b/.github/workflows/java-17-builds.yml @@ -26,7 +26,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build Skript and run test scripts - run: ./gradlew clean skriptTestJava17 + run: ./gradlew clean skriptTestJava17 -PparallelTests=true - name: Upload Nightly Build uses: actions/upload-artifact@v4 if: success() diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index a5469c0c675..e29e9543895 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -11,9 +11,6 @@ jobs: build: if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" runs-on: ubuntu-latest - strategy: - matrix: - minecraft-version: [1.20.6, 1.21.3, 1.21.4, 1.21.5, 1.21.8, 1.21.10] steps: - uses: actions/checkout@v5 with: @@ -29,11 +26,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build Skript and run test scripts - run: ./gradlew clean specificTest -PtestEnv=java21/paper-${{ matrix.minecraft-version }} -PtestEnvJavaVersion=21 - upload: - needs: build - runs-on: ubuntu-latest - steps: + run: ./gradlew clean skriptTestJava21 -PparallelTests=true - name: Upload Nightly Build uses: actions/upload-artifact@v4 if: success() diff --git a/.github/workflows/junit-17-builds.yml b/.github/workflows/junit-17-builds.yml index 1b8187f1087..86e37ecbecc 100644 --- a/.github/workflows/junit-17-builds.yml +++ b/.github/workflows/junit-17-builds.yml @@ -26,4 +26,4 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build Skript and run JUnit - run: ./gradlew clean JUnitJava17 + run: ./gradlew clean JUnitJava17 -PparallelTests=true diff --git a/.github/workflows/junit-21-builds.yml b/.github/workflows/junit-21-builds.yml index 52fb32ee22f..e14f0f79752 100644 --- a/.github/workflows/junit-21-builds.yml +++ b/.github/workflows/junit-21-builds.yml @@ -26,4 +26,4 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build Skript and run JUnit - run: ./gradlew clean JUnitJava21 + run: ./gradlew clean JUnitJava21 -PparallelTests=true diff --git a/build.gradle b/build.gradle index 603adb0d700..29cb3a27cec 100644 --- a/build.gradle +++ b/build.gradle @@ -176,7 +176,7 @@ tasks.register('testNaming') { } enum Modifiers { - DEV_MODE, GEN_NIGHTLY_DOCS, GEN_RELEASE_DOCS, DEBUG, PROFILE, JUNIT + DEV_MODE, GEN_NIGHTLY_DOCS, GEN_RELEASE_DOCS, DEBUG, PROFILE, JUNIT, PARALLEL } // Create a test task with given name, environments dir/file, dev mode and java version. @@ -187,6 +187,7 @@ void createTestTask(String name, String desc, String environments, int javaVersi boolean junit = modifiers.contains(Modifiers.JUNIT) boolean releaseDocs = modifiers.contains(Modifiers.GEN_RELEASE_DOCS) boolean docs = modifiers.contains(Modifiers.GEN_NIGHTLY_DOCS) || releaseDocs + boolean parallel = modifiers.contains(Modifiers.PARALLEL) def artifact = 'build' + File.separator + 'libs' + File.separator if (junit) { artifact += 'Skript-JUnit.jar' @@ -227,7 +228,8 @@ void createTestTask(String name, String desc, String environments, int javaVersi junit, modifiers.contains(Modifiers.DEBUG), project.findProperty('verbosity') ?: "null", - timeout + timeout, + parallel ] // Do first is used when throwing exceptions. @@ -267,10 +269,13 @@ compileTestJava.options.encoding = 'UTF-8' // Register different Skript testing tasks String environments = 'src/test/skript/environments/'; int envJava = project.property('testEnvJavaVersion') == null ? latestJava : Integer.parseInt(project.property('testEnvJavaVersion') as String) + +boolean useParallelExecution = project.hasProperty('parallelTests') && project.property('parallelTests').toString().toLowerCase() == 'true' +Modifiers[] parallel = useParallelExecution ? [Modifiers.PARALLEL] as Modifiers[] : [] as Modifiers[] + createTestTask('quickTest', 'Runs tests on one environment being the latest supported Java and Minecraft.', environments + env, latestJava, 0) -createTestTask('specificTest', 'Runs tests on a specific environment defined in \'testEnv\' project property using the java version defined in the \'testEnvJavaVersion\' property.', environments + env, envJava, 0) -createTestTask('skriptTestJava21', 'Runs tests on all Java 21 environments.', environments + 'java21', java21, 0) -createTestTask('skriptTestJava17', 'Runs tests on all Java 17 environments.', environments + 'java17', java17, 0) +createTestTask('skriptTestJava21', 'Runs tests on all Java 21 environments.', environments + 'java21', java21, 0, parallel) +createTestTask('skriptTestJava17', 'Runs tests on all Java 17 environments.', environments + 'java17', java17, 0, parallel) createTestTask('skriptTestDev', 'Runs testing server and uses \'system.in\' for command input, stop server to finish.', environments + env, envJava, 0, Modifiers.DEV_MODE, Modifiers.DEBUG) createTestTask('skriptProfile', 'Starts the testing server with JProfiler support.', environments + env, latestJava, -1, Modifiers.PROFILE) createTestTask('genNightlyDocs', 'Generates the Skript documentation website html files.', environments + env, envJava, 0, Modifiers.GEN_NIGHTLY_DOCS) @@ -280,9 +285,10 @@ tasks.register('skriptTest') { dependsOn skriptTestJava17, skriptTestJava21 } +Modifiers[] junitParallel = useParallelExecution ? [Modifiers.JUNIT, Modifiers.PARALLEL] as Modifiers[] : [Modifiers.JUNIT] as Modifiers[] createTestTask('JUnitQuick', 'Runs JUnit tests on one environment being the latest supported Java and Minecraft.', environments + latestJUnitEnv, latestJUnitJava, 0, Modifiers.JUNIT) -createTestTask('JUnitJava21', 'Runs JUnit tests on all Java 21 environments.', environments + 'java21', java21, 0, Modifiers.JUNIT) -createTestTask('JUnitJava17', 'Runs JUnit tests on all Java 17 environments.', environments + 'java17', java17, 0, Modifiers.JUNIT) +createTestTask('JUnitJava21', 'Runs JUnit tests on all Java 21 environments.', environments + 'java21', java21, 0, junitParallel) +createTestTask('JUnitJava17', 'Runs JUnit tests on all Java 17 environments.', environments + 'java17', java17, 0, junitParallel) tasks.register('JUnit') { description = 'Runs JUnit tests on all environments.' dependsOn JUnitJava17, JUnitJava21 diff --git a/gradle.properties b/gradle.properties index eb770b2f5e5..92bc49dcea5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,3 +9,4 @@ version=2.13.0 jarName=Skript.jar testEnv=java21/paper-1.21.10 testEnvJavaVersion=21 +parallelTests=true diff --git a/src/main/java/ch/njol/skript/test/platform/Environment.java b/src/main/java/ch/njol/skript/test/platform/Environment.java index 7588bbd2122..2331776e7c1 100644 --- a/src/main/java/ch/njol/skript/test/platform/Environment.java +++ b/src/main/java/ch/njol/skript/test/platform/Environment.java @@ -5,10 +5,7 @@ import com.google.gson.JsonObject; import org.jetbrains.annotations.Nullable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.lang.ProcessBuilder.Redirect; import java.net.URI; import java.net.URISyntaxException; @@ -21,12 +18,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; +import java.util.*; /** * Test environment information. @@ -158,7 +150,7 @@ public String getName() { return name; } - public void initialize(Path dataRoot, Path runnerRoot, boolean remake) throws IOException { + public void initialize(Path dataRoot, Path runnerRoot, boolean remake, int parallelPort) throws IOException { Path env = runnerRoot.resolve(name); boolean onlyCopySkript = Files.exists(env) && !remake; @@ -181,6 +173,21 @@ public void initialize(Path dataRoot, Path runnerRoot, boolean remake) throws IO Path source = dataRoot.resolve(resource.getSource()); Path target = env.resolve(resource.getTarget()); Files.createDirectories(target.getParent()); + // Copy file, but if the resource is server.properties, modify it to use a different port for parallel tests + if (resource.getTarget().endsWith("server.properties") && parallelPort > 0) { + List lines = Files.readAllLines(source, StandardCharsets.UTF_8); + List modifiedLines = new ArrayList<>(); + for (String line : lines) { + if (line.startsWith("server-port=")) { + modifiedLines.add("server-port=" + parallelPort); + } else { + modifiedLines.add(line); + } + } + Files.write(target, modifiedLines, StandardCharsets.UTF_8); + continue; + } + // normal copy Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING); } @@ -232,8 +239,8 @@ public TestResults runTests(Path runnerRoot, Path testsRoot, boolean devMode, bo Process process = new ProcessBuilder(args) .directory(env.toFile()) - .redirectOutput(Redirect.INHERIT) - .redirectError(Redirect.INHERIT) +// .redirectOutput(Redirect.INHERIT) +// .redirectError(Redirect.INHERIT) .redirectInput(Redirect.INHERIT) .start(); @@ -253,7 +260,37 @@ public void run() { }, timeout); } + // Create threads to read and prefix the output + Thread outThread = new Thread(() -> { + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println("[" + this.getName() + "] " + line); + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + + Thread errThread = new Thread(() -> { + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.err.println("[" + this.getName() + "] " + line); + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + + outThread.start(); + errThread.start(); + int code = process.waitFor(); + outThread.join(); + errThread.join(); if (code != 0) throw new IOException("environment returned with code " + code); diff --git a/src/main/java/ch/njol/skript/test/platform/PlatformMain.java b/src/main/java/ch/njol/skript/test/platform/PlatformMain.java index 744caa675b3..adf31a339b5 100644 --- a/src/main/java/ch/njol/skript/test/platform/PlatformMain.java +++ b/src/main/java/ch/njol/skript/test/platform/PlatformMain.java @@ -1,7 +1,6 @@ package ch.njol.skript.test.platform; import ch.njol.skript.test.utils.TestResults; -import ch.njol.util.NonNullPair; import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -9,20 +8,11 @@ import org.apache.commons.lang.StringUtils; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; /** @@ -36,13 +26,9 @@ public static void main(String... args) throws IOException, InterruptedException Gson gson = new GsonBuilder().setPrettyPrinting().create(); Path runnerRoot = Paths.get(args[0]); - assert runnerRoot != null; Path testsRoot = Paths.get(args[1]).toAbsolutePath(); - assert testsRoot != null; Path dataRoot = Paths.get(args[2]); - assert dataRoot != null; Path envsRoot = Paths.get(args[3]); - assert envsRoot != null; boolean devMode = "true".equals(args[4]); boolean genDocs = "true".equals(args[5]); boolean jUnit = "true".equals(args[6]); @@ -51,7 +37,8 @@ public static void main(String... args) throws IOException, InterruptedException long timeout = Long.parseLong(args[9]); if (timeout < 0) timeout = 0; - Set jvmArgs = Sets.newHashSet(Arrays.copyOfRange(args, 10, args.length)); + boolean parallel = "true".equals(args[10]); + Set jvmArgs = Sets.newHashSet(Arrays.copyOfRange(args, 11, args.length)); if (jvmArgs.stream().noneMatch(arg -> arg.contains("-Xmx"))) jvmArgs.add("-Xmx5G"); @@ -61,48 +48,79 @@ public static void main(String... args) throws IOException, InterruptedException envs = Files.walk(envsRoot).filter(path -> !Files.isDirectory(path)) .map(path -> { try { - return gson.fromJson(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), Environment.class); + return gson.fromJson(Files.readString(path), Environment.class); } catch (JsonSyntaxException | IOException e) { throw new RuntimeException(e); } }).collect(Collectors.toList()); } else { - envs = Collections.singletonList(gson.fromJson(new String( - Files.readAllBytes(envsRoot),StandardCharsets.UTF_8), Environment.class)); + envs = Collections.singletonList(gson.fromJson(Files.readString(envsRoot), Environment.class)); } - System.out.println("Test environments: " + String.join(", ", - envs.stream().map(Environment::getName).collect(Collectors.toList()))); + System.out.println("Test environments: " + envs.stream().map(Environment::getName).collect(Collectors.joining(", "))); Set allTests = new HashSet<>(); - Map>> failures = new HashMap<>(); + Map> failures = new HashMap<>(); boolean docsFailed = false; // Run tests and collect the results envs.sort(Comparator.comparing(Environment::getName)); + int parallelPort = 25600; // Port to start from for parallel tests, so the servers don't clash + long finalTimeout = timeout; + List tasks = new ArrayList<>(); + Map collectedResults = Collections.synchronizedMap(new HashMap<>()); for (Environment env : envs) { - System.out.println("Starting testing on " + env.getName()); - env.initialize(dataRoot, runnerRoot, false); - TestResults results = env.runTests(runnerRoot, testsRoot, devMode, genDocs, jUnit, debug, verbosity, timeout, jvmArgs); - if (results == null) { - if (devMode) { - // Nothing to report, it's the dev mode environment. - System.exit(0); - return; + int finalParallelPort = parallelPort; + tasks.add(() -> { + try { + System.out.println("Starting testing on " + env.getName()); + env.initialize(dataRoot, runnerRoot, false, finalParallelPort); + TestResults results = env.runTests(runnerRoot, testsRoot, devMode, genDocs, jUnit, debug, verbosity, finalTimeout, jvmArgs); + if (results == null) { + if (devMode) { + // Nothing to report, it's the dev mode environment. + System.exit(0); + return; + } + System.err.println("The test environment '" + env.getName() + "' failed to produce test results."); + System.exit(3); + return; + } + collectedResults.put(env, results); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); } - System.err.println("The test environment '" + env.getName() + "' failed to produce test results."); - System.exit(3); - return; + }); + if (parallel) { + parallelPort += 1; // Increment port for next environment } - - // Collect results - docsFailed = results.docsFailed(); + } + + // Execute tasks either in parallel or sequentially + if (parallel) { + List> futures = new ArrayList<>(); + for (Runnable task : tasks) { + futures.add(CompletableFuture.runAsync(task)); + } + // Wait for all to complete + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); + } else { + for (Runnable task : tasks) { + task.run(); + } + } + + // Process collected results + for (var entry : collectedResults.entrySet()) { + TestResults results = entry.getValue(); + Environment env = entry.getKey(); + docsFailed |= results.docsFailed(); allTests.addAll(results.getSucceeded()); allTests.addAll(results.getFailed().keySet()); for (Map.Entry fail : results.getFailed().entrySet()) { String error = fail.getValue(); assert error != null; failures.computeIfAbsent(fail.getKey(), (k) -> new ArrayList<>()) - .add(new NonNullPair<>(env, error)); + .add(new TestError(env, error)); } } @@ -119,33 +137,33 @@ public static void main(String... args) throws IOException, InterruptedException } // Sort results in alphabetical order - List succeeded = allTests.stream().filter(name -> !failures.containsKey(name)).collect(Collectors.toList()); - Collections.sort(succeeded); + List succeeded = allTests.stream().filter(name -> !failures.containsKey(name)).sorted().collect(Collectors.toList()); List failNames = new ArrayList<>(failures.keySet()); Collections.sort(failNames); // All succeeded tests in a single line StringBuilder output = new StringBuilder(String.format("%s Results %s%n", StringUtils.repeat("-", 25), StringUtils.repeat("-", 25))); - output.append("\nTested environments: " + String.join(", ", - envs.stream().map(Environment::getName).collect(Collectors.toList()))); - output.append("\nSucceeded:\n " + String.join((jUnit ? "\n " : ", "), succeeded)); + output.append("\nTested environments: ").append(envs.stream().map(Environment::getName).collect(Collectors.joining(", "))); + output.append("\nSucceeded:\n ").append(String.join((jUnit ? "\n " : ", "), succeeded)); if (!failNames.isEmpty()) { // More space for failed tests, they're important output.append("\nFailed:"); for (String failed : failNames) { - List> errors = failures.get(failed); - output.append("\n " + failed + " (on " + errors.size() + " environment" + (errors.size() == 1 ? "" : "s") + ")"); - for (NonNullPair error : errors) { - output.append("\n " + error.getSecond() + " (on " + error.getFirst().getName() + ")"); + List errors = failures.get(failed); + output.append("\n ").append(failed).append(" (on ").append(errors.size()).append(" environment").append(errors.size() == 1 ? "" : "s").append(")"); + for (TestError error : errors) { + output.append("\n ").append(error.message()).append(" (on ").append(error.environment().getName()).append(")"); } } output.append(String.format("%n%n%s", StringUtils.repeat("-", 60))); - System.err.print(output.toString()); + System.err.print(output); System.exit(failNames.size()); // Error code to indicate how many tests failed. return; } output.append(String.format("%n%n%s", StringUtils.repeat("-", 60))); - System.out.print(output.toString()); + System.out.print(output); } + private record TestError(Environment environment, String message) { } + } diff --git a/src/test/resources/runner_data/server.properties.generic b/src/test/resources/runner_data/server.properties.generic index 84816088740..a32881f64d2 100644 --- a/src/test/resources/runner_data/server.properties.generic +++ b/src/test/resources/runner_data/server.properties.generic @@ -42,4 +42,4 @@ resource-pack-sha1= spawn-protection=0 online-mode=true allow-flight=false -max-world-size=29999984 \ No newline at end of file +max-world-size=29999984 From 6607965e9d0e79afe7fded1e99c5cbf28b3e83f1 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 14:20:42 -0700 Subject: [PATCH 05/16] disable parallel runs --- build.gradle | 13 ++++--------- gradle.properties | 1 - 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 29cb3a27cec..9873cc3823c 100644 --- a/build.gradle +++ b/build.gradle @@ -269,13 +269,9 @@ compileTestJava.options.encoding = 'UTF-8' // Register different Skript testing tasks String environments = 'src/test/skript/environments/'; int envJava = project.property('testEnvJavaVersion') == null ? latestJava : Integer.parseInt(project.property('testEnvJavaVersion') as String) - -boolean useParallelExecution = project.hasProperty('parallelTests') && project.property('parallelTests').toString().toLowerCase() == 'true' -Modifiers[] parallel = useParallelExecution ? [Modifiers.PARALLEL] as Modifiers[] : [] as Modifiers[] - createTestTask('quickTest', 'Runs tests on one environment being the latest supported Java and Minecraft.', environments + env, latestJava, 0) -createTestTask('skriptTestJava21', 'Runs tests on all Java 21 environments.', environments + 'java21', java21, 0, parallel) -createTestTask('skriptTestJava17', 'Runs tests on all Java 17 environments.', environments + 'java17', java17, 0, parallel) +createTestTask('skriptTestJava21', 'Runs tests on all Java 21 environments.', environments + 'java21', java21, 0) +createTestTask('skriptTestJava17', 'Runs tests on all Java 17 environments.', environments + 'java17', java17, 0) createTestTask('skriptTestDev', 'Runs testing server and uses \'system.in\' for command input, stop server to finish.', environments + env, envJava, 0, Modifiers.DEV_MODE, Modifiers.DEBUG) createTestTask('skriptProfile', 'Starts the testing server with JProfiler support.', environments + env, latestJava, -1, Modifiers.PROFILE) createTestTask('genNightlyDocs', 'Generates the Skript documentation website html files.', environments + env, envJava, 0, Modifiers.GEN_NIGHTLY_DOCS) @@ -285,10 +281,9 @@ tasks.register('skriptTest') { dependsOn skriptTestJava17, skriptTestJava21 } -Modifiers[] junitParallel = useParallelExecution ? [Modifiers.JUNIT, Modifiers.PARALLEL] as Modifiers[] : [Modifiers.JUNIT] as Modifiers[] createTestTask('JUnitQuick', 'Runs JUnit tests on one environment being the latest supported Java and Minecraft.', environments + latestJUnitEnv, latestJUnitJava, 0, Modifiers.JUNIT) -createTestTask('JUnitJava21', 'Runs JUnit tests on all Java 21 environments.', environments + 'java21', java21, 0, junitParallel) -createTestTask('JUnitJava17', 'Runs JUnit tests on all Java 17 environments.', environments + 'java17', java17, 0, junitParallel) +createTestTask('JUnitJava21', 'Runs JUnit tests on all Java 21 environments.', environments + 'java21', java21, 0, Modifiers.JUNIT) +createTestTask('JUnitJava17', 'Runs JUnit tests on all Java 17 environments.', environments + 'java17', java17, 0, Modifiers.JUNIT) tasks.register('JUnit') { description = 'Runs JUnit tests on all environments.' dependsOn JUnitJava17, JUnitJava21 diff --git a/gradle.properties b/gradle.properties index 92bc49dcea5..eb770b2f5e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,4 +9,3 @@ version=2.13.0 jarName=Skript.jar testEnv=java21/paper-1.21.10 testEnvJavaVersion=21 -parallelTests=true From 0650abd618e0077beb80caf044e811a1ec8c726e Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:07:20 -0700 Subject: [PATCH 06/16] test customTest balancing --- .github/workflows/java-21-builds.yml | 70 ++++++++++++++++--- build.gradle | 30 +++++++- .../skript/test/platform/PlatformMain.java | 24 +++++-- 3 files changed, 107 insertions(+), 17 deletions(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index e29e9543895..cabcb76a380 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -8,13 +8,65 @@ on: pull_request: jobs: - build: + prepare: if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.split.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + + - name: Split environments into balanced groups + id: split + run: | + # This code was primarily generated by Claude AI. Beware of potential mistakes. - sovde + # Number of parallel jobs + N=3 + + # Find all JSON files in environments directory + files=$(find environments -name "*.json" -type f | sort) + mapfile -t file_array <<< "$files" + total=${#file_array[@]} + + # Calculate items per group (round up) + per_group=$(( (total + N - 1) / N )) + + # Build JSON matrix + matrix_json='{"include":[' + for i in $(seq 0 $((N - 1))); do + start=$((i * per_group)) + end=$((start + per_group)) + + # Get slice of files for this group + group_files=$(printf '%s\n' "${file_array[@]:$start:$per_group}" | jq -R . | jq -s -c .) + + if [ $i -gt 0 ]; then + matrix_json+="," + fi + matrix_json+="{\"group\":$((i + 1)),\"files\":$group_files}" + done + + matrix_json+=']}' + + echo "matrix=$matrix_json" >> $GITHUB_OUTPUT + echo "Generated matrix:" + echo "$matrix_json" | jq . + + build: + needs: prepare + runs-on: ubuntu-latest + strategy: + matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} steps: - uses: actions/checkout@v5 with: submodules: recursive + + - name: Display group info + run: | + echo "Processing Group ${{ matrix.group }}" + echo "Files in this group:" + echo '${{ toJSON(matrix.files) }}' | jq -r '.[]' - name: validate gradle wrapper uses: gradle/actions/wrapper-validation@v4 - name: Set up JDK 21 @@ -25,11 +77,11 @@ jobs: cache: gradle - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Build Skript and run test scripts - run: ./gradlew clean skriptTestJava21 -PparallelTests=true - - name: Upload Nightly Build - uses: actions/upload-artifact@v4 - if: success() - with: - name: skript-nightly - path: build/libs/* +# - name: Build Skript and run test scripts +# run: ./gradlew clean skriptTestJava21 -PparallelTests=true +# - name: Upload Nightly Build +# uses: actions/upload-artifact@v4 +# if: success() +# with: +# name: skript-nightly +# path: build/libs/* diff --git a/build.gradle b/build.gradle index 9873cc3823c..56070bc9968 100644 --- a/build.gradle +++ b/build.gradle @@ -267,7 +267,7 @@ compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' // Register different Skript testing tasks -String environments = 'src/test/skript/environments/'; +String environments = 'src/test/skript/environments/' int envJava = project.property('testEnvJavaVersion') == null ? latestJava : Integer.parseInt(project.property('testEnvJavaVersion') as String) createTestTask('quickTest', 'Runs tests on one environment being the latest supported Java and Minecraft.', environments + env, latestJava, 0) createTestTask('skriptTestJava21', 'Runs tests on all Java 21 environments.', environments + 'java21', java21, 0) @@ -289,6 +289,34 @@ tasks.register('JUnit') { dependsOn JUnitJava17, JUnitJava21 } +// custom test task +// usage: gradle customTest -PtestEnvs= -PtestEnvJavaVersion= -Ptimeout= -Pjunit=[true|false] -Pparallel=[true|false] +// defaults: testEnvJavaVersion=latestJava, timeout=0, junit=false, parallel=false +// example: gradle customTest -PtestEnvs=java21/1.21.4,java21/1.21.6 -PtestEnvJavaVersion=21 -Ptimeout=600000 -Pjunit=true -Pparallel=true + +// get environments +String propEnvs = project.hasProperty('testEnvs') ? project.property('testEnvs') as String : project.testEnv +String[] envList = propEnvs != null ? propEnvs.split(',') : [env] +StringBuilder customEnvironmentsBuilder = new StringBuilder() +for (int i = 0; i < envList.length; i++) { + customEnvironmentsBuilder.append(environments).append(envList[i]).append('.json') + if (i < envList.length - 1) { + customEnvironmentsBuilder.append(',') // use ',' as separator for multiple environments + } +} +String customEnvironments = customEnvironmentsBuilder.toString() + +long customTimeout = project.hasProperty('timeout') ? Long.parseLong(project.property('timeout') as String) : 0 +List customModifiers = new ArrayList<>() +if (project.hasProperty('junit') && (project.property('junit') as String).toLowerCase() == 'true') { + customModifiers.add(Modifiers.JUNIT) +} +if (project.hasProperty('parallel') && (project.property('parallel') as String).toLowerCase() == 'true') { + customModifiers.add(Modifiers.PARALLEL) +} +createTestTask('customTest', 'Runs tests based on provided parameters.', customEnvironments, envJava, customTimeout, customModifiers.toArray(new Modifiers[0]) as Modifiers[]) + + // Build flavor configurations task githubResources(type: ProcessResources) { from 'src/main/resources', { diff --git a/src/main/java/ch/njol/skript/test/platform/PlatformMain.java b/src/main/java/ch/njol/skript/test/platform/PlatformMain.java index adf31a339b5..d52b20fb3e7 100644 --- a/src/main/java/ch/njol/skript/test/platform/PlatformMain.java +++ b/src/main/java/ch/njol/skript/test/platform/PlatformMain.java @@ -28,7 +28,14 @@ public static void main(String... args) throws IOException, InterruptedException Path runnerRoot = Paths.get(args[0]); Path testsRoot = Paths.get(args[1]).toAbsolutePath(); Path dataRoot = Paths.get(args[2]); - Path envsRoot = Paths.get(args[3]); + // allow multiple environments separated by commas + List envPaths = new ArrayList<>(); + String envsArg = args[3]; + envsArg = envsArg.trim(); + String[] envPathStrings = envsArg.split(","); + for (String envPath : envPathStrings) { + envPaths.add(Paths.get(envPath.trim())); + } boolean devMode = "true".equals(args[4]); boolean genDocs = "true".equals(args[5]); boolean jUnit = "true".equals(args[6]); @@ -43,19 +50,22 @@ public static void main(String... args) throws IOException, InterruptedException jvmArgs.add("-Xmx5G"); // Load environments - List envs; - if (Files.isDirectory(envsRoot)) { - envs = Files.walk(envsRoot).filter(path -> !Files.isDirectory(path)) + List envs = new ArrayList<>(); + for (Path envPath : envPaths) { + if (Files.isDirectory(envPath)) { + envs.addAll(Files.walk(envPath).filter(path -> !Files.isDirectory(path)) .map(path -> { try { return gson.fromJson(Files.readString(path), Environment.class); } catch (JsonSyntaxException | IOException e) { throw new RuntimeException(e); } - }).collect(Collectors.toList()); - } else { - envs = Collections.singletonList(gson.fromJson(Files.readString(envsRoot), Environment.class)); + }).toList()); + } else { + envs.add(gson.fromJson(Files.readString(envPath), Environment.class)); + } } + System.out.println("Test environments: " + envs.stream().map(Environment::getName).collect(Collectors.joining(", "))); Set allTests = new HashSet<>(); From a6313a4bc122d569856ee5f0dbc9600155a55644 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:19:53 -0700 Subject: [PATCH 07/16] testing some ai ideas don't have high hopes --- .github/workflows/java-21-builds.yml | 106 ++++++++++++++------------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index cabcb76a380..c3c488466aa 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -7,50 +7,60 @@ on: - 'dev/**' pull_request: +# environments = 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 + jobs: prepare: if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" runs-on: ubuntu-latest outputs: - matrix: ${{ steps.split.outputs.matrix }} + matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - - uses: actions/checkout@v4 - - - name: Split environments into balanced groups - id: split + - name: Generate matrix + id: set-matrix run: | - # This code was primarily generated by Claude AI. Beware of potential mistakes. - sovde - # Number of parallel jobs - N=3 - - # Find all JSON files in environments directory - files=$(find environments -name "*.json" -type f | sort) - mapfile -t file_array <<< "$files" - total=${#file_array[@]} - - # Calculate items per group (round up) - per_group=$(( (total + N - 1) / N )) - - # Build JSON matrix - matrix_json='{"include":[' - for i in $(seq 0 $((N - 1))); do - start=$((i * per_group)) - end=$((start + per_group)) - - # Get slice of files for this group - group_files=$(printf '%s\n' "${file_array[@]:$start:$per_group}" | jq -R . | jq -s -c .) - - if [ $i -gt 0 ]; then - matrix_json+="," - fi - matrix_json+="{\"group\":$((i + 1)),\"files\":$group_files}" - done - - matrix_json+=']}' - - echo "matrix=$matrix_json" >> $GITHUB_OUTPUT - echo "Generated matrix:" - echo "$matrix_json" | jq . + # Define environments and number of splits + ENVIRONMENTS="1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10" + N=3 # Change this to your desired number of parallel jobs + + # Convert to array + IFS=',' read -ra ENVS <<< "$ENVIRONMENTS" + TOTAL=${#ENVS[@]} + + # Calculate actual number of jobs (min of N and total environments) + JOBS=$((TOTAL < N ? TOTAL : N)) + + # Calculate environments per job + BASE=$((TOTAL / JOBS)) + EXTRA=$((TOTAL % JOBS)) + + # Build matrix JSON + MATRIX="[" + INDEX=0 + for ((i=0; i> $GITHUB_OUTPUT + echo "Generated matrix: {\"include\":$MATRIX}" build: needs: prepare @@ -61,12 +71,6 @@ jobs: - uses: actions/checkout@v5 with: submodules: recursive - - - name: Display group info - run: | - echo "Processing Group ${{ matrix.group }}" - echo "Files in this group:" - echo '${{ toJSON(matrix.files) }}' | jq -r '.[]' - name: validate gradle wrapper uses: gradle/actions/wrapper-validation@v4 - name: Set up JDK 21 @@ -77,11 +81,11 @@ jobs: cache: gradle - name: Grant execute permission for gradlew run: chmod +x gradlew -# - name: Build Skript and run test scripts -# run: ./gradlew clean skriptTestJava21 -PparallelTests=true -# - name: Upload Nightly Build -# uses: actions/upload-artifact@v4 -# if: success() -# with: -# name: skript-nightly -# path: build/libs/* + - name: Build Skript and run test scripts + run: ./gradlew clean customTest -PtestEnvs="${{ matrix.envs }}" -PtestEnvJavaVersion=21 + - name: Upload Nightly Build + uses: actions/upload-artifact@v4 + if: success() + with: + name: skript-nightly-${{ matrix.id }} + path: build/libs/* From c1b9024b9f1b9b1455477c58e5a27f91395bc13e Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:29:58 -0700 Subject: [PATCH 08/16] Update java-21-builds.yml --- .github/workflows/java-21-builds.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index c3c488466aa..59f06b8521d 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -22,10 +22,16 @@ jobs: # Define environments and number of splits ENVIRONMENTS="1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10" N=3 # Change this to your desired number of parallel jobs + JAVA_VERSION=21 # Java version for the transformation - # Convert to array + # Convert to array and transform IFS=',' read -ra ENVS <<< "$ENVIRONMENTS" - TOTAL=${#ENVS[@]} + TRANSFORMED=() + for env in "${ENVS[@]}"; do + TRANSFORMED+=("java${JAVA_VERSION}/paper-${env}") + done + + TOTAL=${#TRANSFORMED[@]} # Calculate actual number of jobs (min of N and total environments) JOBS=$((TOTAL < N ? TOTAL : N)) @@ -48,7 +54,7 @@ jobs: if [ -n "$GROUP" ]; then GROUP="$GROUP," fi - GROUP="$GROUP${ENVS[$INDEX]}" + GROUP="$GROUP${TRANSFORMED[$INDEX]}" INDEX=$((INDEX + 1)) done From 28008cc192eed856616fa4f85823a54ecfd2027f Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:42:09 -0700 Subject: [PATCH 09/16] readability improvements, only one artifact --- .github/workflows/java-21-builds.yml | 42 ++++++++++++++++++---------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index 59f06b8521d..f738afc1109 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -7,10 +7,14 @@ on: - 'dev/**' pull_request: -# environments = 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 +env: + ENVIRONMENTS: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 + PARALLEL_JOBS: 3 + JAVA_VERSION: 21 jobs: prepare: + name: Java ${{ env.JAVA_VERSION }} CI - Parallelize Tests if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" runs-on: ubuntu-latest outputs: @@ -19,13 +23,12 @@ jobs: - name: Generate matrix id: set-matrix run: | - # Define environments and number of splits - ENVIRONMENTS="1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10" - N=3 # Change this to your desired number of parallel jobs - JAVA_VERSION=21 # Java version for the transformation + # Use environment variables + N=${{ env.PARALLEL_JOBS }} + JAVA_VERSION=${{ env.JAVA_VERSION }} # Convert to array and transform - IFS=',' read -ra ENVS <<< "$ENVIRONMENTS" + IFS=',' read -ra ENVS <<< "${{ env.ENVIRONMENTS }}" TRANSFORMED=() for env in "${ENVS[@]}"; do TRANSFORMED+=("java${JAVA_VERSION}/paper-${env}") @@ -33,35 +36,43 @@ jobs: TOTAL=${#TRANSFORMED[@]} - # Calculate actual number of jobs (min of N and total environments) + # avoid creating more jobs than needed JOBS=$((TOTAL < N ? TOTAL : N)) - - # Calculate environments per job + # environments per job BASE=$((TOTAL / JOBS)) EXTRA=$((TOTAL % JOBS)) # Build matrix JSON + # Format is: + # [{"id":1,"envs":"java21/paper-1.20.6,java21/paper-1.21.3","display":"1.20.6, 1.21.3"},...] + # Where "envs" is the actual environment strings and "display" is for easier identification MATRIX="[" INDEX=0 for ((i=0; i Date: Fri, 24 Oct 2025 15:51:14 -0700 Subject: [PATCH 10/16] pull out the parallelization task --- .github/workflows/java-21-builds.yml | 76 +++------------------ .github/workflows/parallelize-tests.yml | 87 +++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 68 deletions(-) create mode 100644 .github/workflows/parallelize-tests.yml diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index f738afc1109..63252133a7a 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -7,84 +7,24 @@ on: - 'dev/**' pull_request: -env: - ENVIRONMENTS: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 - PARALLEL_JOBS: 3 - JAVA_VERSION: 21 - jobs: prepare: name: Java ${{ env.JAVA_VERSION }} CI - Parallelize Tests if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - - name: Generate matrix - id: set-matrix - run: | - # Use environment variables - N=${{ env.PARALLEL_JOBS }} - JAVA_VERSION=${{ env.JAVA_VERSION }} - - # Convert to array and transform - IFS=',' read -ra ENVS <<< "${{ env.ENVIRONMENTS }}" - TRANSFORMED=() - for env in "${ENVS[@]}"; do - TRANSFORMED+=("java${JAVA_VERSION}/paper-${env}") - done - - TOTAL=${#TRANSFORMED[@]} - - # avoid creating more jobs than needed - JOBS=$((TOTAL < N ? TOTAL : N)) - # environments per job - BASE=$((TOTAL / JOBS)) - EXTRA=$((TOTAL % JOBS)) - - # Build matrix JSON - # Format is: - # [{"id":1,"envs":"java21/paper-1.20.6,java21/paper-1.21.3","display":"1.20.6, 1.21.3"},...] - # Where "envs" is the actual environment strings and "display" is for easier identification - MATRIX="[" - INDEX=0 - for ((i=0; i> $GITHUB_OUTPUT - echo "Generated matrix: {\"include\":$MATRIX}" + uses: ./.github/workflows/parallelize-tests.yml + with: + environments: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 + parallel_jobs: 3 + java_version: 21 build: - name: Java ${{ env.JAVA_VERSION }} CI (${{ matrix.display }}) + name: Java ${{ needs.prepare.outputs.java_version }} CI (${{ matrix.display }}) needs: prepare runs-on: ubuntu-latest strategy: matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} + env: + JAVA_VERSION: ${{ needs.prepare.outputs.java_version }} steps: - uses: actions/checkout@v5 with: diff --git a/.github/workflows/parallelize-tests.yml b/.github/workflows/parallelize-tests.yml new file mode 100644 index 00000000000..5a8642f165a --- /dev/null +++ b/.github/workflows/parallelize-tests.yml @@ -0,0 +1,87 @@ +name: Parallelize Tests + +on: + workflow_call: + inputs: + environments: + required: true + type: string + parallel_jobs: + required: true + type: number + java_version: + required: true + type: number + outputs: + matrix: + description: "Generated test matrix" + value: ${{ jobs.prepare.outputs.matrix }} + java_version: + description: "Java version passed through" + value: ${{ jobs.prepare.outputs.java_version }} + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + java_version: ${{ inputs.java_version }} + steps: + - name: Generate matrix + id: set-matrix + run: | + # Use environment variables + N=${{ inputs.parallel_jobs }} + JAVA_VERSION=${{ inputs.java_version }} + + # Convert to array and transform + IFS=',' read -ra ENVS <<< "${{ inputs.environments }}" + TRANSFORMED=() + for env in "${ENVS[@]}"; do + TRANSFORMED+=("java${JAVA_VERSION}/paper-${env}") + done + + TOTAL=${#TRANSFORMED[@]} + + # avoid creating more jobs than needed + JOBS=$((TOTAL < N ? TOTAL : N)) + # environments per job + BASE=$((TOTAL / JOBS)) + EXTRA=$((TOTAL % JOBS)) + + # Build matrix JSON + # Format is: + # [{"id":1,"envs":"java21/paper-1.20.6,java21/paper-1.21.3","display":"1.20.6, 1.21.3"},...] + # Where "envs" is the actual environment strings and "display" is for easier identification + MATRIX="[" + INDEX=0 + for ((i=0; i> $GITHUB_OUTPUT + echo "Generated matrix: {\"include\":$MATRIX}" From 2b3230994e242d777522d942c73605362e7f7944 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:54:30 -0700 Subject: [PATCH 11/16] back to env vars --- .github/workflows/java-21-builds.yml | 15 +++++++++------ .github/workflows/parallelize-tests.yml | 4 ---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index 63252133a7a..ec9cd469b30 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -7,24 +7,27 @@ on: - 'dev/**' pull_request: +env: + ENVIRONMENTS: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 + PARALLEL_JOBS: 3 + JAVA_VERSION: 21 + jobs: prepare: name: Java ${{ env.JAVA_VERSION }} CI - Parallelize Tests if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" uses: ./.github/workflows/parallelize-tests.yml with: - environments: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 - parallel_jobs: 3 - java_version: 21 + environments: ${{ env.ENVIRONMENTS }} + parallel_jobs: ${{ env.PARALLEL_JOBS }} + java_version: ${{ env.JAVA_VERSION }} build: - name: Java ${{ needs.prepare.outputs.java_version }} CI (${{ matrix.display }}) + name: Java ${{ env.JAVA_VERSION }} CI (${{ matrix.display }}) needs: prepare runs-on: ubuntu-latest strategy: matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} - env: - JAVA_VERSION: ${{ needs.prepare.outputs.java_version }} steps: - uses: actions/checkout@v5 with: diff --git a/.github/workflows/parallelize-tests.yml b/.github/workflows/parallelize-tests.yml index 5a8642f165a..16cd6b9d692 100644 --- a/.github/workflows/parallelize-tests.yml +++ b/.github/workflows/parallelize-tests.yml @@ -16,16 +16,12 @@ on: matrix: description: "Generated test matrix" value: ${{ jobs.prepare.outputs.matrix }} - java_version: - description: "Java version passed through" - value: ${{ jobs.prepare.outputs.java_version }} jobs: prepare: runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} - java_version: ${{ inputs.java_version }} steps: - name: Generate matrix id: set-matrix From 1fb3fdd98a4be0ddceb7bde2e0adb11e7431229b Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:56:49 -0700 Subject: [PATCH 12/16] give up on java version --- .github/workflows/java-21-builds.yml | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index ec9cd469b30..e67f8069299 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -7,23 +7,18 @@ on: - 'dev/**' pull_request: -env: - ENVIRONMENTS: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 - PARALLEL_JOBS: 3 - JAVA_VERSION: 21 - jobs: prepare: - name: Java ${{ env.JAVA_VERSION }} CI - Parallelize Tests + name: Java 21 CI - Parallelize Tests if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" uses: ./.github/workflows/parallelize-tests.yml with: - environments: ${{ env.ENVIRONMENTS }} - parallel_jobs: ${{ env.PARALLEL_JOBS }} - java_version: ${{ env.JAVA_VERSION }} + environments: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 + parallel_jobs: 3 + java_version: 21 build: - name: Java ${{ env.JAVA_VERSION }} CI (${{ matrix.display }}) + name: Java 21 CI (${{ matrix.display }}) needs: prepare runs-on: ubuntu-latest strategy: @@ -34,16 +29,16 @@ jobs: submodules: recursive - name: validate gradle wrapper uses: gradle/actions/wrapper-validation@v4 - - name: Set up JDK ${{ env.JAVA_VERSION }} + - name: Set up JDK 21 uses: actions/setup-java@v5 with: - java-version: '${{ env.JAVA_VERSION }}' + java-version: '21' distribution: 'adopt' cache: gradle - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build Skript and run test scripts - run: ./gradlew clean customTest -PtestEnvs="${{ matrix.envs }}" -PtestEnvJavaVersion=${{ env.JAVA_VERSION }} + run: ./gradlew clean customTest -PtestEnvs="${{ matrix.envs }}" -PtestEnvJavaVersion=21 - name: Upload Nightly Build uses: actions/upload-artifact@v4 if: success() && matrix.id == 1 From cd9753921870cb0f8ca3cb2b6667361bf2dcf7c4 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:57:42 -0700 Subject: [PATCH 13/16] better names --- .github/workflows/java-21-builds.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index e67f8069299..83be748ced3 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -1,4 +1,4 @@ -name: Java 21 CI (MC 1.20.6+) +name: Java 21 CI on: push: @@ -9,7 +9,7 @@ on: jobs: prepare: - name: Java 21 CI - Parallelize Tests + name: Parallelize Tests if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" uses: ./.github/workflows/parallelize-tests.yml with: @@ -18,7 +18,7 @@ jobs: java_version: 21 build: - name: Java 21 CI (${{ matrix.display }}) + name: ${{ matrix.display }} needs: prepare runs-on: ubuntu-latest strategy: From b58c8c57001d99c348d939136e879c8d5c83aa04 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:03:59 -0700 Subject: [PATCH 14/16] apply to all tests --- .github/workflows/java-17-builds.yml | 20 ++++++++++++++++---- .github/workflows/junit-17-builds.yml | 20 ++++++++++++++++---- .github/workflows/junit-21-builds.yml | 27 +++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/.github/workflows/java-17-builds.yml b/.github/workflows/java-17-builds.yml index 37326275392..3c27910aee5 100644 --- a/.github/workflows/java-17-builds.yml +++ b/.github/workflows/java-17-builds.yml @@ -1,4 +1,4 @@ -name: Java 17 CI (MC 1.20.4) +name: Java 17 CI on: push: @@ -8,9 +8,21 @@ on: pull_request: jobs: - build: + prepare: + name: Parallelize Tests if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" + uses: ./.github/workflows/parallelize-tests.yml + with: + environments: 1.20.4 + parallel_jobs: 3 + java_version: 17 + + build: + name: ${{ matrix.display }} + needs: prepare runs-on: ubuntu-latest + strategy: + matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} steps: - uses: actions/checkout@v5 with: @@ -26,10 +38,10 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build Skript and run test scripts - run: ./gradlew clean skriptTestJava17 -PparallelTests=true + run: ./gradlew clean customTest -PtestEnvs="${{ matrix.envs }}" -PtestEnvJavaVersion=17 - name: Upload Nightly Build uses: actions/upload-artifact@v4 - if: success() + if: success() && matrix.id == 1 with: name: skript-nightly path: build/libs/* diff --git a/.github/workflows/junit-17-builds.yml b/.github/workflows/junit-17-builds.yml index 86e37ecbecc..24dc1356dd2 100644 --- a/.github/workflows/junit-17-builds.yml +++ b/.github/workflows/junit-17-builds.yml @@ -1,4 +1,4 @@ -name: JUnit (MC 1.20.4) +name: JUnit 17 on: push: @@ -8,9 +8,21 @@ on: pull_request: jobs: - build: + prepare: + name: Parallelize Tests if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" + uses: ./.github/workflows/parallelize-tests.yml + with: + environments: 1.20.4 + parallel_jobs: 3 + java_version: 17 + + build: + name: ${{ matrix.display }} + needs: prepare runs-on: ubuntu-latest + strategy: + matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} steps: - uses: actions/checkout@v5 with: @@ -25,5 +37,5 @@ jobs: cache: gradle - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Build Skript and run JUnit - run: ./gradlew clean JUnitJava17 -PparallelTests=true + - name: Build Skript and run test scripts + run: ./gradlew clean customTest -PtestEnvs="${{ matrix.envs }}" -PtestEnvJavaVersion=17 -Pjunit=true diff --git a/.github/workflows/junit-21-builds.yml b/.github/workflows/junit-21-builds.yml index e14f0f79752..7960c9740f2 100644 --- a/.github/workflows/junit-21-builds.yml +++ b/.github/workflows/junit-21-builds.yml @@ -1,4 +1,4 @@ -name: JUnit (MC 1.20.6+) +name: JUnit 21 on: push: @@ -8,9 +8,21 @@ on: pull_request: jobs: - build: + prepare: + name: Parallelize Tests if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" + uses: ./.github/workflows/parallelize-tests.yml + with: + environments: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 + parallel_jobs: 3 + java_version: 21 + + build: + name: ${{ matrix.display }} + needs: prepare runs-on: ubuntu-latest + strategy: + matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} steps: - uses: actions/checkout@v5 with: @@ -25,5 +37,12 @@ jobs: cache: gradle - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Build Skript and run JUnit - run: ./gradlew clean JUnitJava21 -PparallelTests=true + - name: Build Skript and run test scripts + run: ./gradlew clean customTest -PtestEnvs="${{ matrix.envs }}" -PtestEnvJavaVersion=21 -Pjunit=true + - name: Upload Nightly Build + uses: actions/upload-artifact@v4 + if: success() && matrix.id == 1 + with: + name: skript-nightly + path: build/libs/* + From 9dba9c02d33c0a978a4aba2dd65401891e3362c4 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:12:31 -0700 Subject: [PATCH 15/16] 2 parallel tasks --- .github/workflows/java-17-builds.yml | 1 - .github/workflows/java-21-builds.yml | 1 - .github/workflows/junit-17-builds.yml | 1 - .github/workflows/junit-21-builds.yml | 1 - .github/workflows/parallelize-tests.yml | 4 +++- 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/java-17-builds.yml b/.github/workflows/java-17-builds.yml index 3c27910aee5..55a6176febb 100644 --- a/.github/workflows/java-17-builds.yml +++ b/.github/workflows/java-17-builds.yml @@ -14,7 +14,6 @@ jobs: uses: ./.github/workflows/parallelize-tests.yml with: environments: 1.20.4 - parallel_jobs: 3 java_version: 17 build: diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index 83be748ced3..e3aa29999a7 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -14,7 +14,6 @@ jobs: uses: ./.github/workflows/parallelize-tests.yml with: environments: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 - parallel_jobs: 3 java_version: 21 build: diff --git a/.github/workflows/junit-17-builds.yml b/.github/workflows/junit-17-builds.yml index 24dc1356dd2..bb7210b04f4 100644 --- a/.github/workflows/junit-17-builds.yml +++ b/.github/workflows/junit-17-builds.yml @@ -14,7 +14,6 @@ jobs: uses: ./.github/workflows/parallelize-tests.yml with: environments: 1.20.4 - parallel_jobs: 3 java_version: 17 build: diff --git a/.github/workflows/junit-21-builds.yml b/.github/workflows/junit-21-builds.yml index 7960c9740f2..e5130dbd4d4 100644 --- a/.github/workflows/junit-21-builds.yml +++ b/.github/workflows/junit-21-builds.yml @@ -14,7 +14,6 @@ jobs: uses: ./.github/workflows/parallelize-tests.yml with: environments: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 - parallel_jobs: 3 java_version: 21 build: diff --git a/.github/workflows/parallelize-tests.yml b/.github/workflows/parallelize-tests.yml index 16cd6b9d692..c751627c6a0 100644 --- a/.github/workflows/parallelize-tests.yml +++ b/.github/workflows/parallelize-tests.yml @@ -7,8 +7,9 @@ on: required: true type: string parallel_jobs: - required: true + required: false type: number + default: 2 java_version: required: true type: number @@ -19,6 +20,7 @@ on: jobs: prepare: + name: "" runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} From fa280052f73cdfbafaf6253b3fff5d2df9327c18 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:26:45 -0700 Subject: [PATCH 16/16] 2.14 tests only --- .github/workflows/java-17-builds.yml | 46 --------------------------- .github/workflows/java-21-builds.yml | 2 +- .github/workflows/junit-17-builds.yml | 40 ----------------------- .github/workflows/junit-21-builds.yml | 2 +- 4 files changed, 2 insertions(+), 88 deletions(-) delete mode 100644 .github/workflows/java-17-builds.yml delete mode 100644 .github/workflows/junit-17-builds.yml diff --git a/.github/workflows/java-17-builds.yml b/.github/workflows/java-17-builds.yml deleted file mode 100644 index 55a6176febb..00000000000 --- a/.github/workflows/java-17-builds.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Java 17 CI - -on: - push: - branches: - - master - - 'dev/**' - pull_request: - -jobs: - prepare: - name: Parallelize Tests - if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" - uses: ./.github/workflows/parallelize-tests.yml - with: - environments: 1.20.4 - java_version: 17 - - build: - name: ${{ matrix.display }} - needs: prepare - runs-on: ubuntu-latest - strategy: - matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} - steps: - - uses: actions/checkout@v5 - with: - submodules: recursive - - name: validate gradle wrapper - uses: gradle/actions/wrapper-validation@v4 - - name: Set up JDK 21 - uses: actions/setup-java@v5 - with: - java-version: '21' - distribution: 'adopt' - cache: gradle - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Build Skript and run test scripts - run: ./gradlew clean customTest -PtestEnvs="${{ matrix.envs }}" -PtestEnvJavaVersion=17 - - name: Upload Nightly Build - uses: actions/upload-artifact@v4 - if: success() && matrix.id == 1 - with: - name: skript-nightly - path: build/libs/* diff --git a/.github/workflows/java-21-builds.yml b/.github/workflows/java-21-builds.yml index e3aa29999a7..55b067a123b 100644 --- a/.github/workflows/java-21-builds.yml +++ b/.github/workflows/java-21-builds.yml @@ -13,7 +13,7 @@ jobs: if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" uses: ./.github/workflows/parallelize-tests.yml with: - environments: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 + environments: 1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 java_version: 21 build: diff --git a/.github/workflows/junit-17-builds.yml b/.github/workflows/junit-17-builds.yml deleted file mode 100644 index bb7210b04f4..00000000000 --- a/.github/workflows/junit-17-builds.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: JUnit 17 - -on: - push: - branches: - - master - - 'dev/**' - pull_request: - -jobs: - prepare: - name: Parallelize Tests - if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" - uses: ./.github/workflows/parallelize-tests.yml - with: - environments: 1.20.4 - java_version: 17 - - build: - name: ${{ matrix.display }} - needs: prepare - runs-on: ubuntu-latest - strategy: - matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} - steps: - - uses: actions/checkout@v5 - with: - submodules: recursive - - name: validate gradle wrapper - uses: gradle/actions/wrapper-validation@v4 - - name: Set up JDK 21 - uses: actions/setup-java@v5 - with: - java-version: '21' - distribution: 'adopt' - cache: gradle - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Build Skript and run test scripts - run: ./gradlew clean customTest -PtestEnvs="${{ matrix.envs }}" -PtestEnvJavaVersion=17 -Pjunit=true diff --git a/.github/workflows/junit-21-builds.yml b/.github/workflows/junit-21-builds.yml index e5130dbd4d4..675c40d17a1 100644 --- a/.github/workflows/junit-21-builds.yml +++ b/.github/workflows/junit-21-builds.yml @@ -13,7 +13,7 @@ jobs: if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')" uses: ./.github/workflows/parallelize-tests.yml with: - environments: 1.20.6,1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 + environments: 1.21.3,1.21.4,1.21.5,1.21.8,1.21.10 java_version: 21 build: