Skip to content

Commit bcfe3f1

Browse files
committed
test 2
1 parent aa7f3c7 commit bcfe3f1

2 files changed

Lines changed: 164 additions & 39 deletions

File tree

.github/workflows/runtime-test.yml

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010

1111
permissions:
1212
contents: read
13+
actions: write
1314

1415
env:
1516
JAVA_VERSION: 25
@@ -35,10 +36,12 @@ jobs:
3536
build/runtime-test/headlessmc-launcher-*.jar
3637
build/runtime-test/support
3738
build/runtime-test/client-mods
39+
build/runtime-test/remapped-mods
40+
build/runtime-test/runtime-mcp-remap.marker
3841
build/runtime-test/cleanroom-client-installed.marker
39-
key: ${{ runner.os }}-runtime-test-${{ hashFiles('build.gradle', 'gradle.properties', 'gradle/wrapper/gradle-wrapper.properties', 'gradle/scripts/**', '.github/workflows/runtime-test.yml') }}
42+
key: ${{ runner.os }}-java${{ env.JAVA_VERSION }}-gradle9.7-cleanroom${{ env.CLEANROOM_VERSION }}-hmc${{ env.HEADLESSMC_VERSION }}-helper4.5.1-runtime-test-${{ hashFiles('build.gradle', 'gradle.properties', 'gradle/wrapper/gradle-wrapper.properties', 'gradle/wrapper/gradle-wrapper.jar', 'gradle/scripts/**', '.github/workflows/runtime-test.yml') }}
4043
restore-keys: |
41-
${{ runner.os }}-runtime-test-
44+
${{ runner.os }}-java${{ env.JAVA_VERSION }}-gradle9.7-cleanroom${{ env.CLEANROOM_VERSION }}-hmc${{ env.HEADLESSMC_VERSION }}-helper4.5.1-runtime-test-
4245
4346
- name: Setup Java
4447
uses: actions/setup-java@v4
@@ -73,15 +76,10 @@ jobs:
7376
fileName: "mc-runtime-test-1.12.2-*-lexforge-release.jar"
7477
out-file-path: build/runtime-test/support
7578

76-
- name: Build and Stage Production Mods
79+
- name: Build, Stage, and Install Production Runtime
7780
env:
7881
GRADLE_OPTS: -Xmx6g -XX:MaxMetaspaceSize=1g
79-
run: ./gradlew --build-cache build stageRuntimeTestMods stageRuntimeTestClientMods -x spotlessCheck --no-daemon --max-workers=1 -Pmod_version="${MOD_VERSION}"
80-
81-
- name: Install Cleanroom Client
82-
env:
83-
GRADLE_OPTS: -Xmx2g -XX:MaxMetaspaceSize=768m
84-
run: ./gradlew installRuntimeTestClient -x spotlessCheck --no-daemon --max-workers=1 -Pmod_version="${MOD_VERSION}"
82+
run: ./gradlew --build-cache build stageRuntimeTestMods stageRuntimeTestClientMods installRuntimeTestClient -x spotlessCheck --no-daemon --max-workers=1 -Pmod_version="${MOD_VERSION}"
8583

8684
- name: Prepare Cleanroom Server Jar
8785
run: |
@@ -112,7 +110,11 @@ jobs:
112110
echo "${server_sha1} ${server_jar}" | sha1sum --check
113111
114112
- name: Install Headless Display
115-
run: sudo apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y xvfb
113+
run: |
114+
if ! command -v xvfb-run >/dev/null 2>&1; then
115+
sudo apt-get update
116+
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y xvfb
117+
fi
116118
117119
- name: Download HeadlessMC
118120
if: ${{ hashFiles('build/runtime-test/headlessmc-launcher-*.jar') == '' }}
@@ -214,6 +216,47 @@ jobs:
214216
--jvm "-Djava.awt.headless=true"
215217
)
216218
219+
- name: Prune Old Runtime Test Caches
220+
if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
221+
uses: actions/github-script@v7
222+
env:
223+
RUNTIME_CACHE_PREFIX: ${{ runner.os }}-java${{ env.JAVA_VERSION }}-gradle9.7-cleanroom${{ env.CLEANROOM_VERSION }}-hmc${{ env.HEADLESSMC_VERSION }}-helper4.5.1-runtime-test-
224+
RUNTIME_CACHE_RETENTION: 3
225+
with:
226+
script: |
227+
const prefix = process.env.RUNTIME_CACHE_PREFIX;
228+
const retention = Number(process.env.RUNTIME_CACHE_RETENTION);
229+
const caches = await github.paginate(
230+
github.rest.actions.getActionsCachesForRepo,
231+
{
232+
owner: context.repo.owner,
233+
repo: context.repo.repo,
234+
per_page: 100,
235+
}
236+
);
237+
const runtimeCaches = caches
238+
.filter(cache =>
239+
cache.ref === 'refs/heads/main' &&
240+
cache.key.startsWith(prefix)
241+
)
242+
.sort((a, b) =>
243+
Date.parse(b.last_accessed_at) - Date.parse(a.last_accessed_at)
244+
);
245+
const staleCaches = runtimeCaches.slice(retention);
246+
for (const cache of staleCaches) {
247+
core.info(`Deleting stale runtime-test cache ${cache.key} (${cache.id})`);
248+
await github.rest.actions.deleteActionsCacheById({
249+
owner: context.repo.owner,
250+
repo: context.repo.repo,
251+
cache_id: cache.id,
252+
});
253+
}
254+
core.info(
255+
`Runtime-test caches: ${runtimeCaches.length}; ` +
256+
`retained: ${Math.min(runtimeCaches.length, retention)}; ` +
257+
`deleted: ${staleCaches.length}`
258+
);
259+
217260
- name: Upload Runtime Logs
218261
if: always()
219262
uses: actions/upload-artifact@v4

