@@ -15,7 +15,6 @@ import org.graalvm.internal.tck.ContributionTask
1515import org.graalvm.internal.tck.DockerTask
1616import org.graalvm.internal.tck.ConfigFilesChecker
1717import org.graalvm.internal.tck.DockerUtils
18- import org.graalvm.internal.tck.PullImagesFromFileTask
1918import org.graalvm.internal.tck.ScaffoldTask
2019import org.graalvm.internal.tck.GrypeTask
2120import org.graalvm.internal.tck.TestedVersionUpdaterTask
@@ -28,6 +27,9 @@ import org.graalvm.internal.tck.harness.tasks.NativeTestCompileInvocationTask
2827import org.graalvm.internal.tck.updaters.FetchExistingLibrariesWithNewerVersionsTask
2928import org.graalvm.internal.tck.updaters.GroupUnsupportedLibraries
3029import org.gradle.util.internal.VersionNumber
30+ import org.gradle.api.Action
31+ import org.gradle.process.ExecSpec
32+ import org.graalvm.internal.tck.PullImagesFromFileTask
3133
3234
3335import static org.graalvm.internal.tck.Utils.generateTaskName
@@ -47,28 +49,28 @@ def writeGithubOutput(String key, String value) {
4749String coordinateFilter = Objects . requireNonNullElse(project. findProperty(" coordinates" ), " " )
4850
4951// Support fractional batching coordinates in the form "k/n" (e.g., "1/16")
50- boolean isFractionalBatch (String s ) {
52+ static boolean isFractionalBatch (String s ) {
5153 return s != null && (s ==~ / \d +\/\d +/ )
5254}
5355
54- List<Integer > parseFraction (String s ) {
56+ static List<Integer > parseFraction (String s ) {
5557 def m = s =~ / (\d +)\/ (\d +)/
5658 if (! m. matches()) return null
5759 int k = (m[0 ][1 ] as int )
5860 int n = (m[0 ][2 ] as int )
5961 return [k, n]
6062}
6163
62- List<String > computeBatchedCoordinates (List<String > allCoords , int k , int n ) {
63- if (n <= 0 ) throw new GradleException (" Invalid batches denominator: ${ n } " )
64- if (k < 1 || k > n ) throw new GradleException (" Invalid batch index: ${ k } /${ n } " )
65- def sorted = new ArrayList<String > (allCoords )
66- java.util. Collections. sort(sorted)
67- int target = (k - 1 )
64+ static List<String > computeBatchedCoordinates (List<String > coordinates , int index , int batches ) {
65+ if (batches <= 0 ) throw new GradleException (" Invalid batches denominator: ${ batches } " )
66+ if (index < 1 || index > batches ) throw new GradleException (" Invalid batch index: ${ index } /${ batches } " )
67+ def sorted = new ArrayList<String > (coordinates )
68+ Collections . sort(sorted)
69+ int target = (index - 1 )
6870 def result = []
6971 int i = 0
7072 for (String c : sorted) {
71- if ((i % n ) == target) {
73+ if ((i % batches ) == target) {
7274 result. add(c)
7375 }
7476 i++
@@ -79,10 +81,8 @@ List<String> computeBatchedCoordinates(List<String> allCoords, int k, int n) {
7981List<String > matchingCoordinates
8082if (isFractionalBatch(coordinateFilter)) {
8183 def frac = parseFraction(coordinateFilter)
82- int k = frac[0 ]
83- int n = frac[1 ]
8484 List<String > all = tck. getMatchingCoordinates(" all" )
85- matchingCoordinates = computeBatchedCoordinates(all, k, n )
85+ matchingCoordinates = computeBatchedCoordinates(all, frac[ 0 ], frac[ 1 ] )
8686} else {
8787 matchingCoordinates = tck. getMatchingCoordinates(coordinateFilter)
8888}
@@ -123,76 +123,8 @@ tasks.named("check").configure {
123123
124124final String METADATA_GROUP = " Metadata"
125125
126- Provider<Task > pullAllowedDockerImagesMatching = tasks. register(" pullAllowedDockerImagesMatching" , DefaultTask ) { task ->
127- task. setDescription(" Pull allowed docker images for all matching coordinates" )
128- task. setGroup(METADATA_GROUP )
129- task. doFirst {
130- if (matchingCoordinates == null || matchingCoordinates. isEmpty()) {
131- throw new GradleException (" No matching coordinates found for property 'coordinates'. Provide -Pcoordinates=<filter> or a fractional batch 'k/n'." )
132- }
133- println " Pulling allowed docker images for ${ matchingCoordinates.size()} coordinate(s):"
134- matchingCoordinates. each { c -> println (" - ${ c} " ) }
135- }
136- }
137126
138- // Collect unique required images across matching coordinates and filter by allowed list
139- tasks. register(" collectRequiredAllowedDockerImagesMatching" , DefaultTask ) { task ->
140- task. setDescription(" Collect unique allowed docker images required by matching coordinates into a file" )
141- task. setGroup(METADATA_GROUP )
142- File out = new File (buildDir, " required-docker-images-union.txt" )
143- // Declare the output so Gradle can track it
144- task. outputs. file(out)
145- task. doFirst {
146- if (matchingCoordinates == null || matchingCoordinates. isEmpty()) {
147- throw new GradleException (" No matching coordinates found for property 'coordinates'. Provide -Pcoordinates=<filter> or a fractional batch 'k/n'." )
148- }
149- Set<String > unionRequired = new LinkedHashSet<> ()
150- matchingCoordinates. each { c ->
151- def parts = c. split(" :" )
152- if (parts. length < 3 ) {
153- logger. warn(" Skipping invalid coordinates: ${ c} " )
154- return
155- }
156- def group = parts[0 ]
157- def artifact = parts[1 ]
158- def version = parts[2 ]
159- File f = project. file(" tests/src/${ group} /${ artifact} /${ version} /required-docker-images.txt" )
160- if (f. exists()) {
161- f. readLines()
162- .collect { it?. trim() }
163- .findAll { it && ! it. startsWith(" #" ) }
164- .each { unionRequired. add(it) }
165- }
166- }
167127
168- Set<String > allowed = DockerUtils . getAllAllowedImages()
169- def notAllowed = unionRequired. findAll { ! allowed. contains(it) }
170- if (! notAllowed. isEmpty()) {
171- throw new GradleException (" The following images are not in the allowed list: ${ notAllowed} . " +
172- " If you need them, add Dockerfiles under tests/tck-build-logic/src/main/resources/allowed-docker-images " +
173- " per CONTRIBUTING.md, or adjust required-docker-images.txt files." )
174- }
175-
176- out. parentFile. mkdirs()
177- def finalList = unionRequired. findAll { allowed. contains(it) }. toList()
178- out. text = finalList. join(System . lineSeparator())
179- println " Collected ${ finalList.size()} required allowed image(s):"
180- finalList. each { println (" - ${ it} " ) }
181- }
182- }
183-
184- // Pull the collected unique images (once)
185- tasks. register(" pullRequiredAllowedDockerImagesMatching" , PullImagesFromFileTask . class) { task ->
186- task. setDescription(" Pull unique allowed docker images required by matching coordinates" )
187- task. setGroup(METADATA_GROUP )
188- task. dependsOn(" collectRequiredAllowedDockerImagesMatching" )
189- task. imagesFile. set(new File (buildDir, " required-docker-images-union.txt" ))
190- }
191-
192- // Rewire the aggregate to depend on the unique pull task
193- pullAllowedDockerImagesMatching. configure {
194- dependsOn(" pullRequiredAllowedDockerImagesMatching" )
195- }
196128
197129// Here we want to configure all test and checkstyle tasks for all filtered subprojects
198130for (String coordinates in matchingCoordinates) {
@@ -422,9 +354,57 @@ tasks.register("checkAllowedDockerImages", GrypeTask.class) { task ->
422354 task. setGroup(METADATA_GROUP )
423355}
424356
425- tasks. register(" pullAllowedDockerImages" , DockerTask . class) { task ->
426- task. setDescription(" Pull allowed docker images from list." )
357+ def imagesFileProvider = project. layout. buildDirectory. file(" tck/required-docker-images.txt" )
358+
359+ def computeImages = tasks. register(" computeAllowedDockerImagesFile" , DefaultTask ) { task ->
360+ task. setDescription(" Computes allowed docker images required by matching coordinates and writes them to a file" )
361+ task. setGroup(METADATA_GROUP )
362+ task. outputs. file(imagesFileProvider)
363+ task. doFirst {
364+ if (matchingCoordinates == null || matchingCoordinates. isEmpty()) {
365+ throw new GradleException (" No matching coordinates found for property 'coordinates'. Provide -Pcoordinates=<filter> or a fractional batch 'k/n'." )
366+ }
367+ Set<String > unionRequired = new LinkedHashSet<> ()
368+ matchingCoordinates. each { c ->
369+ def parts = c. split(" :" )
370+ if (parts. length < 3 ) {
371+ logger. warn(" Skipping invalid coordinates: ${ c} " )
372+ return
373+ }
374+ def group = parts[0 ]
375+ def artifact = parts[1 ]
376+ def version = parts[2 ]
377+ File f = project. file(" tests/src/${ group} /${ artifact} /${ version} /required-docker-images.txt" )
378+ if (f. exists()) {
379+ f. readLines()
380+ .collect { it?. trim() }
381+ .findAll { it && ! it. startsWith(" #" ) }
382+ .each { unionRequired. add(it) }
383+ }
384+ }
385+
386+ Set<String > allowed = DockerUtils . getAllAllowedImages()
387+ def notAllowed = unionRequired. findAll { ! allowed. contains(it) }
388+ if (! notAllowed. isEmpty()) {
389+ throw new GradleException (" The following images are not in the allowed list: ${ notAllowed} . " +
390+ " If you need them, add Dockerfiles under tests/tck-build-logic/src/main/resources/allowed-docker-images " +
391+ " per CONTRIBUTING.md, or adjust required-docker-images.txt files." )
392+ }
393+
394+ def finalList = unionRequired. findAll { allowed. contains(it) }. toList()
395+ println " Collected ${ finalList.size()} required allowed image(s)"
396+ File outFile = imagesFileProvider. get(). asFile
397+ outFile. parentFile. mkdirs()
398+ outFile. text = finalList. join(System . lineSeparator())
399+ }
400+ }
401+
402+ tasks. register(" pullAllowedDockerImages" , PullImagesFromFileTask . class) { task ->
403+ task. setDescription(" Pull allowed docker images required by matching coordinates" )
427404 task. setGroup(METADATA_GROUP )
405+ task. getImagesFile(). set(imagesFileProvider)
406+ }. configure { t ->
407+ t. dependsOn(computeImages)
428408}
429409
430410
0 commit comments