creates release notes in wiki; fixes gh-92
This commit is contained in:
@@ -250,4 +250,13 @@ public class Releaser {
|
||||
log.warn("\nUnable to update all samples", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateReleaseTrainWiki(Projects projects) {
|
||||
try {
|
||||
this.documentationUpdater.updateReleaseTrainWiki(projects);
|
||||
log.info("\nSuccessfully updated project wiki");
|
||||
} catch (Exception e) {
|
||||
log.warn("\nUnable to update project wiki", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,11 @@ public class ReleaserProperties implements Serializable {
|
||||
*/
|
||||
private String releaseTrainDocsUrl = "https://github.com/spring-cloud-samples/scripts";
|
||||
|
||||
/**
|
||||
* URL to the release train wiki
|
||||
*/
|
||||
private String releaseTrainWikiUrl = "https://github.com/spring-projects/spring-cloud.wiki.git";
|
||||
|
||||
/**
|
||||
* Branch to check out for the documentation project
|
||||
*/
|
||||
@@ -181,6 +186,12 @@ public class ReleaserProperties implements Serializable {
|
||||
*/
|
||||
private String releaseTrainDocsBranch = "master";
|
||||
|
||||
/**
|
||||
* Page prefix for the release train wiki. E.g. for [Spring-Cloud-Finchley-Release-Notes]
|
||||
* it would be [Spring-Cloud].
|
||||
*/
|
||||
private String releaseTrainWikiPagePrefix = "Spring-Cloud";
|
||||
|
||||
/**
|
||||
* Where should the Spring Cloud Release repo get cloned to. If {@code null} defaults to a temporary directory
|
||||
*/
|
||||
@@ -238,6 +249,11 @@ public class ReleaserProperties implements Serializable {
|
||||
*/
|
||||
private boolean updateReleaseTrainDocs = true;
|
||||
|
||||
/**
|
||||
* If set to {@code false}, will not clone and update the release train wiki
|
||||
*/
|
||||
private boolean updateReleaseTrainWiki = true;
|
||||
|
||||
/**
|
||||
* If set to {@code false}, will not clone and update the samples for all projects
|
||||
*/
|
||||
@@ -433,15 +449,41 @@ public class ReleaserProperties implements Serializable {
|
||||
this.allTestSampleUrls = allTestSampleUrls;
|
||||
}
|
||||
|
||||
public String getReleaseTrainWikiUrl() {
|
||||
return this.releaseTrainWikiUrl;
|
||||
}
|
||||
|
||||
public void setReleaseTrainWikiUrl(String releaseTrainWikiUrl) {
|
||||
this.releaseTrainWikiUrl = releaseTrainWikiUrl;
|
||||
}
|
||||
|
||||
public boolean isUpdateReleaseTrainWiki() {
|
||||
return this.updateReleaseTrainWiki;
|
||||
}
|
||||
|
||||
public void setUpdateReleaseTrainWiki(boolean updateReleaseTrainWiki) {
|
||||
this.updateReleaseTrainWiki = updateReleaseTrainWiki;
|
||||
}
|
||||
|
||||
public String getReleaseTrainWikiPagePrefix() {
|
||||
return this.releaseTrainWikiPagePrefix;
|
||||
}
|
||||
|
||||
public void setReleaseTrainWikiPagePrefix(String releaseTrainWikiPagePrefix) {
|
||||
this.releaseTrainWikiPagePrefix = releaseTrainWikiPagePrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Git{" +
|
||||
"releaseTrainBomUrl='" + this.releaseTrainBomUrl + '\'' +
|
||||
", documentationUrl='" + this.documentationUrl + '\'' +
|
||||
", documentationBranch='" + this.documentationBranch + '\'' +
|
||||
", releaseTrainWikiUrl='" + this.releaseTrainWikiUrl + '\'' +
|
||||
", updateDocumentationRepo=" + this.updateDocumentationRepo +
|
||||
", springProjectUrl=" + this.springProjectUrl+
|
||||
", springProjectBranch=" + this.springProjectBranch +
|
||||
", releaseTrainWikiPagePrefix=" + this.releaseTrainWikiPagePrefix +
|
||||
", cloneDestinationDir='" + this.cloneDestinationDir + '\'' +
|
||||
", fetchVersionsFromGit=" + this.fetchVersionsFromGit +
|
||||
", oauthToken='" + this.oauthToken + '\'' +
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
|
||||
import org.springframework.cloud.release.internal.git.ProjectGitHandler;
|
||||
import org.springframework.cloud.release.internal.pom.ProjectVersion;
|
||||
import org.springframework.cloud.release.internal.pom.Projects;
|
||||
import org.springframework.cloud.release.internal.template.TemplateGenerator;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
@@ -17,10 +18,12 @@ public class DocumentationUpdater implements ReleaserPropertiesAware {
|
||||
private final ReleaseTrainContentsUpdater releaseTrainContentsUpdater;
|
||||
private ReleaserProperties properties;
|
||||
|
||||
public DocumentationUpdater(ProjectGitHandler gitHandler, ReleaserProperties properties) {
|
||||
public DocumentationUpdater(ProjectGitHandler gitHandler, ReleaserProperties properties,
|
||||
TemplateGenerator templateGenerator) {
|
||||
this.properties = properties;
|
||||
this.projectDocumentationUpdater = new ProjectDocumentationUpdater(this.properties, gitHandler);
|
||||
this.releaseTrainContentsUpdater = new ReleaseTrainContentsUpdater(this.properties, gitHandler);
|
||||
this.releaseTrainContentsUpdater = new ReleaseTrainContentsUpdater(this.properties, gitHandler,
|
||||
templateGenerator);
|
||||
}
|
||||
|
||||
DocumentationUpdater(ReleaserProperties properties, ProjectDocumentationUpdater updater,
|
||||
@@ -54,6 +57,16 @@ public class DocumentationUpdater implements ReleaserPropertiesAware {
|
||||
return this.releaseTrainContentsUpdater.updateProjectRepo(projects);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the release train wiki page
|
||||
*
|
||||
* @param projects
|
||||
* @return {@link File cloned temporary directory} - {@code null} if wrong version is used or the switch is turned off
|
||||
*/
|
||||
public File updateReleaseTrainWiki(Projects projects) {
|
||||
return this.releaseTrainContentsUpdater.updateReleaseTrainWiki(projects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReleaserProperties(ReleaserProperties properties) {
|
||||
this.properties = properties;
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.nio.file.Files;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.github.jknack.handlebars.Template;
|
||||
@@ -19,6 +20,7 @@ import org.springframework.cloud.release.internal.git.ProjectGitHandler;
|
||||
import org.springframework.cloud.release.internal.pom.ProjectVersion;
|
||||
import org.springframework.cloud.release.internal.pom.Projects;
|
||||
import org.springframework.cloud.release.internal.tech.HandlebarsHelper;
|
||||
import org.springframework.cloud.release.internal.template.TemplateGenerator;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -33,10 +35,12 @@ class ReleaseTrainContentsUpdater implements ReleaserPropertiesAware {
|
||||
private final ReleaseTrainContentsGitHandler handler;
|
||||
private final ReleaseTrainContentsParser parser;
|
||||
private final ReleaseTrainContentsGenerator generator;
|
||||
private final TemplateGenerator templateGenerator;
|
||||
|
||||
ReleaseTrainContentsUpdater(ReleaserProperties properties, ProjectGitHandler handler) {
|
||||
ReleaseTrainContentsUpdater(ReleaserProperties properties, ProjectGitHandler handler, TemplateGenerator templateGenerator) {
|
||||
this.properties = properties;
|
||||
this.handler = new ReleaseTrainContentsGitHandler(handler);
|
||||
this.templateGenerator = templateGenerator;
|
||||
this.parser = new ReleaseTrainContentsParser();
|
||||
this.generator = new ReleaseTrainContentsGenerator(properties);
|
||||
}
|
||||
@@ -55,7 +59,7 @@ class ReleaseTrainContentsUpdater implements ReleaserPropertiesAware {
|
||||
}
|
||||
File releaseTrainProject = this.handler.cloneSpringDocProject();
|
||||
File index = new File(releaseTrainProject, "index.html");
|
||||
ReleaseTrainContents contents = this.parser.parse(index);
|
||||
ReleaseTrainContents contents = this.parser.parseProjectPage(index);
|
||||
String newContents = this.generator.releaseTrainContents(contents, projects);
|
||||
if (StringUtils.isEmpty(newContents)) {
|
||||
log.info("No changes to commit to the Spring Project page.");
|
||||
@@ -79,6 +83,94 @@ class ReleaseTrainContentsUpdater implements ReleaserPropertiesAware {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the test project, updates it and runs tests
|
||||
*
|
||||
* @param projects - set of project with versions to assert against
|
||||
*/
|
||||
File updateReleaseTrainWiki(Projects projects) {
|
||||
if (!this.properties.getGit().isUpdateReleaseTrainWiki() ||
|
||||
!this.properties.getMetaRelease().isEnabled()) {
|
||||
log.info("Will not clone and update the release train wiki, since the switch to do so "
|
||||
+ "is off or it's not a meta-release. Set [releaser.git.update-release-train-wiki] to [true] to change that");
|
||||
return null;
|
||||
}
|
||||
File releaseTrainWiki = this.handler.cloneReleaseTrainWiki();
|
||||
ProjectVersion releaseTrain = projects.releaseTrain(this.properties);
|
||||
String releaseTrainName = releaseTrain.major();
|
||||
String wikiPagePrefix = this.properties.getGit().getReleaseTrainWikiPagePrefix();
|
||||
String releaseTrainDocFileName = releaseTrainDocFileName(releaseTrainName, wikiPagePrefix);
|
||||
log.info("Reading the file [{}] for the current release train", releaseTrainDocFileName);
|
||||
File releaseTrainDocFile = releaseTrainDocFile(releaseTrainWiki, releaseTrainDocFileName);
|
||||
String releaseVersionFromCurrentFile = this.parser.latestReleaseTrainFromWiki(releaseTrainDocFile);
|
||||
log.info("Latest release train version in the file is [{}]", releaseVersionFromCurrentFile);
|
||||
if (!isThisReleaseTrainVersionNewer(releaseTrain, releaseVersionFromCurrentFile)) {
|
||||
log.info("Current release train version [{}] is not "
|
||||
+ "newer than the version taken from the wiki [{}]",
|
||||
releaseTrain.version, releaseVersionFromCurrentFile);
|
||||
return releaseTrainWiki;
|
||||
}
|
||||
return generateNewWikiEntry(projects, releaseTrainWiki, releaseTrain,
|
||||
releaseTrainName, releaseTrainDocFile, releaseVersionFromCurrentFile);
|
||||
}
|
||||
|
||||
private File generateNewWikiEntry(Projects projects, File releaseTrainWiki, ProjectVersion releaseTrain, String releaseTrainName, File releaseTrainDocFile, String releaseVersionFromCurrentFile) {
|
||||
File releaseNotes = this.templateGenerator.releaseNotes(projects);
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(releaseTrainDocFile.toPath());
|
||||
int lineIndex;
|
||||
for (lineIndex = 0; lineIndex < lines.size(); lineIndex++) {
|
||||
if (lines.get(lineIndex).contains(releaseVersionFromCurrentFile)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return insertNewWikiContentBeforeTheLatestRelease(releaseTrainWiki, releaseTrain,
|
||||
releaseTrainName, releaseTrainDocFile, releaseNotes, lines, lineIndex);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private File insertNewWikiContentBeforeTheLatestRelease(File releaseTrainWiki, ProjectVersion releaseTrain, String releaseTrainName, File releaseTrainDocFile, File releaseNotes, List<String> lines, int lineIndex) throws IOException {
|
||||
String newContent = new StringJoiner("\n")
|
||||
.add(String.join("\n", lines.subList(0, lineIndex)))
|
||||
.add("\n").add(new String(Files.readAllBytes(releaseNotes.toPath())))
|
||||
.add(String.join("\n", lines.subList(lineIndex, lines.size())))
|
||||
.toString();
|
||||
Files.write(releaseTrainDocFile.toPath(), newContent.getBytes());
|
||||
log.info("Successfully stored new wiki contents for release train [{}]", releaseTrainName);
|
||||
this.handler.commitAndPushChanges(releaseTrainWiki, releaseTrain);
|
||||
return releaseTrainWiki;
|
||||
}
|
||||
|
||||
private String releaseTrainDocFileName(String releaseTrainName, String wikiPagePrefix) {
|
||||
return new StringJoiner("-")
|
||||
.add(wikiPagePrefix).add(releaseTrainName).add("Release-Notes.md").toString();
|
||||
}
|
||||
|
||||
private boolean isThisReleaseTrainVersionNewer(ProjectVersion releaseTrain, String releaseVersionFromCurrentFile) {
|
||||
if (StringUtils.hasText(releaseVersionFromCurrentFile)) {
|
||||
return releaseTrain.compareToReleaseTrainName(releaseVersionFromCurrentFile) > 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private File releaseTrainDocFile(File releaseTrainWiki, String releaseTrainDocFileName) {
|
||||
File releaseTrainDocFile = new File(releaseTrainWiki, releaseTrainDocFileName);
|
||||
if (!releaseTrainDocFile.exists()) {
|
||||
try {
|
||||
if (!releaseTrainDocFile.createNewFile()) {
|
||||
throw new IllegalStateException("Failed to create releae train doc file");
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return releaseTrainDocFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReleaserProperties(ReleaserProperties properties) {
|
||||
this.properties = properties;
|
||||
@@ -121,7 +213,7 @@ class ReleaseTrainContentsGenerator implements ReleaserPropertiesAware {
|
||||
}
|
||||
|
||||
ProjectVersion currentReleaseTrainProject(Projects projects) {
|
||||
return projects.forName(this.properties.getMetaRelease().getReleaseTrainProjectName());
|
||||
return projects.releaseTrain(this.properties);
|
||||
}
|
||||
|
||||
private String generate(File contentOutput, Template template, ReleaseTrainContents releaseTrainContents) {
|
||||
@@ -205,11 +297,14 @@ class ReleaseTrainContentsGitHandler {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
// clones the project and checks out the branch
|
||||
File cloneSpringDocProject() {
|
||||
return this.handler.cloneSpringDocProject();
|
||||
}
|
||||
|
||||
File cloneReleaseTrainWiki() {
|
||||
return this.handler.cloneReleaseTrainWiki();
|
||||
}
|
||||
|
||||
void commitAndPushChanges(File repo, ProjectVersion releaseTrain) {
|
||||
log.debug("Committing and pushing changes");
|
||||
this.handler.commit(repo, String.format(PROJECT_PAGE_UPDATED_COMMIT_MSG, releaseTrain.version));
|
||||
@@ -223,7 +318,7 @@ class ReleaseTrainContentsParser {
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ReleaseTrainContentsParser.class);
|
||||
|
||||
ReleaseTrainContents parse(File rawHtml) {
|
||||
ReleaseTrainContents parseProjectPage(File rawHtml) {
|
||||
try {
|
||||
String contents = new String(Files.readAllBytes(rawHtml.toPath()));
|
||||
String[] split = contents.split("<!-- (BEGIN|END) COMPONENTS -->");
|
||||
@@ -246,4 +341,18 @@ class ReleaseTrainContentsParser {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
String latestReleaseTrainFromWiki(File rawMd) {
|
||||
try {
|
||||
return Files.readAllLines(rawMd.toPath()).stream()
|
||||
.filter(s -> s.trim().startsWith("#"))
|
||||
.map(s -> s.substring(1).trim())
|
||||
.filter(s -> new ProjectVersion("foo", s).isValid())
|
||||
.findFirst()
|
||||
.orElse("");
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ public class ProjectGitHandler implements ReleaserPropertiesAware {
|
||||
this.properties.getGit().getTestSamplesBranch());
|
||||
}
|
||||
|
||||
public File cloneReleaseTrainWiki() {
|
||||
return cloneProject(this.properties.getGit().getReleaseTrainWikiUrl());
|
||||
}
|
||||
|
||||
public File cloneReleaseTrainProject() {
|
||||
return cloneProject(this.properties.getGit().getReleaseTrainBomUrl());
|
||||
}
|
||||
|
||||
@@ -59,7 +59,8 @@ public class ProjectVersion {
|
||||
}
|
||||
// 1.0.0.BUILD-SNAPSHOT
|
||||
String[] splitVersion = this.version.split("\\.");
|
||||
if (splitVersion.length < 4 && isNumeric(splitVersion[0])) {
|
||||
if (splitVersion.length < 4 && isNumeric(splitVersion[0]) ||
|
||||
splitVersion.length == 1 && !isNumeric(splitVersion[0])) {
|
||||
throw new IllegalStateException("Version is invalid. Should be of format [1.2.3.A]");
|
||||
}
|
||||
return splitVersion;
|
||||
@@ -101,6 +102,19 @@ public class ProjectVersion {
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
try {
|
||||
assertVersion();
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String major() {
|
||||
return this.assertVersion()[0];
|
||||
}
|
||||
|
||||
public boolean isSnapshot() {
|
||||
return this.version != null && this.version.contains("SNAPSHOT");
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.cloud.release.internal.ReleaserProperties;
|
||||
|
||||
/**
|
||||
* Abstraction over collection of projects
|
||||
*
|
||||
@@ -31,6 +33,10 @@ public class Projects extends HashSet<ProjectVersion> {
|
||||
return newProjects;
|
||||
}
|
||||
|
||||
public ProjectVersion releaseTrain(ReleaserProperties properties) {
|
||||
return this.forName(properties.getMetaRelease().getReleaseTrainProjectName());
|
||||
}
|
||||
|
||||
@Override public boolean add(ProjectVersion projectVersion) {
|
||||
if (projectVersion == null) {
|
||||
return false;
|
||||
|
||||
@@ -59,8 +59,7 @@ public class PostReleaseActions implements Closeable {
|
||||
}
|
||||
File file = this.projectGitHandler.cloneTestSamplesProject();
|
||||
ProjectVersion projectVersion = new ProjectVersion(file);
|
||||
String releaseTrainVersion =
|
||||
projects.forName(this.properties.getMetaRelease().getReleaseTrainProjectName()).version;
|
||||
String releaseTrainVersion = projects.releaseTrain(this.properties).version;
|
||||
Projects newProjects = addVersionForTestsProject(projects, projectVersion, releaseTrainVersion);
|
||||
this.projectPomUpdater
|
||||
.updateProjectFromReleaseTrain(file, newProjects, projectVersion, false);
|
||||
@@ -180,8 +179,7 @@ public class PostReleaseActions implements Closeable {
|
||||
}
|
||||
File file = this.projectGitHandler.cloneReleaseTrainDocumentationProject();
|
||||
ProjectVersion projectVersion = new ProjectVersion(file);
|
||||
String releaseTrainVersion =
|
||||
projects.forName(this.properties.getMetaRelease().getReleaseTrainProjectName()).version;
|
||||
String releaseTrainVersion = projects.releaseTrain(this.properties).version;
|
||||
Projects newProjects = addVersionForTestsProject(projects, projectVersion, releaseTrainVersion);
|
||||
this.projectPomUpdater
|
||||
.updateProjectFromReleaseTrain(file, newProjects, projectVersion, false);
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.cloud.release.internal.git.ProjectGitHandler;
|
||||
@@ -32,6 +33,8 @@ class ReleaseNotesTemplateGenerator {
|
||||
private final Projects projects;
|
||||
private final NotesGenerator notesGenerator;
|
||||
|
||||
static final Map<String, File> CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
ReleaseNotesTemplateGenerator(Template template, String releaseVersion,
|
||||
File blogOutput, Projects projects, ProjectGitHandler handler) {
|
||||
this.template = template;
|
||||
@@ -41,7 +44,13 @@ class ReleaseNotesTemplateGenerator {
|
||||
this.notesGenerator = new NotesGenerator(handler);
|
||||
}
|
||||
|
||||
File releseNotes() {
|
||||
File releaseNotes() {
|
||||
File cached = CACHE.get(this.releaseVersion);
|
||||
if (cached != null) {
|
||||
log.info("Found an existing entry [{}] in the cache "
|
||||
+ "for version [{}]", cached, this.releaseVersion);
|
||||
return cached;
|
||||
}
|
||||
try {
|
||||
Map<String, Object> map = ImmutableMap.<String, Object>builder()
|
||||
.put("date", LocalDate.now().format(DateTimeFormatter.ISO_DATE))
|
||||
@@ -50,7 +59,9 @@ class ReleaseNotesTemplateGenerator {
|
||||
.build();
|
||||
String blog = this.template.apply(map);
|
||||
Files.write(this.blogOutput.toPath(), blog.getBytes());
|
||||
return this.blogOutput;
|
||||
File output = this.blogOutput;
|
||||
CACHE.put(this.releaseVersion, output);
|
||||
return output;
|
||||
}
|
||||
catch (IOException e) {
|
||||
log.warn("Exception occurred while trying to generate release notes", e);
|
||||
|
||||
@@ -87,12 +87,12 @@ public class TemplateGenerator implements ReleaserPropertiesAware {
|
||||
String releaseVersion = parsedVersion(projects);
|
||||
Template template = template(RELEASE_NOTES_TEMPLATE);
|
||||
return new ReleaseNotesTemplateGenerator(template, releaseVersion,
|
||||
output, projects, this.handler).releseNotes();
|
||||
output, projects, this.handler).releaseNotes();
|
||||
}
|
||||
|
||||
private String parsedVersion(Projects projects) {
|
||||
if (this.props.getMetaRelease().isEnabled()) {
|
||||
return projects.forName(this.props.getMetaRelease().getReleaseTrainProjectName()).version;
|
||||
return projects.releaseTrain(this.props).version;
|
||||
}
|
||||
String version = this.props.getPom().getBranch();
|
||||
if (version.startsWith("v")) {
|
||||
|
||||
Reference in New Issue
Block a user