From 75c7bed6c68b4d7179eaedaa0b7575592df2c125 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 27 Feb 2024 23:16:17 -0800 Subject: [PATCH] Add external links to `spring-boot-dependencies` Update the BOM `Library` model to support external links that we can use in documentation and the release process. An additional `checkLinks` task has also been added to verify returned HTTP status codes. Closes gh-39779 Co-authored-by: Andy Wilkinson --- buildSrc/build.gradle | 1 + .../boot/build/bom/BomExtension.java | 76 ++- .../boot/build/bom/BomPlugin.java | 2 +- .../boot/build/bom/CheckLinks.java | 85 ++++ .../boot/build/bom/Library.java | 54 ++- .../bom/bomr/UpgradeApplicatorTests.java | 5 +- .../spring-boot-dependencies/build.gradle | 449 +++++++++++++++++- 7 files changed, 666 insertions(+), 6 deletions(-) create mode 100644 buildSrc/src/main/java/org/springframework/boot/build/bom/CheckLinks.java diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 870f4a7355..eeb0d02146 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -47,6 +47,7 @@ dependencies { implementation("commons-codec:commons-codec:${versions.commonsCodec}") implementation("de.undercouch.download:de.undercouch.download.gradle.plugin:5.5.0") implementation("io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}") + implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1") implementation("org.apache.maven:maven-embedder:${versions.maven}") implementation("org.asciidoctor:asciidoctor-gradle-jvm:3.3.2") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}") diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/BomExtension.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/BomExtension.java index 7fa7ed2f00..650c411b2a 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/bom/BomExtension.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/BomExtension.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import javax.inject.Inject; import javax.xml.parsers.DocumentBuilderFactory; @@ -66,11 +67,14 @@ import org.springframework.boot.build.bom.Library.VersionAlignment; import org.springframework.boot.build.bom.bomr.version.DependencyVersion; import org.springframework.boot.build.mavenplugin.MavenExec; import org.springframework.util.FileCopyUtils; +import org.springframework.util.PropertyPlaceholderHelper; +import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; /** * DSL extensions for {@link BomPlugin}. * * @author Andy Wilkinson + * @author Phillip Webb */ public class BomExtension { @@ -119,7 +123,8 @@ public class BomExtension { this.project, this.libraries, libraryHandler.groups) : null; addLibrary(new Library(name, libraryHandler.calendarName, libraryVersion, libraryHandler.groups, - libraryHandler.prohibitedVersions, libraryHandler.considerSnapshots, versionAlignment)); + libraryHandler.prohibitedVersions, libraryHandler.considerSnapshots, versionAlignment, + libraryHandler.links)); } public void effectiveBomArtifact() { @@ -227,6 +232,8 @@ public class BomExtension { private AlignWithVersionHandler alignWithVersion; + private final Map> links = new HashMap<>(); + @Inject public LibraryHandler(String version) { this.version = version; @@ -263,6 +270,12 @@ public class BomExtension { action.execute(this.alignWithVersion); } + public void links(Action action) { + LinksHandler handler = new LinksHandler(); + action.execute(handler); + this.links.putAll(handler.links); + } + public static class ProhibitedHandler { private String reason; @@ -398,6 +411,67 @@ public class BomExtension { } + public static class LinksHandler { + + private final Map> links = new HashMap<>(); + + public void site(String linkTemplate) { + site(asFactory(linkTemplate)); + } + + public void site(Function linkFactory) { + add("site", linkFactory); + } + + public void github(String linkTemplate) { + github(asFactory(linkTemplate)); + } + + public void github(Function linkFactory) { + add("github", linkFactory); + } + + public void javadoc(String linkTemplate) { + javadoc(asFactory(linkTemplate)); + } + + public void javadoc(Function linkFactory) { + add("javadoc", linkFactory); + } + + public void reference(String linkTemplate) { + reference(asFactory(linkTemplate)); + } + + public void reference(Function linkFactory) { + add("reference", linkFactory); + } + + public void releaseNotes(String linkTemplate) { + releaseNotes(asFactory(linkTemplate)); + } + + public void releaseNotes(Function linkFactory) { + add("releaseNotes", linkFactory); + } + + public void add(String name, String linkTemplate) { + add(name, asFactory(linkTemplate)); + } + + public void add(String name, Function linkFactory) { + this.links.put(name, linkFactory); + } + + private Function asFactory(String linkTemplate) { + return (version) -> { + PlaceholderResolver resolver = (name) -> "version".equals(name) ? version.toString() : null; + return new PropertyPlaceholderHelper("{", "}").replacePlaceholders(linkTemplate, resolver); + }; + } + + } + public static class UpgradeHandler { private UpgradePolicy upgradePolicy; diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/BomPlugin.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/BomPlugin.java index 0cc7b41890..07474bd79b 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/bom/BomPlugin.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/BomPlugin.java @@ -66,8 +66,8 @@ public class BomPlugin implements Plugin { project.getTasks().named("check").configure((check) -> check.dependsOn(checkBom)); project.getTasks().create("bomrUpgrade", UpgradeBom.class, bom); project.getTasks().create("moveToSnapshots", MoveToSnapshots.class, bom); + project.getTasks().register("checkLinks", CheckLinks.class, bom); new PublishingCustomizer(project, bom).customize(); - } private void createApiEnforcedConfiguration(Project project) { diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/CheckLinks.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/CheckLinks.java new file mode 100644 index 0000000000..81e53106bb --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/CheckLinks.java @@ -0,0 +1,85 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.build.bom; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.inject.Inject; + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.gradle.api.DefaultTask; +import org.gradle.api.tasks.TaskAction; +import org.gradle.internal.impldep.org.apache.http.client.config.CookieSpecs; + +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.RestTemplate; + +/** + * Task to check that links are working. + * + * @author Andy Wilkinson + * @author Phillip Webb + */ +public class CheckLinks extends DefaultTask { + + private final BomExtension bom; + + @Inject + public CheckLinks(BomExtension bom) { + this.bom = bom; + } + + @TaskAction + void releaseNotes() { + RequestConfig config = RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build(); + CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(config).build(); + HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); + RestTemplate restTemplate = new RestTemplate(requestFactory); + restTemplate.setErrorHandler(new IgnoringErrorHandler()); + for (Library library : this.bom.getLibraries()) { + library.getLinks().forEach((name, link) -> { + URI uri; + try { + uri = new URI(link); + ResponseEntity response = restTemplate.exchange(uri, HttpMethod.HEAD, null, String.class); + System.out.println("[%3d] %s - %s (%s)".formatted(response.getStatusCode().value(), + library.getName(), name, uri)); + } + catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + }); + } + } + + static class IgnoringErrorHandler extends DefaultResponseErrorHandler { + + @Override + public void handleError(ClientHttpResponse response) throws IOException { + } + + } + +} diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/Library.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/Library.java index 8fa5f37f2f..0337c28208 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/bom/Library.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/Library.java @@ -17,6 +17,7 @@ package org.springframework.boot.build.bom; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -24,6 +25,8 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.TreeMap; +import java.util.function.Function; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.VersionRange; @@ -59,6 +62,8 @@ public class Library { private final VersionAlignment versionAlignment; + private final Map> links; + /** * Create a new {@code Library} with the given {@code name}, {@code version}, and * {@code groups}. @@ -70,9 +75,11 @@ public class Library { * @param prohibitedVersions version of the library that are prohibited * @param considerSnapshots whether to consider snapshots * @param versionAlignment version alignment, if any, for the library + * @param links a list of HTTP links relevant to the library */ public Library(String name, String calendarName, LibraryVersion version, List groups, - List prohibitedVersions, boolean considerSnapshots, VersionAlignment versionAlignment) { + List prohibitedVersions, boolean considerSnapshots, VersionAlignment versionAlignment, + Map> links) { this.name = name; this.calendarName = (calendarName != null) ? calendarName : name; this.version = version; @@ -82,6 +89,7 @@ public class Library { this.prohibitedVersions = prohibitedVersions; this.considerSnapshots = considerSnapshots; this.versionAlignment = versionAlignment; + this.links = Collections.unmodifiableMap(links); } public String getName() { @@ -116,6 +124,12 @@ public class Library { return this.versionAlignment; } + public Map getLinks() { + Map links = new TreeMap<>(); + this.links.forEach((name, linkFactory) -> links.put(name, linkFactory.apply(this.version))); + return Collections.unmodifiableMap(links); + } + /** * A version or range of versions that are prohibited from being used in a bom. */ @@ -184,6 +198,44 @@ public class Library { return this.version; } + public int[] componentInts() { + return Arrays.stream(parts()).mapToInt(Integer::parseInt).toArray(); + } + + public String major() { + return parts()[0]; + } + + public String minor() { + return parts()[1]; + } + + public String patch() { + return parts()[2]; + } + + @Override + public String toString() { + return this.version.toString(); + } + + public String toString(String separator) { + return this.version.toString().replace(".", separator); + } + + public String forAntora() { + String[] parts = parts(); + String result = parts[0] + "." + parts[1]; + if (toString().endsWith("SNAPSHOT")) { + result += "-SNAPSHOT"; + } + return result; + } + + private String[] parts() { + return toString().split("[\\.-]"); + } + } /** diff --git a/buildSrc/src/test/java/org/springframework/boot/build/bom/bomr/UpgradeApplicatorTests.java b/buildSrc/src/test/java/org/springframework/boot/build/bom/bomr/UpgradeApplicatorTests.java index 7ef6061fb1..7466dfc04c 100644 --- a/buildSrc/src/test/java/org/springframework/boot/build/bom/bomr/UpgradeApplicatorTests.java +++ b/buildSrc/src/test/java/org/springframework/boot/build/bom/bomr/UpgradeApplicatorTests.java @@ -21,6 +21,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.util.Collections; import java.util.Properties; import org.junit.jupiter.api.Test; @@ -53,7 +54,7 @@ class UpgradeApplicatorTests { FileCopyUtils.copy(new File("src/test/resources/gradle.properties"), gradleProperties); new UpgradeApplicator(bom.toPath(), gradleProperties.toPath()) .apply(new Upgrade(new Library("ActiveMQ", null, new LibraryVersion(DependencyVersion.parse("5.15.11")), - null, null, false, null), DependencyVersion.parse("5.16"))); + null, null, false, null, Collections.emptyMap()), DependencyVersion.parse("5.16"))); String bomContents = Files.readString(bom.toPath()); assertThat(bomContents).hasSize(originalContents.length() - 3); } @@ -66,7 +67,7 @@ class UpgradeApplicatorTests { FileCopyUtils.copy(new File("src/test/resources/gradle.properties"), gradleProperties); new UpgradeApplicator(bom.toPath(), gradleProperties.toPath()) .apply(new Upgrade(new Library("Kotlin", null, new LibraryVersion(DependencyVersion.parse("1.3.70")), null, - null, false, null), DependencyVersion.parse("1.4"))); + null, false, null, Collections.emptyMap()), DependencyVersion.parse("1.4"))); Properties properties = new Properties(); try (InputStream in = new FileInputStream(gradleProperties)) { properties.load(in); diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a9798584a0..7e99c94fd8 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -49,6 +49,12 @@ bom { "activemq-web" ] } + links { + site("https://activemq.apache.org") + reference("https://activemq.apache.org/components/classic/documentation") + releaseNotes { version -> "https://activemq.apache.org/components/classic/download/classic-%02d-%02d-%02d" + .formatted(version.componentInts()) } + } } library("Angus Mail", "2.0.2") { group("org.eclipse.angus") { @@ -64,6 +70,10 @@ bom { "smtp" ] } + links { + site("https://github.com/eclipse-ee4j/angus-mail") + releaseNotes("https://github.com/eclipse-ee4j/angus-mail/releases/tag/{version}") + } } library("Artemis", "2.32.0") { group("org.apache.activemq") { @@ -82,6 +92,10 @@ bom { "artemis-service-extensions" ] } + links { + site("https://activemq.apache.org/components/artemis") + releaseNotes("https://activemq.apache.org/components/artemis/download/release-notes-{version}") + } } library("AspectJ", "1.9.21") { group("org.aspectj") { @@ -91,6 +105,10 @@ bom { "aspectjweaver" ] } + links { + site("https://eclipse.dev/aspectj") + releaseNotes("https://github.com/eclipse-aspectj/aspectj/blob/master/docs/release/README-{version}.adoc") + } } library("AssertJ", "${assertjVersion}") { group("org.assertj") { @@ -98,6 +116,10 @@ bom { "assertj-bom" ] } + links { + site("https://assertj.github.io/doc/") + releaseNotes("https://github.com/assertj/assertj/releases/tag/assertj-build-{version}") + } } library("Awaitility", "4.2.0") { group("org.awaitility") { @@ -108,6 +130,10 @@ bom { "awaitility-scala" ] } + links { + site("http://www.awaitility.org/") + releaseNotes { version -> "https://github.com/awaitility/awaitility/wiki/ReleaseNotes%s.%s".formatted(version.major(), version.minor()) } + } } library("Zipkin Reporter", "3.3.0") { group("io.zipkin.reporter2") { @@ -115,6 +141,10 @@ bom { "zipkin-reporter-bom" ] } + links { + site("https://github.com/openzipkin/zipkin-reporter-java") + releaseNotes("https://github.com/openzipkin/zipkin-reporter-java/releases/tag/{version}") + } } library("Brave", "6.0.1") { group("io.zipkin.brave") { @@ -122,6 +152,10 @@ bom { "brave-bom" ] } + links { + site("https://github.com/openzipkin/brave") + releaseNotes("https://github.com/openzipkin/brave/releases/tag/{version}") + } } library("Build Helper Maven Plugin", "3.5.0") { group("org.codehaus.mojo") { @@ -129,6 +163,10 @@ bom { "build-helper-maven-plugin" ] } + links { + site("https://www.mojohaus.org/build-helper-maven-plugin") + releaseNotes("https://github.com/mojohaus/build-helper-maven-plugin/releases/tag/{version}") + } } library("Byte Buddy", "1.14.12") { group("net.bytebuddy") { @@ -137,6 +175,11 @@ bom { "byte-buddy-agent" ] } + links { + site("https://bytebuddy.net/") + reference("https://bytebuddy.net/#/tutorial") + releaseNotes("https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-{version}") + } } library("cache2k", "2.6.1.Final") { group("org.cache2k") { @@ -149,6 +192,10 @@ bom { "cache2k-spring" ] } + links { + site("https://cache2k.org") + releaseNotes("https://github.com/cache2k/cache2k/releases/tag/v{version}") + } } library("Caffeine", "3.1.8") { group("com.github.ben-manes.caffeine") { @@ -159,6 +206,11 @@ bom { "simulator" ] } + links { + site("https://github.com/ben-manes/caffeine") + reference("https://github.com/ben-manes/caffeine/wiki") + releaseNotes("https://github.com/ben-manes/caffeine/releases/tag/v{version}") + } } library("Cassandra Driver", "4.17.0") { group("com.datastax.oss") { @@ -169,6 +221,12 @@ bom { "java-driver-core" ] } + links { + site { version -> "https://docs.datastax.com/en/developer/java-driver/%s.%s/" + .formatted(version.major(), version.minor()) } + releaseNotes { version -> "https://docs.datastax.com/en/developer/java-driver/%s.%s/changelog/#%s" + .formatted(version.major(), version.minor(), version.toString("-")) } + } } library("Classmate", "1.7.0") { group("com.fasterxml") { @@ -176,6 +234,9 @@ bom { "classmate" ] } + links { + site("https://github.com/FasterXML/java-classmate") + } } library("Commons Codec", "${commonsCodecVersion}") { group("commons-codec") { @@ -183,6 +244,10 @@ bom { "commons-codec" ] } + links { + site("https://commons.apache.org/proper/commons-codec") + releaseNotes("https://commons.apache.org/proper/commons-codec/changes-report.html#a{version}") + } } library("Commons DBCP2", "2.11.0") { group("org.apache.commons") { @@ -192,6 +257,9 @@ bom { } ] } + links { + site("https://commons.apache.org/proper/commons-dbcp") + } } library("Commons Lang3", "3.14.0") { group("org.apache.commons") { @@ -199,6 +267,9 @@ bom { "commons-lang3" ] } + links { + site("https://commons.apache.org/proper/commons-lang") + } } library("Commons Pool", "1.6") { group("commons-pool") { @@ -213,6 +284,9 @@ bom { "commons-pool2" ] } + links { + site("https://commons.apache.org/proper/commons-pool") + } } library("Couchbase Client", "3.5.3") { group("com.couchbase.client") { @@ -220,6 +294,9 @@ bom { "java-client" ] } + links { + site("https://docs.couchbase.com/java-sdk/current/hello-world/overview.html") + } } library("Crac", "1.4.0") { group("org.crac") { @@ -241,6 +318,10 @@ bom { "dependency-management-plugin" ] } + links { + site("https://github.com/spring-gradle-plugins/dependency-management-plugin") + releaseNotes("https://github.com/spring-gradle-plugins/dependency-management-plugin/releases/tag/v{version}") + } } library("Derby", "10.16.1.1") { prohibit { @@ -272,6 +353,10 @@ bom { } ] } + links { + site("https://www.ehcache.org/") + releaseNotes("https://github.com/ehcache/ehcache3/releases/tag/v{version}") + } } library("Elasticsearch Client", "8.11.4") { group("org.elasticsearch.client") { @@ -289,6 +374,9 @@ bom { "elasticsearch-java" ] } + links { + releaseNotes("https://www.elastic.co/guide/en/elasticsearch/reference/current/release-notes-{version}.html") + } } library("Flyway", "9.22.3") { group("org.flywaydb") { @@ -303,6 +391,9 @@ bom { "flyway-maven-plugin" ] } + links { + site("https://documentation.red-gate.com/flyway") + } } library("FreeMarker", "2.3.32") { group("org.freemarker") { @@ -310,6 +401,10 @@ bom { "freemarker" ] } + links { + site("https://freemarker.apache.org") + releaseNotes { version -> "https://freemarker.apache.org/docs/versions_%s.html".formatted(version.toString("_")) } + } } library("Git Commit ID Maven Plugin", "6.0.0") { group("io.github.git-commit-id") { @@ -317,6 +412,10 @@ bom { "git-commit-id-maven-plugin" ] } + links { + site("https://github.com/git-commit-id/git-commit-id-maven-plugin") + releaseNotes("https://github.com/git-commit-id/git-commit-id-maven-plugin/releases/tag/v{version}") + } } library("Glassfish JAXB", "4.0.4") { group("org.glassfish.jaxb") { @@ -342,6 +441,10 @@ bom { "graphql-java" ] } + links { + site("https://www.graphql-java.com/") + releaseNotes("https://github.com/graphql-java/graphql-java/releases/tag/v{version}") + } } library("Groovy", "4.0.18") { group("org.apache.groovy") { @@ -349,6 +452,9 @@ bom { "groovy-bom" ] } + links { + site("http://groovy-lang.org") + } } library("Gson", "2.10.1") { group("com.google.code.gson") { @@ -356,6 +462,10 @@ bom { "gson" ] } + links { + site("https://github.com/google/gson") + releaseNotes("https://github.com/google/gson/releases/tag/gson-parent-{version}") + } } library("H2", "2.2.224") { group("com.h2database") { @@ -363,6 +473,10 @@ bom { "h2" ] } + links { + site("https://www.h2database.com") + releaseNotes("https://github.com/h2database/h2database/releases/tag/version-{version}") + } } library("Hamcrest", "${hamcrestVersion}") { group("org.hamcrest") { @@ -380,6 +494,10 @@ bom { "hazelcast-spring" ] } + links { + site("https://hazelcast.com") + releaseNotes("https://github.com/hazelcast/hazelcast/releases/tag/v{version}") + } } library("Hibernate", "6.4.4.Final") { group("org.hibernate.orm") { @@ -401,6 +519,12 @@ bom { "hibernate-vibur" ] } + links { + site("https://hibernate.org/orm") + javadoc { version -> "https://docs.jboss.org/hibernate/orm/%s.%s/javadocs".formatted(version.major(), version.minor()) } + reference { version -> "https://hibernate.org/orm/documentation/%s.%s".formatted(version.major(), version.minor()) } + releaseNotes { version -> "https://github.com/hibernate/hibernate-orm/releases/tag/%s".formatted(version.toString().replace(".Final", "")) } + } } library("Hibernate Validator", "8.0.1.Final") { group("org.hibernate.validator") { @@ -432,6 +556,10 @@ bom { } ] } + links { + site("https://www.htmlunit.org") + releaseNotes("https://github.com/HtmlUnit/htmlunit/releases/tag/{version}") + } } library("HttpAsyncClient", "4.1.5") { group("org.apache.httpcomponents") { @@ -474,6 +602,10 @@ bom { "infinispan-bom" ] } + links { + site("https://infinispan.org/") + releaseNotes("https://github.com/infinispan/infinispan/releases/tag/{version}") + } } library("InfluxDB Java", "2.24") { group("org.influxdb") { @@ -481,6 +613,10 @@ bom { "influxdb-java" ] } + links { + site("https://github.com/influxdata/influxdb-java") + releaseNotes("https://github.com/influxdata/influxdb-java/releases/tag/influxdb-java-{version}") + } } library("Jackson Bom", "${jacksonVersion}") { group("com.fasterxml.jackson") { @@ -495,6 +631,10 @@ bom { "jakarta.activation-api" ] } + links { + site("https://github.com/jakartaee/jaf-api") + releaseNotes("https://github.com/jakartaee/jaf-api/releases/tag/{version}") + } } library("Jakarta Annotation", "2.1.1") { group("jakarta.annotation") { @@ -537,6 +677,10 @@ bom { "jakarta.mail-api" ] } + links { + site("https://github.com/jakartaee/mail-api") + releaseNotes("https://github.com/jakartaee/mail-api/releases/tag/{version}") + } } library("Jakarta Management", "1.1.4") { group("jakarta.management.j2ee") { @@ -673,6 +817,10 @@ bom { "jedis" ] } + links { + site("https://github.com/redis/jedis") + releaseNotes("https://github.com/redis/jedis/releases/tag/v{version}") + } } library("Jersey", "3.1.5") { group("org.glassfish.jersey") { @@ -680,6 +828,10 @@ bom { "jersey-bom" ] } + links { + site("https://github.com/eclipse-ee4j/jersey") + releaseNotes("https://github.com/eclipse-ee4j/jersey/releases/tag/{version}") + } } library("Jetty Reactive HTTPClient", "4.0.3") { group("org.eclipse.jetty") { @@ -699,6 +851,10 @@ bom { "jetty-bom" ] } + links { + site("https://eclipse.dev/jetty") + releaseNotes("https://github.com/jetty/jetty.project/releases/tag/jetty-{version}") + } } library("JMustache", "1.16") { group("com.samskivert") { @@ -719,6 +875,10 @@ bom { "jooq-codegen-maven" ] } + links { + site("https://www.jooq.org") + releaseNotes("https://github.com/jOOQ/jOOQ/releases/tag/version-{version}") + } } library("Json Path", "2.9.0") { group("com.jayway.jsonpath") { @@ -727,6 +887,10 @@ bom { "json-path-assert" ] } + links { + site("https://github.com/json-path/JsonPath") + releaseNotes("https://github.com/json-path/JsonPath/releases/tag/json-path-{version}") + } } library("Json-smart", "2.5.0") { group("net.minidev") { @@ -734,6 +898,10 @@ bom { "json-smart" ] } + links { + site("https://github.com/netplex/json-smart-v2") + releaseNotes("https://github.com/netplex/json-smart-v2/releases/tag/{version}") + } } library("JsonAssert", "1.5.1") { group("org.skyscreamer") { @@ -741,6 +909,10 @@ bom { "jsonassert" ] } + links { + site("https://github.com/skyscreamer/JSONassert") + releaseNotes("https://github.com/skyscreamer/JSONassert/releases/tag/jsonassert-{version}") + } } library("JTDS", "1.3.1") { group("net.sourceforge.jtds") { @@ -762,6 +934,12 @@ bom { "junit-bom" ] } + links { + site("https://junit.org/junit5") + javadoc("https://junit.org/junit5/docs/{version}/api") + reference("https://junit.org/junit5/docs/{version}/user-guide") + releaseNotes("https://junit.org/junit5/docs/{version}/release-notes") + } } library("Kafka", "3.6.1") { group("org.apache.kafka") { @@ -806,6 +984,10 @@ bom { "trogdor" ] } + links { + site("https://kafka.apache.org") + releaseNotes("https://downloads.apache.org/kafka/{version}/RELEASE_NOTES.html") + } } library("Kotlin", "${kotlinVersion}") { group("org.jetbrains.kotlin") { @@ -816,6 +998,10 @@ bom { "kotlin-maven-plugin" ] } + links { + site("https://kotlinlang.org/") + releaseNotes("https://github.com/JetBrains/kotlin/releases/tag/v{version}") + } } library("Kotlin Coroutines", "1.8.0") { group("org.jetbrains.kotlinx") { @@ -823,6 +1009,10 @@ bom { "kotlinx-coroutines-bom" ] } + links { + site("https://github.com/Kotlin/kotlinx.coroutines") + releaseNotes("https://github.com/Kotlin/kotlinx.coroutines/releases/tag/{version}") + } } library("Kotlin Serialization", "1.6.3") { group("org.jetbrains.kotlinx") { @@ -830,6 +1020,10 @@ bom { "kotlinx-serialization-bom" ] } + links { + site("https://github.com/Kotlin/kotlinx.serialization") + releaseNotes("https://github.com/Kotlin/kotlinx.serialization/releases/tag/v{version}") + } } library("Lettuce", "6.3.1.RELEASE") { group("io.lettuce") { @@ -837,6 +1031,10 @@ bom { "lettuce-core" ] } + links { + site("https://github.com/lettuce-io/lettuce-core") + releaseNotes("https://github.com/lettuce-io/lettuce-core/releases/tag/{version}") + } } library("Liquibase", "4.26.0") { group("org.liquibase") { @@ -848,6 +1046,10 @@ bom { "liquibase-maven-plugin" ] } + links { + site("https://www.liquibase.com") + releaseNotes("https://github.com/liquibase/liquibase/releases/tag/v{version}") + } } library("Log4j2", "2.23.0") { group("org.apache.logging.log4j") { @@ -855,6 +1057,10 @@ bom { "log4j-bom" ] } + links { + site("https://logging.apache.org/log4j") + releaseNotes("https://github.com/apache/logging-log4j2/releases/tag/rel%2F{version}") + } } library("Logback", "1.4.14") { group("ch.qos.logback") { @@ -864,6 +1070,9 @@ bom { "logback-core" ] } + links { + site("https://logback.qos.ch") + } } library("Lombok", "1.18.30") { group("org.projectlombok") { @@ -871,6 +1080,9 @@ bom { "lombok" ] } + links { + site("https://projectlombok.org") + } } library("MariaDB", "3.3.3") { group("org.mariadb.jdbc") { @@ -878,6 +1090,10 @@ bom { "mariadb-java-client" ] } + links { + site("https://mariadb.com/kb/en/mariadb-connector-j/") + releaseNotes { version -> "https://mariadb.com/kb/en/mariadb-connector-j-%s-release-notes/".formatted(version.toString("-")) } + } } library("Maven AntRun Plugin", "3.1.0") { group("org.apache.maven.plugins") { @@ -1017,6 +1233,11 @@ bom { "micrometer-bom" ] } + links { + site("https://micrometer.io") + reference { version -> "https://docs.micrometer.io/micrometer/reference/%s.%s".formatted(version.major(), version.minor()) } + releaseNotes("https://github.com/micrometer-metrics/micrometer/releases/tag/v{version}") + } } library("Micrometer Tracing", "1.3.0-M1") { considerSnapshots() @@ -1026,6 +1247,11 @@ bom { "micrometer-tracing-bom" ] } + links { + site("https://micrometer.io") + reference { version -> "https://docs.micrometer.io/tracing/reference/%s.%s".formatted(version.major(), version.minor()) } + releaseNotes("https://github.com/micrometer-metrics/tracing/releases/tag/v{version}") + } } library("Mockito", "5.10.0") { group("org.mockito") { @@ -1033,6 +1259,10 @@ bom { "mockito-bom" ] } + links { + site("https://site.mockito.org/") + releaseNotes("https://github.com/mockito/mockito/releases/tag/v{version}") + } } library("MongoDB", "4.11.1") { group("org.mongodb") { @@ -1045,6 +1275,10 @@ bom { "mongodb-driver-sync" ] } + links { + site("https://github.com/mongodb/mongo-java-driver") + releaseNotes("https://github.com/mongodb/mongo-java-driver/releases/tag/r{version}") + } } library("MSSQL JDBC", "12.6.1.jre11") { prohibit { @@ -1056,6 +1290,11 @@ bom { "mssql-jdbc" ] } + links { + site("https://github.com/microsoft/mssql-jdbc") + releaseNotes { version -> "https://github.com/microsoft/mssql-jdbc/releases/tag/v%s" + .formatted(version.toString().replace(".jre11", "")) } + } } library("MySQL", "8.3.0") { group("com.mysql") { @@ -1072,6 +1311,10 @@ bom { "native-maven-plugin" ] } + links { + site("https://github.com/graalvm/native-build-tools") + releaseNotes("https://github.com/graalvm/native-build-tools/releases/tag/{version}") + } } library("NekoHTML", "1.9.22") { group("net.sourceforge.nekohtml") { @@ -1090,6 +1333,10 @@ bom { "neo4j-java-driver" ] } + links { + site("https://github.com/neo4j/neo4j-java-driver") + releaseNotes("https://github.com/neo4j/neo4j-java-driver/releases/tag/{version}") + } } library("Netty", "4.1.107.Final") { group("io.netty") { @@ -1097,6 +1344,9 @@ bom { "netty-bom" ] } + links { + site("https://netty.io") + } } library("OkHttp", "4.12.0") { group("com.squareup.okhttp3") { @@ -1111,6 +1361,10 @@ bom { "opentelemetry-bom" ] } + links { + site("https://github.com/open-telemetry/opentelemetry-java") + releaseNotes("https://github.com/open-telemetry/opentelemetry-java/releases/tag/v{version}") + } } library("Oracle Database", "21.9.0.0") { group("com.oracle.database.jdbc") { @@ -1139,6 +1393,10 @@ bom { "postgresql" ] } + links { + site("https://github.com/pgjdbc/pgjdbc") + releaseNotes("https://github.com/pgjdbc/pgjdbc/releases/tag/REL{version}") + } } library("Prometheus Client", "0.16.0") { group("io.prometheus") { @@ -1146,6 +1404,10 @@ bom { "simpleclient_bom" ] } + links { + site("https://github.com/prometheus/client_java") + releaseNotes("https://github.com/prometheus/client_java/releases/tag/parent-{version}") + } } library("Pulsar", "3.2.0") { group("org.apache.pulsar") { @@ -1153,6 +1415,11 @@ bom { "pulsar-bom" ] } + links { + site("https://pulsar.apache.org") + reference { version -> "https://pulsar.apache.org/docs/%s.%s.x".formatted(version.major(), version.minor()) } + releaseNotes("https://pulsar.apache.org/release-notes/versioned/pulsar-{version}") + } } library("Pulsar Reactive", "0.5.3") { group("org.apache.pulsar") { @@ -1164,6 +1431,10 @@ bom { "pulsar-client-reactive-producer-cache-caffeine" ] } + links { + site("https://github.com/apache/pulsar-client-reactive") + releaseNotes("https://github.com/apache/pulsar-client-reactive/releases/tag/v{version}") + } } library("Quartz", "2.3.2") { group("org.quartz-scheduler") { @@ -1175,6 +1446,9 @@ bom { "quartz-jobs" ] } + links { + site("https://github.com/quartz-scheduler/quartz") + } } library("QueryDSL", "5.1.0") { group("com.querydsl") { @@ -1182,6 +1456,10 @@ bom { "querydsl-bom" ] } + links { + site("https://github.com/querydsl/querydsl") + releaseNotes { version -> "https://github.com/querydsl/querydsl/releases/tag/QUERYDSL_%s".formatted(version.toString("_")) } + } } library("R2DBC H2", "1.0.0.RELEASE") { considerSnapshots() @@ -1219,6 +1497,10 @@ bom { "r2dbc-pool" ] } + links { + site("https://github.com/r2dbc/r2dbc-pool") + releaseNotes("https://github.com/r2dbc/r2dbc-pool/releases/tag/v{version}") + } } library("R2DBC Postgresql", "1.0.4.RELEASE") { considerSnapshots() @@ -1250,6 +1532,10 @@ bom { "amqp-client" ] } + links { + site("https://github.com/rabbitmq/rabbitmq-java-client") + releaseNotes("https://github.com/rabbitmq/rabbitmq-java-client/releases/tag/v{version}") + } } library("Rabbit Stream Client", "0.15.0") { group("com.rabbitmq") { @@ -1257,6 +1543,10 @@ bom { "stream-client" ] } + links { + site("https://github.com/rabbitmq/rabbitmq-stream-java-client") + releaseNotes("https://github.com/rabbitmq/rabbitmq-stream-java-client/releases/tag/v{version}") + } } library("Reactive Streams", "1.0.4") { group("org.reactivestreams") { @@ -1273,6 +1563,10 @@ bom { "reactor-bom" ] } + links { + site("https://projectreactor.io/") + releaseNotes("https://github.com/reactor/reactor/releases/tag/{version}") + } } library("REST Assured", "5.4.0") { group("io.rest-assured") { @@ -1291,6 +1585,10 @@ bom { "rsocket-bom" ] } + links { + site("https://github.com/rsocket/rsocket-java") + releaseNotes("https://github.com/rsocket/rsocket-java/releases/tag/{version}") + } } library("RxJava3", "3.1.8") { group("io.reactivex.rxjava3") { @@ -1380,6 +1678,13 @@ bom { "spring-boot-maven-plugin" ] } + links { + site("https://spring.io/projects/spring-boot") + github("https://github.com/spring-projects/spring-boot") + javadoc("https://docs.spring.io/spring-boot/docs/{version}/api") + reference("https://docs.spring.io/spring-boot/docs/{version}/reference/htmlsingle") + releaseNotes("https://github.com/spring-projects/spring-boot/releases/tag/v{version}") + } } library("SAAJ Impl", "3.0.3") { group("com.sun.xml.messaging.saaj") { @@ -1394,6 +1699,10 @@ bom { "selenium-bom" ] } + links { + site("https://www.selenium.dev") + releaseNotes("https://github.com/SeleniumHQ/selenium/releases/tag/selenium-{version}") + } } library("Selenium HtmlUnit", "4.13.0") { group("org.seleniumhq.selenium") { @@ -1401,6 +1710,10 @@ bom { "htmlunit-driver" ] } + links { + site("https://github.com/SeleniumHQ/htmlunit-driver") + releaseNotes("https://github.com/SeleniumHQ/htmlunit-driver/releases/tag/htmlunit3-driver-{version}") + } } library("SendGrid", "4.10.2") { group("com.sendgrid") { @@ -1408,6 +1721,10 @@ bom { "sendgrid-java" ] } + links { + site("https://github.com/sendgrid/sendgrid-java") + releaseNotes("https://github.com/sendgrid/sendgrid-java/releases/tag/{version}") + } } library("SLF4J", "2.0.12") { group("org.slf4j") { @@ -1440,6 +1757,13 @@ bom { "spring-amqp-bom" ] } + links { + site("https://spring.io/projects/spring-amqp") + github("https://github.com/spring-projects/spring-amqp") + javadoc("https://docs.spring.io/spring-amqp/docs/{version}/api") + reference("https://docs.spring.io/spring-amqp/reference/{version}") + releaseNotes("https://github.com/spring-projects/spring-amqp/releases/tag/v{version}") + } } library("Spring Authorization Server", "1.3.0-M2") { considerSnapshots() @@ -1448,6 +1772,14 @@ bom { "spring-security-oauth2-authorization-server" ] } + links { + site("https://spring.io/projects/spring-authorization-server") + github("https://github.com/spring-projects/spring-authorization-server") + javadoc("https://docs.spring.io/spring-authorization-server/docs/{version}/api") + reference { version -> "https://docs.spring.io/spring-authorization-server/reference/%s" + .formatted(version.forAntora()) } + releaseNotes("https://github.com/spring-projects/spring-authorization-server/releases/tag/{version}") + } } library("Spring Batch", "5.1.1") { considerSnapshots() @@ -1456,6 +1788,13 @@ bom { "spring-batch-bom" ] } + links { + site("https://spring.io/projects/spring-batch") + github("http://github.com/spring-projects/spring-batch") + javadoc("https://docs.spring.io/spring-batch/docs/{version}/api") + reference { version -> "https://docs.spring.io/spring-batch/reference/%s".formatted(version.forAntora()) } + releaseNotes("https://github.com/spring-projects/spring-batch/releases/tag/v{version}") + } } library("Spring Data Bom", "2023.1.3") { considerSnapshots() @@ -1465,7 +1804,11 @@ bom { "spring-data-bom" ] } - + links { + site("https://spring.io/projects/spring-data") + github("https://github.com/spring-projects/spring-data-bom") + releaseNotes("https://github.com/spring-projects/spring-data-bom/releases/tag/{version}") + } } library("Spring Framework", "${springFrameworkVersion}") { considerSnapshots() @@ -1474,6 +1817,13 @@ bom { "spring-framework-bom" ] } + links { + site("https://spring.io/projects/spring-framework") + github("https://github.com/spring-projects/spring-framework") + javadoc("https://docs.spring.io/spring-framework/docs/{version}/javadoc-api") + reference("https://docs.spring.io/spring-framework/reference/{version}") + releaseNotes("https://github.com/spring-projects/spring-framework/releases/tag/v{version}") + } } library("Spring GraphQL", "1.3.0-M1") { considerSnapshots() @@ -1483,6 +1833,13 @@ bom { "spring-graphql-test" ] } + links { + site("https://spring.io/projects/spring-graphql") + github("https://github.com/spring-projects/spring-graphql") + javadoc("https://docs.spring.io/spring-graphql/docs/{version}/api") + reference { version -> "https://docs.spring.io/spring-graphql/reference/%s".formatted(version.forAntora()) } + releaseNotes("https://github.com/spring-projects/spring-graphql/releases/tag/v{version}") + } } library("Spring HATEOAS", "2.2.0") { considerSnapshots() @@ -1491,6 +1848,13 @@ bom { "spring-hateoas" ] } + links { + site("https://spring.io/projects/spring-hateoas") + github("https://github.com/spring-projects/spring-hateoas") + javadoc("https://docs.spring.io/spring-hateoas/docs/{version}/api") + reference("https://docs.spring.io/spring-hateoas/docs/{version}/reference/html") + releaseNotes("https://github.com/spring-projects/spring-hateoas/releases/tag/{version}") + } } library("Spring Integration", "6.3.0-M1") { considerSnapshots() @@ -1499,6 +1863,13 @@ bom { "spring-integration-bom" ] } + links { + site("https://spring.io/projects/spring-integration") + github("http://github.com/spring-projects/spring-integration") + javadoc("https://docs.spring.io/spring-integration/docs/{version}/api") + reference { version -> "https://docs.spring.io/spring-integration/reference/%s".formatted(version.forAntora()) } + releaseNotes("https://github.com/spring-projects/spring-integration/releases/tag/v{version}") + } } library("Spring Kafka", "3.2.0-M1") { considerSnapshots() @@ -1508,6 +1879,13 @@ bom { "spring-kafka-test" ] } + links { + site("https://spring.io/projects/spring-kafka") + github("http://github.com/spring-projects/spring-kafka") + javadoc("https://docs.spring.io/spring-kafka/docs/{version}/api") + reference { version -> "https://docs.spring.io/spring-kafka/reference/%s".formatted(version.forAntora()) } + releaseNotes("https://github.com/spring-projects/spring-kafka/releases/tag/v{version}") + } } library("Spring LDAP", "3.2.2") { considerSnapshots() @@ -1519,6 +1897,13 @@ bom { "spring-ldap-test" ] } + links { + site("https://spring.io/projects/spring-ldap") + github("http://github.com/spring-projects/spring-ldap") + javadoc("https://docs.spring.io/spring-ldap/docs/{version}/api") + reference("https://docs.spring.io/spring-ldap/reference/{version}") + releaseNotes("https://github.com/spring-projects/spring-ldap/releases/tag/{version}") + } } library("Spring Pulsar", "1.1.0-M1") { considerSnapshots() @@ -1527,6 +1912,13 @@ bom { "spring-pulsar-bom" ] } + links { + site("https://spring.io/projects/spring-pulsar") + github("http://github.com/spring-projects/spring-pulsar") + javadoc("https://docs.spring.io/spring-pulsar/docs/{version}/api/") + reference("https://docs.spring.io/spring-pulsar/docs/{version}/reference") + releaseNotes("https://github.com/spring-projects/spring-pulsar/releases/tag/v{version}") + } } library("Spring RESTDocs", "3.0.1") { considerSnapshots() @@ -1535,6 +1927,13 @@ bom { "spring-restdocs-bom" ] } + links { + site("https://spring.io/projects/spring-restdocs") + github("http://github.com/spring-projects/spring-restdocs") + javadoc("https://docs.spring.io/spring-restdocs/docs/{version}/api/") + reference("https://docs.spring.io/spring-restdocs/docs/{version}/reference/htmlsingle/") + releaseNotes("https://github.com/spring-projects/spring-restdocs/releases/tag/v{version}") + } } library("Spring Retry", "2.0.5") { considerSnapshots() @@ -1543,6 +1942,10 @@ bom { "spring-retry" ] } + links { + site("https://github.com/spring-projects/spring-retry") + releaseNotes("https://github.com/spring-projects/spring-retry/releases/tag/v{version}") + } } library("Spring Security", "6.3.0-M2") { considerSnapshots() @@ -1551,6 +1954,13 @@ bom { "spring-security-bom" ] } + links { + site("https://spring.io/projects/spring-security") + github("https://github.com/spring-projects/spring-security") + javadoc("https://docs.spring.io/spring-security/site/docs/{version}/api") + reference { version -> "https://docs.spring.io/spring-security/reference/%s".formatted(version.forAntora()) } + releaseNotes("https://github.com/spring-projects/spring-security/releases/tag/{version}") + } } library("Spring Session", "3.3.0-M2") { considerSnapshots() @@ -1563,6 +1973,13 @@ bom { "spring-session-bom" ] } + links { + site("https://spring.io/projects/spring-session") + github("https://github.com/spring-projects/spring-session") + javadoc("https://docs.spring.io/spring-session/docs/{version}/api") + reference { version -> "https://docs.spring.io/spring-session/reference/%s".formatted(version.forAntora()) } + releaseNotes("https://github.com/spring-projects/spring-session/releases/tag/{version}") + } } library("Spring WS", "4.0.10") { considerSnapshots() @@ -1571,6 +1988,13 @@ bom { "spring-ws-bom" ] } + links { + site("https://spring.io/projects/spring-ws") + github("http://github.com/spring-projects/spring-ws") + javadoc("https://docs.spring.io/spring-ws/docs/{version}/api") + reference("https://docs.spring.io/spring-ws/docs/{version}/reference/html") + releaseNotes("https://github.com/spring-projects/spring-ws/releases/tag/v{version}") + } } library("SQLite JDBC", "3.45.1.0") { group("org.xerial") { @@ -1578,6 +2002,10 @@ bom { "sqlite-jdbc" ] } + links { + site("https://github.com/xerial/sqlite-jdbc") + releaseNotes("https://github.com/xerial/sqlite-jdbc/releases/tag/{version}") + } } library("Testcontainers", "1.19.6") { group("org.testcontainers") { @@ -1585,6 +2013,10 @@ bom { "testcontainers-bom" ] } + links { + site("https://java.testcontainers.org") + releaseNotes("https://github.com/testcontainers/testcontainers-java/releases/tag/{version}") + } } library("Thymeleaf", "3.1.2.RELEASE") { group("org.thymeleaf") { @@ -1593,6 +2025,10 @@ bom { "thymeleaf-spring6" ] } + links { + site("https://www.thymeleaf.org/") + releaseNotes("https://github.com/thymeleaf/thymeleaf/releases/tag/thymeleaf-{version}") + } } library("Thymeleaf Extras Data Attribute", "2.0.1") { group("com.github.mxab.thymeleaf.extras") { @@ -1631,6 +2067,9 @@ bom { "tomcat-embed-websocket" ] } + links { + site("https://tomcat.apache.org") + } } library("UnboundID LDAPSDK", "6.0.11") { group("com.unboundid") { @@ -1688,6 +2127,10 @@ bom { "xmlunit-placeholders" ] } + links { + site("https://github.com/xmlunit/xmlunit") + releaseNotes("https://github.com/xmlunit/xmlunit/releases/tag/v{version}") + } } library("Yasson", "3.0.3") { group("org.eclipse") { @@ -1695,6 +2138,10 @@ bom { "yasson" ] } + links { + site("https://github.com/eclipse-ee4j/yasson") + releaseNotes("https://github.com/eclipse-ee4j/yasson/releases/tag/{version}") + } } }