commit
a804355f5c
44
build.gradle
44
build.gradle
|
@ -23,7 +23,6 @@ apply plugin: 'locks'
|
||||||
apply plugin: 's101'
|
apply plugin: 's101'
|
||||||
apply plugin: 'io.spring.convention.root'
|
apply plugin: 'io.spring.convention.root'
|
||||||
apply plugin: 'org.jetbrains.kotlin.jvm'
|
apply plugin: 'org.jetbrains.kotlin.jvm'
|
||||||
apply plugin: 'org.springframework.security.update-dependencies'
|
|
||||||
apply plugin: 'org.springframework.security.update-version'
|
apply plugin: 'org.springframework.security.update-version'
|
||||||
apply plugin: 'org.springframework.security.sagan'
|
apply plugin: 'org.springframework.security.sagan'
|
||||||
apply plugin: 'org.springframework.github.milestone'
|
apply plugin: 'org.springframework.github.milestone'
|
||||||
|
@ -91,49 +90,6 @@ tasks.named("dispatchGitHubWorkflow") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named("updateDependencies") {
|
|
||||||
// we aren't Gradle 7 compatible yet
|
|
||||||
checkForGradleUpdate = false
|
|
||||||
}
|
|
||||||
|
|
||||||
updateDependenciesSettings {
|
|
||||||
gitHub {
|
|
||||||
organization = "spring-projects"
|
|
||||||
repository = "spring-security"
|
|
||||||
}
|
|
||||||
addFiles({
|
|
||||||
return [
|
|
||||||
project.file("buildSrc/src/main/groovy/io/spring/gradle/convention/CheckstylePlugin.groovy")
|
|
||||||
]
|
|
||||||
})
|
|
||||||
dependencyExcludes {
|
|
||||||
majorVersionBump()
|
|
||||||
alphaBetaVersions()
|
|
||||||
snapshotVersions()
|
|
||||||
addRule { components ->
|
|
||||||
components.withModule("org.python:jython") { selection ->
|
|
||||||
ModuleComponentIdentifier candidate = selection.getCandidate();
|
|
||||||
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
|
|
||||||
selection.reject("jython updates break integration tests");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
components.withModule("com.nimbusds:nimbus-jose-jwt") { selection ->
|
|
||||||
ModuleComponentIdentifier candidate = selection.getCandidate();
|
|
||||||
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
|
|
||||||
selection.reject("nimbus-jose-jwt gets updated when oauth2-oidc-sdk is updated to ensure consistency");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def toolchainVersion() {
|
|
||||||
if (project.hasProperty('testToolchain')) {
|
|
||||||
return project.property('testToolchain').toString().toInteger()
|
|
||||||
}
|
|
||||||
return 17
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
|
|
|
@ -2,7 +2,6 @@ plugins {
|
||||||
id "java-gradle-plugin"
|
id "java-gradle-plugin"
|
||||||
id "java"
|
id "java"
|
||||||
id "groovy"
|
id "groovy"
|
||||||
id 'com.apollographql.apollo' version '2.4.5'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
@ -42,10 +41,6 @@ gradlePlugin {
|
||||||
id = "io.spring.convention.management-configuration"
|
id = "io.spring.convention.management-configuration"
|
||||||
implementationClass = "io.spring.gradle.convention.ManagementConfigurationPlugin"
|
implementationClass = "io.spring.gradle.convention.ManagementConfigurationPlugin"
|
||||||
}
|
}
|
||||||
updateDependencies {
|
|
||||||
id = "org.springframework.security.update-dependencies"
|
|
||||||
implementationClass = "org.springframework.security.convention.versions.UpdateDependenciesPlugin"
|
|
||||||
}
|
|
||||||
updateProjectVersion {
|
updateProjectVersion {
|
||||||
id = "org.springframework.security.update-version"
|
id = "org.springframework.security.update-version"
|
||||||
implementationClass = "org.springframework.security.convention.versions.UpdateProjectVersionPlugin"
|
implementationClass = "org.springframework.security.convention.versions.UpdateProjectVersionPlugin"
|
||||||
|
@ -91,7 +86,6 @@ dependencies {
|
||||||
implementation libs.io.github.gradle.nexus.publish.plugin
|
implementation libs.io.github.gradle.nexus.publish.plugin
|
||||||
implementation 'io.projectreactor:reactor-core'
|
implementation 'io.projectreactor:reactor-core'
|
||||||
implementation libs.org.gretty.gretty
|
implementation libs.org.gretty.gretty
|
||||||
implementation libs.com.apollographql.apollo.apollo.runtime
|
|
||||||
implementation libs.com.github.ben.manes.gradle.versions.plugin
|
implementation libs.com.github.ben.manes.gradle.versions.plugin
|
||||||
implementation libs.com.github.spullara.mustache.java.compiler
|
implementation libs.com.github.spullara.mustache.java.compiler
|
||||||
implementation libs.io.spring.javaformat.spring.javaformat.gradle.plugin
|
implementation libs.io.spring.javaformat.spring.javaformat.gradle.plugin
|
||||||
|
@ -100,6 +94,7 @@ dependencies {
|
||||||
implementation libs.org.hidetake.gradle.ssh.plugin
|
implementation libs.org.hidetake.gradle.ssh.plugin
|
||||||
implementation libs.org.jfrog.buildinfo.build.info.extractor.gradle
|
implementation libs.org.jfrog.buildinfo.build.info.extractor.gradle
|
||||||
implementation libs.org.sonarsource.scanner.gradle.sonarqube.gradle.plugin
|
implementation libs.org.sonarsource.scanner.gradle.sonarqube.gradle.plugin
|
||||||
|
implementation libs.com.squareup.okhttp3.okhttp
|
||||||
|
|
||||||
testImplementation platform(libs.org.junit.junit.bom)
|
testImplementation platform(libs.org.junit.junit.bom)
|
||||||
testImplementation platform(libs.org.mockito.mockito.bom)
|
testImplementation platform(libs.org.mockito.mockito.bom)
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019-2022 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.security.convention.versions;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Scanner;
|
|
||||||
|
|
||||||
class CommandLineUtils {
|
|
||||||
static void runCommand(File dir, String... args) {
|
|
||||||
try {
|
|
||||||
Process process = new ProcessBuilder()
|
|
||||||
.directory(dir)
|
|
||||||
.command(args)
|
|
||||||
.start();
|
|
||||||
writeLinesTo(process.getInputStream(), System.out);
|
|
||||||
writeLinesTo(process.getErrorStream(), System.out);
|
|
||||||
if (process.waitFor() != 0) {
|
|
||||||
new RuntimeException("Failed to run " + Arrays.toString(args));
|
|
||||||
}
|
|
||||||
} catch (IOException | InterruptedException e) {
|
|
||||||
throw new RuntimeException("Failed to run " + Arrays.toString(args), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void writeLinesTo(InputStream input, PrintStream out) {
|
|
||||||
Scanner scanner = new Scanner(input);
|
|
||||||
while(scanner.hasNextLine()) {
|
|
||||||
out.println(scanner.nextLine());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,179 +0,0 @@
|
||||||
package org.springframework.security.convention.versions;
|
|
||||||
|
|
||||||
import com.apollographql.apollo.ApolloCall;
|
|
||||||
import com.apollographql.apollo.ApolloClient;
|
|
||||||
import com.apollographql.apollo.api.Input;
|
|
||||||
import com.apollographql.apollo.api.Response;
|
|
||||||
import com.apollographql.apollo.exception.ApolloException;
|
|
||||||
import okhttp3.Interceptor;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
import reactor.util.retry.Retry;
|
|
||||||
import reactor.util.retry.RetrySpec;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class GitHubApi {
|
|
||||||
|
|
||||||
private final ApolloClient apolloClient;
|
|
||||||
|
|
||||||
public GitHubApi(String githubToken) {
|
|
||||||
if (githubToken == null) {
|
|
||||||
throw new IllegalArgumentException("githubToken is required. You can set it using -PgitHubAccessToken=");
|
|
||||||
}
|
|
||||||
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
|
|
||||||
clientBuilder.addInterceptor(new AuthorizationInterceptor(githubToken));
|
|
||||||
this.apolloClient = ApolloClient.builder()
|
|
||||||
.serverUrl("https://api.github.com/graphql")
|
|
||||||
.okHttpClient(clientBuilder.build())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<FindCreateIssueResult> findCreateIssueInput(String owner, String name, String milestone) {
|
|
||||||
String label = "\"type: dependency-upgrade\"";
|
|
||||||
FindCreateIssueInputQuery findCreateIssueInputQuery = new FindCreateIssueInputQuery(owner, name, Input.optional(label), Input.optional(milestone));
|
|
||||||
return Mono.create( sink -> this.apolloClient.query(findCreateIssueInputQuery)
|
|
||||||
.enqueue(new ApolloCall.Callback<FindCreateIssueInputQuery.Data>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NotNull Response<FindCreateIssueInputQuery.Data> response) {
|
|
||||||
if (response.hasErrors()) {
|
|
||||||
sink.error(new RuntimeException(response.getErrors().stream().map(e -> e.getMessage()).collect(Collectors.joining(" "))));
|
|
||||||
} else {
|
|
||||||
FindCreateIssueInputQuery.Data data = response.getData();
|
|
||||||
FindCreateIssueInputQuery.Repository repository = data.repository();
|
|
||||||
List<String> labels = repository.labels().nodes().stream().map(FindCreateIssueInputQuery.Node::id).collect(Collectors.toList());
|
|
||||||
if (labels.isEmpty()) {
|
|
||||||
sink.error(new IllegalArgumentException("Could not find label for " + label));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Optional<String> firstMilestoneId = repository.milestones().nodes().stream().map(FindCreateIssueInputQuery.Node1::id).findFirst();
|
|
||||||
if (!firstMilestoneId.isPresent()) {
|
|
||||||
sink.error(new IllegalArgumentException("Could not find OPEN milestone id for " + milestone));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String milestoneId = firstMilestoneId.get();
|
|
||||||
String repositoryId = repository.id();
|
|
||||||
String assigneeId = data.viewer().id();
|
|
||||||
sink.success(new FindCreateIssueResult(repositoryId, labels, milestoneId, assigneeId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NotNull ApolloException e) {
|
|
||||||
sink.error(e);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FindCreateIssueResult {
|
|
||||||
private final String repositoryId;
|
|
||||||
private final List<String> labelIds;
|
|
||||||
private final String milestoneId;
|
|
||||||
private final String assigneeId;
|
|
||||||
|
|
||||||
public FindCreateIssueResult(String repositoryId, List<String> labelIds, String milestoneId, String assigneeId) {
|
|
||||||
this.repositoryId = repositoryId;
|
|
||||||
this.labelIds = labelIds;
|
|
||||||
this.milestoneId = milestoneId;
|
|
||||||
this.assigneeId = assigneeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryId() {
|
|
||||||
return repositoryId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getLabelIds() {
|
|
||||||
return labelIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMilestoneId() {
|
|
||||||
return milestoneId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAssigneeId() {
|
|
||||||
return assigneeId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<RateLimitQuery.RateLimit> findRateLimit() {
|
|
||||||
return Mono.create( sink -> this.apolloClient.query(new RateLimitQuery())
|
|
||||||
.enqueue(new ApolloCall.Callback<RateLimitQuery.Data>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NotNull Response<RateLimitQuery.Data> response) {
|
|
||||||
if (response.hasErrors()) {
|
|
||||||
sink.error(new RuntimeException(response.getErrors().stream().map(e -> e.getMessage()).collect(Collectors.joining(" "))));
|
|
||||||
} else {
|
|
||||||
sink.success(response.getData().rateLimit());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NotNull ApolloException e) {
|
|
||||||
sink.error(e);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<Integer> createIssue(String repositoryId, String title, List<String> labelIds, String milestoneId, String assigneeId) {
|
|
||||||
CreateIssueInputMutation createIssue = new CreateIssueInputMutation.Builder()
|
|
||||||
.repositoryId(repositoryId)
|
|
||||||
.title(title)
|
|
||||||
.labelIds(labelIds)
|
|
||||||
.milestoneId(milestoneId)
|
|
||||||
.assigneeId(assigneeId)
|
|
||||||
.build();
|
|
||||||
return Mono.create( sink -> this.apolloClient.mutate(createIssue)
|
|
||||||
.enqueue(new ApolloCall.Callback<CreateIssueInputMutation.Data>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NotNull Response<CreateIssueInputMutation.Data> response) {
|
|
||||||
if (response.hasErrors()) {
|
|
||||||
String message = response.getErrors().stream().map(e -> e.getMessage() + " " + e.getCustomAttributes() + " " + e.getLocations()).collect(Collectors.joining(" "));
|
|
||||||
if (message.contains("was submitted too quickly")) {
|
|
||||||
sink.error(new SubmittedTooQuick(message));
|
|
||||||
} else {
|
|
||||||
sink.error(new RuntimeException(message));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sink.success(response.getData().createIssue().issue().number());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NotNull ApolloException e) {
|
|
||||||
sink.error(e);
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
.retryWhen(
|
|
||||||
RetrySpec.fixedDelay(3, Duration.ofMinutes(1))
|
|
||||||
.filter(SubmittedTooQuick.class::isInstance)
|
|
||||||
.doBeforeRetry(r -> System.out.println("Pausing for 1 minute and then retrying due to receiving \"submitted too quickly\" error from GitHub API"))
|
|
||||||
)
|
|
||||||
.cast(Integer.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SubmittedTooQuick extends RuntimeException {
|
|
||||||
public SubmittedTooQuick(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AuthorizationInterceptor implements Interceptor {
|
|
||||||
|
|
||||||
private final String token;
|
|
||||||
|
|
||||||
public AuthorizationInterceptor(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public okhttp3.Response intercept(Chain chain) throws IOException {
|
|
||||||
Request request = chain.request().newBuilder()
|
|
||||||
.addHeader("Authorization", "Bearer " + this.token).build();
|
|
||||||
return chain.proceed(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019-2020 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.security.convention.versions;
|
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
import javax.xml.XMLConstants;
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.xpath.XPath;
|
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
|
||||||
import javax.xml.xpath.XPathFactory;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
class TransitiveDependencyLookupUtils {
|
|
||||||
static String OIDC_SDK_NAME = "oauth2-oidc-sdk";
|
|
||||||
static String NIMBUS_JOSE_JWT_NAME = "nimbus-jose-jwt";
|
|
||||||
|
|
||||||
private static OkHttpClient client = new OkHttpClient();
|
|
||||||
|
|
||||||
static String lookupJwtVersion(String oauthSdcVersion) {
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.get()
|
|
||||||
.url("https://repo.maven.apache.org/maven2/com/nimbusds/" + OIDC_SDK_NAME + "/" + oauthSdcVersion + "/" + OIDC_SDK_NAME + "-" + oauthSdcVersion + ".pom")
|
|
||||||
.build();
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
}
|
|
||||||
InputStream inputStream = response.body().byteStream();
|
|
||||||
return getVersion(inputStream);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getVersion(InputStream inputStream) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
|
|
||||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
|
||||||
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
|
||||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
|
||||||
|
|
||||||
Document doc = db.parse(inputStream);
|
|
||||||
|
|
||||||
doc.getDocumentElement().normalize();
|
|
||||||
|
|
||||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
|
||||||
return xPath.evaluate("/project/dependencies/dependency/version[../artifactId/text() = \"" + NIMBUS_JOSE_JWT_NAME + "\"]", doc);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,198 +0,0 @@
|
||||||
package org.springframework.security.convention.versions;
|
|
||||||
|
|
||||||
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionRulesWithCurrent;
|
|
||||||
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionWithCurrent;
|
|
||||||
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ResolutionStrategyWithCurrent;
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class UpdateDependenciesExtension {
|
|
||||||
private Supplier<List<File>> files;
|
|
||||||
|
|
||||||
private UpdateMode updateMode = UpdateMode.COMMIT;
|
|
||||||
|
|
||||||
private DependencyExcludes dependencyExcludes = new DependencyExcludes();
|
|
||||||
|
|
||||||
private GitHub gitHub = new GitHub();
|
|
||||||
|
|
||||||
public UpdateDependenciesExtension(Supplier<List<File>> files) {
|
|
||||||
this.files = files;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdateMode(UpdateMode updateMode) {
|
|
||||||
this.updateMode = updateMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UpdateMode getUpdateMode() {
|
|
||||||
return updateMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
GitHub getGitHub() {
|
|
||||||
return this.gitHub;
|
|
||||||
}
|
|
||||||
|
|
||||||
DependencyExcludes getExcludes() {
|
|
||||||
return dependencyExcludes;
|
|
||||||
}
|
|
||||||
|
|
||||||
Supplier<List<File>> getFiles() {
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFiles(Supplier<List<File>> files) {
|
|
||||||
this.files = files;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addFiles(Supplier<List<File>> files) {
|
|
||||||
Supplier<List<File>> original = this.files;
|
|
||||||
setFiles(() -> {
|
|
||||||
List<File> result = new ArrayList<>(original.get());
|
|
||||||
result.addAll(files.get());
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dependencyExcludes(Action<DependencyExcludes> excludes) {
|
|
||||||
excludes.execute(this.dependencyExcludes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void gitHub(Action<GitHub> gitHub) {
|
|
||||||
gitHub.execute(this.gitHub);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum UpdateMode {
|
|
||||||
COMMIT,
|
|
||||||
GITHUB_ISSUE
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GitHub {
|
|
||||||
private String organization;
|
|
||||||
|
|
||||||
private String repository;
|
|
||||||
|
|
||||||
private String accessToken;
|
|
||||||
|
|
||||||
private String milestone;
|
|
||||||
|
|
||||||
public String getOrganization() {
|
|
||||||
return organization;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrganization(String organization) {
|
|
||||||
this.organization = organization;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepository() {
|
|
||||||
return repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRepository(String repository) {
|
|
||||||
this.repository = repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAccessToken(String accessToken) {
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMilestone() {
|
|
||||||
return milestone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMilestone(String milestone) {
|
|
||||||
this.milestone = milestone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Consider creating some Predicates instead since they are composible
|
|
||||||
*/
|
|
||||||
public class DependencyExcludes {
|
|
||||||
private List<Action<ComponentSelectionWithCurrent>> actions = new ArrayList<>();
|
|
||||||
private List<Action<ComponentSelectionRulesWithCurrent>> components = new ArrayList<>();
|
|
||||||
|
|
||||||
List<Action<ComponentSelectionWithCurrent>> getActions() {
|
|
||||||
return actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Action<ComponentSelectionRulesWithCurrent>> getComponents() {
|
|
||||||
return components;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyExcludes alphaBetaVersions() {
|
|
||||||
this.actions.add(excludeVersionWithRegex("(?i).*?(alpha|beta).*", "an alpha or beta version"));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyExcludes majorVersionBump() {
|
|
||||||
this.actions.add((selection) -> {
|
|
||||||
String currentVersion = selection.getCurrentVersion();
|
|
||||||
int separator = currentVersion.indexOf(".");
|
|
||||||
String major = separator > 0 ? currentVersion.substring(0, separator) : currentVersion;
|
|
||||||
String candidateVersion = selection.getCandidate().getVersion();
|
|
||||||
Pattern calVerPattern = Pattern.compile("\\d\\d\\d\\d.*");
|
|
||||||
boolean isCalVer = calVerPattern.matcher(candidateVersion).matches();
|
|
||||||
if (!isCalVer && !candidateVersion.startsWith(major)) {
|
|
||||||
selection.reject("Cannot upgrade to new Major Version");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyExcludes minorVersionBump() {
|
|
||||||
this.actions.add(createExcludeMinorVersionBump());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action<ComponentSelectionWithCurrent> createExcludeMinorVersionBump() {
|
|
||||||
return (selection) -> {
|
|
||||||
String currentVersion = selection.getCurrentVersion();
|
|
||||||
int majorSeparator = currentVersion.indexOf(".");
|
|
||||||
int separator = currentVersion.indexOf(".", majorSeparator + 1);
|
|
||||||
String majorMinor = separator > 0 ? currentVersion.substring(0, separator) : currentVersion;
|
|
||||||
String candidateVersion = selection.getCandidate().getVersion();
|
|
||||||
if (!candidateVersion.startsWith(majorMinor)) {
|
|
||||||
selection.reject("Cannot upgrade to new Minor Version");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyExcludes releaseCandidatesVersions() {
|
|
||||||
this.actions.add(excludeVersionWithRegex("(?i).*?rc.*", "a release candidate version"));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyExcludes milestoneVersions() {
|
|
||||||
this.actions.add(excludeVersionWithRegex("(?i).*?m\\d+.*", "a milestone version"));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyExcludes snapshotVersions() {
|
|
||||||
this.actions.add(excludeVersionWithRegex(".*?-SNAPSHOT.*", "a SNAPSHOT version"));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyExcludes addRule(Action<ComponentSelectionRulesWithCurrent> rule) {
|
|
||||||
this.components.add(rule);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Action<ComponentSelectionWithCurrent> excludeVersionWithRegex(String regex, String reason) {
|
|
||||||
Pattern pattern = Pattern.compile(regex);
|
|
||||||
return (selection) -> {
|
|
||||||
String candidateVersion = selection.getCandidate().getVersion();
|
|
||||||
if (pattern.matcher(candidateVersion).matches()) {
|
|
||||||
selection.reject(candidateVersion + " is not allowed because it is " + reason);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,244 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019-2020 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.security.convention.versions;
|
|
||||||
|
|
||||||
import com.github.benmanes.gradle.versions.reporter.result.Dependency;
|
|
||||||
import com.github.benmanes.gradle.versions.reporter.result.DependencyOutdated;
|
|
||||||
import com.github.benmanes.gradle.versions.reporter.result.Result;
|
|
||||||
import com.github.benmanes.gradle.versions.reporter.result.VersionAvailable;
|
|
||||||
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask;
|
|
||||||
import com.github.benmanes.gradle.versions.updates.gradle.GradleUpdateResult;
|
|
||||||
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionRulesWithCurrent;
|
|
||||||
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionWithCurrent;
|
|
||||||
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ResolutionStrategyWithCurrent;
|
|
||||||
import groovy.lang.Closure;
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.Plugin;
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import static org.springframework.security.convention.versions.TransitiveDependencyLookupUtils.NIMBUS_JOSE_JWT_NAME;
|
|
||||||
import static org.springframework.security.convention.versions.TransitiveDependencyLookupUtils.OIDC_SDK_NAME;
|
|
||||||
|
|
||||||
public class UpdateDependenciesPlugin implements Plugin<Project> {
|
|
||||||
private GitHubApi gitHubApi;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(Project project) {
|
|
||||||
UpdateDependenciesExtension updateDependenciesSettings = project.getExtensions().create("updateDependenciesSettings", UpdateDependenciesExtension.class, defaultFiles(project));
|
|
||||||
if (project.hasProperty("updateMode")) {
|
|
||||||
String updateMode = String.valueOf(project.findProperty("updateMode"));
|
|
||||||
updateDependenciesSettings.setUpdateMode(UpdateDependenciesExtension.UpdateMode.valueOf(updateMode));
|
|
||||||
}
|
|
||||||
if (project.hasProperty("nextVersion")) {
|
|
||||||
String nextVersion = String.valueOf(project.findProperty("nextVersion"));
|
|
||||||
updateDependenciesSettings.getGitHub().setMilestone(nextVersion);
|
|
||||||
}
|
|
||||||
if (project.hasProperty("gitHubAccessToken")) {
|
|
||||||
String gitHubAccessToken = String.valueOf(project.findProperty("gitHubAccessToken"));
|
|
||||||
updateDependenciesSettings.getGitHub().setAccessToken(gitHubAccessToken);
|
|
||||||
}
|
|
||||||
project.getTasks().register("updateDependencies", DependencyUpdatesTask.class, new Action<DependencyUpdatesTask>() {
|
|
||||||
@Override
|
|
||||||
public void execute(DependencyUpdatesTask updateDependencies) {
|
|
||||||
updateDependencies.setDescription("Update the dependencies");
|
|
||||||
updateDependencies.setCheckConstraints(true);
|
|
||||||
updateDependencies.setOutputFormatter(new Closure<Void>(null) {
|
|
||||||
@Override
|
|
||||||
public Void call(Object argument) {
|
|
||||||
Result result = (Result) argument;
|
|
||||||
if (gitHubApi == null && updateDependenciesSettings.getUpdateMode() != UpdateDependenciesExtension.UpdateMode.COMMIT) {
|
|
||||||
gitHubApi = new GitHubApi(updateDependenciesSettings.getGitHub().getAccessToken());
|
|
||||||
}
|
|
||||||
updateDependencies(result, project, updateDependenciesSettings);
|
|
||||||
updateGradleVersion(result, project, updateDependenciesSettings);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
updateDependencies.resolutionStrategy(new Action<ResolutionStrategyWithCurrent>() {
|
|
||||||
@Override
|
|
||||||
public void execute(ResolutionStrategyWithCurrent resolution) {
|
|
||||||
resolution.componentSelection(new Action<ComponentSelectionRulesWithCurrent>() {
|
|
||||||
@Override
|
|
||||||
public void execute(ComponentSelectionRulesWithCurrent components) {
|
|
||||||
updateDependenciesSettings.getExcludes().getActions().forEach((action) -> {
|
|
||||||
components.all(action);
|
|
||||||
});
|
|
||||||
updateDependenciesSettings.getExcludes().getComponents().forEach((action) -> {
|
|
||||||
action.execute(components);
|
|
||||||
});
|
|
||||||
components.all((selection) -> {
|
|
||||||
ModuleComponentIdentifier candidate = selection.getCandidate();
|
|
||||||
if (candidate.getGroup().startsWith("org.apache.directory.") && !candidate.getVersion().equals(selection.getCurrentVersion())) {
|
|
||||||
selection.reject("org.apache.directory.* has breaking changes in newer versions");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
String jaxbBetaRegex = ".*?b\\d+.*";
|
|
||||||
components.withModule("javax.xml.bind:jaxb-api", excludeWithRegex(jaxbBetaRegex, "Reject jaxb-api beta versions"));
|
|
||||||
components.withModule("com.sun.xml.bind:jaxb-impl", excludeWithRegex(jaxbBetaRegex, "Reject jaxb-api beta versions"));
|
|
||||||
components.withModule("commons-collections:commons-collections", excludeWithRegex("^\\d{3,}.*", "Reject commons-collections date based releases"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDependencies(Result result, Project project, UpdateDependenciesExtension updateDependenciesSettings) {
|
|
||||||
SortedSet<DependencyOutdated> dependencies = result.getOutdated().getDependencies();
|
|
||||||
if (dependencies.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Map<String, List<DependencyOutdated>> groups = new LinkedHashMap<>();
|
|
||||||
dependencies.forEach(outdated -> {
|
|
||||||
groups.computeIfAbsent(outdated.getGroup(), (key) -> new ArrayList<>()).add(outdated);
|
|
||||||
});
|
|
||||||
List<DependencyOutdated> nimbusds = groups.getOrDefault("com.nimbusds", new ArrayList<>());
|
|
||||||
DependencyOutdated oidcSdc = nimbusds.stream().filter(d -> d.getName().equals(OIDC_SDK_NAME)).findFirst().orElseGet(() -> null);
|
|
||||||
if(oidcSdc != null) {
|
|
||||||
String oidcVersion = updatedVersion(oidcSdc);
|
|
||||||
String jwtVersion = TransitiveDependencyLookupUtils.lookupJwtVersion(oidcVersion);
|
|
||||||
|
|
||||||
Dependency nimbusJoseJwtDependency = result.getCurrent().getDependencies().stream().filter(d -> d.getName().equals(NIMBUS_JOSE_JWT_NAME)).findFirst().get();
|
|
||||||
DependencyOutdated outdatedJwt = new DependencyOutdated();
|
|
||||||
outdatedJwt.setVersion(nimbusJoseJwtDependency.getVersion());
|
|
||||||
outdatedJwt.setGroup(oidcSdc.getGroup());
|
|
||||||
outdatedJwt.setName(NIMBUS_JOSE_JWT_NAME);
|
|
||||||
VersionAvailable available = new VersionAvailable();
|
|
||||||
available.setRelease(jwtVersion);
|
|
||||||
outdatedJwt.setAvailable(available);
|
|
||||||
nimbusds.add(outdatedJwt);
|
|
||||||
}
|
|
||||||
File gradlePropertiesFile = project.getRootProject().file(Project.GRADLE_PROPERTIES);
|
|
||||||
Mono<GitHubApi.FindCreateIssueResult> createIssueResult = createIssueResultMono(updateDependenciesSettings);
|
|
||||||
List<File> filesWithDependencies = updateDependenciesSettings.getFiles().get();
|
|
||||||
groups.forEach((group, outdated) -> {
|
|
||||||
outdated.forEach((dependency) -> {
|
|
||||||
String ga = dependency.getGroup() + ":" + dependency.getName() + ":";
|
|
||||||
String originalDependency = ga + dependency.getVersion();
|
|
||||||
String replacementDependency = ga + updatedVersion(dependency);
|
|
||||||
System.out.println("Update " + originalDependency + " to " + replacementDependency);
|
|
||||||
filesWithDependencies.forEach((fileWithDependency) -> {
|
|
||||||
updateDependencyInlineVersion(fileWithDependency, dependency);
|
|
||||||
updateDependencyWithVersionVariable(fileWithDependency, gradlePropertiesFile, dependency);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// commit
|
|
||||||
DependencyOutdated firstDependency = outdated.get(0);
|
|
||||||
String updatedVersion = updatedVersion(firstDependency);
|
|
||||||
String title = outdated.size() == 1 ? "Update " + firstDependency.getName() + " to " + updatedVersion : "Update " + firstDependency.getGroup() + " to " + updatedVersion;
|
|
||||||
afterGroup(updateDependenciesSettings, project.getRootDir(), title, createIssueResult);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void afterGroup(UpdateDependenciesExtension updateDependenciesExtension, File rootDir, String title, Mono<GitHubApi.FindCreateIssueResult> createIssueResultMono) {
|
|
||||||
|
|
||||||
String commitMessage = title;
|
|
||||||
if (updateDependenciesExtension.getUpdateMode() == UpdateDependenciesExtension.UpdateMode.GITHUB_ISSUE) {
|
|
||||||
GitHubApi.FindCreateIssueResult createIssueResult = createIssueResultMono.block();
|
|
||||||
Integer issueNumber = gitHubApi.createIssue(createIssueResult.getRepositoryId(), title, createIssueResult.getLabelIds(), createIssueResult.getMilestoneId(), createIssueResult.getAssigneeId()).delayElement(Duration.ofSeconds(1)).block();
|
|
||||||
commitMessage += "\n\nCloses gh-" + issueNumber;
|
|
||||||
}
|
|
||||||
CommandLineUtils.runCommand(rootDir, "git", "commit", "-am", commitMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mono<GitHubApi.FindCreateIssueResult> createIssueResultMono(UpdateDependenciesExtension updateDependenciesExtension) {
|
|
||||||
return Mono.defer(() -> {
|
|
||||||
UpdateDependenciesExtension.GitHub gitHub = updateDependenciesExtension.getGitHub();
|
|
||||||
return gitHubApi.findCreateIssueInput(gitHub.getOrganization(), gitHub.getRepository(), gitHub.getMilestone()).cache();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateGradleVersion(Result result, Project project, UpdateDependenciesExtension updateDependenciesSettings) {
|
|
||||||
if (!result.getGradle().isEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GradleUpdateResult current = result.getGradle().getCurrent();
|
|
||||||
GradleUpdateResult running = result.getGradle().getRunning();
|
|
||||||
if (current.compareTo(running) > 0) {
|
|
||||||
String title = "Update Gradle to " + current.getVersion();
|
|
||||||
System.out.println(title);
|
|
||||||
CommandLineUtils.runCommand(project.getRootDir(), "./gradlew", "wrapper", "--gradle-version", current.getVersion(), "--no-daemon");
|
|
||||||
afterGroup(updateDependenciesSettings, project.getRootDir(), title, createIssueResultMono(updateDependenciesSettings));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Supplier<List<File>> defaultFiles(Project project) {
|
|
||||||
return () -> {
|
|
||||||
List<File> result = new ArrayList<>();
|
|
||||||
result.add(project.getBuildFile());
|
|
||||||
project.getChildProjects().values().forEach((childProject) ->
|
|
||||||
result.add(childProject.getBuildFile())
|
|
||||||
);
|
|
||||||
result.add(project.getRootProject().file("buildSrc/build.gradle"));
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static Action<ComponentSelectionWithCurrent> excludeWithRegex(String regex, String reason) {
|
|
||||||
Pattern pattern = Pattern.compile(regex);
|
|
||||||
return (selection) -> {
|
|
||||||
String candidateVersion = selection.getCandidate().getVersion();
|
|
||||||
if (pattern.matcher(candidateVersion).matches()) {
|
|
||||||
selection.reject(candidateVersion + " is not allowed because it is " + reason);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void updateDependencyInlineVersion(File buildFile, DependencyOutdated dependency){
|
|
||||||
String ga = dependency.getGroup() + ":" + dependency.getName() + ":";
|
|
||||||
String originalDependency = ga + dependency.getVersion();
|
|
||||||
String replacementDependency = ga + updatedVersion(dependency);
|
|
||||||
FileUtils.replaceFileText(buildFile, buildFileText -> buildFileText.replace(originalDependency, replacementDependency));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void updateDependencyWithVersionVariable(File scanFile, File gradlePropertiesFile, DependencyOutdated dependency) {
|
|
||||||
if (!gradlePropertiesFile.exists()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FileUtils.replaceFileText(gradlePropertiesFile, (gradlePropertiesText) -> {
|
|
||||||
String ga = dependency.getGroup() + ":" + dependency.getName() + ":";
|
|
||||||
Pattern pattern = Pattern.compile("\"" + ga + "\\$\\{?([^'\"]+?)\\}?\"");
|
|
||||||
String buildFileText = FileUtils.readString(scanFile);
|
|
||||||
Matcher matcher = pattern.matcher(buildFileText);
|
|
||||||
while (matcher.find()) {
|
|
||||||
String versionVariable = matcher.group(1);
|
|
||||||
gradlePropertiesText = gradlePropertiesText.replace(versionVariable + "=" + dependency.getVersion(), versionVariable + "=" + updatedVersion(dependency));
|
|
||||||
}
|
|
||||||
return gradlePropertiesText;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String updatedVersion(DependencyOutdated dependency) {
|
|
||||||
VersionAvailable available = dependency.getAvailable();
|
|
||||||
String release = available.getRelease();
|
|
||||||
if (release != null) {
|
|
||||||
return release;
|
|
||||||
}
|
|
||||||
return available.getMilestone();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019-2020 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.security.convention.versions;
|
|
||||||
|
|
||||||
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionWithCurrent;
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.artifacts.ComponentSelection;
|
|
||||||
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.BDDMockito.given;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
public class DependencyExcludesTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createExcludeMinorVersionBumpWhenMajorVersionBumpThenReject() {
|
|
||||||
ComponentSelection componentSelection = executeCreateExcludeMinorVersionBump("1.0.0", "2.0.0");
|
|
||||||
verify(componentSelection).reject(any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createExcludeMinorVersionBumpWhenMajorCalVersionBumpThenReject() {
|
|
||||||
ComponentSelection componentSelection = executeCreateExcludeMinorVersionBump("2000.0.0", "2001.0.0");
|
|
||||||
verify(componentSelection).reject(any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createExcludeMinorVersionBumpWhenMinorVersionBumpThenReject() {
|
|
||||||
ComponentSelection componentSelection = executeCreateExcludeMinorVersionBump("1.0.0", "1.1.0");
|
|
||||||
verify(componentSelection).reject(any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createExcludeMinorVersionBumpWhenMinorCalVersionBumpThenReject() {
|
|
||||||
ComponentSelection componentSelection = executeCreateExcludeMinorVersionBump("2000.0.0", "2000.1.0");
|
|
||||||
verify(componentSelection).reject(any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createExcludeMinorVersionBumpWhenMinorAndPatchVersionBumpThenReject() {
|
|
||||||
ComponentSelection componentSelection = executeCreateExcludeMinorVersionBump("1.0.0", "1.1.1");
|
|
||||||
verify(componentSelection).reject(any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createExcludeMinorVersionBumpWhenPatchVersionBumpThenDoesNotReject() {
|
|
||||||
ComponentSelection componentSelection = executeCreateExcludeMinorVersionBump("1.0.0", "1.0.1");
|
|
||||||
verify(componentSelection, times(0)).reject(any());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComponentSelection executeCreateExcludeMinorVersionBump(String currentVersion, String candidateVersion) {
|
|
||||||
ComponentSelection componentSelection = mock(ComponentSelection.class);
|
|
||||||
UpdateDependenciesExtension.DependencyExcludes excludes = new UpdateDependenciesExtension(() -> Collections.emptyList()).new DependencyExcludes();
|
|
||||||
Action<ComponentSelectionWithCurrent> excludeMinorVersionBump = excludes.createExcludeMinorVersionBump();
|
|
||||||
ComponentSelectionWithCurrent selection = currentVersionAndCandidateVersion(componentSelection, currentVersion, candidateVersion);
|
|
||||||
excludeMinorVersionBump.execute(selection);
|
|
||||||
return componentSelection;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComponentSelectionWithCurrent currentVersionAndCandidateVersion(ComponentSelection componentSelection, String currentVersion, String candidateVersion) {
|
|
||||||
ModuleComponentIdentifier candidate = mock(ModuleComponentIdentifier.class);
|
|
||||||
given(componentSelection.getCandidate()).willReturn(candidate);
|
|
||||||
ComponentSelectionWithCurrent selection = new ComponentSelectionWithCurrent(currentVersion, componentSelection);
|
|
||||||
given(candidate.getVersion()).willReturn(candidateVersion);
|
|
||||||
given(componentSelection.getCandidate()).willReturn(candidate);
|
|
||||||
return selection;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019-2020 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.security.convention.versions;
|
|
||||||
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
public class TransitiveDependencyLookupUtilsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void lookupJwtVersionWhen93Then961() {
|
|
||||||
String s = TransitiveDependencyLookupUtils.lookupJwtVersion("9.3");
|
|
||||||
assertThat(s).isEqualTo("9.6.1");
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue