diff --git a/build.gradle b/build.gradle index 259106f678..a23c8da4f6 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,6 @@ apply plugin: 'locks' apply plugin: 's101' apply plugin: 'io.spring.convention.root' 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.sagan' 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 { java { toolchain { diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 5935248b37..ffb8bca6cc 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -2,7 +2,6 @@ plugins { id "java-gradle-plugin" id "java" id "groovy" - id 'com.apollographql.apollo' version '2.4.5' } sourceCompatibility = JavaVersion.VERSION_17 @@ -42,10 +41,6 @@ gradlePlugin { id = "io.spring.convention.management-configuration" implementationClass = "io.spring.gradle.convention.ManagementConfigurationPlugin" } - updateDependencies { - id = "org.springframework.security.update-dependencies" - implementationClass = "org.springframework.security.convention.versions.UpdateDependenciesPlugin" - } updateProjectVersion { id = "org.springframework.security.update-version" implementationClass = "org.springframework.security.convention.versions.UpdateProjectVersionPlugin" @@ -91,7 +86,6 @@ dependencies { implementation libs.io.github.gradle.nexus.publish.plugin implementation 'io.projectreactor:reactor-core' 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.spullara.mustache.java.compiler implementation libs.io.spring.javaformat.spring.javaformat.gradle.plugin @@ -100,6 +94,7 @@ dependencies { implementation libs.org.hidetake.gradle.ssh.plugin implementation libs.org.jfrog.buildinfo.build.info.extractor.gradle 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.mockito.mockito.bom) diff --git a/buildSrc/src/main/java/org/springframework/security/convention/versions/CommandLineUtils.java b/buildSrc/src/main/java/org/springframework/security/convention/versions/CommandLineUtils.java deleted file mode 100644 index ae073aff8b..0000000000 --- a/buildSrc/src/main/java/org/springframework/security/convention/versions/CommandLineUtils.java +++ /dev/null @@ -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()); - } - } -} diff --git a/buildSrc/src/main/java/org/springframework/security/convention/versions/GitHubApi.java b/buildSrc/src/main/java/org/springframework/security/convention/versions/GitHubApi.java deleted file mode 100644 index 74738e2ce4..0000000000 --- a/buildSrc/src/main/java/org/springframework/security/convention/versions/GitHubApi.java +++ /dev/null @@ -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 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() { - @Override - public void onResponse(@NotNull Response 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 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 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 labelIds; - private final String milestoneId; - private final String assigneeId; - - public FindCreateIssueResult(String repositoryId, List labelIds, String milestoneId, String assigneeId) { - this.repositoryId = repositoryId; - this.labelIds = labelIds; - this.milestoneId = milestoneId; - this.assigneeId = assigneeId; - } - - public String getRepositoryId() { - return repositoryId; - } - - public List getLabelIds() { - return labelIds; - } - - public String getMilestoneId() { - return milestoneId; - } - - public String getAssigneeId() { - return assigneeId; - } - } - - public Mono findRateLimit() { - return Mono.create( sink -> this.apolloClient.query(new RateLimitQuery()) - .enqueue(new ApolloCall.Callback() { - @Override - public void onResponse(@NotNull Response 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 createIssue(String repositoryId, String title, List 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() { - @Override - public void onResponse(@NotNull Response 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); - } - } -} diff --git a/buildSrc/src/main/java/org/springframework/security/convention/versions/TransitiveDependencyLookupUtils.java b/buildSrc/src/main/java/org/springframework/security/convention/versions/TransitiveDependencyLookupUtils.java deleted file mode 100644 index 66eb8b5f0d..0000000000 --- a/buildSrc/src/main/java/org/springframework/security/convention/versions/TransitiveDependencyLookupUtils.java +++ /dev/null @@ -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); - } -} diff --git a/buildSrc/src/main/java/org/springframework/security/convention/versions/UpdateDependenciesExtension.java b/buildSrc/src/main/java/org/springframework/security/convention/versions/UpdateDependenciesExtension.java deleted file mode 100644 index 129d571162..0000000000 --- a/buildSrc/src/main/java/org/springframework/security/convention/versions/UpdateDependenciesExtension.java +++ /dev/null @@ -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> files; - - private UpdateMode updateMode = UpdateMode.COMMIT; - - private DependencyExcludes dependencyExcludes = new DependencyExcludes(); - - private GitHub gitHub = new GitHub(); - - public UpdateDependenciesExtension(Supplier> 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> getFiles() { - return files; - } - - public void setFiles(Supplier> files) { - this.files = files; - } - - public void addFiles(Supplier> files) { - Supplier> original = this.files; - setFiles(() -> { - List result = new ArrayList<>(original.get()); - result.addAll(files.get()); - return result; - }); - } - - public void dependencyExcludes(Action excludes) { - excludes.execute(this.dependencyExcludes); - } - - public void gitHub(Action 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> actions = new ArrayList<>(); - private List> components = new ArrayList<>(); - - List> getActions() { - return actions; - } - - public List> 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 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 rule) { - this.components.add(rule); - return this; - } - - private Action 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); - } - }; - } - } -} diff --git a/buildSrc/src/main/java/org/springframework/security/convention/versions/UpdateDependenciesPlugin.java b/buildSrc/src/main/java/org/springframework/security/convention/versions/UpdateDependenciesPlugin.java deleted file mode 100644 index 4f68fc656e..0000000000 --- a/buildSrc/src/main/java/org/springframework/security/convention/versions/UpdateDependenciesPlugin.java +++ /dev/null @@ -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 { - 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() { - @Override - public void execute(DependencyUpdatesTask updateDependencies) { - updateDependencies.setDescription("Update the dependencies"); - updateDependencies.setCheckConstraints(true); - updateDependencies.setOutputFormatter(new Closure(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() { - @Override - public void execute(ResolutionStrategyWithCurrent resolution) { - resolution.componentSelection(new Action() { - @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 dependencies = result.getOutdated().getDependencies(); - if (dependencies.isEmpty()) { - return; - } - Map> groups = new LinkedHashMap<>(); - dependencies.forEach(outdated -> { - groups.computeIfAbsent(outdated.getGroup(), (key) -> new ArrayList<>()).add(outdated); - }); - List 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 createIssueResult = createIssueResultMono(updateDependenciesSettings); - List 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 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 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> defaultFiles(Project project) { - return () -> { - List 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 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(); - } -} diff --git a/buildSrc/src/test/java/org/springframework/security/convention/versions/DependencyExcludesTests.java b/buildSrc/src/test/java/org/springframework/security/convention/versions/DependencyExcludesTests.java deleted file mode 100644 index 4b1aa905d2..0000000000 --- a/buildSrc/src/test/java/org/springframework/security/convention/versions/DependencyExcludesTests.java +++ /dev/null @@ -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 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; - } -} diff --git a/buildSrc/src/test/java/org/springframework/security/convention/versions/TransitiveDependencyLookupUtilsTest.java b/buildSrc/src/test/java/org/springframework/security/convention/versions/TransitiveDependencyLookupUtilsTest.java deleted file mode 100644 index cc6a821f85..0000000000 --- a/buildSrc/src/test/java/org/springframework/security/convention/versions/TransitiveDependencyLookupUtilsTest.java +++ /dev/null @@ -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"); - } -}