Skip to content

Commit

Permalink
Fetch versions from Gradle website to automatically pull in new versi…
Browse files Browse the repository at this point in the history
…ons.

Versions are filtered to be greater than 5.6 and to be a release version.
To be able to keep our build matrix, the strategy there has to be
changed to slice the set of discovered versions in a number of parts,
and to select the part to run
  • Loading branch information
vierbergenlars committed Aug 17, 2022
1 parent 0ede3d4 commit 14fcf4b
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 30 deletions.
20 changes: 10 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ jobs:
env:
GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PLUGINS_PUBLISH_KEY }}
GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PLUGINS_PUBLISH_SECRET }}
run: ./gradlew publishPlugins -Pgradle.publish.key=$GRADLE_PUBLISH_KEY -Pgradle.publish.secret=$GRADLE_PUBLISH_SECRET
run: ./gradlew check -PintegrationTestMajorsOnly=true publishPlugins -Pgradle.publish.key=$GRADLE_PUBLISH_KEY -Pgradle.publish.secret=$GRADLE_PUBLISH_SECRET
integration-test:
name: "integration-test (gradle-versions=${{ matrix.gradle-versions}})"
name: "integration-test (slice=${{ matrix.slice }})"
runs-on: ubuntu-latest
strategy:
matrix:
gradle-versions:
- 5.6
- 6.0,6.1,6.2
- 6.3,6.4,6.5
- 6.6,6.7,6.8
- 7.0,7.1,7.2
slice:
- 0
- 1
- 2
- 3
- 4
steps:
- uses: actions/checkout@v2
with:
Expand All @@ -64,10 +64,10 @@ jobs:
- name: Pull docker images
run: 'parallel docker pull -- alfresco/alfresco-content-repository-community:6.0.7-ga tomcat:7-jre8 hello-world alpine:edge'
- name: Check
run: ./gradlew check -PintegrationTestGradleVersions=${{ matrix.gradle-versions }}
run: ./gradlew check -PintegrationTestSlice.index=${{ matrix.slice }} -PintegrationTestSlice.total=5
- name: Upload reports
if: ${{ failure() }}
uses: actions/upload-artifact@v2
with:
name: reports-integration-test-${{ matrix.gradle-versions }}
name: reports-integration-test-${{ matrix.slice }}
path: build/reports
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ dependencies {
testImplementation gradleTestKit()
testImplementation "org.mockito:mockito-core:4.+"
testImplementation 'com.github.stefanbirkner:system-rules:1.19.0'

integrationTestImplementation 'com.fasterxml.jackson.core:jackson-databind:2.10.3'
}


