Skip to content

Commit 6aceca7

Browse files
committed
Merge branch '3.0.x'
Closes gh-34159
2 parents dfcb4d9 + a6f357c commit 6aceca7

File tree

7 files changed

+340
-181
lines changed

7 files changed

+340
-181
lines changed

buildSrc/src/main/java/org/springframework/boot/build/bom/BomPlugin.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2022 the original author or authors.
2+
* Copyright 2012-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@
3737
import org.springframework.boot.build.MavenRepositoryPlugin;
3838
import org.springframework.boot.build.bom.Library.Group;
3939
import org.springframework.boot.build.bom.Library.Module;
40+
import org.springframework.boot.build.bom.bomr.MoveToSnapshots;
4041
import org.springframework.boot.build.bom.bomr.UpgradeBom;
4142

4243
/**
@@ -63,6 +64,7 @@ public void apply(Project project) {
6364
project);
6465
project.getTasks().create("bomrCheck", CheckBom.class, bom);
6566
project.getTasks().create("bomrUpgrade", UpgradeBom.class, bom);
67+
project.getTasks().create("moveToSnapshots", MoveToSnapshots.class, bom);
6668
new PublishingCustomizer(project, bom).customize();
6769

6870
}

buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/MavenMetadataVersionResolver.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.build.bom.bomr;
1818

1919
import java.io.StringReader;
20+
import java.net.URI;
2021
import java.util.Collection;
2122
import java.util.Collections;
2223
import java.util.HashSet;
@@ -49,29 +50,29 @@ final class MavenMetadataVersionResolver implements VersionResolver {
4950

5051
private final RestTemplate rest;
5152

52-
private final Collection<String> repositoryUrls;
53+
private final Collection<URI> repositoryUrls;
5354

54-
MavenMetadataVersionResolver(Collection<String> repositoryUrls) {
55+
MavenMetadataVersionResolver(Collection<URI> repositoryUrls) {
5556
this(new RestTemplate(Collections.singletonList(new StringHttpMessageConverter())), repositoryUrls);
5657
}
5758

58-
MavenMetadataVersionResolver(RestTemplate restTemplate, Collection<String> repositoryUrls) {
59+
MavenMetadataVersionResolver(RestTemplate restTemplate, Collection<URI> repositoryUrls) {
5960
this.rest = restTemplate;
6061
this.repositoryUrls = repositoryUrls;
6162
}
6263

6364
@Override
6465
public SortedSet<DependencyVersion> resolveVersions(String groupId, String artifactId) {
6566
Set<String> versions = new HashSet<>();
66-
for (String repositoryUrl : this.repositoryUrls) {
67+
for (URI repositoryUrl : this.repositoryUrls) {
6768
versions.addAll(resolveVersions(groupId, artifactId, repositoryUrl));
6869
}
6970
return versions.stream().map(DependencyVersion::parse).collect(Collectors.toCollection(TreeSet::new));
7071
}
7172

72-
private Set<String> resolveVersions(String groupId, String artifactId, String repositoryUrl) {
73+
private Set<String> resolveVersions(String groupId, String artifactId, URI repositoryUrl) {
7374
Set<String> versions = new HashSet<>();
74-
String url = repositoryUrl + "/" + groupId.replace('.', '/') + "/" + artifactId + "/maven-metadata.xml";
75+
URI url = repositoryUrl.resolve(groupId.replace('.', '/') + "/" + artifactId + "/maven-metadata.xml");
7576
try {
7677
String metadata = this.rest.getForObject(url, String.class);
7778
Document metadataDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder()
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2021-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.build.bom.bomr;
18+
19+
import java.net.URI;
20+
21+
import javax.inject.Inject;
22+
23+
import org.gradle.api.Task;
24+
25+
import org.springframework.boot.build.bom.BomExtension;
26+
27+
/**
28+
* A {@link Task} to move to snapshot dependencies.
29+
*
30+
* @author Andy Wilkinson
31+
*/
32+
public abstract class MoveToSnapshots extends UpgradeDependencies {
33+
34+
private final URI REPOSITORY_URI = URI.create("https://repo.spring.io/snapshot/");
35+
36+
@Inject
37+
public MoveToSnapshots(BomExtension bom) {
38+
super(bom);
39+
getRepositoryUris().add(this.REPOSITORY_URI);
40+
}
41+
42+
@Override
43+
protected String issueTitle(Upgrade upgrade) {
44+
String snapshotVersion = upgrade.getVersion().toString();
45+
String releaseVersion = snapshotVersion.substring(0, snapshotVersion.length() - "-SNAPSHOT".length());
46+
return "Upgrade to " + upgrade.getLibrary().getName() + " " + releaseVersion;
47+
}
48+
49+
@Override
50+
protected String commitMessage(Upgrade upgrade, int issueNumber) {
51+
return "Start building against " + upgrade.getLibrary().getName() + " " + releaseVersion(upgrade) + " snapshots"
52+
+ "\n\nSee gh-" + issueNumber;
53+
}
54+
55+
private String releaseVersion(Upgrade upgrade) {
56+
String snapshotVersion = upgrade.getVersion().toString();
57+
return snapshotVersion.substring(0, snapshotVersion.length() - "-SNAPSHOT".length());
58+
}
59+
60+
}

buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/UpgradeBom.java

Lines changed: 12 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -16,202 +16,42 @@
1616

1717
package org.springframework.boot.build.bom.bomr;
1818

19-
import java.io.File;
20-
import java.io.FileReader;
21-
import java.io.IOException;
22-
import java.io.Reader;
23-
import java.nio.file.Path;
24-
import java.util.ArrayList;
25-
import java.util.Arrays;
26-
import java.util.LinkedHashSet;
27-
import java.util.List;
28-
import java.util.Optional;
29-
import java.util.Properties;
30-
import java.util.Set;
31-
import java.util.function.Predicate;
32-
import java.util.regex.Pattern;
19+
import java.net.URI;
3320

3421
import javax.inject.Inject;
3522

36-
import org.gradle.api.DefaultTask;
37-
import org.gradle.api.InvalidUserDataException;
3823
import org.gradle.api.Task;
3924
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
40-
import org.gradle.api.internal.tasks.userinput.UserInputHandler;
41-
import org.gradle.api.tasks.Input;
42-
import org.gradle.api.tasks.TaskAction;
43-
import org.gradle.api.tasks.TaskExecutionException;
44-
import org.gradle.api.tasks.options.Option;
4525

4626
import org.springframework.boot.build.bom.BomExtension;
47-
import org.springframework.boot.build.bom.Library;
48-
import org.springframework.boot.build.bom.bomr.github.GitHub;
49-
import org.springframework.boot.build.bom.bomr.github.GitHubRepository;
50-
import org.springframework.boot.build.bom.bomr.github.Issue;
51-
import org.springframework.boot.build.bom.bomr.github.Milestone;
52-
import org.springframework.util.StringUtils;
5327