gradle/scripts/extra.gradle

Lines changed: 111 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,26 @@ runtimeTestProductionMods.transitive = false
2323

2424
[configurations.modImplementation, configurations.modRuntimeOnly].each { sourceConfiguration ->
2525
sourceConfiguration.dependencies.each { dependency ->
26-
if (!(dependency instanceof org.gradle.api.artifacts.ModuleDependency)) {
26+
if (!(dependency instanceof ModuleDependency)) {
2727
return
2828
}
29-
def productionDependency = project.dependencies.create([
29+
def productionNotation = [
3030
group: dependency.group,
3131
name: dependency.name,
3232
version: dependency.version
33-
])
33+
]
34+
if (!dependency.artifacts.empty) {
35+
def requestedArtifact = dependency.artifacts.iterator().next()
36+
if (requestedArtifact.classifier != null) {
37+
productionNotation.classifier = requestedArtifact.classifier
38+
}
39+
if (requestedArtifact.extension != null) {
40+
productionNotation.ext = requestedArtifact.extension
41+
}
42+
}
43+
def productionDependency = project.dependencies.create(
44+
productionNotation
45+
)
3446
productionDependency.transitive = false
3547
runtimeTestProductionMods.dependencies.add(productionDependency)
3648
}
@@ -44,17 +56,19 @@ def runtimeTestMinecraftDir = providers.gradleProperty('runtimeTestMinecraftDir'
4456
def runtimeTestSupportDir = layout.buildDirectory.dir('runtime-test/support')
4557
def runtimeTestClientModsDir = layout.buildDirectory.dir('runtime-test/client-mods')
4658
def runtimeRemappedDir = layout.buildDirectory.dir('runtime-test/remapped-mods')
47-
def runtimeInputDir = layout.buildDirectory.dir('runtime-test/inputs')
59+
def runtimeMcpRemapMarker = layout.buildDirectory.file(
60+
'runtime-test/runtime-mcp-remap.marker'
61+
)
62+
def runtimeRemapSchema = 'runtime-mcp-remap-v2'
4863

4964
def runtimeProductionFiles = []
50-
def runtimeRemapTasks = []
51-
def runtimeDependencyIndex = 0
52-
def namespaceAttribute = org.gradle.api.attributes.Attribute.of(
65+
def runtimeTestMcpDependencies = []
66+
def namespaceAttribute = Attribute.of(
5367
'com.gtnewhorizons.retrofuturagradle.obfuscation',
5468
String
5569
)
5670
runtimeTestProductionMods.incoming.artifactView {}.artifacts.each { artifact ->
57-
if (artifact.file.name.endsWith('.jar') == false
71+
if (!artifact.file.name.endsWith('.jar')
5872
|| artifact.file.name.endsWith('-sources.jar')) {
5973
return
6074
}
@@ -67,35 +81,89 @@ runtimeTestProductionMods.incoming.artifactView {}.artifacts.each { artifact ->
6781
return
6882
}
6983

70-
def index = runtimeDependencyIndex++
71-
def inputTask = tasks.register("runtimeTestInput${index}", Jar) {
72-
archiveFileName = "runtime-test-input-${index}.jar"
73-
destinationDirectory = runtimeInputDir
74-
from { zipTree(artifact.file) }
84+
def moduleId = artifact.variant.owner
85+
if (!(moduleId instanceof ModuleComponentIdentifier)) {
86+
throw new GradleException(
87+
"Runtime test artifact is not an external module: ${artifact.file}"
88+
)
7589
}
76-
def remapTask = minecraftConfig.remap(inputTask.get(), "runtimeTestRemap${index}") {
77-
devNamespace 'mcp'
78-
prodNamespace productionNamespace.name
79-
mixinRemap {
80-
enableBaseMixin()
81-
enableMixinExtra()
82-
disableRefmap()
83-
}
90+
def dependencyNotation = [
91+
group: moduleId.group,
92+
name: moduleId.module,
93+
version: moduleId.version
94+
]
95+
if (artifact.file.name.endsWith('-dev.jar')) {
96+
dependencyNotation.classifier = 'dev'
97+
}
98+
runtimeTestMcpDependencies.add(
99+
project.dependencies.create(dependencyNotation)
100+
)
101+
}
102+
103+
def runtimeTestMcpMods = configurations.maybeCreate('runtimeTestMcpMods')
104+
runtimeTestMcpMods.canBeConsumed = false
105+
runtimeTestMcpMods.canBeResolved = true
106+
runtimeTestMcpMods.transitive = false
107+
runtimeTestMcpMods.dependencies.addAll(runtimeTestMcpDependencies)
108+
109+
minecraftConfig.mods.remap(runtimeTestMcpMods) {
110+
namespace 'mcp'
111+
mixinRemap {
112+
enableBaseMixin()
113+
enableMixinExtra()
114+
disableRefmap()
84115
}
85-
remapTask.configure {
86-
destinationDirectory = runtimeRemappedDir
87-
archiveFileName = artifact.file.name.replaceFirst('-dev(?=\\.jar$)', '')
116+
}
117+
118+
def runtimeMcpRemapTask = tasks.register('runtimeTestRemapMcp') {
119+
inputs.files(runtimeTestMcpMods)
120+
inputs.property('runtimeRemapSchema', runtimeRemapSchema)
121+
inputs.property('minecraftVersion', minecraftVersion)
122+
inputs.property('cleanroomVersion', cleanroomVersion)
123+
inputs.property('productionNamespace', productionNamespace.name)
124+
inputs.file(layout.projectDirectory.file(
125+
'.gradle/unimined/local/mappings/srg2mcp.tsrg'
126+
)).optional()
127+
outputs.dir(runtimeRemappedDir)
128+
outputs.file(runtimeMcpRemapMarker)
129+
doLast {
130+
def inputFiles = runtimeTestMcpMods.resolve() as Set
131+
logger.lifecycle(
132+
"[RuntimeTest] Remapping ${inputFiles.size()} MCP mod(s) " +
133+
"from mcp to ${productionNamespace.name} in one batch"
134+
)
135+
def remappedDir = runtimeRemappedDir.get().asFile
136+
project.delete(remappedDir)
137+
remappedDir.mkdirs()
138+
def remappedFiles = minecraftConfig.mods.getClasspathAs(
139+
productionNamespace,
140+
inputFiles
141+
)
142+
project.copy {
143+
from remappedFiles
144+
into remappedDir
145+
include '*.jar'
146+
rename { fileName ->
147+
fileName.replaceFirst('-dev(?=\\.jar$)', '')
148+
}
149+
}
150+
runtimeMcpRemapMarker.get().asFile.text = inputFiles.collect {
151+
it.name + ':' + it.length() + ':' + it.lastModified()
152+
}.sort().join('\n') + '\n'
153+
logger.lifecycle(
154+
"[RuntimeTest] Finished MCP remap; produced " +
155+
"${remappedFiles.size()} file(s)"
156+
)
88157
}
89-
runtimeRemapTasks.add(remapTask)
90158
}
91159

92160
tasks.register('stageRuntimeTestMods', Sync) {
93161
dependsOn productionJarTask
94-
dependsOn runtimeRemapTasks
162+
dependsOn(runtimeMcpRemapTask)
95163
from(productionJarTask.flatMap { it.archiveFile })
96164
from(runtimeProductionFiles)
97-
runtimeRemapTasks.each { remapTask ->
98-
from(remapTask.flatMap { it.archiveFile })
165+
from(runtimeRemappedDir) {
166+
include '*.jar'
99167
}
100168
into(runtimeTestModsDir)
101169
include '*.jar'
@@ -114,12 +182,26 @@ tasks.register('stageRuntimeTestClientMods', Sync) {
114182

115183
tasks.register('installRuntimeTestClient', JavaExec) {
116184
dependsOn cleanroomInstaller
185+
dependsOn 'stageRuntimeTestClientMods'
117186
classpath = cleanroomInstaller
118187
mainClass = 'net.minecraftforge.installer.SimpleInstaller'
119188
def installDir = runtimeTestMinecraftDir.get().asFile
189+
def profile = new File(
190+
installDir,
191+
"versions/${minecraftVersion}-Cleanroom-${cleanroomVersion}/" +
192+
"${minecraftVersion}-Cleanroom-${cleanroomVersion}.json"
193+
)
194+
def cleanroomJar = new File(
195+
installDir,
196+
"libraries/com/cleanroommc/cleanroom/${cleanroomVersion}/" +
197+
"cleanroom-${cleanroomVersion}.jar"
198+
)
120199
def marker = layout.buildDirectory.file('runtime-test/cleanroom-client-installed.marker').get().asFile
121200
onlyIf {
122-
!marker.exists() || marker.text.trim() != "${minecraftVersion}-Cleanroom-${cleanroomVersion}"
201+
!marker.exists()
202+
|| marker.text.trim() != "${minecraftVersion}-Cleanroom-${cleanroomVersion}"
203+
|| !profile.isFile()
204+
|| !cleanroomJar.isFile()
123205
}
124206
doFirst {
125207
installDir.mkdirs()

0 commit comments

Comments
 (0)