Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion .github/scripts/dependency_age.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
MAVEN_SEARCH_URL = "https://search.maven.org/solrsearch/select"
MAVEN_REPO_URL = "https://repo1.maven.org/maven2"
DEFAULT_MIN_AGE_HOURS = 48
# Oldest Gradle major release we track a latest-patch for. The legacy Gradle instrumentation
# targets Gradle 3.0+ (the `gradle-3.0` module), so older majors are never exercised.
OLDEST_TRACKED_GRADLE_MAJOR = 3


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

return emit_selection_result(
status = emit_selection_result(
label="Gradle",
github_output=args.github_output,
candidates=candidates,
Expand All @@ -181,6 +184,26 @@ def select_gradle_release(args: argparse.Namespace) -> int:
current_version=args.current_version,
)

# Also emit the newest eligible stable patch for every major release, as ready-to-write
# `gradle.latest.<major>=<version>` property lines. The Gradle smoke tests use these to
# resolve the "oldest" Gradle version dynamically (the latest patch of the major that the
# current Gradle TestKit still supports), so the tested floor follows Gradle automatically
# instead of being hardcoded.
latest_by_major = {
major: candidate
for major, candidate in newest_stable_per_major(candidates).items()
if major >= OLDEST_TRACKED_GRADLE_MAJOR
}
block = "\n".join(
f"gradle.latest.{major}={candidate.version}"
for major, candidate in sorted(latest_by_major.items())
)
emit_outputs({"latest_by_major": block}, args.github_output)
for major, candidate in sorted(latest_by_major.items()):
print(f"Latest eligible stable Gradle {major}.x: {candidate.version}")

return status


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


# parse the leading integer of a version string as its major release number
def _major_version(version: str) -> int:
match = re.match(r"\s*(\d+)", version)
if not match:
raise ValueError(f"Cannot determine major version from '{version}'")
return int(match.group(1))


# group candidates by major release and keep the newest one in each group
def newest_stable_per_major(candidates: list[Candidate]) -> dict[int, Candidate]:
newest: dict[int, Candidate] = {}
for candidate in candidates:
major = _major_version(candidate.version)
current = newest.get(major)
if current is None or _version_sort_key(candidate.version) > _version_sort_key(
current.version
):
newest[major] = candidate
return newest


# emit selection result to stdout and GitHub Actions output file for select-gradle and select-maven
def emit_selection_result(
*,
Expand Down
16 changes: 10 additions & 6 deletions .github/workflows/update-smoke-test-latest-versions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ jobs:
gradle_props="dd-smoke-tests/gradle/src/test/resources/latest-tool-versions.properties"
maven_props="dd-smoke-tests/maven/src/test/resources/latest-tool-versions.properties"
get_prop() { grep "^$1=" "$2" 2>/dev/null | cut -d= -f2 || true; }
echo "gradle_version=$(get_prop gradle.version "$gradle_props")" >> "$GITHUB_OUTPUT"
echo "maven_version=$(get_prop maven.version "$maven_props")" >> "$GITHUB_OUTPUT"
echo "surefire_version=$(get_prop maven-surefire.version "$maven_props")" >> "$GITHUB_OUTPUT"
echo "gradle_version=$(get_prop gradle.latest "$gradle_props")" >> "$GITHUB_OUTPUT"
echo "maven_version=$(get_prop maven.latest "$maven_props")" >> "$GITHUB_OUTPUT"
echo "surefire_version=$(get_prop maven-surefire.latest "$maven_props")" >> "$GITHUB_OUTPUT"

- name: Resolve latest eligible Gradle version
id: gradle
Expand Down Expand Up @@ -77,6 +77,7 @@ jobs:
env:
GRADLE_VERSION: ${{ steps.gradle.outputs.version }}
GRADLE_PUBLISHED: ${{ steps.gradle.outputs.published_at }}
GRADLE_LATEST_BY_MAJOR: ${{ steps.gradle.outputs.latest_by_major }}
MAVEN_VERSION: ${{ steps.maven.outputs.version }}
MAVEN_PUBLISHED: ${{ steps.maven.outputs.published_at }}
SUREFIRE_VERSION: ${{ steps.surefire.outputs.version }}
Expand All @@ -96,14 +97,17 @@ jobs:
printf '%s\n' \
"# Pinned latest eligible stable versions (>=${MIN_DEPENDENCY_AGE_HOURS}h old) for CI Visibility Gradle smoke tests." \
"# Updated automatically by the update-smoke-test-latest-versions workflow." \
"gradle.version=${GRADLE_VERSION}" \
"gradle.latest=${GRADLE_VERSION}" \
"# Latest eligible stable patch per Gradle major release. Used to resolve the \"oldest\" smoke-test" \
"# Gradle version (the latest patch of the oldest major the current TestKit supports)." \
"${GRADLE_LATEST_BY_MAJOR}" \
> dd-smoke-tests/gradle/src/test/resources/latest-tool-versions.properties

printf '%s\n' \
"# Pinned latest eligible stable versions (>=${MIN_DEPENDENCY_AGE_HOURS}h old) for CI Visibility Maven smoke tests." \
"# Updated automatically by the update-smoke-test-latest-versions workflow." \
"maven.version=${MAVEN_VERSION}" \
"maven-surefire.version=${SUREFIRE_VERSION}" \
"maven.latest=${MAVEN_VERSION}" \
"maven-surefire.latest=${SUREFIRE_VERSION}" \
> dd-smoke-tests/maven/src/test/resources/latest-tool-versions.properties

- name: Check for changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public abstract class AbstractGradleTest extends CiVisibilitySmokeTest {

protected static final String LATEST_GRADLE_VERSION = getLatestGradleVersion();
private static final Properties TOOL_VERSIONS = loadToolVersions();
protected static final String LATEST_GRADLE_VERSION = toolVersion("gradle.latest");

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

private static String getLatestGradleVersion() {
private static Properties loadToolVersions() {
Properties properties = new Properties();
try (InputStream stream =
AbstractGradleTest.class
Expand All @@ -261,6 +262,18 @@ private static String getLatestGradleVersion() {
} catch (IOException e) {
throw new RuntimeException(e);
}
return properties.getProperty("gradle.version");
return properties;
}

protected static String toolVersion(String key) {
String value = TOOL_VERSIONS.getProperty(key);
if (value == null) {
throw new IllegalStateException(
"Missing '"
+ key
+ "' in latest-tool-versions.properties; re-run the "
+ "update-smoke-test-latest-versions workflow.");
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void stopGradleTestKitDaemons() {

@TableTest({
"scenario | gradleVersion | projectName | successExpected | expectedTraces | expectedCoverages",
"succeed-old-gradle-4.10 | 4.10 | test-succeed-old-gradle | true | 5 | 1 ",
"succeed-old-gradle-oldest | oldest | test-succeed-old-gradle | true | 5 | 1 ",
"succeed-legacy | 7.6.4 | test-succeed-legacy-instrumentation | true | 5 | 1 ",
"succeed-multi-module-legacy | 7.6.4 | test-succeed-multi-module-legacy-instrumentation | true | 7 | 2 ",
"succeed-multi-forks-legacy | 7.6.4 | test-succeed-multi-forks-legacy-instrumentation | true | 6 | 2 ",
Expand Down Expand Up @@ -117,9 +117,8 @@ void testNew(
int expectedTraces,
int expectedCoverages)
throws IOException {
String resolvedGradleVersion = resolveLatest(gradleVersion);
runGradleTest(
resolvedGradleVersion,
gradleVersion,
projectName,
configurationCache,
successExpected,
Expand Down Expand Up @@ -159,8 +158,27 @@ void testJunit4ClassOrdering(
verifyTestOrder(mockBackend.waitForEvents(eventsNumber), expectedOrder);
}

private static String resolveLatest(String gradleVersion) {
return "latest".equals(gradleVersion) ? LATEST_GRADLE_VERSION : gradleVersion;
// Resolves the symbolic versions used in the scenario tables:
// - "latest": the newest eligible Gradle release
// - "oldest": the latest patch of the oldest major the current Gradle TestKit still supports
// Any other value is treated as a concrete version and returned as-is.
private static String resolveVersion(String gradleVersion) {
if ("latest".equals(gradleVersion)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: FYI I didn't see any test using the "latest" marker.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the testLegacy scenarios all are either pinned or using oldest, but in the testNew scenarios almost all of them use latest as the Gradle version

return LATEST_GRADLE_VERSION;
}
if ("oldest".equals(gradleVersion)) {
return oldestSupportedGradleVersion();
}
return gradleVersion;
}

private static String oldestSupportedGradleVersion() {
// The oldest major the current Gradle TestKit can run is dictated by Gradle itself; tracking it
// dynamically (rather than hardcoding a version) means the floor follows TestKit automatically.
// We test the latest patch of that major rather than its initial release for stability.
int oldestSupportedMajor =
DefaultGradleConnector.MINIMUM_SUPPORTED_GRADLE_VERSION.getMajorVersion();
return toolVersion("gradle.latest." + oldestSupportedMajor);
}

private static void givenGradleVersionIsSupportedByCurrentGradleTestKit(String gradleVersion) {
Expand All @@ -183,6 +201,7 @@ private void runGradleTest(
int expectedTraces,
int expectedCoverages)
throws IOException {
gradleVersion = resolveVersion(gradleVersion);
givenGradleVersionIsCompatibleWithCurrentJvm(gradleVersion);
givenGradleVersionIsSupportedByCurrentGradleTestKit(gradleVersion);
givenConfigurationCacheIsCompatibleWithCurrentPlatform(configurationCache);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Pinned latest eligible stable versions (>=48h old) for CI Visibility Gradle smoke tests.
# Updated automatically by the update-smoke-test-latest-versions workflow.
gradle.version=9.5.1
gradle.latest=9.5.1
# Latest eligible stable patch per Gradle major release. Used to resolve the "oldest" smoke-test
# Gradle version (the latest patch of the oldest major the current TestKit supports).
gradle.latest.3=3.5.1
gradle.latest.4=4.10.3
gradle.latest.5=5.6.4
gradle.latest.6=6.9.4
gradle.latest.7=7.6.6
gradle.latest.8=8.14.5
gradle.latest.9=9.5.1
Original file line number Diff line number Diff line change
Expand Up @@ -587,13 +587,13 @@ private static Properties loadLatestToolVersions() {
}

private static String getLatestMavenVersion() {
String version = loadLatestToolVersions().getProperty("maven.version");
String version = loadLatestToolVersions().getProperty("maven.latest");
LOGGER.info("Will run the 'latest' tests with Maven version {}", version);
return version;
}

private static String getLatestMavenSurefireVersion() {
String version = loadLatestToolVersions().getProperty("maven-surefire.version");
String version = loadLatestToolVersions().getProperty("maven-surefire.latest");
LOGGER.info("Will run the 'latest' tests with Maven Surefire version {}", version);
return version;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Pinned latest eligible stable versions (>=48h old) for CI Visibility Maven smoke tests.
# Updated automatically by the update-smoke-test-latest-versions workflow.
maven.version=4.0.0-beta-3
maven-surefire.version=3.5.5
maven.latest=4.0.0-beta-3
maven-surefire.latest=3.5.5