Expand Down Expand Up @@ -180,6 +182,9 @@ task integrationTest(type: Test, group: "verification") {
filter.includeTestsMatching("*[Gradle v${version}.*]")
})
}
systemProperty "eu.xenit.gradle.integration.majorsOnly", project.findProperty("integrationTestMajorsOnly") ?: "false"
systemProperty "eu.xenit.gradle.integration.slice.index", project.findProperty("integrationTestSlice.index") ?: "0"
systemProperty "eu.xenit.gradle.integration.slice.total", project.findProperty("integrationTestSlice.total") ?: "1"
doFirst {
if (gradle.startParameter.offline) {
systemProperty "eu.xenit.gradle.integration.useGradleVersion", GradleVersion.current().version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,28 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import eu.xenit.gradle.testrunner.versions.GradleVersionSpec;
import eu.xenit.gradle.testrunner.versions.VersionFetcher;
import java.io.File;
import java.io.IOException;
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.Collection;
import java.util.HashSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
import org.gradle.testkit.runner.TaskOutcome;
import org.gradle.util.GradleVersion;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
Expand All @@ -36,28 +42,71 @@ public abstract class AbstractIntegrationTest {
public String gradleVersion;

@Parameters(name = "Gradle v{0}")
public static Collection<Object[]> testData() {
public static List<String[]> testData() {
String forceGradleVersion = System.getProperty("eu.xenit.gradle.integration.useGradleVersion");
if (forceGradleVersion != null) {
return Arrays.asList(new Object[][]{
return Arrays.asList(new String[][]{
{forceGradleVersion},
});
}
return Arrays.asList(new Object[][]{
{"7.2"},
{"7.1"},
{"7.0"},
{"6.8.3"},
{"6.7.1"},
{"6.6.1"},
{"6.5.1"},
{"6.4.1"},
{"6.3"},
{"6.2.2"},
{"6.1.1"},
{"6.0.1"},
{"5.6.4"},
});

boolean majorsOnly = Boolean.getBoolean("eu.xenit.gradle.integration.majorsOnly");
Comparator<GradleVersionSpec> byVersionNumber = Comparator.comparing(versionSpec -> GradleVersion.version(versionSpec.getVersion()));
List<GradleVersionSpec> fetchedVersions = VersionFetcher.fetchVersions()
.filter(VersionFetcher::isRelease)
.filter(VersionFetcher.greaterThan("5.6"))
.sorted(byVersionNumber)
.collect(Collectors.toList());

Map<String, List<GradleVersionSpec>> versionsByMinor = new HashMap<>();

for (GradleVersionSpec versionSpec : fetchedVersions) {
String[] versionParts = GradleVersion.version(versionSpec.getVersion()).getBaseVersion().getVersion().split("\\.");
String versionKey = majorsOnly?versionParts[0]:(versionParts[0]+"."+versionParts[1]);
if(versionsByMinor.containsKey(versionKey)) {
versionsByMinor.get(versionKey).add(versionSpec);
} else {
versionsByMinor.put(versionKey, new ArrayList<>(Collections.singletonList(versionSpec)));
if(majorsOnly) {
versionsByMinor.put(versionKey + "-lowest", Collections.singletonList(versionSpec));
}
}
}


List<String[]> versionsToBuild = versionsByMinor.values()
.stream()
.map(versions -> versions.stream()
// Find latest patch version
.sorted(byVersionNumber.reversed())
.findFirst()
.orElse(null)
)
.filter(Objects::nonNull)
.sorted(byVersionNumber)
.map(GradleVersionSpec::getVersion)
.map(version -> new String[]{version})
.collect(Collectors.toList());

List<String[]> slicedVersions = slice(versionsToBuild);
System.out.println(slicedVersions.stream()
.map(i -> i[0])
.collect(Collectors.joining(", ", "Running test on versions: ", "")));
return slicedVersions;
}

private static <T> List<T> slice(List<T> items) {
try {
int sliceTotal = Integer.parseUnsignedInt(
System.getProperty("eu.xenit.gradle.integration.slice.total", "1"));
int sliceIndex = Integer.parseUnsignedInt(
System.getProperty("eu.xenit.gradle.integration.slice.index", "0"));
int itemsPerSlice = (int)Math.ceil(items.size()/(float)sliceTotal);
System.out.println("Executing slice "+(sliceIndex+1)+"/"+sliceTotal+ " with "+itemsPerSlice+" items per slice");
return items.subList(itemsPerSlice*sliceIndex, Math.min(itemsPerSlice*(sliceIndex+1), items.size()));
} catch (NumberFormatException e) {
return items;
}
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package eu.xenit.gradle.testrunner.versions;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.Comparator;
import org.gradle.util.GradleVersion;

@JsonIgnoreProperties(ignoreUnknown = true)
public class GradleVersionSpec {
private String version;
private boolean snapshot;
private boolean broken;
private String rcFor;

public String getVersion() {
return version;
}

public void setVersion(String version) {
this.version = version;
}

public boolean isSnapshot() {
return snapshot;
}

public void setSnapshot(boolean snapshot) {
this.snapshot = snapshot;
}

public boolean isBroken() {
return broken;
}

public void setBroken(boolean broken) {
this.broken = broken;
}

public String getRcFor() {
return rcFor;
}

public void setRcFor(String rcFor) {
this.rcFor = rcFor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package eu.xenit.gradle.testrunner.versions;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.gradle.util.GradleVersion;

public class VersionFetcher {
private static List<GradleVersionSpec> fetchAllVersions() {
ObjectMapper mapper = new ObjectMapper();

try {
CollectionType type = mapper.getTypeFactory().constructCollectionType(List.class, GradleVersionSpec.class);
return mapper.readerFor(type).readValue(new URL("https://services.gradle.org/versions/all"));
} catch (MalformedURLException | JsonMappingException | JsonParseException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

public static boolean isRelease(GradleVersionSpec versionSpec) {
GradleVersion gradleVersion = GradleVersion.version(versionSpec.getVersion());
return !versionSpec.isSnapshot() && versionSpec.getRcFor().isEmpty() && Objects.equals(gradleVersion.getBaseVersion(), gradleVersion);
}

public static boolean isBroken(GradleVersionSpec versionSpec) {
return versionSpec.isBroken();
}

public static Predicate<GradleVersionSpec> greaterThan(String version) {
return versionSpec -> GradleVersion.version(versionSpec.getVersion()).compareTo(GradleVersion.version(version)) > 0;
}

public static boolean firstPointRelease(GradleVersionSpec versionSpec) {
return GradleVersion.version(versionSpec.getVersion()).getBaseVersion().getVersion().endsWith(".0");
}

public static Stream<GradleVersionSpec> fetchVersions() {
return fetchAllVersions()
.stream()
.filter(((Predicate<? super GradleVersionSpec>) GradleVersionSpec::isBroken).negate());
}

}

0 comments on commit 14fcf4b

Please sign in to comment.