Skip to content

Commit 7126136

Browse files
committed
improve dependencyUpdates by providing hints for recent Jiras/commits that look relevant
1 parent d10c1a9 commit 7126136

6 files changed

Lines changed: 180 additions & 15 deletions

File tree

build-logic/src/main/groovy/org.apache.groovy-asciidoctor.gradle

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,6 @@ asciidoctor {
9595
asciidoctorj {
9696
jrubyVersion = versions.jruby
9797
version = versions.asciidoctorj
98-
resolutionStrategy {
99-
it.disableDependencyVerification()
100-
}
10198
docExtensions project(':asciidoc-extensions')
10299
modules {
103100
diagram.version(versions.asciidoctorDiagram)
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
// Dependency-update workflow enhancements for `./gradlew depUp`:
21+
// * reject candidate versions that aren't stable
22+
// * reject candidate versions whose POM declares a JDK target above our floor
23+
// * on finish, run depUpHints (git-log one-liner + Apache Jira link per outdated dep)
24+
// * on finish, run depUpCapped (in-track updates for multi-track deps like junit5/junit6)
25+
26+
def UNSTABLE = /^([\d.-]+(alpha|beta|rc|m)[\d.-]+(groovy[\d.-]+)?|20030203.000550|20031129.200437|200404\d\d|2004-03-19)$/
27+
def jdkFloor = sharedConfiguration.targetJavaVersion.get().toInteger()
28+
def jdkRejections = new java.util.concurrent.ConcurrentHashMap<String, Set<String>>()
29+
30+
// Registry of dependencies whose updates must be tracked on a capped version line.
31+
// Used for two purposes:
32+
// * hint-skip gate in depUpHints (suppress misleading cross-track bump hints)
33+
// * in-track update detection in depUpCapped (proactively warn when a newer
34+
// within-track version is available, e.g. binary-compat baseline drift)
35+
// TODO: migrate performance-test baselines ('3.0.25', '4.0.31', '5.0.5' currently hardcoded
36+
// in subprojects/performance/build.gradle:24) into versions.properties and add
37+
// matching cappedTracks entries so depUpCapped surfaces drift on those too.
38+
def cappedTracks = [
39+
[group: 'org.junit.jupiter', name: 'junit-jupiter', current: versions.junit5, maxPrefix: '5.'],
40+
[group: 'org.junit.jupiter', name: 'junit-jupiter-api', current: versions.junit5, maxPrefix: '5.'],
41+
[group: 'org.junit.jupiter', name: 'junit-jupiter-engine', current: versions.junit5, maxPrefix: '5.'],
42+
[group: 'org.junit.jupiter', name: 'junit-jupiter-params', current: versions.junit5, maxPrefix: '5.'],
43+
[group: 'org.junit.platform', name: 'junit-platform-launcher', current: versions.junit5Platform, maxPrefix: '1.'],
44+
[group: 'org.apache.groovy', name: 'groovy',
45+
current: sharedConfiguration.binaryCompatibilityBaselineVersion.get(), maxPrefix: '5.0.'],
46+
]
47+
def capByCoord = cappedTracks.collectEntries { [("${it.group}:${it.name}".toString()): it.maxPrefix] }
48+
49+
def majorJdk = { String v ->
50+
def m = (v =~ /(?:1\.)?(\d+)/)
51+
m ? m[0][1].toInteger() : 0
52+
}
53+
54+
def pomRequiredJdk = { String group, String name, String version ->
55+
def url = "https://repo1.maven.org/maven2/${group.replace('.', '/')}/$name/$version/${name}-${version}.pom"
56+
try {
57+
def xml = new groovy.xml.XmlSlurper().parseText(new URL(url).text)
58+
def vals = [
59+
xml.properties.'maven.compiler.release'.text(),
60+
xml.properties.'maven.compiler.target'.text(),
61+
xml.properties.'maven.compiler.source'.text(),
62+
xml.properties.'java.version'.text(),
63+
]
64+
xml.build.plugins.plugin.findAll { it.artifactId.text() == 'maven-compiler-plugin' }.each { p ->
65+
vals << p.configuration.release.text()
66+
vals << p.configuration.target.text()
67+
vals << p.configuration.source.text()
68+
}
69+
return vals.findAll { it }.collect(majorJdk).max() ?: 0
70+
} catch (ignored) {
71+
return 0 // fail-safe: network/parse errors never reject
72+
}
73+
}
74+
75+
tasks.named('dependencyUpdates')?.configure {
76+
gradleReleaseChannel = 'current'
77+
outputFormatter = 'plain,json'
78+
rejectVersionIf {
79+
def current = it.currentVersion.toLowerCase()
80+
def candidate = it.candidate.version.toLowerCase()
81+
if (!(current ==~ UNSTABLE) && candidate ==~ UNSTABLE) return true
82+
def required = pomRequiredJdk(it.candidate.group, it.candidate.module, it.candidate.version)
83+
if (required > jdkFloor) {
84+
def key = "${it.candidate.group}:${it.candidate.module}".toString()
85+
jdkRejections.computeIfAbsent(key) { java.util.Collections.synchronizedSet(new TreeSet<String>()) }
86+
.add("${it.candidate.version} (requires JDK $required)".toString())
87+
return true
88+
}
89+
return false
90+
}
91+
finalizedBy 'depUpHints', 'depUpCapped'
92+
}
93+
94+
tasks.register('depUpHints') {
95+
doLast {
96+
def report = new File(buildDir, 'dependencyUpdates/report.json')
97+
if (!report.exists()) return
98+
def outdated = new groovy.json.JsonSlurper().parse(report).outdated?.dependencies ?: []
99+
if (!outdated) return
100+
def hintSkipGroups = ['org.apache.groovy', 'org.codehaus.groovy'] as Set
101+
def findJira = { String term ->
102+
def proc = ['git', '-C', rootDir.absolutePath,
103+
'log', '--oneline', '-20', '--since=3 years ago', '-G', term].execute()
104+
proc.waitFor()
105+
for (line in proc.text.readLines()) {
106+
def m = (line =~ /GROOVY-\d+/)
107+
if (m.find()) return [ticket: m.group(), commit: line]
108+
}
109+
return null
110+
}
111+
println '\n--- depUpHints: latest prior bump + Jira link ---'
112+
outdated.each { d ->
113+
def newVer = d.available.release ?: d.available.milestone ?: d.available.integration
114+
println "\n${d.group}:${d.name}: ${d.version} \u2192 $newVer"
115+
if (d.group in hintSkipGroups) return
116+
def cap = capByCoord["${d.group}:${d.name}".toString()]
117+
if (cap && !newVer.startsWith(cap)) {
118+
println " (capped at ${cap}x \u2014 cross-track bump; in-track updates shown by :depUpCapped)"
119+
return
120+
}
121+
def hit = findJira(d.name)
122+
if (!hit && d.name.contains('-')) {
123+
hit = findJira(d.name.substring(0, d.name.indexOf('-')))
124+
}
125+
if (hit) {
126+
println " ${hit.commit}"
127+
println " Latest Jira: https://issues.apache.org/jira/browse/${hit.ticket}"
128+
}
129+
}
130+
if (jdkRejections) {
131+
println "\n--- Candidates rejected (JDK floor: $jdkFloor) ---"
132+
jdkRejections.sort().each { key, versions ->
133+
println "\n$key"
134+
versions.each { println " $it" }
135+
}
136+
}
137+
}
138+
}
139+
140+
tasks.register('depUpCapped') {
141+
doLast {
142+
def stableOnly = { String v -> v ==~ /\d+(\.\d+)*/ }
143+
def versionCompare = { String a, String b ->
144+
def pa = a.tokenize('.').collect { it.toInteger() }
145+
def pb = b.tokenize('.').collect { it.toInteger() }
146+
for (int i = 0; i < Math.max(pa.size(), pb.size()); i++) {
147+
int ai = i < pa.size() ? pa[i] : 0
148+
int bi = i < pb.size() ? pb[i] : 0
149+
if (ai != bi) return ai <=> bi
150+
}
151+
0
152+
}
153+
def anyReported = false
154+
cappedTracks.each { t ->
155+
def url = "https://repo1.maven.org/maven2/${t.group.replace('.', '/')}/${t.name}/maven-metadata.xml"
156+
try {
157+
def xml = new groovy.xml.XmlSlurper().parseText(new URL(url).text)
158+
def matching = xml.versioning.versions.version*.text().findAll {
159+
it.startsWith(t.maxPrefix) && stableOnly(it)
160+
}
161+
if (!matching) return
162+
def latest = matching.max(versionCompare)
163+
if (versionCompare(latest, t.current) > 0) {
164+
if (!anyReported) {
165+
println '\n--- Capped-track updates ---'
166+
anyReported = true
167+
}
168+
println " ${t.group}:${t.name}: ${t.current} \u2192 ${latest} (capped at ${t.maxPrefix}x)"
169+
}
170+
} catch (ignored) { /* skip: network/parse errors don't matter here */ }
171+
}
172+
}
173+
}

build-logic/src/main/groovy/org/apache/groovy/gradle/PerformanceTestsExtension.groovy

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@ class PerformanceTestsExtension {
7676
def groovyConf = configurations.create("perfGroovy$version") { Configuration conf ->
7777
conf.canBeResolved = true
7878
conf.canBeConsumed = false
79-
conf.resolutionStrategy {
80-
disableDependencyVerification()
81-
}
8279
conf.extendsFrom(configurations.getByName("stats"))
8380
conf.attributes {
8481
it.attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY))

build.gradle

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ plugins {
2424
id 'org.apache.groovy-core'
2525
id 'java-test-fixtures'
2626
id 'org.apache.groovy-jacoco-aggregation'
27+
id 'org.apache.groovy-dep-updates'
2728
}
2829

2930
base {
@@ -271,14 +272,6 @@ sonarqube {
271272
}
272273
}
273274

274-
def UNSTABLE = /^([\d.-]+(alpha|beta|rc|m)[\d.-]+(groovy[\d.-]+)?|20030203.000550|20031129.200437|200404\d\d|2004-03-19)$/
275-
// ignore non-stable releases
276-
tasks.named('dependencyUpdates')?.configure {
277-
gradleReleaseChannel = 'current'
278-
rejectVersionIf {
279-
!(it.currentVersion.toLowerCase() ==~ UNSTABLE) && it.candidate.version.toLowerCase() ==~ UNSTABLE
280-
}
281-
}
282275

283276
artifacts {
284277
grapesRuntimeElements file: jar.archiveFile.get().asFile, type: 'jar'

gradle/verification-metadata.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@
5454
<ignored-keys>
5555
<ignored-key id="74DAFDFD6DAE2441" reason="Key not available on any key server"/>
5656
</ignored-keys>
57+
<trusted-artifacts>
58+
<trust group="org.apache.groovy" reason="binary compatibility and performance check baselines resolved against previously-released Groovy versions"/>
59+
<trust group="org.asciidoctor" reason="asciidoctor documentation toolchain; plugin-internal configs resolve a large transitive tree including unsigned gem-related artifacts"/>
60+
<trust group="org.jruby" reason="JRuby runtime pulled in by the asciidoctor toolchain"/>
61+
<trust group="org.codehaus.groovy" reason="pre-4.x Groovy namespace: performance-check baselines against Groovy 3.x and transitive of org.asciidoctor:asciidoctorj-groovy-dsl"/>
62+
</trusted-artifacts>
5763
<trusted-keys>
5864
<trusted-key id="5A022DE16956DECDAD4EBC161FE771E34EF57D42">
5965
<trusting group="jakarta.servlet.jsp"/>

subprojects/binary-compatibility/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ rootProject.allprojects {
4242
def baseline = thisProject.configurations.create("${taskName}Baseline") {
4343
dependencies.add(thisProject.dependencies.create(baselineCoords))
4444
}
45-
baseline.resolutionStrategy.disableDependencyVerification()
4645
def singleProjectCheck = thisProject.tasks.register(taskName, JapicmpTask) {
4746
oldArchives.from(baseline)
4847
newArchives.from(files(tasks.named("jarjar")))

0 commit comments

Comments
 (0)