mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-26 05:50:39 +00:00
- Mod targets run through bounded Gradle workers with separate caches and daemon slots - Target logs retain verification failures and bounded output summaries - Nested tests use bounded forks and JVM thread counts - Lifecycle tests control deadlines through injected clocks
86 lines
3.8 KiB
Java
86 lines
3.8 KiB
Java
import org.gradle.api.GradleException;
|
|
import org.gradle.api.logging.Logger;
|
|
import org.gradle.api.logging.Logging;
|
|
import org.gradle.process.ExecOperations;
|
|
import org.gradle.workers.WorkAction;
|
|
|
|
import javax.inject.Inject;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.io.PrintWriter;
|
|
import java.io.RandomAccessFile;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.StandardOpenOption;
|
|
import java.util.Arrays;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
public abstract class IrisModdedBuildAction implements WorkAction<IrisModdedBuildParameters> {
|
|
private static final Logger LOGGER = Logging.getLogger(IrisModdedBuildAction.class);
|
|
private static final int LOG_TAIL_BYTES = 16 * 1024;
|
|
private static final int LOG_TAIL_LINES = 40;
|
|
|
|
@Inject
|
|
protected abstract ExecOperations getExecOperations();
|
|
|
|
@Override
|
|
public void execute() {
|
|
IrisModdedBuildParameters parameters = getParameters();
|
|
String label = parameters.getLabel().get();
|
|
Path log = parameters.getLogFile().get().getAsFile().toPath();
|
|
long started = System.nanoTime();
|
|
LOGGER.lifecycle("{} started; log: {}", label, log);
|
|
try {
|
|
Files.createDirectories(log.getParent());
|
|
try (OutputStream output = Files.newOutputStream(log)) {
|
|
getExecOperations().exec(spec -> {
|
|
spec.setWorkingDir(parameters.getWorkingDirectory().get().getAsFile());
|
|
spec.commandLine(parameters.getCommandLine().get());
|
|
spec.environment(parameters.getEnvironment().get());
|
|
spec.setStandardOutput(output);
|
|
spec.setErrorOutput(output);
|
|
}).assertNormalExitValue();
|
|
}
|
|
ModdedArtifactVerifier.verify(parameters.getArtifactFile().get().getAsFile(),
|
|
parameters.getRequiredEntries().get(), parameters.getForbiddenCoreClasses().get());
|
|
ModdedArtifactVerifier.verifyJavaRuntime(parameters.getArtifactFile().get().getAsFile(),
|
|
parameters.getJavaRuntime().get());
|
|
LOGGER.lifecycle("{} succeeded in {} ms", label,
|
|
TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - started));
|
|
} catch (Exception failure) {
|
|
appendFailure(log, failure);
|
|
String details;
|
|
try {
|
|
details = logTail(log);
|
|
} catch (IOException unreadable) {
|
|
failure.addSuppressed(unreadable);
|
|
details = "Log could not be read.";
|
|
}
|
|
LOGGER.error(label + " failed; log: " + log + System.lineSeparator() + details, failure);
|
|
throw new GradleException(label + " failed; log: " + log, failure);
|
|
}
|
|
}
|
|
|
|
static String logTail(Path log) throws IOException {
|
|
try (RandomAccessFile input = new RandomAccessFile(log.toFile(), "r")) {
|
|
long offset = Math.max(0L, input.length() - LOG_TAIL_BYTES);
|
|
input.seek(offset);
|
|
byte[] bytes = new byte[(int) (input.length() - offset)];
|
|
input.readFully(bytes);
|
|
String[] lines = new String(bytes, StandardCharsets.UTF_8).split("\\R");
|
|
return String.join(System.lineSeparator(), Arrays.copyOfRange(lines,
|
|
Math.max(0, lines.length - LOG_TAIL_LINES), lines.length));
|
|
}
|
|
}
|
|
|
|
private static void appendFailure(Path log, Exception failure) {
|
|
try (PrintWriter output = new PrintWriter(Files.newBufferedWriter(log, StandardCharsets.UTF_8,
|
|
StandardOpenOption.CREATE, StandardOpenOption.APPEND))) {
|
|
failure.printStackTrace(output);
|
|
} catch (IOException unwritable) {
|
|
failure.addSuppressed(unwritable);
|
|
}
|
|
}
|
|
}
|