Persist authored Age generation plans (#31)
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-30 16:17:25 -04:00
1 parent 27abebe3aa
commit 28c2ca0db3
15 files changed
+369 -62

No files matched your search

+66 -29
View File
@@ -148,42 +148,79 @@ neoForge {
}
}
// GameTests generate Ages, so their dedicated world can grow quickly across runs.
// Never auto-delete a caller-supplied gameTestRunDir or a normal dev world.
long gameTestWorldLimitMiB = providers.gradleProperty('gameTestMaxWorldMiB').orElse('512').get().toLong()
if (gameTestWorldLimitMiB <= 0) {
throw new GradleException('gameTestMaxWorldMiB must be a positive number')
}
// Every default run gets a fresh world. Failed worlds stay available until a
// successful run; caller-supplied directories are never managed here.
boolean customGameTestRunDir = providers.gradleProperty('gameTestRunDir').isPresent()
File dedicatedGameTestDir = layout.buildDirectory.dir('gametest-run').get().asFile.canonicalFile
File dedicatedGameTestBuildDir = layout.buildDirectory.get().asFile
File dedicatedGameTestDir = layout.buildDirectory.dir('gametest-run').get().asFile
File dedicatedGameTestWorld = new File(dedicatedGameTestDir, 'world')
def cleanOversizedGameTestWorld = tasks.register('cleanOversizedGameTestWorld') {
File gameTestSuccessMarker = new File(dedicatedGameTestDir, '.last-gametest-succeeded')
def prepareGameTestWorld = tasks.register('prepareGameTestWorld') {
onlyIf { !customGameTestRunDir }
doLast {
if (customGameTestRunDir) {
getLogger().lifecycle('Skipping automatic GameTest world cleanup for custom gameTestRunDir')
return
}
def worldDir = dedicatedGameTestWorld
if (!worldDir.isDirectory() || java.nio.file.Files.isSymbolicLink(worldDir.toPath())) {
return
}
def paths = java.nio.file.Files.walk(worldDir.toPath()).withCloseable { it.toList() }
long bytes = paths.sum(0L) { path ->
java.nio.file.Files.isRegularFile(path, java.nio.file.LinkOption.NOFOLLOW_LINKS)
? java.nio.file.Files.size(path) : 0L
}
long limit = gameTestWorldLimitMiB * 1024L * 1024L
if (bytes > limit) {
getLogger().lifecycle('Removing oversized GameTest world {} ({} MiB; limit {} MiB)',
worldDir, Math.ceil(bytes / 1048576d) as long, gameTestWorldLimitMiB)
paths.toSorted(java.util.Comparator.reverseOrder()).each { java.nio.file.Files.delete(it) }
java.nio.file.Files.deleteIfExists(gameTestSuccessMarker.toPath())
File preserved = GameTestWorlds.preserve(dedicatedGameTestBuildDir, dedicatedGameTestDir)
if (preserved != null) logger.lifecycle('Preserved GameTest world for inspection at {}', preserved)
}
}
def finishGameTestWorld = tasks.register('finishGameTestWorld') {
onlyIf { !customGameTestRunDir }
doLast {
if (gameTestSuccessMarker.exists()) {
GameTestWorlds.clean(dedicatedGameTestBuildDir, dedicatedGameTestDir)
java.nio.file.Files.delete(gameTestSuccessMarker.toPath())
} else {
File preserved = GameTestWorlds.preserve(dedicatedGameTestBuildDir, dedicatedGameTestDir)
if (preserved != null) logger.lifecycle('Preserved GameTest world for inspection at {}', preserved)
}
}
}
tasks.named('runGameTestServer').configure {
dependsOn(cleanOversizedGameTestWorld)
dependsOn(prepareGameTestWorld)
finalizedBy(finishGameTestWorld)
doLast {
if (!customGameTestRunDir) {
GameTestWorlds.check(dedicatedGameTestBuildDir, dedicatedGameTestDir)
java.nio.file.Files.createFile(gameTestSuccessMarker.toPath())
}
}
}
class GameTestWorlds {
static void check(File buildDir, File runDir) {
[buildDir, runDir, new File(runDir, 'world'), new File(runDir, 'failed-worlds')].each { path ->
if (java.nio.file.Files.isSymbolicLink(path.toPath())) {
throw new GradleException("Refusing to manage a symlinked GameTest path: ${path}")
}
}
}
static File preserve(File buildDir, File runDir) {
File world = new File(runDir, 'world')
if (!world.exists()) return null
check(buildDir, runDir)
if (!world.isDirectory()) throw new GradleException("Expected a GameTest world directory: ${world}")
File failures = new File(runDir, 'failed-worlds')
java.nio.file.Files.createDirectories(failures.toPath())
String snapshot = java.time.format.DateTimeFormatter.ofPattern('yyyyMMdd-HHmmss-SSS')
.format(java.time.LocalDateTime.now()) + '-' + java.util.UUID.randomUUID()
File destination = new File(failures, snapshot)
java.nio.file.Files.move(world.toPath(), destination.toPath())
return destination
}
static void clean(File buildDir, File runDir) {
check(buildDir, runDir)
[new File(runDir, 'world'), new File(runDir, 'failed-worlds')].each { root ->
if (root.exists()) {
java.nio.file.Files.walk(root.toPath()).withCloseable { paths ->
paths.sorted(java.util.Comparator.reverseOrder()).forEach { path ->
java.nio.file.Files.delete(path)
}
}
}
}
}
}
// Sets up a dependency configuration called 'localRuntime'.