Skip to content

Commit 64fea60

Browse files
Resolve latest patches per major Gradle version in CI workflow (#11635)
feat: resolve latest patches per major Gradle version nit: change latest property from `*.version` to `*.latest` Merge branch 'master' into daniel.mohedano/gradle-latest-patches Co-authored-by: daniel.mohedano <daniel.mohedano@datadoghq.com>
1 parent da24e73 commit 64fea60

7 files changed

Lines changed: 109 additions & 20 deletions

File tree

.github/scripts/dependency_age.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
MAVEN_SEARCH_URL = "https://search.maven.org/solrsearch/select"
2121
MAVEN_REPO_URL = "https://repo1.maven.org/maven2"
2222
DEFAULT_MIN_AGE_HOURS = 48
23+
# Oldest Gradle major release we track a latest-patch for. The legacy Gradle instrumentation
24+
# targets Gradle 3.0+ (the `gradle-3.0` module), so older majors are never exercised.
25+
OLDEST_TRACKED_GRADLE_MAJOR = 3
2326

2427

2528
@dataclass(frozen=True)
@@ -171,7 +174,7 @@ def select_gradle_release(args: argparse.Namespace) -> int:
171174
if published_at <= cutoff:
172175
candidates.append(Candidate(version=version, published_at=published_at))
173176

174-
return emit_selection_result(
177+
status = emit_selection_result(
175178
label="Gradle",
176179
github_output=args.github_output,
177180
candidates=candidates,
@@ -181,6 +184,26 @@ def select_gradle_release(args: argparse.Namespace) -> int:
181184
current_version=args.current_version,
182185
)
183186

187+
# Also emit the newest eligible stable patch for every major release, as ready-to-write
188+
# `gradle.latest.<major>=<version>` property lines. The Gradle smoke tests use these to
189+
# resolve the "oldest" Gradle version dynamically (the latest patch of the major that the
190+
# current Gradle TestKit still supports), so the tested floor follows Gradle automatically
191+
# instead of being hardcoded.
192+
latest_by_major = {
193+
major: candidate
194+
for major, candidate in newest_stable_per_major(candidates).items()
195+
if major >= OLDEST_TRACKED_GRADLE_MAJOR
196+
}
197+
block = "\n".join(
198+
f"gradle.latest.{major}={candidate.version}"
199+
for major, candidate in sorted(latest_by_major.items())
200+
)
201+
emit_outputs({"latest_by_major": block}, args.github_output)
202+
for major, candidate in sorted(latest_by_major.items()):
203+
print(f"Latest eligible stable Gradle {major}.x: {candidate.version}")
204+
205+
return status
206+
184207

185208
# select latest Maven artifact release that is at least MIN_DEPENDENCY_AGE_HOURS hours old
186209
def select_maven_release(args: argparse.Namespace) -> int:
@@ -283,6 +306,27 @@ def _version_sort_key(version: str) -> tuple:
283306
return (tuple(release), not bool(prerelease), tuple(prerelease))
284307

285308

309+
# parse the leading integer of a version string as its major release number
310+
def _major_version(version: str) -> int:
311+
match = re.match(r"\s*(\d+)", version)
312+
if not match:
313+
raise ValueError(f"Cannot determine major version from '{version}'")
314+
return int(match.group(1))
315+
316+
317+
# group candidates by major release and keep the newest one in each group
318+
def newest_stable_per_major(candidates: list[Candidate]) -> dict[int, Candidate]:
319+
newest: dict[int, Candidate] = {}
320+
for candidate in candidates:
321+
major = _major_version(candidate.version)
322+
current = newest.get(major)
323+
if current is None or _version_sort_key(candidate.version) > _version_sort_key(
324+
current.version
325+
):
326+
newest[major] = candidate
327+
return newest
328+
329+
286330
# emit selection result to stdout and GitHub Actions output file for select-gradle and select-maven
287331
def emit_selection_result(
288332
*,

.github/workflows/update-smoke-test-latest-versions.yaml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ jobs:
3535
gradle_props="dd-smoke-tests/gradle/src/test/resources/latest-tool-versions.properties"
3636
maven_props="dd-smoke-tests/maven/src/test/resources/latest-tool-versions.properties"
3737
get_prop() { grep "^$1=" "$2" 2>/dev/null | cut -d= -f2 || true; }
38-
echo "gradle_version=$(get_prop gradle.version "$gradle_props")" >> "$GITHUB_OUTPUT"
39-
echo "maven_version=$(get_prop maven.version "$maven_props")" >> "$GITHUB_OUTPUT"
40-
echo "surefire_version=$(get_prop maven-surefire.version "$maven_props")" >> "$GITHUB_OUTPUT"
38+
echo "gradle_version=$(get_prop gradle.latest "$gradle_props")" >> "$GITHUB_OUTPUT"
39+
echo "maven_version=$(get_prop maven.latest "$maven_props")" >> "$GITHUB_OUTPUT"
40+
echo "surefire_version=$(get_prop maven-surefire.latest "$maven_props")" >> "$GITHUB_OUTPUT"
4141
4242
- name: Resolve latest eligible Gradle version
4343
id: gradle
@@ -77,6 +77,7 @@ jobs:
7777
env:
7878
GRADLE_VERSION: ${{ steps.gradle.outputs.version }}
7979
GRADLE_PUBLISHED: ${{ steps.gradle.outputs.published_at }}
80+
GRADLE_LATEST_BY_MAJOR: ${{ steps.gradle.outputs.latest_by_major }}
8081
MAVEN_VERSION: ${{ steps.maven.outputs.version }}
8182
MAVEN_PUBLISHED: ${{ steps.maven.outputs.published_at }}
8283
SUREFIRE_VERSION: ${{ steps.surefire.outputs.version }}
@@ -96,14 +97,17 @@ jobs:
9697
printf '%s\n' \
9798
"# Pinned latest eligible stable versions (>=${MIN_DEPENDENCY_AGE_HOURS}h old) for CI Visibility Gradle smoke tests." \
9899
"# Updated automatically by the update-smoke-test-latest-versions workflow." \
99-
"gradle.version=${GRADLE_VERSION}" \
100+
"gradle.latest=${GRADLE_VERSION}" \
101+
"# Latest eligible stable patch per Gradle major release. Used to resolve the \"oldest\" smoke-test" \
102+
"# Gradle version (the latest patch of the oldest major the current TestKit supports)." \
103+
"${GRADLE_LATEST_BY_MAJOR}" \
100104
> dd-smoke-tests/gradle/src/test/resources/latest-tool-versions.properties
101105
102106
printf '%s\n' \
103107
"# Pinned latest eligible stable versions (>=${MIN_DEPENDENCY_AGE_HOURS}h old) for CI Visibility Maven smoke tests." \
104108
"# Updated automatically by the update-smoke-test-latest-versions workflow." \
105-
"maven.version=${MAVEN_VERSION}" \
106-
"maven-surefire.version=${SUREFIRE_VERSION}" \
109+
"maven.latest=${MAVEN_VERSION}" \
110+
"maven-surefire.latest=${SUREFIRE_VERSION}" \
107111
> dd-smoke-tests/maven/src/test/resources/latest-tool-versions.properties
108112
109113
- name: Check for changes

dd-smoke-tests/gradle/src/test/java/datadog/smoketest/AbstractGradleTest.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
3131
public abstract class AbstractGradleTest extends CiVisibilitySmokeTest {
3232

33-
protected static final String LATEST_GRADLE_VERSION = getLatestGradleVersion();
33+
private static final Properties TOOL_VERSIONS = loadToolVersions();
34+
protected static final String LATEST_GRADLE_VERSION = toolVersion("gradle.latest");
3435

3536
// test resources use this instead of ".gradle" to avoid unwanted evaluation
3637
private static final String GRADLE_TEST_RESOURCE_EXTENSION = ".gradleTest";
@@ -247,7 +248,7 @@ protected void givenConfigurationCacheIsCompatibleWithCurrentPlatform(
247248
}
248249
}
249250

250-
private static String getLatestGradleVersion() {
251+
private static Properties loadToolVersions() {
251252
Properties properties = new Properties();
252253
try (InputStream stream =
253254
AbstractGradleTest.class
@@ -261,6 +262,18 @@ private static String getLatestGradleVersion() {
261262
} catch (IOException e) {
262263
throw new RuntimeException(e);
263264
}
264-
return properties.getProperty("gradle.version");
265+
return properties;
266+
}
267+
268+
protected static String toolVersion(String key) {
269+
String value = TOOL_VERSIONS.getProperty(key);
270+
if (value == null) {
271+
throw new IllegalStateException(
272+
"Missing '"
273+
+ key
274+
+ "' in latest-tool-versions.properties; re-run the "
275+
+ "update-smoke-test-latest-versions workflow.");
276+
}
277+
return value;
265278
}
266279
}

dd-smoke-tests/gradle/src/test/java/datadog/smoketest/GradleDaemonSmokeTest.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void stopGradleTestKitDaemons() {
6363

6464
@TableTest({
6565
"scenario | gradleVersion | projectName | successExpected | expectedTraces | expectedCoverages",
66-
"succeed-old-gradle-4.10 | 4.10 | test-succeed-old-gradle | true | 5 | 1 ",
66+
"succeed-old-gradle-oldest | oldest | test-succeed-old-gradle | true | 5 | 1 ",
6767
"succeed-legacy | 7.6.4 | test-succeed-legacy-instrumentation | true | 5 | 1 ",
6868
"succeed-multi-module-legacy | 7.6.4 | test-succeed-multi-module-legacy-instrumentation | true | 7 | 2 ",
6969
"succeed-multi-forks-legacy | 7.6.4 | test-succeed-multi-forks-legacy-instrumentation | true | 6 | 2 ",
@@ -117,9 +117,8 @@ void testNew(
117117
int expectedTraces,
118118
int expectedCoverages)
119119
throws IOException {
120-
String resolvedGradleVersion = resolveLatest(gradleVersion);
121120
runGradleTest(
122-
resolvedGradleVersion,
121+
gradleVersion,
123122
projectName,
124123
configurationCache,
125124
successExpected,
@@ -159,8 +158,27 @@ void testJunit4ClassOrdering(
159158
verifyTestOrder(mockBackend.waitForEvents(eventsNumber), expectedOrder);
160159
}
161160

162-
private static String resolveLatest(String gradleVersion) {
163-
return "latest".equals(gradleVersion) ? LATEST_GRADLE_VERSION : gradleVersion;
161+
// Resolves the symbolic versions used in the scenario tables:
162+
// - "latest": the newest eligible Gradle release
163+
// - "oldest": the latest patch of the oldest major the current Gradle TestKit still supports
164+
// Any other value is treated as a concrete version and returned as-is.
165+
private static String resolveVersion(String gradleVersion) {
166+
if ("latest".equals(gradleVersion)) {
167+
return LATEST_GRADLE_VERSION;
168+
}
169+
if ("oldest".equals(gradleVersion)) {
170+
return oldestSupportedGradleVersion();
171+
}
172+
return gradleVersion;
173+
}
174+
175+
private static String oldestSupportedGradleVersion() {
176+
// The oldest major the current Gradle TestKit can run is dictated by Gradle itself; tracking it
177+
// dynamically (rather than hardcoding a version) means the floor follows TestKit automatically.
178+
// We test the latest patch of that major rather than its initial release for stability.
179+
int oldestSupportedMajor =
180+
DefaultGradleConnector.MINIMUM_SUPPORTED_GRADLE_VERSION.getMajorVersion();
181+
return toolVersion("gradle.latest." + oldestSupportedMajor);
164182
}
165183

166184
private static void givenGradleVersionIsSupportedByCurrentGradleTestKit(String gradleVersion) {
@@ -183,6 +201,7 @@ private void runGradleTest(
183201
int expectedTraces,
184202
int expectedCoverages)
185203
throws IOException {
204+
gradleVersion = resolveVersion(gradleVersion);
186205
givenGradleVersionIsCompatibleWithCurrentJvm(gradleVersion);
187206
givenGradleVersionIsSupportedByCurrentGradleTestKit(gradleVersion);
188207
givenConfigurationCacheIsCompatibleWithCurrentPlatform(configurationCache);
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
# Pinned latest eligible stable versions (>=48h old) for CI Visibility Gradle smoke tests.
22
# Updated automatically by the update-smoke-test-latest-versions workflow.
3-
gradle.version=9.5.1
3+
gradle.latest=9.5.1
4+
# Latest eligible stable patch per Gradle major release. Used to resolve the "oldest" smoke-test
5+
# Gradle version (the latest patch of the oldest major the current TestKit supports).
6+
gradle.latest.3=3.5.1
7+
gradle.latest.4=4.10.3
8+
gradle.latest.5=5.6.4
9+
gradle.latest.6=6.9.4
10+
gradle.latest.7=7.6.6
11+
gradle.latest.8=8.14.5
12+
gradle.latest.9=9.5.1

dd-smoke-tests/maven/src/test/java/datadog/smoketest/MavenSmokeTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,13 +587,13 @@ private static Properties loadLatestToolVersions() {
587587
}
588588

589589
private static String getLatestMavenVersion() {
590-
String version = loadLatestToolVersions().getProperty("maven.version");
590+
String version = loadLatestToolVersions().getProperty("maven.latest");
591591
LOGGER.info("Will run the 'latest' tests with Maven version {}", version);
592592
return version;
593593
}
594594

595595
private static String getLatestMavenSurefireVersion() {
596-
String version = loadLatestToolVersions().getProperty("maven-surefire.version");
596+
String version = loadLatestToolVersions().getProperty("maven-surefire.latest");
597597
LOGGER.info("Will run the 'latest' tests with Maven Surefire version {}", version);
598598
return version;
599599
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Pinned latest eligible stable versions (>=48h old) for CI Visibility Maven smoke tests.
22
# Updated automatically by the update-smoke-test-latest-versions workflow.
3-
maven.version=4.0.0-beta-3
4-
maven-surefire.version=3.5.5
3+
maven.latest=4.0.0-beta-3
4+
maven-surefire.latest=3.5.5

0 commit comments

Comments
 (0)