Further fancy stuff.
Added a changelog command to render a changelog for a given module from the JIRA tickets. Some internal refactorings and enhancements to the model to be able to work with artifact versions, branches, tags.
This commit is contained in:
37
pom.xml
37
pom.xml
@@ -97,43 +97,6 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
<!-- <plugin> -->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId> -->
|
||||
<!-- <artifactId>maven-dependency-plugin</artifactId> -->
|
||||
<!-- <executions> -->
|
||||
<!-- <execution> -->
|
||||
<!-- <id>copy-dependencies</id> -->
|
||||
<!-- <phase>prepare-package</phase> -->
|
||||
<!-- <goals> -->
|
||||
<!-- <goal>copy-dependencies</goal> -->
|
||||
<!-- </goals> -->
|
||||
<!-- <configuration> -->
|
||||
<!-- <outputDirectory>${project.build.directory}/lib</outputDirectory> -->
|
||||
<!-- <overWriteReleases>true</overWriteReleases> -->
|
||||
<!-- <overWriteSnapshots>true</overWriteSnapshots> -->
|
||||
<!-- <overWriteIfNewer>true</overWriteIfNewer> -->
|
||||
<!-- </configuration> -->
|
||||
<!-- </execution> -->
|
||||
<!-- </executions> -->
|
||||
<!-- </plugin> -->
|
||||
<!-- <plugin> -->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId> -->
|
||||
<!-- <artifactId>maven-jar-plugin</artifactId> -->
|
||||
<!-- <configuration> -->
|
||||
<!-- <archive> -->
|
||||
<!-- <manifest> -->
|
||||
<!-- <addClasspath>true</addClasspath> -->
|
||||
<!-- <useUniqueVersions>false</useUniqueVersions> -->
|
||||
<!-- <classpathPrefix>lib/</classpathPrefix> -->
|
||||
<!-- <mainClass>${jar.mainclass}</mainClass> -->
|
||||
<!-- </manifest> -->
|
||||
<!-- <manifestEntries> -->
|
||||
<!-- <version>${project.version}</version> -->
|
||||
<!-- </manifestEntries> -->
|
||||
<!-- </archive> -->
|
||||
<!-- </configuration> -->
|
||||
<!-- </plugin> -->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2014 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.announcement;
|
||||
|
||||
import org.springframework.data.release.cli.StaticResources;
|
||||
import org.springframework.data.release.maven.Artifact;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AnnouncementOperations {
|
||||
|
||||
/**
|
||||
* Returns the project list and links to be included in the release announcement for the given {@link Train} and
|
||||
* {@link Iteration}.
|
||||
*
|
||||
* @param train must not be {@literal null}.
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public String getProjectBulletpoints(Train train, Iteration iteration) {
|
||||
|
||||
Assert.notNull(train, "Train must not be null!");
|
||||
Assert.notNull(iteration, "Iteration must not be null!");
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (ModuleIteration module : train.getModuleIterations(iteration, ReleaseTrains.BUILD)) {
|
||||
|
||||
Project project = module.getProject();
|
||||
|
||||
builder.append("* ");
|
||||
builder.append(project.getFullName()).append(" ");
|
||||
builder.append(module.getVersion()).append(" ").append(module.getIteration().getName());
|
||||
builder.append(" - ");
|
||||
|
||||
Artifact artifact = new Artifact(module);
|
||||
|
||||
builder.append(getMarkDownLink("Artifacts", artifact.getRootUrl()));
|
||||
builder.append(" - ");
|
||||
|
||||
StaticResources resources = new StaticResources(module);
|
||||
|
||||
builder.append(getMarkDownLink("JavaDocs", resources.getJavaDocUrl())).append(" - ");
|
||||
builder.append(getMarkDownLink("Documentation", resources.getDocumentationUrl())).append(" - ");
|
||||
builder.append(getMarkDownLink("Changelog", resources.getChangelogUrl()));
|
||||
|
||||
builder.append("\n");
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String getMarkDownLink(String name, String url) {
|
||||
return String.format("[%s](%s)", name, url);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
AnnouncementOperations operations = new AnnouncementOperations();
|
||||
System.out.println(operations.getProjectBulletpoints(ReleaseTrains.DIJKSTRA, Iteration.M1));
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,6 @@ public class JiraCommands implements CommandMarker {
|
||||
|
||||
@CliCommand(value = "jira tickets")
|
||||
public String jira(
|
||||
//
|
||||
@CliOption(key = { "", "train" }, mandatory = true, help = "The name of the release train.") String trainName, //
|
||||
@CliOption(key = "iteration", mandatory = true, help = "An iteration key (one of M1, RC1, GA).") String iterationName, //
|
||||
@CliOption(key = "for-current-user", specifiedDefaultValue = "true", unspecifiedDefaultValue = "false") boolean forCurrentUser) {
|
||||
@@ -72,4 +71,13 @@ public class JiraCommands implements CommandMarker {
|
||||
|
||||
return connector.getTicketsFor(train, iteration, forCurrentUser ? credentials : null).toString();
|
||||
}
|
||||
|
||||
@CliCommand("changelog")
|
||||
public String changelog(@CliOption(key = { "", "module" }, mandatory = true) String moduleName, @CliOption(
|
||||
key = { "iteration" }, mandatory = true) String iterationName) {
|
||||
|
||||
Train dijkstra = ReleaseTrains.DIJKSTRA;
|
||||
return connector.getChangelogFor(dijkstra, dijkstra.getModule(moduleName),
|
||||
dijkstra.getIterations().getIterationByName(iterationName)).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,19 +15,22 @@
|
||||
*/
|
||||
package org.springframework.data.release.cli;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.git.GitOperations;
|
||||
import org.springframework.data.release.git.Tags;
|
||||
import org.springframework.data.release.maven.MavenOperations;
|
||||
import org.springframework.data.release.maven.Pom;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -37,19 +40,25 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class ReleaseCommands implements CommandMarker {
|
||||
|
||||
private final MavenOperations mavenOperations;
|
||||
private final MavenOperations maven;
|
||||
private final GitOperations git;
|
||||
|
||||
@CliCommand("release predict")
|
||||
public String predictTrainAndIteration() throws IOException {
|
||||
public String predictTrainAndIteration() throws Exception {
|
||||
|
||||
Project commons = ReleaseTrains.COMMONS;
|
||||
Pom pom = mavenOperations.getMavenProject(commons);
|
||||
Pom pom = maven.getMavenProject(commons);
|
||||
|
||||
Tags tags = git.getTags(commons);
|
||||
|
||||
ArtifactVersion version = tags.getLatest().toArtifactVersion();
|
||||
System.out.println(version);
|
||||
|
||||
for (Train train : ReleaseTrains.TRAINS) {
|
||||
|
||||
Module module = train.getModule(commons);
|
||||
|
||||
if (!pom.getVersion().startsWith(module.getVersion().toMajorMinorBugfix())) {
|
||||
if (!pom.getVersion().toString().startsWith(module.getVersion().toMajorMinorBugfix())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -58,4 +67,36 @@ public class ReleaseCommands implements CommandMarker {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the distribution of release artifacts for all projects.
|
||||
*
|
||||
* @param trainName
|
||||
* @param iterationName
|
||||
* @throws Exception
|
||||
*/
|
||||
@CliCommand("release distribute")
|
||||
public void distribute(@CliOption(key = { "", "train" }, mandatory = true) String trainName, @CliOption(
|
||||
key = "iteration", mandatory = true) String iterationName) throws Exception {
|
||||
|
||||
Train train = ReleaseTrains.getTrainByName(trainName);
|
||||
Iteration iteration = train.getIteration(iterationName);
|
||||
|
||||
git.checkout(train, iteration);
|
||||
maven.triggerDistributionBuild(train, iteration);
|
||||
}
|
||||
|
||||
@CliCommand("release prepare")
|
||||
public void prepare(@CliOption(key = { "", "train" }, mandatory = true) String trainName, @CliOption(
|
||||
key = "iteration", mandatory = true) String iterationName) throws Exception {
|
||||
|
||||
Train train = ReleaseTrains.getTrainByName(trainName);
|
||||
Iteration iteration = train.getIteration(iterationName);
|
||||
|
||||
git.prepare(train, iteration);
|
||||
|
||||
for (Module module : train) {
|
||||
maven.prepareProject(train, iteration, module.getProject());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2014 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.cli;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class StaticResources {
|
||||
|
||||
private static final String URL_TEMPLATE = "http://docs.spring.io/spring-data/%s/docs/%s";
|
||||
|
||||
private final String baseUrl;
|
||||
|
||||
public StaticResources(ModuleIteration module) {
|
||||
|
||||
Project project = module.getProject();
|
||||
ArtifactVersion version = ArtifactVersion.from(module);
|
||||
|
||||
this.baseUrl = String.format(URL_TEMPLATE, project.getName().toLowerCase(), version);
|
||||
}
|
||||
|
||||
public String getDocumentationUrl() {
|
||||
return baseUrl.concat("/reference/htmlsingle");
|
||||
}
|
||||
|
||||
public String getJavaDocUrl() {
|
||||
return baseUrl.concat("/api");
|
||||
}
|
||||
|
||||
public String getChangelogUrl() {
|
||||
return baseUrl.concat("/changelog.txt");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2014 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.git;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.release.model.IterationVersion;
|
||||
import org.springframework.data.release.model.Version;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value type to represent an SCM branch.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class Branch {
|
||||
|
||||
private static final Branch MASTER = new Branch("master");
|
||||
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Branch} from the given {@link IterationVersion}.
|
||||
*
|
||||
* @param iterationVersion must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static Branch from(IterationVersion iterationVersion) {
|
||||
|
||||
Assert.notNull(iterationVersion, "Iteration versoin must not be null!");
|
||||
|
||||
Version version = iterationVersion.getVersion();
|
||||
|
||||
if (iterationVersion.getIteration().isServiceIteration()) {
|
||||
return new Branch(version.toString().concat(".x"));
|
||||
}
|
||||
|
||||
return MASTER;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.release.git;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
@@ -35,20 +35,30 @@ import org.springframework.util.StringUtils;
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class GiCommands implements CommandMarker {
|
||||
|
||||
private final GitOperations gitOperations;
|
||||
private final GitOperations git;
|
||||
|
||||
@CliCommand("git checkout")
|
||||
public void checkout(@CliOption(key = { "", "train" }, mandatory = true) String trainName, @CliOption(
|
||||
key = "iteration", mandatory = true) String iterationName) throws Exception {
|
||||
|
||||
Train train = ReleaseTrains.getTrainByName(trainName);
|
||||
Iteration iteration = train.getIteration(iterationName);
|
||||
|
||||
git.checkout(train, iteration);
|
||||
}
|
||||
|
||||
@CliCommand("git update")
|
||||
public void checkout(@CliOption(key = { "train" }, mandatory = true) String trainName) throws IOException,
|
||||
public void checkout(@CliOption(key = { "", "train" }, mandatory = true) String trainName) throws Exception,
|
||||
InterruptedException {
|
||||
|
||||
gitOperations.update(ReleaseTrains.getProjectByName(trainName));
|
||||
git.update(ReleaseTrains.getTrainByName(trainName));
|
||||
}
|
||||
|
||||
@CliCommand("git tags")
|
||||
public String tags(@CliOption(key = { "project" }, mandatory = true) String projectName) throws IOException {
|
||||
public String tags(@CliOption(key = { "project" }, mandatory = true) String projectName) throws Exception {
|
||||
|
||||
Project project = ReleaseTrains.getProjectByName(projectName);
|
||||
|
||||
return StringUtils.collectionToDelimitedString(gitOperations.getTags(project), "\n");
|
||||
return StringUtils.collectionToDelimitedString(git.getTags(project).asList(), "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,21 +19,28 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.io.CommandExecution;
|
||||
import org.springframework.data.release.io.CommandResult;
|
||||
import org.springframework.data.release.io.OsCommandOperations;
|
||||
import org.springframework.data.release.io.Workspace;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Component to execut Git related operations.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@@ -50,20 +57,66 @@ public class GitOperations {
|
||||
return new GitProject(project, server);
|
||||
}
|
||||
|
||||
public void update(Train train) throws IOException, InterruptedException {
|
||||
/**
|
||||
* Checks out all projects of the given {@link Train} at the tags for the given {@link Iteration}.
|
||||
*
|
||||
* @param train
|
||||
* @param iteration
|
||||
* @throws Exception
|
||||
*/
|
||||
public void checkout(Train train, Iteration iteration) throws Exception {
|
||||
|
||||
List<CommandExecution> executions = new ArrayList<>();
|
||||
update(train);
|
||||
|
||||
for (ModuleIteration module : train.getModuleIterations(iteration)) {
|
||||
|
||||
Project project = module.getProject();
|
||||
ArtifactVersion artifactVersion = ArtifactVersion.from(module);
|
||||
|
||||
Tag tag = findTagFor(project, artifactVersion);
|
||||
|
||||
if (tag == null) {
|
||||
throw new IllegalStateException(String.format("No tag found for version %s of project %s, aborting.",
|
||||
artifactVersion, project));
|
||||
}
|
||||
|
||||
osCommandOperations.executeCommand(String.format("git checkout %s", tag), project).get();
|
||||
}
|
||||
|
||||
LOGGER.info(String.format("Successfully checked out iteration %s for release train %s.", iteration.getName(),
|
||||
train.getName()));
|
||||
}
|
||||
|
||||
public void prepare(Train train, Iteration iteration) throws Exception {
|
||||
|
||||
for (ModuleIteration module : train.getModuleIterations(iteration)) {
|
||||
|
||||
Branch branch = Branch.from(module);
|
||||
|
||||
update(module.getProject());
|
||||
|
||||
String checkoutCommand = String.format("git checkout %s", branch);
|
||||
osCommandOperations.executeCommand(checkoutCommand, module.getProject()).get();
|
||||
|
||||
String updateCommand = String.format("git pull origin %s", branch);
|
||||
osCommandOperations.executeCommand(updateCommand, module.getProject()).get();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Train train) throws Exception {
|
||||
|
||||
List<Future<CommandResult>> executions = new ArrayList<>();
|
||||
|
||||
for (Module module : train) {
|
||||
executions.add(update(module.getProject()));
|
||||
}
|
||||
|
||||
for (CommandExecution execution : executions) {
|
||||
execution.waitForResult();
|
||||
for (Future<CommandResult> execution : executions) {
|
||||
execution.get();
|
||||
}
|
||||
}
|
||||
|
||||
public CommandExecution update(Project project) throws IOException {
|
||||
public Future<CommandResult> update(Project project) throws Exception {
|
||||
|
||||
GitProject gitProject = new GitProject(project, server);
|
||||
String repositoryName = gitProject.getRepositoryName();
|
||||
@@ -71,28 +124,54 @@ public class GitOperations {
|
||||
if (workspace.hasProjectDirectory(project)) {
|
||||
|
||||
LOGGER.info(String.format("Found existing repository %s. Obtaining latest changes…", repositoryName));
|
||||
return osCommandOperations.executeCommand("git pull origin master", project);
|
||||
|
||||
return osCommandOperations.executeCommand("git checkout master && git fetch --tags && git pull origin master",
|
||||
project);
|
||||
|
||||
} else {
|
||||
|
||||
File projectDirectory = workspace.getProjectDirectory(project);
|
||||
|
||||
LOGGER.info(String.format("No repository found for project %s. Cloning repository from %s…", repositoryName,
|
||||
gitProject.getProjectUri()));
|
||||
return osCommandOperations.executeCommand(String.format("git clone %s %s", gitProject.getProjectUri(),
|
||||
projectDirectory.getName()));
|
||||
|
||||
File projectDirectory = workspace.getProjectDirectory(project);
|
||||
String command = String.format("git clone %s %s", gitProject.getProjectUri(), projectDirectory.getName());
|
||||
|
||||
return osCommandOperations.executeCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Tag> getTags(Project project) throws IOException {
|
||||
public Tags getTags(Project project) throws Exception {
|
||||
|
||||
CommandExecution command = osCommandOperations.executeCommand("git tag -l", project);
|
||||
String result = osCommandOperations.executeForResult("git tag -l", project);
|
||||
List<Tag> tags = new ArrayList<>();
|
||||
|
||||
for (String line : command.waitAndGetOutput().split("\n")) {
|
||||
tags.add(new Tag(line));
|
||||
for (String line : result.split("\n")) {
|
||||
|
||||
if (!StringUtils.isEmpty(line)) {
|
||||
tags.add(new Tag(line));
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
return new Tags(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Tag} that represents the {@link ArtifactVersion} of the given {@link Project}.
|
||||
*
|
||||
* @param project
|
||||
* @param version
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private Tag findTagFor(Project project, ArtifactVersion version) throws Exception {
|
||||
|
||||
for (Tag tag : getTags(project)) {
|
||||
|
||||
if (tag.toArtifactVersion().equals(version)) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,20 @@ public class GitProject {
|
||||
private final Project project;
|
||||
private final GitServer server;
|
||||
|
||||
/**
|
||||
* Returns the name of the repository the project is using.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getRepositoryName() {
|
||||
return String.format("%s-%s", PROJECT_PREFIX, project.getName().toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URI of the {@link Project}'s repository.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getProjectUri() {
|
||||
return server.getUri() + getRepositoryName();
|
||||
}
|
||||
|
||||
@@ -15,13 +15,51 @@
|
||||
*/
|
||||
package org.springframework.data.release.git;
|
||||
|
||||
import lombok.Value;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
|
||||
/**
|
||||
* Value object to represent an SCM tag.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
public class Tag {
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class Tag implements Comparable<Tag> {
|
||||
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Returns the part of the name of the tag that is suitable to derive a version from the tag. Will transparently strip
|
||||
* a {@code v} prefix from the name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getVersionSource() {
|
||||
return name.startsWith("v") ? name.substring(1) : name;
|
||||
}
|
||||
|
||||
public ArtifactVersion toArtifactVersion() {
|
||||
return ArtifactVersion.parse(getVersionSource());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Tag that) {
|
||||
return that.name.compareTo(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
78
src/main/java/org/springframework/data/release/git/Tags.java
Normal file
78
src/main/java/org/springframework/data/release/git/Tags.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2014 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.git;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to represent a collection of {@link Tag}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public class Tags implements Iterable<Tag> {
|
||||
|
||||
private final List<Tag> tags;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Tags} instance for the given {@link List} of {@link Tag}s.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
*/
|
||||
Tags(List<Tag> source) {
|
||||
|
||||
Assert.notNull(source, "Tags must not be null!");
|
||||
|
||||
List<Tag> tags = new ArrayList<>(source);
|
||||
Collections.sort(tags);
|
||||
|
||||
this.tags = Collections.unmodifiableList(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest {@link Tag}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Tag getLatest() {
|
||||
return tags.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link Tag}s as {@link List}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Tag> asList() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Tag> iterator() {
|
||||
return tags.iterator();
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 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.io;
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.apache.commons.exec.DefaultExecuteResultHandler;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class CommandExecution {
|
||||
|
||||
private final DefaultExecuteResultHandler resultHandler;
|
||||
private final StringWriter writer;
|
||||
|
||||
private String output;
|
||||
|
||||
public Exception getException() {
|
||||
return resultHandler.getException();
|
||||
}
|
||||
|
||||
public int getExitValue() {
|
||||
return resultHandler.getExitValue();
|
||||
}
|
||||
|
||||
public String waitAndGetOutput() {
|
||||
|
||||
if (output != null) {
|
||||
return output;
|
||||
}
|
||||
|
||||
try {
|
||||
waitForResult();
|
||||
} catch (InterruptedException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
this.output = writer.toString();
|
||||
IOUtils.closeQuietly(writer);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public void waitForResult() throws InterruptedException {
|
||||
resultHandler.waitFor();
|
||||
}
|
||||
}
|
||||
@@ -15,22 +15,19 @@
|
||||
*/
|
||||
package org.springframework.data.release.io;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import lombok.Value;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class OsConfigurationIntegrationTests {
|
||||
@Value
|
||||
public class CommandResult {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testname() {
|
||||
private final int status;
|
||||
private final String output;
|
||||
private final Exception exception;
|
||||
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(OsConfiguration.class);
|
||||
File file = new File(context.getEnvironment().getProperty("io.workDir"));
|
||||
public boolean hasError() {
|
||||
return status != 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2011-2012 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.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.apache.commons.exec.CommandLine;
|
||||
import org.apache.commons.exec.DefaultExecuteResultHandler;
|
||||
import org.apache.commons.exec.DefaultExecutor;
|
||||
import org.apache.commons.exec.PumpStreamHandler;
|
||||
import org.apache.commons.io.output.WriterOutputStream;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.git.GitOperations;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncResult;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Implementation of {@link OsCommandOperations} interface.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @author Oliver Gierke
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
class CommonsExecOsCommandOperations implements OsCommandOperations {
|
||||
|
||||
private static final Logger LOGGER = HandlerUtils.getLogger(GitOperations.class);
|
||||
private static final String PREFIX_TEMPLATE = "%s > %s";
|
||||
|
||||
private static final Map<String, String> ENVIRONMENT = new HashMap<>();
|
||||
|
||||
private final Workspace workspace;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.shell.commands.OsOperations#executeCommand(java.lang.String)
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
public Future<CommandResult> executeCommand(String command) throws IOException {
|
||||
return executeCommand((String) null, command);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.io.OsCommandOperations#executeCommand(java.lang.String, org.springframework.data.release.model.Project)
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
public Future<CommandResult> executeCommand(String command, Project project) throws IOException {
|
||||
|
||||
LOGGER.info(String.format(PREFIX_TEMPLATE, project.getName(), command));
|
||||
|
||||
return executeCommand(command, workspace.getProjectDirectory(project), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.io.OsCommandOperations#executeAndListen(org.springframework.data.release.model.Project, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Future<CommandResult> executeWithOutput(String command, Project project) throws IOException {
|
||||
|
||||
LOGGER.info(String.format(PREFIX_TEMPLATE, project.getName(), command));
|
||||
|
||||
return executeCommand(command, workspace.getProjectDirectory(project), false);
|
||||
}
|
||||
|
||||
private Future<CommandResult> executeCommand(String subfolder, String command) throws IOException {
|
||||
|
||||
File workingDirectory = workspace.getWorkingDirectory();
|
||||
File executionDirectory = subfolder == null ? workingDirectory : new File(workingDirectory, subfolder);
|
||||
|
||||
return executeCommand(command, executionDirectory, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.io.OsCommandOperations#executeForResult(java.lang.String, org.springframework.data.release.model.Project)
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
public String executeForResult(String command, Project project) throws Exception {
|
||||
return executeCommand(command, workspace.getProjectDirectory(project), true).get().getOutput();
|
||||
}
|
||||
|
||||
private Future<CommandResult> executeCommand(String command, File executionDirectory, boolean silent)
|
||||
throws IOException {
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
|
||||
|
||||
try (WriterOutputStream outputStream = new WriterOutputStream(writer)) {
|
||||
|
||||
String outerCommand = "/bin/bash -lc";
|
||||
|
||||
CommandLine outer = CommandLine.parse(outerCommand);
|
||||
outer.addArgument(command, false);
|
||||
|
||||
DefaultExecutor executor = new DefaultExecutor();
|
||||
executor.setWorkingDirectory(executionDirectory);
|
||||
executor.setStreamHandler(new PumpStreamHandler(silent ? outputStream : System.out, null));
|
||||
executor.execute(outer, ENVIRONMENT, resultHandler);
|
||||
|
||||
resultHandler.waitFor();
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
return new AsyncResult<CommandResult>(new CommandResult(resultHandler.getExitValue(), writer.toString(),
|
||||
resultHandler.getException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@code JAVA_HOME} to the ENVIRONMENT variables lookuing up the path to a Java 7.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initialize() throws Exception {
|
||||
|
||||
String javaHome = executeCommand("/usr/libexec/java_home -F -v 1.7 -a x86_64 -d64").get().getOutput();
|
||||
|
||||
if (javaHome.endsWith("\n")) {
|
||||
javaHome = javaHome.substring(0, javaHome.length() - 1);
|
||||
}
|
||||
|
||||
ENVIRONMENT.put("JAVA_HOME", javaHome);
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 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.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.apache.commons.exec.CommandLine;
|
||||
import org.apache.commons.exec.DefaultExecuteResultHandler;
|
||||
import org.apache.commons.exec.DefaultExecutor;
|
||||
import org.apache.commons.exec.PumpStreamHandler;
|
||||
import org.apache.commons.io.output.WriterOutputStream;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Implementation of {@link OsCommandOperations} interface.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @author Oliver Gierke
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
class IoConfigAwareOsCommandOperations implements OsCommandOperations {
|
||||
|
||||
private final Workspace workspace;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.shell.commands.OsOperations#executeCommand(java.lang.String)
|
||||
*/
|
||||
public CommandExecution executeCommand(String command) throws IOException {
|
||||
return executeCommand(command, (String) null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.io.OsCommandOperations#executeCommand(java.lang.String, org.springframework.data.release.model.Project)
|
||||
*/
|
||||
@Override
|
||||
public CommandExecution executeCommand(String command, Project project) throws IOException {
|
||||
return executeCommand(command, workspace.getProjectDirectory(project));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.io.OsCommandOperations#executeCommand(java.lang.String, java.io.File)
|
||||
*/
|
||||
@Override
|
||||
public CommandExecution executeCommand(String command, String subfolder) throws IOException {
|
||||
|
||||
File workingDirectory = workspace.getWorkingDirectory();
|
||||
File executionDirectory = subfolder == null ? workingDirectory : new File(workingDirectory, subfolder);
|
||||
|
||||
return executeCommand(command, executionDirectory);
|
||||
}
|
||||
|
||||
private CommandExecution executeCommand(String command, File executionDirectory) throws IOException {
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
WriterOutputStream outputStream = new WriterOutputStream(writer);
|
||||
|
||||
CommandLine commandLine = CommandLine.parse(command);
|
||||
DefaultExecuteResultHandler executeResultHandler = new DefaultExecuteResultHandler();
|
||||
|
||||
DefaultExecutor executor = new DefaultExecutor();
|
||||
executor.setWorkingDirectory(executionDirectory);
|
||||
executor.setStreamHandler(new PumpStreamHandler(outputStream, null));
|
||||
executor.execute(commandLine, executeResultHandler);
|
||||
|
||||
return new CommandExecution(executeResultHandler, writer);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.release.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.springframework.data.release.model.Project;
|
||||
|
||||
@@ -33,9 +34,11 @@ public interface OsCommandOperations {
|
||||
* @param command the command to execute
|
||||
* @throws IOException if an error occurs
|
||||
*/
|
||||
CommandExecution executeCommand(String command) throws IOException;
|
||||
Future<CommandResult> executeCommand(String command) throws IOException;
|
||||
|
||||
CommandExecution executeCommand(String command, Project project) throws IOException;
|
||||
Future<CommandResult> executeCommand(String command, Project project) throws IOException;
|
||||
|
||||
CommandExecution executeCommand(String command, String subfolder) throws IOException;
|
||||
Future<CommandResult> executeWithOutput(String command, Project project) throws IOException;
|
||||
|
||||
String executeForResult(String command, Project project) throws Exception;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstraction of the workspace that is used to work with the {@link Project}'s repositories, execute builds, etc.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@@ -40,28 +43,61 @@ public class Workspace {
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
/**
|
||||
* Returns the current working directory.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public File getWorkingDirectory() {
|
||||
|
||||
String workDir = environment.getProperty("io.workDir");
|
||||
return new File(workDir.replace("~", System.getProperty("user.home")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory for the given {@link Project}.
|
||||
*
|
||||
* @param project must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public File getProjectDirectory(Project project) {
|
||||
|
||||
Assert.notNull(project, "Project must not be null!");
|
||||
return new File(getWorkingDirectory(), project.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the project directory for the given project already exists.
|
||||
*
|
||||
* @param project must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public boolean hasProjectDirectory(Project project) {
|
||||
|
||||
Assert.notNull(project, "Project must not be null!");
|
||||
return getProjectDirectory(project).exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a file with the given name relative to the working directory for the given {@link Project}.
|
||||
*
|
||||
* @param name must not be {@literal null} or empty.
|
||||
* @param project must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public File getFile(String name, Project project) {
|
||||
return new File(new File(getWorkingDirectory(), project.getName()), name);
|
||||
}
|
||||
|
||||
public boolean exists(String subfolder) {
|
||||
return new File(getWorkingDirectory(), subfolder).exists();
|
||||
|
||||
Assert.hasText(name, "Filename must not be null or empty!");
|
||||
Assert.notNull(project, "Project must not be null!");
|
||||
|
||||
return new File(getProjectDirectory(project), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the working directory and creates the folders if necessary.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@PostConstruct
|
||||
public void setUp() throws IOException {
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2014 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.jira;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.format.datetime.DateFormatter;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@EqualsAndHashCode
|
||||
public class Changelog {
|
||||
|
||||
private final Module module;
|
||||
private final Iteration iteration;
|
||||
private final Tickets tickets;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
String headline = String.format("Changes in version %s (%s)", module.getVersion(),
|
||||
new DateFormatter("YYYY-MM-dd").print(new Date(), Locale.US));
|
||||
|
||||
StringBuilder builder = new StringBuilder(headline).append(OsUtils.LINE_SEPARATOR);
|
||||
|
||||
for (int i = 0; i < headline.length(); i++) {
|
||||
builder.append("-");
|
||||
}
|
||||
|
||||
builder.append(OsUtils.LINE_SEPARATOR);
|
||||
|
||||
for (Ticket ticket : tickets) {
|
||||
|
||||
String summary = ticket.getSummary();
|
||||
|
||||
builder.append("* ").append(ticket.getId()).append(" - ").append(summary);
|
||||
|
||||
if (!summary.endsWith(".")) {
|
||||
builder.append(".");
|
||||
}
|
||||
|
||||
builder.append(OsUtils.LINE_SEPARATOR);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.release.jira;
|
||||
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.data.release.model.Train;
|
||||
|
||||
/**
|
||||
@@ -37,4 +38,6 @@ public interface JiraConnector {
|
||||
void verifyBeforeRelease(Train train, Iteration iteration);
|
||||
|
||||
void closeIteration(Train train, Iteration iteration, Credentials credentials);
|
||||
|
||||
Changelog getChangelogFor(Train train, Module module, Iteration iteration);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import lombok.Value;
|
||||
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -49,6 +50,10 @@ class JqlQuery {
|
||||
|
||||
for (Module module : train) {
|
||||
|
||||
if (ReleaseTrains.BUILD.equals(module.getProject())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JiraVersion version = new JiraVersion(module, train, iteration);
|
||||
parts.add(String.format(PROJECT_VERSION_TEMPLATE, module.getProject().getKey(), version));
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -145,4 +147,16 @@ class RestJiraConnector implements JiraConnector {
|
||||
// - mark version as releases
|
||||
// - if no next version exists, create
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.jira.JiraConnector#getChangelogFor(org.springframework.data.release.model.Module, org.springframework.data.release.model.Iteration)
|
||||
*/
|
||||
@Override
|
||||
public Changelog getChangelogFor(Train train, Module module, Iteration iteration) {
|
||||
|
||||
Tickets tickets = getTicketsFor(ReleaseTrains.DIJKSTRA, iteration, null);
|
||||
|
||||
return new Changelog(module, iteration, tickets);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2014 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.maven;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to represent a Maven {@link Artifact}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Artifact {
|
||||
|
||||
private static final GroupId GROUP_ID = new GroupId("org.springframework.data");
|
||||
|
||||
private final ModuleIteration module;
|
||||
private final Repository repository;
|
||||
private final ArtifactVersion version;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Artifact} for the given {@link ModuleIteration}.
|
||||
*
|
||||
* @param module must not be {@literal null}.
|
||||
*/
|
||||
public Artifact(ModuleIteration module) {
|
||||
|
||||
Assert.notNull(module, "Module iteration must not be null!");
|
||||
|
||||
this.module = module;
|
||||
this.repository = new Repository(module.getIteration());
|
||||
this.version = ArtifactVersion.from(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Maven artifact identifier.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getArtifactId() {
|
||||
|
||||
String artifactId = String.format("spring-data-%s", module.getProject().getName().toLowerCase());
|
||||
return ReleaseTrains.REST.equals(module.getProject()) ? artifactId.concat("-webmvc") : artifactId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL pointing to the artifacts.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getRootUrl() {
|
||||
return String.format("%s/%s/%s/%s", repository.getUrl(), GROUP_ID.asPath(), getArtifactId(), version);
|
||||
}
|
||||
}
|
||||
@@ -17,21 +17,17 @@ package org.springframework.data.release.maven;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.data.release.model.Version;
|
||||
|
||||
/**
|
||||
* Value object to represent an artifacts group identifier.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
public class MavenVersion {
|
||||
class GroupId {
|
||||
|
||||
private final Version version;
|
||||
private final String value;
|
||||
|
||||
public String getReleaseVersion() {
|
||||
return String.format("%s.RELEASE", version.toMajorMinorBugfix());
|
||||
}
|
||||
|
||||
public String getSnapshotVersion() {
|
||||
return String.format("%s.BUILD-SNAPSHOT", version.toMajorMinorBugfix());
|
||||
public String asPath() {
|
||||
return value.replace('.', '/');
|
||||
}
|
||||
}
|
||||
@@ -17,23 +17,56 @@ package org.springframework.data.release.maven;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.xmlbeam.ProjectionFactory;
|
||||
import org.xmlbeam.XBProjector;
|
||||
import org.xmlbeam.XBProjector.Flags;
|
||||
import org.xmlbeam.config.DefaultXMLFactoriesConfig;
|
||||
import org.xmlbeam.config.DefaultXMLFactoriesConfig.NamespacePhilosophy;
|
||||
import org.xmlbeam.types.DefaultTypeConverter;
|
||||
import org.xmlbeam.types.TypeConverter;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
public class MavenConfig {
|
||||
class MavenConfig {
|
||||
|
||||
@Bean
|
||||
public ProjectionFactory projectionFactory() {
|
||||
|
||||
TypeConverter converter = new DefaultTypeConverter().setConversionForType(ArtifactVersion.class,
|
||||
new ArtifactVersionConverter());
|
||||
|
||||
DefaultXMLFactoriesConfig config = new DefaultXMLFactoriesConfig();
|
||||
config.setNamespacePhilosophy(NamespacePhilosophy.AGNOSTIC);
|
||||
return new XBProjector(config, Flags.TO_STRING_RENDERS_XML);
|
||||
|
||||
XBProjector projector = new XBProjector(config, Flags.TO_STRING_RENDERS_XML);
|
||||
projector.config().setTypeConverter(converter);
|
||||
|
||||
return projector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom converter to be able to use {@link ArtifactVersion} directly from within an XmlBeam projection.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ArtifactVersionConverter extends DefaultTypeConverter.Conversion<ArtifactVersion> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ArtifactVersionConverter() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xmlbeam.types.DefaultTypeConverter.Conversion#convert(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public ArtifactVersion convert(String data) {
|
||||
return ArtifactVersion.parse(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,24 @@ package org.springframework.data.release.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.io.CommandResult;
|
||||
import org.springframework.data.release.io.OsCommandOperations;
|
||||
import org.springframework.data.release.io.Workspace;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.xmlbeam.ProjectionFactory;
|
||||
import org.xmlbeam.io.XBFileIO;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
@@ -33,14 +43,91 @@ import org.xmlbeam.ProjectionFactory;
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class MavenOperations {
|
||||
|
||||
private static final Logger LOGGER = HandlerUtils.getLogger(MavenOperations.class);
|
||||
private static final String POM_XML = "pom.xml";
|
||||
|
||||
private final Workspace workspace;
|
||||
private final ProjectionFactory projectionFactory;
|
||||
private final OsCommandOperations os;
|
||||
|
||||
public Pom getMavenProject(Project project) throws IOException {
|
||||
|
||||
File file = workspace.getFile(POM_XML, project);
|
||||
return projectionFactory.io().file(file).read(Pom.class);
|
||||
}
|
||||
|
||||
public void prepareProject(Train train, Iteration iteration, Project project) throws IOException {
|
||||
|
||||
if (ReleaseTrains.BUILD.equals(project)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArtifactVersion commonsVersion = train.getModuleVersion(ReleaseTrains.COMMONS, iteration);
|
||||
ArtifactVersion buildVersion = train.getModuleVersion(ReleaseTrains.BUILD, iteration);
|
||||
Repository repository = new Repository(iteration);
|
||||
|
||||
File file = workspace.getFile(POM_XML, project);
|
||||
XBFileIO io = projectionFactory.io().file(file);
|
||||
Pom pom = io.read(Pom.class);
|
||||
|
||||
if (!project.equals(ReleaseTrains.COMMONS)) {
|
||||
pom.setProperty("spring.data.commons", commonsVersion);
|
||||
}
|
||||
|
||||
pom.setParentVersion(buildVersion);
|
||||
pom.setRepositoryId(repository.getSnapshotId(), repository.getId());
|
||||
pom.setRepositoryUrl(repository.getId(), repository.getUrl());
|
||||
|
||||
io.write(pom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers building the distribution artifacts for all Maven projects of the given {@link Train}.
|
||||
*
|
||||
* @param train
|
||||
* @param iteration
|
||||
* @throws IOException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void triggerDistributionBuild(Train train, Iteration iteration) throws Exception {
|
||||
|
||||
for (ModuleIteration moduleIteration : train.getModuleIterations(iteration)) {
|
||||
|
||||
Project project = moduleIteration.getProject();
|
||||
|
||||
if (ReleaseTrains.BUILD.equals(project)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isMavenProject(project)) {
|
||||
LOGGER.info(String.format("Skipping project %s as no pom.xml could be found in the working directory!",
|
||||
project.getFullName()));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGGER.info(String.format("Triggering distribution build for %s…", project.getFullName()));
|
||||
|
||||
ArtifactVersion version = ArtifactVersion.from(moduleIteration);
|
||||
|
||||
String command = "mvn clean deploy -DskipTests -Pdistribute";
|
||||
|
||||
if (version.isMilestoneVersion()) {
|
||||
command = command.concat(",milestone");
|
||||
} else if (version.isReleaseVersion()) {
|
||||
command = command.concat(",release");
|
||||
}
|
||||
|
||||
CommandResult result = os.executeWithOutput(command, moduleIteration.getProject()).get();
|
||||
|
||||
if (result.hasError()) {
|
||||
throw result.getException();
|
||||
}
|
||||
|
||||
LOGGER.info(String.format("Successfully finished distribution build for %s!", project));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMavenProject(Project project) {
|
||||
return workspace.getFile(POM_XML, project).exists();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.release.maven;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Module;
|
||||
|
||||
/**
|
||||
@@ -35,7 +36,7 @@ public class MavenProject {
|
||||
return String.format("spring-data-%s", module.getProject().getName().toLowerCase());
|
||||
}
|
||||
|
||||
public MavenVersion getVersion() {
|
||||
return new MavenVersion(module.getVersion());
|
||||
public ArtifactVersion getReleaseVersion() {
|
||||
return new ArtifactVersion(module.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.xmlbeam.annotation.XBRead;
|
||||
import org.xmlbeam.annotation.XBValue;
|
||||
import org.xmlbeam.annotation.XBWrite;
|
||||
|
||||
/**
|
||||
@@ -27,7 +29,7 @@ public interface Pom {
|
||||
Artifact getArtifactId();
|
||||
|
||||
@XBRead("/project/version")
|
||||
String getVersion();
|
||||
ArtifactVersion getVersion();
|
||||
|
||||
@XBWrite("/project/version")
|
||||
void setVersion(String version);
|
||||
@@ -35,6 +37,18 @@ public interface Pom {
|
||||
@XBRead("/project/repositories/repository[id=\"spring-libs-snapshot\"]")
|
||||
Repository getSpringRepository();
|
||||
|
||||
@XBWrite("/project/parent/version")
|
||||
void setParentVersion(ArtifactVersion version);
|
||||
|
||||
@XBWrite("/project/properties/{0}")
|
||||
void setProperty(String property, @XBValue ArtifactVersion value);
|
||||
|
||||
@XBWrite("/project/repositories/repository[id={0}]/id")
|
||||
void setRepositoryId(String oldId, @XBValue String newId);
|
||||
|
||||
@XBWrite("/project/repositories/repository[id={0}]/url")
|
||||
void setRepositoryUrl(String id, @XBValue String url);
|
||||
|
||||
public interface Repository {
|
||||
|
||||
@XBRead("child::id")
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2014 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.maven;
|
||||
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Repository {
|
||||
|
||||
private static final String BASE = "http://repo.spring.io/libs-";
|
||||
|
||||
private final String id;
|
||||
private final String url;
|
||||
|
||||
public Repository(Iteration iteration) {
|
||||
this.id = iteration.isPublicVersion() ? "spring-libs-release" : "spring-libs-milestone";
|
||||
this.url = iteration.isPublicVersion() ? BASE.concat("release") : BASE.concat("milestone");
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getSnapshotId() {
|
||||
return "spring-libs-snapshot";
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getSnapshotUrl() {
|
||||
return BASE.concat("snapshot");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2014 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.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to represent version of a particular artifact.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class ArtifactVersion implements Comparable<ArtifactVersion> {
|
||||
|
||||
private static final String RELEASE_SUFFIX = "RELEASE";
|
||||
private static final String MILESTONE_SUFFIX = "M\\d|RC\\d";
|
||||
private static final String SNAPSHOT_SUFFIX = "BUILD-SNAPSHOT";
|
||||
|
||||
private static final String VALID_SUFFIX = String.format("%s|%s|%s", RELEASE_SUFFIX, MILESTONE_SUFFIX,
|
||||
SNAPSHOT_SUFFIX);
|
||||
|
||||
private final Version version;
|
||||
private final String suffix;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ArtifactVersion} from the given logical {@link Version}.
|
||||
*
|
||||
* @param version must not be {@literal null}.
|
||||
*/
|
||||
public ArtifactVersion(Version version) {
|
||||
|
||||
Assert.notNull(version, "Version must not be null!");
|
||||
|
||||
this.version = version;
|
||||
this.suffix = RELEASE_SUFFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given {@link String} into an {@link ArtifactVersion}.
|
||||
*
|
||||
* @param source must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
public static ArtifactVersion parse(String source) {
|
||||
|
||||
Assert.hasText(source, "Version source must not be null or empty!");
|
||||
|
||||
int suffixStart = source.lastIndexOf('.');
|
||||
|
||||
Version version = Version.parse(source.substring(0, suffixStart));
|
||||
String suffix = source.substring(suffixStart + 1);
|
||||
|
||||
Assert.isTrue(suffix.matches(VALID_SUFFIX), "Invalid version suffix!");
|
||||
|
||||
return new ArtifactVersion(version, suffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ArtifactVersion} from the given {@link IterationVersion}.
|
||||
*
|
||||
* @param iterationVersion must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static ArtifactVersion from(IterationVersion iterationVersion) {
|
||||
|
||||
Assert.notNull(iterationVersion, "IterationVersion must not be null!");
|
||||
|
||||
Version version = iterationVersion.getVersion();
|
||||
String iterationName = iterationVersion.getIteration().getName();
|
||||
|
||||
if (iterationName.equals("GA")) {
|
||||
return new ArtifactVersion(version, RELEASE_SUFFIX);
|
||||
}
|
||||
|
||||
if (iterationName.startsWith("SR")) {
|
||||
int bugfixDigits = Integer.parseInt(iterationName.substring(2, iterationName.length()));
|
||||
return new ArtifactVersion(version.withBugfix(bugfixDigits), RELEASE_SUFFIX);
|
||||
}
|
||||
|
||||
return new ArtifactVersion(version, iterationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the release version for the current a
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ArtifactVersion getReleaseVersion() {
|
||||
return new ArtifactVersion(version, RELEASE_SUFFIX);
|
||||
}
|
||||
|
||||
public ArtifactVersion getSnapshotVersion() {
|
||||
return new ArtifactVersion(version, SNAPSHOT_SUFFIX);
|
||||
}
|
||||
|
||||
public boolean isReleaseVersion() {
|
||||
return suffix.equals(RELEASE_SUFFIX);
|
||||
}
|
||||
|
||||
public boolean isMilestoneVersion() {
|
||||
return suffix.matches(MILESTONE_SUFFIX);
|
||||
}
|
||||
|
||||
public ArtifactVersion getNextDevelopmentVersion() {
|
||||
|
||||
if (suffix.equals(SNAPSHOT_SUFFIX)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (suffix.equals(RELEASE_SUFFIX)) {
|
||||
return new ArtifactVersion(version.nextBugfix(), SNAPSHOT_SUFFIX);
|
||||
}
|
||||
|
||||
return new ArtifactVersion(version, SNAPSHOT_SUFFIX);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(ArtifactVersion that) {
|
||||
return this.toString().compareTo(that.toString());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s.%s", version.toMajorMinorBugfix(), suffix);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2014 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;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface IterationVersion {
|
||||
|
||||
Version getVersion();
|
||||
|
||||
Iteration getIteration();
|
||||
}
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.release.model;
|
||||
|
||||
import lombok.Value;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
public class ModuleIteration {
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class ModuleIteration implements IterationVersion {
|
||||
|
||||
private final Module module;
|
||||
private final Iteration iteration;
|
||||
@@ -31,6 +33,23 @@ public class ModuleIteration {
|
||||
return module.getProject().getKey();
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
return module.getProject();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.model.IterationVersion#getVersion()
|
||||
*/
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
return module.getVersion();
|
||||
}
|
||||
|
||||
public Iteration getIteration() {
|
||||
return module.hasCustomFirstIteration() ? module.getCustomFirstIteration() : this.iteration;
|
||||
}
|
||||
|
||||
public String getJiraVersionName() {
|
||||
|
||||
Iteration iteration = module.hasCustomFirstIteration() ? module.getCustomFirstIteration() : this.iteration;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.release.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
/**
|
||||
@@ -25,10 +28,16 @@ public class Project {
|
||||
|
||||
private final ProjectKey key;
|
||||
private final String name;
|
||||
private final List<Project> dependencies;
|
||||
|
||||
public Project(String key, String name) {
|
||||
public Project(String key, String name, Project... dependencies) {
|
||||
|
||||
this.key = new ProjectKey(key);
|
||||
this.name = name;
|
||||
this.dependencies = Arrays.asList(dependencies);
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return "Spring Data ".concat(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,28 +26,29 @@ public class ReleaseTrains {
|
||||
|
||||
public static final List<Train> TRAINS;
|
||||
public static final Train CODD, DIJKSTRA, EVANS, FOWLER;
|
||||
public static final Project COMMONS;
|
||||
public static final Project COMMONS, BUILD, REST;
|
||||
|
||||
private static final Project JPA, MONGO_DB, NEO4J, SOLR, COUCHBASE, CASSANDRA, ELASTICSEARCH, REDIS, GEMFIRE, REST;
|
||||
private static final Project JPA, MONGO_DB, NEO4J, SOLR, COUCHBASE, CASSANDRA, ELASTICSEARCH, REDIS, GEMFIRE;
|
||||
private static final List<Project> PROJECTS;
|
||||
|
||||
static {
|
||||
|
||||
COMMONS = new Project("DATACMNS", "Commons");
|
||||
JPA = new Project("DATAJPA", "JPA");
|
||||
MONGO_DB = new Project("DATAMONGO", "MongoDB");
|
||||
NEO4J = new Project("DATAGRAPH", "Neo4j");
|
||||
SOLR = new Project("DATASOLR", "Solr");
|
||||
COUCHBASE = new Project("DATACOUCH", "Couchbase");
|
||||
CASSANDRA = new Project("DATACASS", "Cassandra");
|
||||
ELASTICSEARCH = new Project("DATAES", "Elasticsearch");
|
||||
BUILD = new Project("DATABUILD", "Build");
|
||||
COMMONS = new Project("DATACMNS", "Commons", BUILD);
|
||||
JPA = new Project("DATAJPA", "JPA", COMMONS);
|
||||
MONGO_DB = new Project("DATAMONGO", "MongoDB", COMMONS);
|
||||
NEO4J = new Project("DATAGRAPH", "Neo4j", COMMONS);
|
||||
SOLR = new Project("DATASOLR", "Solr", COMMONS);
|
||||
COUCHBASE = new Project("DATACOUCH", "Couchbase", COMMONS);
|
||||
CASSANDRA = new Project("DATACASS", "Cassandra", COMMONS);
|
||||
ELASTICSEARCH = new Project("DATAES", "Elasticsearch", COMMONS);
|
||||
REDIS = new Project("DATAREDIS", "Redis");
|
||||
GEMFIRE = new Project("SGF", "Gemfire");
|
||||
GEMFIRE = new Project("SGF", "Gemfire", COMMONS);
|
||||
|
||||
REST = new Project("DATAREST", "REST");
|
||||
REST = new Project("DATAREST", "REST", COMMONS, JPA, MONGO_DB, NEO4J, GEMFIRE);
|
||||
|
||||
PROJECTS = Arrays.asList(COMMONS, JPA, MONGO_DB, NEO4J, SOLR, COUCHBASE, CASSANDRA, ELASTICSEARCH, REDIS, GEMFIRE,
|
||||
REST);
|
||||
PROJECTS = Arrays.asList(BUILD, COMMONS, JPA, MONGO_DB, NEO4J, SOLR, COUCHBASE, CASSANDRA, ELASTICSEARCH, REDIS,
|
||||
GEMFIRE, REST);
|
||||
|
||||
CODD = codd();
|
||||
DIJKSTRA = dijkstra();
|
||||
@@ -69,19 +70,21 @@ public class ReleaseTrains {
|
||||
|
||||
private static Train codd() {
|
||||
|
||||
Module build = new Module(BUILD, "1.3");
|
||||
Module commons = new Module(COMMONS, "1.7");
|
||||
Module jpa = new Module(JPA, "1.5");
|
||||
Module mongoDb = new Module(MONGO_DB, "1.4");
|
||||
Module neo4j = new Module(NEO4J, "3.0");
|
||||
Module solr = new Module(SOLR, "1.1");
|
||||
|
||||
Module rest = new Module(REST, "2.1");
|
||||
Module rest = new Module(REST, "2.0");
|
||||
|
||||
return new Train("Codd", commons, jpa, mongoDb, neo4j, solr, rest);
|
||||
return new Train("Codd", build, commons, jpa, mongoDb, neo4j, solr, rest);
|
||||
}
|
||||
|
||||
private static Train dijkstra() {
|
||||
|
||||
Module build = new Module(BUILD, "1.4");
|
||||
Module commons = new Module(COMMONS, "1.8");
|
||||
Module jpa = new Module(JPA, "1.6");
|
||||
Module mongoDb = new Module(MONGO_DB, "1.5");
|
||||
@@ -95,8 +98,8 @@ public class ReleaseTrains {
|
||||
|
||||
Module rest = new Module(REST, "2.1");
|
||||
|
||||
return new Train("Dijkstra", commons, jpa, mongoDb, neo4j, solr, couchbase, cassandra, elasticsearch, gemfire,
|
||||
redis, rest);
|
||||
return new Train("Dijkstra", build, commons, jpa, mongoDb, neo4j, solr, couchbase, cassandra, elasticsearch,
|
||||
gemfire, redis, rest);
|
||||
}
|
||||
|
||||
public static Train getTrainByName(String name) {
|
||||
|
||||
@@ -92,6 +92,37 @@ public class Train implements Iterable<Module> {
|
||||
return new Train(name, nextModules);
|
||||
}
|
||||
|
||||
public Iterable<ModuleIteration> getModuleIterations(Iteration iteration) {
|
||||
return getModuleIterations(iteration, new Project[0]);
|
||||
}
|
||||
|
||||
public Iterable<ModuleIteration> getModuleIterations(Iteration iteration, Project... exclusions) {
|
||||
|
||||
List<ModuleIteration> iterations = new ArrayList<>(modules.size());
|
||||
List<Project> exclusionList = Arrays.asList(exclusions);
|
||||
|
||||
for (Module module : this) {
|
||||
|
||||
if (exclusionList.contains(module.getProject())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
iterations.add(new ModuleIteration(module, iteration, this));
|
||||
}
|
||||
|
||||
return iterations;
|
||||
}
|
||||
|
||||
public Iteration getIteration(String name) {
|
||||
return iterations.getIterationByName(name);
|
||||
}
|
||||
|
||||
public ArtifactVersion getModuleVersion(Project project, Iteration iteration) {
|
||||
|
||||
Module module = getModule(project);
|
||||
return ArtifactVersion.from(new ModuleIteration(module, iteration, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
|
||||
@@ -117,6 +117,14 @@ public class Version implements Comparable<Version> {
|
||||
return new Version(this.major, this.minor + 1);
|
||||
}
|
||||
|
||||
public Version nextBugfix() {
|
||||
return new Version(this.major, this.minor, this.bugfix + 1);
|
||||
}
|
||||
|
||||
public Version withBugfix(int bugfix) {
|
||||
return new Version(this.major, this.minor, bugfix);
|
||||
}
|
||||
|
||||
public String toMajorMinorBugfix() {
|
||||
return String.format("%s.%s.%s", major, minor, bugfix);
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ package org.springframework.data.release.cli;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.AbstractIntegrationTests;
|
||||
import org.springframework.data.release.git.GitOperations;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
@@ -30,9 +30,13 @@ import org.springframework.data.release.AbstractIntegrationTests;
|
||||
public class ReleaseCommandsIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
@Autowired ReleaseCommands releaseCommands;
|
||||
@Autowired GitOperations git;
|
||||
|
||||
@Test
|
||||
public void foo() throws IOException {
|
||||
public void predictsReleasTrainCorrectly() throws Exception {
|
||||
|
||||
git.update(ReleaseTrains.DIJKSTRA);
|
||||
|
||||
assertThat(releaseCommands.predictTrainAndIteration(), is("Dijkstra"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2014 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.git;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.IterationVersion;
|
||||
import org.springframework.data.release.model.SimpleIterationVersion;
|
||||
import org.springframework.data.release.model.Version;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class BranchUnitTests {
|
||||
|
||||
@Test
|
||||
public void testname() {
|
||||
|
||||
IterationVersion iterationVersion = new SimpleIterationVersion(new Version(1, 4), Iteration.RC1);
|
||||
assertThat(Branch.from(iterationVersion).toString(), is("master"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsBugfixBranchForServiceRelease() {
|
||||
|
||||
IterationVersion iterationVersion = new SimpleIterationVersion(new Version(1, 4), Iteration.SR1);
|
||||
assertThat(Branch.from(iterationVersion).toString(), is("1.4.x"));
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.release.git;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.AbstractIntegrationTests;
|
||||
@@ -32,14 +29,14 @@ public class GitOperationsIntegrationTests extends AbstractIntegrationTests {
|
||||
@Autowired GitOperations gitOperations;
|
||||
|
||||
@Test
|
||||
public void testname() throws IOException, InterruptedException {
|
||||
public void testname() throws Exception {
|
||||
gitOperations.update(ReleaseTrains.CODD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showTags() throws IOException {
|
||||
public void showTags() throws Exception {
|
||||
|
||||
List<Tag> tags = gitOperations.getTags(ReleaseTrains.COMMONS);
|
||||
System.out.println(StringUtils.collectionToDelimitedString(tags, "\n"));
|
||||
Tags tags = gitOperations.getTags(ReleaseTrains.COMMONS);
|
||||
System.out.println(StringUtils.collectionToDelimitedString(tags.asList(), "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2014 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.maven;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.IterationVersion;
|
||||
import org.springframework.data.release.model.SimpleIterationVersion;
|
||||
import org.springframework.data.release.model.Version;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MavenVersionUnitTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsInvalidVersionSuffix() {
|
||||
ArtifactVersion.parse("1.4.5.GA");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parsesReleaseVersionCorrectly() {
|
||||
|
||||
ArtifactVersion version = ArtifactVersion.parse("1.4.5.RELEASE");
|
||||
|
||||
assertThat(version.isReleaseVersion(), is(true));
|
||||
assertThat(version.getNextDevelopmentVersion(), is(ArtifactVersion.parse("1.4.6.BUILD-SNAPSHOT")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsMilestoneVersionCorrectly() {
|
||||
|
||||
ArtifactVersion version = ArtifactVersion.parse("1.4.5.M1");
|
||||
|
||||
assertThat(version.isReleaseVersion(), is(false));
|
||||
assertThat(version.isMilestoneVersion(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsReleaseVersionByDefault() {
|
||||
|
||||
ArtifactVersion version = new ArtifactVersion(new Version(1, 4, 5));
|
||||
|
||||
assertThat(version.isReleaseVersion(), is(true));
|
||||
assertThat(version.toString(), is("1.4.5.RELEASE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsMilestoneVersionFromIteration() {
|
||||
|
||||
IterationVersion oneFourMilestoneOne = new SimpleIterationVersion(new Version(1, 4), Iteration.M1);
|
||||
ArtifactVersion version = ArtifactVersion.from(oneFourMilestoneOne);
|
||||
|
||||
assertThat(version.isMilestoneVersion(), is(true));
|
||||
assertThat(version.toString(), is("1.4.0.M1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsReleaseVersionFromIteration() {
|
||||
|
||||
IterationVersion oneFourGA = new SimpleIterationVersion(new Version(1, 4), Iteration.GA);
|
||||
ArtifactVersion version = ArtifactVersion.from(oneFourGA);
|
||||
|
||||
assertThat(version.isReleaseVersion(), is(true));
|
||||
assertThat(version.toString(), is("1.4.0.RELEASE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsServiceReleaseVersionFromIteration() {
|
||||
|
||||
IterationVersion oneFourServiceReleaseTwo = new SimpleIterationVersion(new Version(1, 4), Iteration.SR2);
|
||||
ArtifactVersion version = ArtifactVersion.from(oneFourServiceReleaseTwo);
|
||||
|
||||
assertThat(version.isReleaseVersion(), is(true));
|
||||
assertThat(version.toString(), is("1.4.2.RELEASE"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2014 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;
|
||||
|
||||
@Value
|
||||
public class SimpleIterationVersion implements IterationVersion {
|
||||
|
||||
private final Version version;
|
||||
private final Iteration iteration;
|
||||
}
|
||||
Reference in New Issue
Block a user