Skip to content

Commit be610e3

Browse files
committed
feat(spring): Automatically curate Spring Boot VCS paths
Use the GitHub API to look up Spring Boot project paths. These paths do not follow a clear pattern and vary depending on the version. Signed-off-by: Sebastian Schuberth <[email protected]>
1 parent 3bc2369 commit be610e3

File tree

4 files changed

+99
-0
lines changed

4 files changed

+99
-0
lines changed

plugins/package-curation-providers/spring/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,10 @@ dependencies {
2626
api(projects.plugins.packageCurationProviders.packageCurationProviderApi)
2727

2828
ksp(projects.plugins.packageCurationProviders.packageCurationProviderApi)
29+
30+
implementation(projects.model)
31+
implementation(projects.utils.commonUtils)
32+
implementation(projects.utils.ortUtils)
33+
34+
implementation(libs.kotlinx.serialization.json)
2935
}

plugins/package-curation-providers/spring/src/main/kotlin/SpringPackageCurationProvider.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package org.ossreviewtoolkit.plugins.packagecurationproviders.spring
2222
import org.ossreviewtoolkit.model.Package
2323
import org.ossreviewtoolkit.model.PackageCuration
2424
import org.ossreviewtoolkit.model.PackageCurationData
25+
import org.ossreviewtoolkit.model.VcsInfoCurationData
2526
import org.ossreviewtoolkit.plugins.api.OrtPlugin
2627
import org.ossreviewtoolkit.plugins.api.PluginDescriptor
2728
import org.ossreviewtoolkit.plugins.packagecurationproviders.api.PackageCurationProvider
@@ -38,6 +39,16 @@ import org.ossreviewtoolkit.plugins.packagecurationproviders.api.PackageCuration
3839
open class SpringPackageCurationProvider(
3940
override val descriptor: PluginDescriptor = SpringPackageCurationProviderFactory.descriptor
4041
) : PackageCurationProvider {
42+
val springBootProjectPaths = mutableMapOf<String, Map<String, String>>()
43+
44+
fun getSpringBootProjectPath(subProjectName: String, projectVersion: String): String {
45+
val paths = springBootProjectPaths.getOrPut(projectVersion) {
46+
getSpringProjectPaths("spring-boot", projectVersion)
47+
}
48+
49+
return paths.getValue(subProjectName)
50+
}
51+
4152
override fun getCurationsFor(packages: Collection<Package>): Set<PackageCuration> {
4253
val springPackages = packages.filter {
4354
it.id.type == "Maven" && it.id.namespace.startsWith("org.springframework")
@@ -62,6 +73,14 @@ open class SpringPackageCurationProvider(
6273
data = data.copy(isMetadataOnly = isMetadataOnly)
6374
}
6475

76+
if (pkg.vcsProcessed.url == "https://github.com/spring-projects/spring-boot.git") {
77+
runCatching {
78+
getSpringBootProjectPath(pkg.id.name, pkg.id.version)
79+
}.onSuccess { path ->
80+
data = data.copy(vcs = VcsInfoCurationData(path = path))
81+
}
82+
}
83+
6584
if (data != PackageCurationData()) {
6685
PackageCuration(pkg.id, data)
6786
} else {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (C) 2025 The ORT Project Authors (see <https://github.com/oss-review-toolkit/ort/blob/main/NOTICE>)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
package org.ossreviewtoolkit.plugins.packagecurationproviders.spring
21+
22+
import kotlinx.serialization.json.Json
23+
import kotlinx.serialization.json.jsonArray
24+
import kotlinx.serialization.json.jsonObject
25+
import kotlinx.serialization.json.jsonPrimitive
26+
27+
import org.ossreviewtoolkit.utils.common.withoutSuffix
28+
import org.ossreviewtoolkit.utils.ort.downloadText
29+
import org.ossreviewtoolkit.utils.ort.okHttpClient
30+
31+
internal fun getGitHubTree(owner: String, repo: String, revision: String): List<String> {
32+
val json = okHttpClient
33+
.downloadText("https://api.github.com/repos/$owner/$repo/git/trees/$revision?recursive=1")
34+
.getOrThrow()
35+
36+
return Json.parseToJsonElement(json).jsonObject.getValue("tree").jsonArray.map {
37+
it.jsonObject.getValue("path").jsonPrimitive.content
38+
}
39+
}
40+
41+
internal fun getSpringProjectPaths(projectName: String, projectVersion: String): Map<String, String> {
42+
val paths = getGitHubTree("spring-projects", projectName, "v$projectVersion")
43+
44+
val projectPaths = paths.mapNotNull { path ->
45+
path.withoutSuffix("/build.gradle")?.takeIf { it.startsWith(projectName) }
46+
}
47+
48+
val projectPathsByName = projectPaths.associateBy { it.substringAfterLast('/') }
49+
50+
check(projectPathsByName.size == projectPaths.size) {
51+
"Ambiguous mapping of project names to project paths."
52+
}
53+
54+
return projectPathsByName
55+
}

plugins/package-curation-providers/spring/src/test/kotlin/SpringPackageCurationProviderTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import org.ossreviewtoolkit.model.Identifier
2626
import org.ossreviewtoolkit.model.Package
2727
import org.ossreviewtoolkit.model.PackageCuration
2828
import org.ossreviewtoolkit.model.PackageCurationData
29+
import org.ossreviewtoolkit.model.VcsInfo
30+
import org.ossreviewtoolkit.model.VcsInfoCurationData
2931

3032
class SpringPackageCurationProviderTest : StringSpec({
3133
val provider = SpringPackageCurationProvider()
@@ -41,4 +43,21 @@ class SpringPackageCurationProviderTest : StringSpec({
4143
)
4244
)
4345
}
46+
47+
"Get the correct paths for Spring Boot projects" {
48+
val id = Identifier("Maven:org.springframework.boot:spring-boot-antlib:3.5.4")
49+
val pkg = Package.EMPTY.copy(
50+
id = id,
51+
vcsProcessed = VcsInfo.EMPTY.copy(url = "https://github.com/spring-projects/spring-boot.git")
52+
)
53+
54+
provider.getCurationsFor(setOf(pkg)) shouldContainExactly setOf(
55+
PackageCuration(
56+
id = id,
57+
data = PackageCurationData(
58+
vcs = VcsInfoCurationData(path = "spring-boot-project/spring-boot-tools/spring-boot-antlib")
59+
)
60+
)
61+
)
62+
}
4463
})

0 commit comments

Comments
 (0)