5428
/**
5529
* {@link Task} to upgrade the libraries managed by a bom.
5630
*
5731
* @author Andy Wilkinson
5832
* @author Moritz Halbritter
5933
*/
60-
public class UpgradeBom extends DefaultTask {
61-
62-
private final Set<String> repositoryUrls = new LinkedHashSet<>();
63-
64-
private final BomExtension bom;
65-
66-
private String milestone;
67-
68-
private String libraries;
69-
70-
private int threads = 2;
34+
public abstract class UpgradeBom extends UpgradeDependencies {
7135

7236
@Inject
7337
public UpgradeBom(BomExtension bom) {
74-
this.bom = bom;
38+
super(bom);
7539
getProject().getRepositories().withType(MavenArtifactRepository.class, (repository) -> {
76-
String repositoryUrl = repository.getUrl().toString();
77-
if (!repositoryUrl.endsWith("snapshot")) {
78-
this.repositoryUrls.add(repositoryUrl);
40+
URI repositoryUrl = repository.getUrl();
41+
if (!repositoryUrl.toString().endsWith("snapshot")) {
42+
getRepositoryUris().add(repositoryUrl);
7943
}
8044
});
8145
}
8246

83-
@Option(option = "milestone", description = "Milestone to which dependency upgrade issues should be assigned")
84-
public void setMilestone(String milestone) {
85-
this.milestone = milestone;
86-
}
87-
88-
@Option(option = "threads", description = "Number of Threads to use for update resolution")
89-
public void setThreads(String threads) {
90-
this.threads = Integer.parseInt(threads);
91-
}
92-
93-
@Input
94-
public String getMilestone() {
95-
return this.milestone;
96-
}
97-
98-
@Option(option = "libraries", description = "Regular expression that identifies the libraries to upgrade")
99-
public void setLibraries(String libraries) {
100-
this.libraries = libraries;
101-
}
102-
103-
@Input
104-
@org.gradle.api.tasks.Optional
105-
public String getLibraries() {
106-
return this.libraries;
107-
}
108-
109-
@TaskAction
110-
@SuppressWarnings("deprecation")
111-
void upgradeDependencies() {
112-
GitHubRepository repository = createGitHub().getRepository(this.bom.getUpgrade().getGitHub().getOrganization(),
113-
this.bom.getUpgrade().getGitHub().getRepository());
114-
Set<String> availableLabels = repository.getLabels();
115-
List<String> issueLabels = this.bom.getUpgrade().getGitHub().getIssueLabels();
116-
if (!availableLabels.containsAll(issueLabels)) {
117-
List<String> unknownLabels = new ArrayList<>(issueLabels);
118-
unknownLabels.removeAll(availableLabels);
119-
throw new InvalidUserDataException(
120-
"Unknown label(s): " + StringUtils.collectionToCommaDelimitedString(unknownLabels));
121-
}
122-
Milestone milestone = determineMilestone(repository);
123-
List<Issue> existingUpgradeIssues = repository.findIssues(issueLabels, milestone);
124-
List<Upgrade> upgrades = new InteractiveUpgradeResolver(getServices().get(UserInputHandler.class),
125-
new MultithreadedLibraryUpdateResolver(new MavenMetadataVersionResolver(this.repositoryUrls),
126-
this.bom.getUpgrade().getPolicy(), this.threads))
127-
.resolveUpgrades(matchingLibraries(this.libraries), this.bom.getLibraries());
128-
Path buildFile = getProject().getBuildFile().toPath();
129-
Path gradleProperties = new File(getProject().getRootProject().getProjectDir(), "gradle.properties").toPath();
130-
UpgradeApplicator upgradeApplicator = new UpgradeApplicator(buildFile, gradleProperties);
131-
for (Upgrade upgrade : upgrades) {
132-
String title = "Upgrade to " + upgrade.getLibrary().getName() + " " + upgrade.getVersion();
133-
Issue existingUpgradeIssue = findExistingUpgradeIssue(existingUpgradeIssues, upgrade);
134-
if (existingUpgradeIssue != null) {
135-
System.out.println(title + " (supersedes #" + existingUpgradeIssue.getNumber() + " "
136-
+ existingUpgradeIssue.getTitle() + ")");
137-
}
138-
else {
139-
System.out.println(title);
140-
}
141-
try {
142-
Path modified = upgradeApplicator.apply(upgrade);
143-
int issueNumber = repository.openIssue(title,
144-
(existingUpgradeIssue != null) ? "Supersedes #" + existingUpgradeIssue.getNumber() : "",
145-
issueLabels, milestone);
146-
if (existingUpgradeIssue != null) {
147-
existingUpgradeIssue.label(Arrays.asList("type: task", "status: superseded"));
148-
}
149-
if (new ProcessBuilder().command("git", "add", modified.toFile().getAbsolutePath()).start()
150-
.waitFor() != 0) {
151-
throw new IllegalStateException("git add failed");
152-
}
153-
if (new ProcessBuilder().command("git", "commit", "-m", title + "\n\nCloses gh-" + issueNumber).start()
154-
.waitFor() != 0) {
155-
throw new IllegalStateException("git commit failed");
156-
}
157-
}
158-
catch (IOException ex) {
159-
throw new TaskExecutionException(this, ex);
160-
}
161-
catch (InterruptedException ex) {
162-
Thread.currentThread().interrupt();
163-
}
164-
}
165-
}
166-
167-
private List<Library> matchingLibraries(String pattern) {
168-
if (pattern == null) {
169-
return this.bom.getLibraries();
170-
}
171-
Predicate<String> libraryPredicate = Pattern.compile(pattern).asPredicate();
172-
List<Library> matchingLibraries = this.bom.getLibraries().stream()
173-
.filter((library) -> libraryPredicate.test(library.getName())).toList();
174-
if (matchingLibraries.isEmpty()) {
175-
throw new InvalidUserDataException("No libraries matched '" + pattern + "'");
176-
}
177-
return matchingLibraries;
178-
}
179-
180-
private Issue findExistingUpgradeIssue(List<Issue> existingUpgradeIssues, Upgrade upgrade) {
181-
String toMatch = "Upgrade to " + upgrade.getLibrary().getName();
182-
for (Issue existingUpgradeIssue : existingUpgradeIssues) {
183-
if (existingUpgradeIssue.getTitle().substring(0, existingUpgradeIssue.getTitle().lastIndexOf(' '))
184-
.equals(toMatch)) {
185-
return existingUpgradeIssue;
186-
}
187-
}
188-
return null;
189-
}
190-
191-
private GitHub createGitHub() {
192-
Properties bomrProperties = new Properties();
193-
try (Reader reader = new FileReader(new File(System.getProperty("user.home"), ".bomr.properties"))) {
194-
bomrProperties.load(reader);
195-
String username = bomrProperties.getProperty("bomr.github.username");
196-
String password = bomrProperties.getProperty("bomr.github.password");
197-
return GitHub.withCredentials(username, password);
198-
}
199-
catch (IOException ex) {
200-
throw new InvalidUserDataException("Failed to load .bomr.properties from user home", ex);
201-
}
47+
@Override
48+
protected String issueTitle(Upgrade upgrade) {
49+
return "Upgrade to " + upgrade.getLibrary().getName() + " " + upgrade.getVersion();
20250
}
20351

204-
private Milestone determineMilestone(GitHubRepository repository) {
205-
if (this.milestone == null) {
206-
return null;
207-
}
208-
List<Milestone> milestones = repository.getMilestones();
209-
Optional<Milestone> matchingMilestone = milestones.stream()
210-
.filter((milestone) -> milestone.getName().equals(this.milestone)).findFirst();
211-
if (!matchingMilestone.isPresent()) {
212-
throw new InvalidUserDataException("Unknown milestone: " + this.milestone);
213-
}
214-
return matchingMilestone.get();
52+
@Override
53+
protected String commitMessage(Upgrade upgrade, int issueNumber) {
54+
return issueTitle(upgrade) + "\n\nCloses gh-" + issueNumber;
21555
}
21656

21757
}

0 commit comments

Comments
 (0)