#160 - Attach changelog to GitHub release.
This commit is contained in:
@@ -48,6 +48,8 @@ $ release build $trainIteration
|
|||||||
$ release conclude $trainIteration
|
$ release conclude $trainIteration
|
||||||
$ git push $trainIteration
|
$ git push $trainIteration
|
||||||
$ git push $trainIteration --tags
|
$ git push $trainIteration --tags
|
||||||
|
# After GitHub issues migration:
|
||||||
|
# github push $trainIteration
|
||||||
$ git backport changelog $trainIteration --target $targets
|
$ git backport changelog $trainIteration --target $targets
|
||||||
$ foreach $target -> git push $target
|
$ foreach $target -> git push $target
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.springframework.data.release.git;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -69,13 +70,23 @@ public class VersionTags implements Streamable<Tag> {
|
|||||||
sorted().collect(Collectors.toList());
|
sorted().collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty {@link VersionTags} object for {@link Project}.
|
||||||
|
*
|
||||||
|
* @param project must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static VersionTags empty(Project project) {
|
||||||
|
return new VersionTags(project, Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the latest {@link Tag}.
|
* Returns the latest {@link Tag}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Tag getLatest() {
|
public Tag getLatest() {
|
||||||
return tags.get(tags.size() - 1);
|
return tags.isEmpty() ? null : tags.get(tags.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tag createTag(ModuleIteration iteration) {
|
public Tag createTag(ModuleIteration iteration) {
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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
|
||||||
|
*
|
||||||
|
* http://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.data.release.issues.github;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a changelog markdown file which includes bug fixes, enhancements and contributors for a given milestone.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ChangelogGenerator {
|
||||||
|
|
||||||
|
private static final Pattern ghUserMentionPattern = Pattern.compile("(^|[^\\w`])(@[\\w-]+)");
|
||||||
|
|
||||||
|
private final Set<String> excludeLabels;
|
||||||
|
|
||||||
|
private final Set<String> excludeContributors;
|
||||||
|
|
||||||
|
private final String contributorsTitle;
|
||||||
|
|
||||||
|
private final ChangelogSections sections;
|
||||||
|
|
||||||
|
public ChangelogGenerator() {
|
||||||
|
this.excludeLabels = new HashSet<>(Arrays.asList("type: task"));
|
||||||
|
this.excludeContributors = Collections.emptySet();
|
||||||
|
this.contributorsTitle = null;
|
||||||
|
this.sections = new ChangelogSections();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a file at the given path which includes bug fixes, enhancements and contributors for the given milestone.
|
||||||
|
*
|
||||||
|
* @param issues the issues to generate the changelog for
|
||||||
|
* @param sectionContentPostProcessor the postprocessor for a changelog section
|
||||||
|
*/
|
||||||
|
public String generate(List<GitHubIssue> issues,
|
||||||
|
BiFunction<ChangelogSection, String, String> sectionContentPostProcessor) {
|
||||||
|
return generateContent(issues, sectionContentPostProcessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isExcluded(GitHubIssue issue) {
|
||||||
|
return issue.getLabels().stream().anyMatch(this::isExcluded);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isExcluded(Label label) {
|
||||||
|
return this.excludeLabels.contains(label.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateContent(List<GitHubIssue> issues,
|
||||||
|
BiFunction<ChangelogSection, String, String> sectionContentPostProcessor) {
|
||||||
|
StringBuilder content = new StringBuilder();
|
||||||
|
addSectionContent(content, this.sections.collate(issues), sectionContentPostProcessor);
|
||||||
|
Set<GitHubUser> contributors = getContributors(issues);
|
||||||
|
if (!contributors.isEmpty()) {
|
||||||
|
addContributorsContent(content, contributors);
|
||||||
|
}
|
||||||
|
return content.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSectionContent(StringBuilder result, Map<ChangelogSection, List<GitHubIssue>> sectionIssues,
|
||||||
|
BiFunction<ChangelogSection, String, String> sectionContentPostProcessor) {
|
||||||
|
|
||||||
|
sectionIssues.forEach((section, issues) -> {
|
||||||
|
|
||||||
|
issues.sort(Comparator.reverseOrder());
|
||||||
|
|
||||||
|
StringBuilder content = new StringBuilder();
|
||||||
|
|
||||||
|
content.append((content.length() != 0) ? String.format("%n") : "");
|
||||||
|
content.append("## ").append(section).append(String.format("%n%n"));
|
||||||
|
issues.stream().map(this::getFormattedIssue).forEach(content::append);
|
||||||
|
|
||||||
|
result.append(sectionContentPostProcessor.apply(section, content.toString()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFormattedIssue(GitHubIssue issue) {
|
||||||
|
String title = issue.getTitle();
|
||||||
|
title = ghUserMentionPattern.matcher(title).replaceAll("$1`$2`");
|
||||||
|
return String.format("- %s %s%n", title, getLinkToIssue(issue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLinkToIssue(GitHubIssue issue) {
|
||||||
|
return "[" + issue.getId() + "]" + "(" + issue.getUrl() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<GitHubUser> getContributors(List<GitHubIssue> issues) {
|
||||||
|
if (this.excludeContributors.contains("*")) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
return issues.stream().filter((issue) -> issue.getPullRequest() != null).map(GitHubIssue::getUser)
|
||||||
|
.filter(this::isIncludedContributor).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isIncludedContributor(GitHubUser user) {
|
||||||
|
return !this.excludeContributors.contains(user.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addContributorsContent(StringBuilder content, Set<GitHubUser> contributors) {
|
||||||
|
content.append(String.format("%n## "));
|
||||||
|
content.append((this.contributorsTitle != null) ? this.contributorsTitle : ":heart: Contributors");
|
||||||
|
content.append(String.format("%n%nWe'd like to thank all the contributors who worked on this release!%n%n"));
|
||||||
|
contributors.stream().map(this::formatContributors).forEach(content::append);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatContributors(GitHubUser c) {
|
||||||
|
return String.format("- [@%s](%s)%n", c.getName(), c.getUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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
|
||||||
|
*
|
||||||
|
* http://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.data.release.issues.github;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single section of a changelog report.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class ChangelogSection {
|
||||||
|
|
||||||
|
private final String title;
|
||||||
|
|
||||||
|
private final String group;
|
||||||
|
|
||||||
|
private final Set<String> labels;
|
||||||
|
|
||||||
|
ChangelogSection(String title, String group, String... labels) {
|
||||||
|
this(title, group, new LinkedHashSet<>(Arrays.asList(labels)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangelogSection(String title, String group, Set<String> labels) {
|
||||||
|
Assert.hasText(title, "Title must not be empty");
|
||||||
|
Assert.isTrue(!CollectionUtils.isEmpty(labels), "Labels must not be empty");
|
||||||
|
this.title = title;
|
||||||
|
this.group = group;
|
||||||
|
this.labels = labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getGroup() {
|
||||||
|
return this.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isMatchFor(GitHubIssue issue) {
|
||||||
|
for (String candidate : this.labels) {
|
||||||
|
for (Label label : issue.getLabels()) {
|
||||||
|
if (label.getName().contains(candidate)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasLabel(String label) {
|
||||||
|
return this.labels.contains(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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
|
||||||
|
*
|
||||||
|
* http://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.data.release.issues.github;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages sections of the changelog report.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class ChangelogSections {
|
||||||
|
|
||||||
|
private static final List<ChangelogSection> DEFAULT_SECTIONS;
|
||||||
|
static {
|
||||||
|
List<ChangelogSection> sections = new ArrayList<>();
|
||||||
|
add(sections, ":star: New Features", "enhancement");
|
||||||
|
add(sections, ":beetle: Bug Fixes", "bug", "regression");
|
||||||
|
add(sections, ":notebook_with_decorative_cover: Documentation", "documentation");
|
||||||
|
add(sections, ":hammer: Dependency Upgrades", "dependency-upgrade");
|
||||||
|
DEFAULT_SECTIONS = Collections.unmodifiableList(sections);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void add(List<ChangelogSection> sections, String title, String... labels) {
|
||||||
|
sections.add(new ChangelogSection(title, null, labels));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<ChangelogSection> sections;
|
||||||
|
|
||||||
|
ChangelogSections() {
|
||||||
|
this.sections = DEFAULT_SECTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<ChangelogSection, List<GitHubIssue>> collate(List<GitHubIssue> issues) {
|
||||||
|
|
||||||
|
SortedMap<ChangelogSection, List<GitHubIssue>> collated = new TreeMap<>(
|
||||||
|
Comparator.comparing(this.sections::indexOf));
|
||||||
|
|
||||||
|
for (GitHubIssue issue : issues) {
|
||||||
|
List<ChangelogSection> sections = getSections(issue);
|
||||||
|
for (ChangelogSection section : sections) {
|
||||||
|
collated.computeIfAbsent(section, (key) -> new ArrayList<>());
|
||||||
|
collated.get(section).add(issue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ChangelogSection> getSections(GitHubIssue issue) {
|
||||||
|
List<ChangelogSection> result = new ArrayList<>();
|
||||||
|
Set<String> groupClaimes = new HashSet<>();
|
||||||
|
for (ChangelogSection section : this.sections) {
|
||||||
|
if (section.isMatchFor(issue) && groupClaimes.add(section.getGroup())) {
|
||||||
|
result.add(section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -34,12 +34,17 @@ import org.springframework.cache.annotation.CacheEvict;
|
|||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
import org.springframework.data.release.git.GitProject;
|
import org.springframework.data.release.git.GitProject;
|
||||||
|
import org.springframework.data.release.git.Tag;
|
||||||
|
import org.springframework.data.release.git.VersionTags;
|
||||||
import org.springframework.data.release.issues.Changelog;
|
import org.springframework.data.release.issues.Changelog;
|
||||||
import org.springframework.data.release.issues.IssueTracker;
|
import org.springframework.data.release.issues.IssueTracker;
|
||||||
import org.springframework.data.release.issues.Ticket;
|
import org.springframework.data.release.issues.Ticket;
|
||||||
import org.springframework.data.release.issues.TicketReference;
|
import org.springframework.data.release.issues.TicketReference;
|
||||||
import org.springframework.data.release.issues.Tickets;
|
import org.springframework.data.release.issues.Tickets;
|
||||||
import org.springframework.data.release.issues.github.GitHubIssue.Milestone;
|
import org.springframework.data.release.issues.github.GitHubIssue.Milestone;
|
||||||
|
import org.springframework.data.release.model.ArtifactVersion;
|
||||||
|
import org.springframework.data.release.model.DocumentationMetadata;
|
||||||
|
import org.springframework.data.release.model.Iteration;
|
||||||
import org.springframework.data.release.model.ModuleIteration;
|
import org.springframework.data.release.model.ModuleIteration;
|
||||||
import org.springframework.data.release.model.Project;
|
import org.springframework.data.release.model.Project;
|
||||||
import org.springframework.data.release.model.Tracker;
|
import org.springframework.data.release.model.Tracker;
|
||||||
@@ -69,6 +74,9 @@ class GitHub extends GitHubSupport implements IssueTracker {
|
|||||||
private static final String MILESTONE_BY_ID_URI_TEMPLATE = "/repos/spring-projects/{repoName}/milestones/{id}";
|
private static final String MILESTONE_BY_ID_URI_TEMPLATE = "/repos/spring-projects/{repoName}/milestones/{id}";
|
||||||
private static final String ISSUE_BY_ID_URI_TEMPLATE = "/repos/spring-projects/{repoName}/issues/{id}";
|
private static final String ISSUE_BY_ID_URI_TEMPLATE = "/repos/spring-projects/{repoName}/issues/{id}";
|
||||||
private static final String ISSUES_URI_TEMPLATE = "/repos/spring-projects/{repoName}/issues";
|
private static final String ISSUES_URI_TEMPLATE = "/repos/spring-projects/{repoName}/issues";
|
||||||
|
private static final String RELEASE_BY_TAG_URI_TEMPLATE = "/repos/spring-projects/{repoName}/releases/tags/{tag}";
|
||||||
|
private static final String RELEASE_URI_TEMPLATE = "/repos/spring-projects/{repoName}/releases";
|
||||||
|
private static final String RELEASE_BY_ID_URI_TEMPLATE = "/repos/spring-projects/{repoName}/releases/{id}";
|
||||||
|
|
||||||
private static final ParameterizedTypeReference<List<Milestone>> MILESTONES_TYPE = new ParameterizedTypeReference<List<Milestone>>() {};
|
private static final ParameterizedTypeReference<List<Milestone>> MILESTONES_TYPE = new ParameterizedTypeReference<List<Milestone>>() {};
|
||||||
private static final ParameterizedTypeReference<List<GitHubIssue>> ISSUES_TYPE = new ParameterizedTypeReference<List<GitHubIssue>>() {};
|
private static final ParameterizedTypeReference<List<GitHubIssue>> ISSUES_TYPE = new ParameterizedTypeReference<List<GitHubIssue>>() {};
|
||||||
@@ -436,6 +444,12 @@ class GitHub extends GitHubSupport implements IssueTracker {
|
|||||||
@Override
|
@Override
|
||||||
public Tickets findTickets(ModuleIteration moduleIteration, List<TicketReference> ticketReferences) {
|
public Tickets findTickets(ModuleIteration moduleIteration, List<TicketReference> ticketReferences) {
|
||||||
|
|
||||||
|
return findGitHubIssues(moduleIteration, ticketReferences).stream().map(GitHub::toTicket)
|
||||||
|
.collect(Tickets.toTicketsCollector());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GitHubIssue> findGitHubIssues(ModuleIteration moduleIteration, List<TicketReference> ticketReferences) {
|
||||||
|
|
||||||
logger.log(moduleIteration, "Looking up GitHub issues from milestone …");
|
logger.log(moduleIteration, "Looking up GitHub issues from milestone …");
|
||||||
|
|
||||||
Map<String, GitHubIssue> issues = getIssuesFor(moduleIteration, false, true)
|
Map<String, GitHubIssue> issues = getIssuesFor(moduleIteration, false, true)
|
||||||
@@ -448,13 +462,14 @@ class GitHub extends GitHubSupport implements IssueTracker {
|
|||||||
Streamable.of(() -> ticketReferences.stream().filter(it -> it.getId().startsWith("#"))),
|
Streamable.of(() -> ticketReferences.stream().filter(it -> it.getId().startsWith("#"))),
|
||||||
ticketReference -> getTicket(issues, repositoryName, ticketReference));
|
ticketReference -> getTicket(issues, repositoryName, ticketReference));
|
||||||
|
|
||||||
Tickets tickets = foundIssues.stream().map(GitHub::toTicket)
|
List<GitHubIssue> gitHubIssues = foundIssues.stream().filter(it -> {
|
||||||
.filter(it -> it.isReleaseTicketFor(moduleIteration) || !it.isReleaseTicket())
|
Ticket ticket = toTicket(it);
|
||||||
.collect(Tickets.toTicketsCollector());
|
return !ticket.isReleaseTicketFor(moduleIteration) && !ticket.isReleaseTicket();
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
logger.log(moduleIteration, "Resolved %s tickets.", tickets.getOverallTotal());
|
logger.log(moduleIteration, "Resolved %s tickets.", gitHubIssues.size());
|
||||||
|
|
||||||
return tickets;
|
return gitHubIssues;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GitHubIssue getTicket(Map<String, GitHubIssue> cache, String repositoryName, TicketReference reference) {
|
private GitHubIssue getTicket(Map<String, GitHubIssue> cache, String repositoryName, TicketReference reference) {
|
||||||
@@ -486,11 +501,9 @@ class GitHub extends GitHubSupport implements IssueTracker {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
GitHubIssue gitHubIssue = operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.GET,
|
return operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.GET,
|
||||||
new HttpEntity<>(new HttpHeaders()), ISSUE_TYPE, parameters).getBody();
|
new HttpEntity<>(new HttpHeaders()), ISSUE_TYPE, parameters).getBody();
|
||||||
|
|
||||||
return gitHubIssue;
|
|
||||||
|
|
||||||
} catch (HttpStatusCodeException e) {
|
} catch (HttpStatusCodeException e) {
|
||||||
|
|
||||||
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
|
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
|
||||||
@@ -501,6 +514,100 @@ class GitHub extends GitHubSupport implements IssueTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param module
|
||||||
|
* @param ticketReferences
|
||||||
|
*/
|
||||||
|
public void createOrUpdateRelease(ModuleIteration module, List<TicketReference> ticketReferences) {
|
||||||
|
|
||||||
|
logger.log(module, "Preparing GitHub Release …");
|
||||||
|
|
||||||
|
List<GitHubIssue> gitHubIssues = findGitHubIssues(module, ticketReferences);
|
||||||
|
|
||||||
|
ArtifactVersion version = ArtifactVersion.of(module);
|
||||||
|
DocumentationMetadata documentation = DocumentationMetadata.of(module.getProject(), version);
|
||||||
|
|
||||||
|
ChangelogGenerator generator = new ChangelogGenerator();
|
||||||
|
String releaseBody = generator.generate(gitHubIssues, (changelogSection, s) -> s);
|
||||||
|
String documentationLinks = getDocumentationLinks(module, documentation);
|
||||||
|
|
||||||
|
createOrUpdateRelease(module, String.format("## :green_book: Links%n%s%n%s%n", documentationLinks, releaseBody));
|
||||||
|
logger.log(module, "GitHub Release up to date");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDocumentationLinks(ModuleIteration module, DocumentationMetadata documentation) {
|
||||||
|
|
||||||
|
String referenceDocUrl = documentation.getReferenceDocUrl(module.getTrain());
|
||||||
|
String apiDocUrl = documentation.getApiDocUrl(module.getTrain());
|
||||||
|
|
||||||
|
String reference = String.format("* [%s %s Reference documentation](%s)", module.getProject().getFullName(),
|
||||||
|
documentation.getVersion(module.getTrain()), referenceDocUrl);
|
||||||
|
|
||||||
|
String apidoc = String.format("* [%s %s Javadoc](%s)", module.getProject().getFullName(),
|
||||||
|
documentation.getVersion(module.getTrain()), apiDocUrl);
|
||||||
|
|
||||||
|
return String.format("%s%n%s%n", reference, apidoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createOrUpdateRelease(ModuleIteration module, String body) {
|
||||||
|
|
||||||
|
String repositoryName = GitProject.of(module.getProject()).getRepositoryName();
|
||||||
|
Tag tag = VersionTags.empty(module.getProject()).createTag(module);
|
||||||
|
logger.log(module, "Looking up GitHub Release …");
|
||||||
|
|
||||||
|
Iteration iteration = module.getTrainIteration().getIteration();
|
||||||
|
boolean prerelase = iteration.isPreview();
|
||||||
|
GitHubRelease release = findRelease(repositoryName, tag.getName());
|
||||||
|
|
||||||
|
if (release == null) {
|
||||||
|
release = new GitHubRelease(null, tag.getName(), tag.getName(), body, false, prerelase);
|
||||||
|
logger.log(module, "Creating new Release …");
|
||||||
|
createRelease(repositoryName, release);
|
||||||
|
} else {
|
||||||
|
release = release.withPrerelease(prerelase).withBody(body);
|
||||||
|
logger.log(module, "Updating new Release …");
|
||||||
|
updateRelease(repositoryName, release);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GitHubRelease findRelease(String repositoryName, String tagName) {
|
||||||
|
|
||||||
|
Map<String, Object> parameters = newUrlTemplateVariables();
|
||||||
|
parameters.put("repoName", repositoryName);
|
||||||
|
parameters.put("tag", tagName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return operations.exchange(RELEASE_BY_TAG_URI_TEMPLATE, HttpMethod.GET, new HttpEntity<>(new HttpHeaders()),
|
||||||
|
GitHubRelease.class, parameters).getBody();
|
||||||
|
} catch (HttpStatusCodeException e) {
|
||||||
|
|
||||||
|
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createRelease(String repositoryName, GitHubRelease release) {
|
||||||
|
|
||||||
|
Map<String, Object> parameters = newUrlTemplateVariables();
|
||||||
|
parameters.put("repoName", repositoryName);
|
||||||
|
|
||||||
|
operations.exchange(RELEASE_URI_TEMPLATE, HttpMethod.POST, new HttpEntity<>(release), GitHubRelease.class,
|
||||||
|
parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateRelease(String repositoryName, GitHubRelease release) {
|
||||||
|
|
||||||
|
Map<String, Object> parameters = newUrlTemplateVariables();
|
||||||
|
parameters.put("repoName", repositoryName);
|
||||||
|
parameters.put("id", release.getId());
|
||||||
|
|
||||||
|
operations.exchange(RELEASE_BY_ID_URI_TEMPLATE, HttpMethod.PATCH, new HttpEntity<>(release), GitHubRelease.class,
|
||||||
|
parameters);
|
||||||
|
}
|
||||||
|
|
||||||
private Stream<GitHubIssue> getIssuesFor(ModuleIteration moduleIteration, boolean forCurrentUser,
|
private Stream<GitHubIssue> getIssuesFor(ModuleIteration moduleIteration, boolean forCurrentUser,
|
||||||
boolean ignoreMissingMilestone) {
|
boolean ignoreMissingMilestone) {
|
||||||
|
|
||||||
@@ -556,4 +663,5 @@ class GitHub extends GitHubSupport implements IssueTracker {
|
|||||||
private static Ticket toTicket(GitHubIssue issue) {
|
private static Ticket toTicket(GitHubIssue issue) {
|
||||||
return new Ticket(issue.getId(), issue.getTitle(), issue.getHtmlUrl(), new GithubTicketStatus(issue.getState()));
|
return new Ticket(issue.getId(), issue.getTitle(), issue.getHtmlUrl(), new GithubTicketStatus(issue.getState()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,17 +20,25 @@ import lombok.NonNull;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.experimental.FieldDefaults;
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import org.springframework.data.release.CliComponent;
|
import org.springframework.data.release.CliComponent;
|
||||||
import org.springframework.data.release.TimedCommand;
|
import org.springframework.data.release.TimedCommand;
|
||||||
|
import org.springframework.data.release.git.GitOperations;
|
||||||
import org.springframework.data.release.issues.IssueTracker;
|
import org.springframework.data.release.issues.IssueTracker;
|
||||||
|
import org.springframework.data.release.issues.TicketReference;
|
||||||
import org.springframework.data.release.model.Project;
|
import org.springframework.data.release.model.Project;
|
||||||
|
import org.springframework.data.release.model.Tracker;
|
||||||
|
import org.springframework.data.release.model.TrainIteration;
|
||||||
|
import org.springframework.data.release.utils.ExecutionUtils;
|
||||||
import org.springframework.plugin.core.PluginRegistry;
|
import org.springframework.plugin.core.PluginRegistry;
|
||||||
import org.springframework.shell.core.annotation.CliCommand;
|
import org.springframework.shell.core.annotation.CliCommand;
|
||||||
import org.springframework.shell.core.annotation.CliOption;
|
import org.springframework.shell.core.annotation.CliOption;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Component to execute GitHub related operations.
|
||||||
|
*
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
@CliComponent
|
@CliComponent
|
||||||
@@ -39,6 +47,8 @@ import org.springframework.shell.core.annotation.CliOption;
|
|||||||
class GitHubCommands extends TimedCommand {
|
class GitHubCommands extends TimedCommand {
|
||||||
|
|
||||||
@NonNull PluginRegistry<IssueTracker, Project> tracker;
|
@NonNull PluginRegistry<IssueTracker, Project> tracker;
|
||||||
|
@NonNull GitHub gitHub;
|
||||||
|
@NonNull GitOperations git;
|
||||||
@NonNull GitHubLabels gitHubLabels;
|
@NonNull GitHubLabels gitHubLabels;
|
||||||
@NonNull Executor executor;
|
@NonNull Executor executor;
|
||||||
|
|
||||||
@@ -47,4 +57,29 @@ class GitHubCommands extends TimedCommand {
|
|||||||
gitHubLabels.createOrUpdateLabels(project);
|
gitHubLabels.createOrUpdateLabels(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CliCommand(value = "github push")
|
||||||
|
public void push(@CliOption(key = "", mandatory = true) TrainIteration iteration) {
|
||||||
|
|
||||||
|
git.push(iteration);
|
||||||
|
git.pushTags(iteration.getTrain());
|
||||||
|
|
||||||
|
createOrUpdateLabels(iteration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@CliCommand(value = "github create release")
|
||||||
|
public void createOrUpdateLabels(@CliOption(key = "", mandatory = true) TrainIteration iteration) {
|
||||||
|
|
||||||
|
TrainIteration previousIteration = git.getPreviousIteration(iteration);
|
||||||
|
|
||||||
|
ExecutionUtils.run(executor, iteration, it -> {
|
||||||
|
|
||||||
|
if (it.getProject().getTracker() == Tracker.GITHUB) {
|
||||||
|
|
||||||
|
List<TicketReference> ticketReferences = git.getTicketReferencesBetween(it.getProject(), previousIteration,
|
||||||
|
iteration);
|
||||||
|
gitHub.createOrUpdateRelease(it, ticketReferences);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,41 +31,59 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
class GitHubIssue {
|
class GitHubIssue implements Comparable<GitHubIssue> {
|
||||||
|
|
||||||
String number, title, state;
|
String number, title, state, url;
|
||||||
|
GitHubUser user;
|
||||||
List<Object> assignees;
|
List<Object> assignees;
|
||||||
String htmlUrl;
|
String htmlUrl;
|
||||||
Object milestone;
|
Object milestone;
|
||||||
|
PullRequest pullRequest;
|
||||||
|
List<Label> labels;
|
||||||
|
|
||||||
public GitHubIssue(String number, String title, String state, List<Object> assignees,
|
public GitHubIssue(String number, String title, String state, String url, GitHubUser user, List<Object> assignees,
|
||||||
@JsonProperty("html_url") String htmlUrl, Object milestone) {
|
@JsonProperty("html_url") String htmlUrl, Object milestone, @JsonProperty("pull_request") PullRequest pullRequest,
|
||||||
|
List<Label> labels) {
|
||||||
this.number = number;
|
this.number = number;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
this.url = url;
|
||||||
|
this.user = user;
|
||||||
this.assignees = assignees;
|
this.assignees = assignees;
|
||||||
this.htmlUrl = htmlUrl;
|
this.htmlUrl = htmlUrl;
|
||||||
this.milestone = milestone;
|
this.milestone = milestone;
|
||||||
|
this.pullRequest = pullRequest;
|
||||||
|
this.labels = labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GitHubIssue of(String title, Milestone milestone) {
|
public static GitHubIssue of(String title, Milestone milestone) {
|
||||||
return new GitHubIssue(null, title, null, null, null, milestone.number);
|
return new GitHubIssue(null, title, null, null, null, null, null, milestone.number, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GitHubIssue assignedTo(String username) {
|
public static GitHubIssue assignedTo(String username) {
|
||||||
|
|
||||||
Assert.hasText(username, "Username must not be null or empty!");
|
Assert.hasText(username, "Username must not be null or empty!");
|
||||||
return new GitHubIssue(null, null, null, Collections.singletonList(username), null, null);
|
return new GitHubIssue(null, null, null, null, null, Collections.singletonList(username), null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GitHubIssue close() {
|
public GitHubIssue close() {
|
||||||
return new GitHubIssue(this.number, this.title, "closed", this.assignees, null, this.milestone);
|
return new GitHubIssue(this.number, this.title, "closed", null, null, this.assignees, null, this.milestone, null,
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return number == null ? null : "#".concat(number);
|
return number == null ? null : "#".concat(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(GitHubIssue o) {
|
||||||
|
|
||||||
|
int number = this.number != null ? Integer.parseInt(this.number) : -1;
|
||||||
|
int other = o.number != null ? Integer.parseInt(o.number) : -1;
|
||||||
|
|
||||||
|
return Integer.compare(number, other);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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
|
||||||
|
*
|
||||||
|
* http://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.data.release.issues.github;
|
||||||
|
|
||||||
|
import lombok.Value;
|
||||||
|
import lombok.With;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details of a Github release.
|
||||||
|
*
|
||||||
|
* @author Mark Paluch
|
||||||
|
*/
|
||||||
|
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||||
|
@Value
|
||||||
|
class GitHubRelease {
|
||||||
|
|
||||||
|
Integer id;
|
||||||
|
@JsonProperty("tag_name") String tagName;
|
||||||
|
String name;
|
||||||
|
@With String body;
|
||||||
|
@With boolean draft;
|
||||||
|
@With boolean prerelease;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-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.data.release.issues.github;
|
||||||
|
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details of a Github user.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
*/
|
||||||
|
@Value
|
||||||
|
class GitHubUser {
|
||||||
|
|
||||||
|
String name;
|
||||||
|
|
||||||
|
String url;
|
||||||
|
|
||||||
|
public GitHubUser(@JsonProperty("login") String name, @JsonProperty("html_url") String url) {
|
||||||
|
this.name = name;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-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.data.release.issues.github;
|
||||||
|
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a GitHub PullRequest.
|
||||||
|
*
|
||||||
|
* @author Mark Paluch
|
||||||
|
*/
|
||||||
|
@Value
|
||||||
|
class PullRequest {
|
||||||
|
|
||||||
|
String url;
|
||||||
|
|
||||||
|
public PullRequest(@JsonProperty("url") String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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
|
||||||
|
*
|
||||||
|
* http://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.data.release.model;
|
||||||
|
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object providing documentation links.
|
||||||
|
*
|
||||||
|
* @author Mark Paluch
|
||||||
|
*/
|
||||||
|
@Value(staticConstructor = "of")
|
||||||
|
public class DocumentationMetadata {
|
||||||
|
|
||||||
|
private static String DOCS_BASE = "https://docs.spring.io/spring-data/%s/docs/%s";
|
||||||
|
private static String DOCS = DOCS_BASE.concat("/reference/html/");
|
||||||
|
private static String JAVADOC = DOCS_BASE.concat("/api");
|
||||||
|
|
||||||
|
Project project;
|
||||||
|
ArtifactVersion version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the JavaDoc URL for non-snapshot versions and not the build project.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getApiDocUrl(Train train) {
|
||||||
|
|
||||||
|
return version.isSnapshotVersion() || Projects.BUILD.equals(project) //
|
||||||
|
? "" //
|
||||||
|
: String.format(JAVADOC, project.getName().toLowerCase(Locale.US), getVersion(train));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the reference documentation URL for non-snapshot versions and not the build project.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getReferenceDocUrl(Train train) {
|
||||||
|
|
||||||
|
return version.isSnapshotVersion() || Projects.BUILD.equals(project) //
|
||||||
|
? "" //
|
||||||
|
: String.format(DOCS, project.getName().toLowerCase(Locale.US), getVersion(train));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion(Train train) {
|
||||||
|
|
||||||
|
if (Projects.BUILD.equals(project)) {
|
||||||
|
|
||||||
|
if (train.usesCalver()) {
|
||||||
|
|
||||||
|
if (version.isBugFixVersion() || version.isReleaseVersion()) {
|
||||||
|
return train.getCalver().toMajorMinorBugfix();
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format("%s-%s", train.getCalver().toMajorMinorBugfix(), version.getReleaseTrainSuffix());
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format("%s-%s", train.getName(),
|
||||||
|
version.isReleaseVersion() && !version.isBugFixVersion() ? "RELEASE" : version.getReleaseTrainSuffix());
|
||||||
|
}
|
||||||
|
|
||||||
|
return version.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,11 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.release.sagan;
|
package org.springframework.data.release.sagan;
|
||||||
|
|
||||||
import java.util.Locale;
|
import org.springframework.data.release.model.DocumentationMetadata;
|
||||||
|
|
||||||
import org.springframework.data.release.model.ArtifactVersion;
|
|
||||||
import org.springframework.data.release.model.Projects;
|
|
||||||
import org.springframework.data.release.model.Train;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
@@ -35,12 +31,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
@JsonInclude(Include.NON_NULL)
|
@JsonInclude(Include.NON_NULL)
|
||||||
class ProjectMetadata {
|
class ProjectMetadata {
|
||||||
|
|
||||||
private static String DOCS_BASE = "https://docs.spring.io/spring-data/%s/docs/{version}";
|
|
||||||
private static String DOCS = DOCS_BASE.concat("/reference/html/");
|
|
||||||
private static String JAVADOC = DOCS_BASE.concat("/api");
|
|
||||||
|
|
||||||
private final MaintainedVersion version;
|
private final MaintainedVersion version;
|
||||||
private final MaintainedVersions versions;
|
private final MaintainedVersions versions;
|
||||||
|
private final DocumentationMetadata documentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link ProjectMetadata} instance from the given {@link MaintainedVersion}.
|
* Creates a new {@link ProjectMetadata} instance from the given {@link MaintainedVersion}.
|
||||||
@@ -54,6 +47,7 @@ class ProjectMetadata {
|
|||||||
|
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.versions = versions;
|
this.versions = versions;
|
||||||
|
this.documentation = DocumentationMetadata.of(version.getProject(), version.getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,10 +56,7 @@ class ProjectMetadata {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getReferenceDocUrl() {
|
public String getReferenceDocUrl() {
|
||||||
|
return documentation.getReferenceDocUrl(version.getTrain());
|
||||||
return version.getVersion().isSnapshotVersion() || Projects.BUILD.equals(version.getProject()) //
|
|
||||||
? "" //
|
|
||||||
: String.format(DOCS, version.getProject().getName().toLowerCase(Locale.US));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,10 +75,7 @@ class ProjectMetadata {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getApiDocUrl() {
|
public String getApiDocUrl() {
|
||||||
|
return documentation.getApiDocUrl(version.getTrain());
|
||||||
return version.getVersion().isSnapshotVersion() || Projects.BUILD.equals(version.getProject()) //
|
|
||||||
? "" //
|
|
||||||
: String.format(JAVADOC, version.getProject().getName().toLowerCase(Locale.US));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,26 +85,6 @@ class ProjectMetadata {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
|
return documentation.getVersion(version.getTrain());
|
||||||
ArtifactVersion version = this.version.getVersion();
|
|
||||||
|
|
||||||
if (Projects.BUILD.equals(this.version.getProject())) {
|
|
||||||
|
|
||||||
Train train = this.version.getTrain();
|
|
||||||
|
|
||||||
if (train.usesCalver()) {
|
|
||||||
|
|
||||||
if (version.isBugFixVersion() || version.isReleaseVersion()) {
|
|
||||||
return train.getCalver().toMajorMinorBugfix();
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.format("%s-%s", train.getCalver().toMajorMinorBugfix(), version.getReleaseTrainSuffix());
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.format("%s-%s", train.getName(),
|
|
||||||
version.isReleaseVersion() && !version.isBugFixVersion() ? "RELEASE" : version.getReleaseTrainSuffix());
|
|
||||||
}
|
|
||||||
|
|
||||||
return version.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user