A way too big commit.
Switched to Apache Maven Invoker for running Maven on the projects. Added JGraphT to correctly sort dependencies in topological order. Upgraded to Spring Boot 1.3.2, Lombok 1.16.6, jGit 4.2.0. Upgraded to Spring Plugin 1.3 to benefit from lazy exception creation using lambdas. Added Lombok configuration to throw IllegalArgumentException on null checks.
This commit is contained in:
11
release-tools/application-local.template
Normal file
11
release-tools/application-local.template
Normal file
@@ -0,0 +1,11 @@
|
||||
# Git
|
||||
git.username=
|
||||
git.author=
|
||||
git.email=
|
||||
git.password=
|
||||
|
||||
# Maven
|
||||
maven.mavenHome=
|
||||
|
||||
# Deployment
|
||||
deployment.password=
|
||||
1
release-tools/lombok.config
Normal file
1
release-tools/lombok.config
Normal file
@@ -0,0 +1 @@
|
||||
lombok.nonNull.exceptionType = IllegalArgumentException
|
||||
@@ -8,12 +8,13 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.3.0.RELEASE</version>
|
||||
<version>1.3.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<jar.mainclass>org.springframework.data.release.Application</jar.mainclass>
|
||||
<spring-plugin.version>1.3.0.BUILD-SNAPSHOT</spring-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -50,9 +51,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xmlbeam</groupId>
|
||||
<artifactId>xmlprojector</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<groupId>org.xmlbeam</groupId>
|
||||
<artifactId>xmlprojector</artifactId>
|
||||
<version>1.4.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -64,7 +65,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.4</version>
|
||||
<version>1.16.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -81,7 +82,7 @@
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>4.0.1.201506240215-r</version>
|
||||
<version>4.2.0.201601211800-r</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -89,6 +90,19 @@
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-invoker</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jgrapht</groupId>
|
||||
<artifactId>jgrapht-core</artifactId>
|
||||
<version>0.9.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
1. Add an `application-local.properties` to the project root and add the following properties:
|
||||
|
||||
- `git.username` - Your GitHub username.
|
||||
- `git.password` - Your GitHub password.
|
||||
- `git.password` - Your GitHub password or API key.
|
||||
- `git.author` - Your full name (used for preparing commits).
|
||||
- `git.email` - Your email (used for preparing commits).
|
||||
- `maven.mavenHome` - Pointing to the location of your Maven installation.
|
||||
- `deployment.api-key` - The API key to use for artifact promotion.
|
||||
- `deployment.password` - The password of the deployment user (buildmaster).
|
||||
|
||||
2. Run `mvn package appassembler:assemble && sh target/appassembler/bin/spring-data-release-shell`
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2016 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;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* SImple interface to ease streamability of {@link Iterable}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface Streamable<T> extends Iterable<T> {
|
||||
|
||||
/**
|
||||
* Creates a non-parallel {@link Stream} of the underlying {@link Iterable}.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public default Stream<T> stream() {
|
||||
return StreamSupport.stream(spliterator(), false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2015 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 lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.CliComponent;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
|
||||
/**
|
||||
* Commands to create markup to be used in announcing blog posts.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@CliComponent
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
public class AnnouncementCommands implements CommandMarker {
|
||||
|
||||
private final @NonNull AnnouncementOperations operations;
|
||||
|
||||
@CliCommand("announcement")
|
||||
public void distribute(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
|
||||
System.out.println(operations.getProjectBulletpoints(iteration));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -17,26 +17,22 @@ package org.springframework.data.release.announcement;
|
||||
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import org.springframework.data.release.build.MavenArtifact;
|
||||
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.data.release.model.TrainIteration;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
public class AnnouncementOperations {
|
||||
|
||||
/**
|
||||
* Returns the project list and links to be included in the release announcement for the given {@link Train} and
|
||||
* {@link Iteration}.
|
||||
* Returns the project list and links to be included in the release announcement for the given {@link TrainIteration}.
|
||||
*
|
||||
* @param train must not be {@literal null}.
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -46,16 +42,16 @@ public class AnnouncementOperations {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (ModuleIteration module : iteration.getModulesExcept(BUILD)) {
|
||||
iteration.getModulesExcept(BUILD).forEach(module -> {
|
||||
|
||||
Project project = module.getProject();
|
||||
|
||||
builder.append("* ");
|
||||
builder.append(project.getFullName()).append(" ");
|
||||
builder.append(module.getVersionString());
|
||||
builder.append(module.getShortVersionString());
|
||||
builder.append(" - ");
|
||||
|
||||
Artifact artifact = new Artifact(module);
|
||||
MavenArtifact artifact = new MavenArtifact(module);
|
||||
|
||||
builder.append(getMarkDownLink("Artifacts", artifact.getRootUrl()));
|
||||
builder.append(" - ");
|
||||
@@ -67,18 +63,12 @@ public class AnnouncementOperations {
|
||||
builder.append(getMarkDownLink("Changelog", resources.getChangelogUrl()));
|
||||
|
||||
builder.append("\n");
|
||||
}
|
||||
});
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String getMarkDownLink(String name, String url) {
|
||||
private static 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(new TrainIteration(ReleaseTrains.GOSLING, Iteration.SR1)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2016 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.
|
||||
@@ -13,10 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
package org.springframework.data.release.build;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.plugin.core.OrderAwarePluginRegistry;
|
||||
import org.springframework.plugin.core.PluginRegistry;
|
||||
import org.xmlbeam.ProjectionFactory;
|
||||
import org.xmlbeam.XBProjector;
|
||||
import org.xmlbeam.XBProjector.Flags;
|
||||
@@ -24,10 +29,17 @@ import org.xmlbeam.config.DefaultXMLFactoriesConfig;
|
||||
import org.xmlbeam.config.DefaultXMLFactoriesConfig.NamespacePhilosophy;
|
||||
|
||||
/**
|
||||
* Spring configuration for build related components.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
class MavenConfig {
|
||||
class BuildConfiguration {
|
||||
|
||||
@Bean
|
||||
public PluginRegistry<BuildSystem, Project> buildSystems(List<? extends BuildSystem> buildSystems) {
|
||||
return OrderAwarePluginRegistry.create(buildSystems);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProjectionFactory projectionFactory() {
|
||||
@@ -36,8 +48,6 @@ class MavenConfig {
|
||||
config.setNamespacePhilosophy(NamespacePhilosophy.AGNOSTIC);
|
||||
config.setOmitXMLDeclaration(false);
|
||||
|
||||
XBProjector projector = new XBProjector(config, Flags.TO_STRING_RENDERS_XML);
|
||||
|
||||
return projector;
|
||||
return new XBProjector(config, Flags.TO_STRING_RENDERS_XML);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2016 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.build;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.deployment.DeploymentInformation;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Phase;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.data.release.model.UpdateInformation;
|
||||
import org.springframework.plugin.core.PluginRegistry;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
public class BuildOperations {
|
||||
|
||||
private final PluginRegistry<BuildSystem, Project> buildSystems;
|
||||
|
||||
/**
|
||||
* Updates all inter-project dependencies based on the given {@link TrainIteration} and release {@link Phase}.
|
||||
*
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @param phase must not be {@literal null}.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void updateProjectDescriptors(TrainIteration iteration, Phase phase) throws Exception {
|
||||
|
||||
Assert.notNull(iteration, "Train iteration must not be null!");
|
||||
Assert.notNull(phase, "Phase must not be null!");
|
||||
|
||||
UpdateInformation updateInformation = new UpdateInformation(iteration, phase);
|
||||
|
||||
doWithBuildSystem(iteration, (system, it) -> system.updateProjectDescriptors(it, updateInformation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the distribution builds for all modules particitpating in the given {@link TrainIteration}.
|
||||
*
|
||||
* @param iteration must not be {@literal null}.
|
||||
*/
|
||||
public void distributeResources(TrainIteration iteration) {
|
||||
|
||||
Assert.notNull(iteration, "Train iteration must not be null!");
|
||||
|
||||
doWithBuildSystem(iteration, BuildSystem::triggerDistributionBuild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the release build for all modules in the given {@link TrainIteration}.
|
||||
*
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public List<DeploymentInformation> performRelease(TrainIteration iteration) {
|
||||
return iteration.stream().map(this::performRelease).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the release build for the given {@link ModuleIteration}.
|
||||
*
|
||||
* @param module must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public DeploymentInformation performRelease(ModuleIteration module) {
|
||||
|
||||
prepareVersion(module, Phase.PREPARE);
|
||||
return buildAndDeployRelease(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the versions of the given {@link TrainIteration} depending on the given {@link Phase}.
|
||||
*
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @param phase must not be {@literal null}.
|
||||
*/
|
||||
public void prepareVersions(TrainIteration iteration, Phase phase) {
|
||||
|
||||
Assert.notNull(iteration, "Train iteration must not be null!");
|
||||
Assert.notNull(phase, "Phase must not be null!");
|
||||
|
||||
doWithBuildSystem(iteration, (system, module) -> system.prepareVersion(module, phase));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the version of the given {@link ModuleIteration} depending on the given {@link Phase}.
|
||||
*
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @param phase must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public ModuleIteration prepareVersion(ModuleIteration iteration, Phase phase) {
|
||||
|
||||
Assert.notNull(iteration, "Module iteration must not be null!");
|
||||
Assert.notNull(phase, "Phase must not be null!");
|
||||
|
||||
return doWithBuildSystem(iteration, (system, module) -> system.prepareVersion(module, phase));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the release for the given {@link ModuleIteration} and deploys it to the staging repository.
|
||||
*
|
||||
* @param module must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public DeploymentInformation buildAndDeployRelease(ModuleIteration module) {
|
||||
return doWithBuildSystem(module, BuildSystem::deploy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the build system for each {@link ModuleIteration} contained in the given {@link TrainIteration} and
|
||||
* executes the given function for it.
|
||||
*
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @param function must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private <T> List<T> doWithBuildSystem(TrainIteration iteration,
|
||||
BiFunction<BuildSystem, ModuleIteration, T> function) {
|
||||
|
||||
return iteration.stream()//
|
||||
.map(module -> doWithBuildSystem(module, function))//
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the build system for the module contained in the given {@link ModuleIteration} and executes the given
|
||||
* function with it.
|
||||
*
|
||||
* @param module must not be {@literal null}.
|
||||
* @param function must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private <T> T doWithBuildSystem(ModuleIteration module, BiFunction<BuildSystem, ModuleIteration, T> function) {
|
||||
return function.apply(buildSystems.getPluginFor(module.getProject(), () -> new IllegalStateException(
|
||||
String.format("No build system plugin found for project %s!", module.getProject()))), module);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016 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.build;
|
||||
|
||||
import org.springframework.data.release.deployment.DeploymentInformation;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Phase;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.UpdateInformation;
|
||||
import org.springframework.plugin.core.Plugin;
|
||||
|
||||
/**
|
||||
* Plugin interface to back different build systems.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
interface BuildSystem extends Plugin<Project> {
|
||||
|
||||
/**
|
||||
* @param iteration
|
||||
* @param train
|
||||
* @param phase
|
||||
* @throws Exception
|
||||
*/
|
||||
ModuleIteration updateProjectDescriptors(ModuleIteration iteration, UpdateInformation updateInformation);
|
||||
|
||||
ModuleIteration prepareVersion(ModuleIteration module, Phase phase);
|
||||
|
||||
ModuleIteration triggerDistributionBuild(ModuleIteration module);
|
||||
|
||||
DeploymentInformation deploy(ModuleIteration module);
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.build;
|
||||
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.release.deployment.DeploymentInformation;
|
||||
import org.springframework.data.release.deployment.DeploymentProperties;
|
||||
import org.springframework.data.release.io.Workspace;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Phase;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.data.release.model.UpdateInformation;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Gradle specific operations.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@Order(200)
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
class GradleBuildSystem implements BuildSystem {
|
||||
|
||||
private static final String BUILD_GRADLE = "build.gradle";
|
||||
private static final String GRADLE_PROPERTIES = "gradle.properties";
|
||||
private static final String COMMONS_PROPERTY = "springDataCommonsVersion";
|
||||
private static final String BUILD_PROPERTY = "springDataBuildVersion";
|
||||
|
||||
private final Workspace workspace;
|
||||
private final Logger logger;
|
||||
private final DeploymentProperties properties;
|
||||
|
||||
/**
|
||||
* Updates all Gradle projects contained in the release.
|
||||
*
|
||||
* @param iteration
|
||||
* @param phase
|
||||
* @throws Exception
|
||||
*/
|
||||
public void updateProject(TrainIteration iteration, final Phase phase) throws Exception {
|
||||
|
||||
UpdateInformation updateInformation = new UpdateInformation(iteration, phase);
|
||||
|
||||
for (ModuleIteration module : iteration.getModulesExcept(BUILD)) {
|
||||
updateProjectDescriptors(module, updateInformation);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.build.BuildSystem#updateProjectDescriptors(org.springframework.data.release.model.ModuleIteration, org.springframework.data.release.model.UpdateInformation)
|
||||
*/
|
||||
@Override
|
||||
public ModuleIteration updateProjectDescriptors(ModuleIteration iteration, UpdateInformation updateInformation) {
|
||||
|
||||
Project project = iteration.getProject();
|
||||
Repository repository = new Repository(iteration.getIteration());
|
||||
ArtifactVersion commonsVersion = updateInformation.getIteration().getModuleVersion(COMMONS);
|
||||
ArtifactVersion buildVersion = updateInformation.getIteration().getModuleVersion(BUILD);
|
||||
|
||||
workspace.processFile(GRADLE_PROPERTIES, project, (line, number) -> {
|
||||
|
||||
if (line.contains(COMMONS_PROPERTY)) {
|
||||
|
||||
ArtifactVersion version = updateInformation.getPhase().equals(Phase.PREPARE) ? commonsVersion
|
||||
: commonsVersion.getNextDevelopmentVersion();
|
||||
|
||||
logger.log(project, "Setting Spring Data Commons version in %s to %s.", GRADLE_PROPERTIES, version);
|
||||
return String.format("%s=%s", COMMONS_PROPERTY, version);
|
||||
}
|
||||
|
||||
if (line.contains(BUILD_PROPERTY)) {
|
||||
|
||||
ArtifactVersion version = updateInformation.getPhase().equals(Phase.PREPARE) ? buildVersion
|
||||
: buildVersion.getNextDevelopmentVersion();
|
||||
|
||||
logger.log(project, "Setting Spring Data Build version in %s to %s.", GRADLE_PROPERTIES, version);
|
||||
return String.format("%s=%s", BUILD_PROPERTY, version);
|
||||
}
|
||||
|
||||
return line;
|
||||
});
|
||||
|
||||
workspace.processFile(BUILD_GRADLE, project, (line, number) -> {
|
||||
|
||||
String snapshotUrl = repository.getSnapshotUrl();
|
||||
String releaseUrl = repository.getUrl();
|
||||
String message = "Switching to Spring repository %s";
|
||||
|
||||
switch (updateInformation.getPhase()) {
|
||||
case CLEANUP:
|
||||
logger.log(project, message, snapshotUrl);
|
||||
return line.contains(releaseUrl) ? line.replace(releaseUrl, snapshotUrl) : line;
|
||||
case PREPARE:
|
||||
default:
|
||||
logger.log(project, message, releaseUrl);
|
||||
return line.contains(snapshotUrl) ? line.replace(snapshotUrl, releaseUrl) : line;
|
||||
}
|
||||
});
|
||||
|
||||
return iteration;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.build.BuildSystem#prepareVersion(org.springframework.data.release.model.ModuleIteration, org.springframework.data.release.model.Phase)
|
||||
*/
|
||||
@Override
|
||||
public ModuleIteration prepareVersion(ModuleIteration module, Phase phase) {
|
||||
return module;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.build.BuildSystem#triggerDistributionBuild(org.springframework.data.release.model.ModuleIteration)
|
||||
*/
|
||||
@Override
|
||||
public ModuleIteration triggerDistributionBuild(ModuleIteration module) {
|
||||
return module;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.build.BuildSystem#deploy(org.springframework.data.release.model.ModuleIteration)
|
||||
*/
|
||||
@Override
|
||||
public DeploymentInformation deploy(ModuleIteration module) {
|
||||
return new DeploymentInformation(module, properties);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.plugin.core.Plugin#supports(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean supports(Project project) {
|
||||
return isGradleProject(project);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given project is a Gradle project (checks for the presence of a build.gradle file).
|
||||
*
|
||||
* @param project
|
||||
* @return
|
||||
*/
|
||||
private boolean isGradleProject(Project project) {
|
||||
return workspace.getFile(BUILD_GRADLE, project).exists();
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
package org.springframework.data.release.build;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@@ -22,7 +22,7 @@ import lombok.Value;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
@Value(staticConstructor = "of")
|
||||
class GroupId {
|
||||
|
||||
private final String value;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -13,9 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
package org.springframework.data.release.build;
|
||||
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -24,25 +25,25 @@ import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to represent a Maven {@link Artifact}.
|
||||
* Value object to represent a Maven artifact.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public class Artifact {
|
||||
public class MavenArtifact {
|
||||
|
||||
private static final GroupId GROUP_ID = new GroupId("org.springframework.data");
|
||||
private static final GroupId GROUP_ID = GroupId.of("org.springframework.data");
|
||||
|
||||
private final ModuleIteration module;
|
||||
private final Repository repository;
|
||||
private final @Getter ArtifactVersion version;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Artifact} for the given {@link ModuleIteration}.
|
||||
* Creates a new {@link MavenArtifact} for the given {@link ModuleIteration}.
|
||||
*
|
||||
* @param module must not be {@literal null}.
|
||||
*/
|
||||
public Artifact(ModuleIteration module) {
|
||||
public MavenArtifact(ModuleIteration module) {
|
||||
|
||||
Assert.notNull(module, "Module iteration must not be null!");
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* 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.build;
|
||||
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.release.deployment.DeploymentInformation;
|
||||
import org.springframework.data.release.deployment.DeploymentProperties;
|
||||
import org.springframework.data.release.io.Workspace;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Phase;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.data.release.model.UpdateInformation;
|
||||
import org.springframework.data.release.utils.ExecutionUtils;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.xmlbeam.ProjectionFactory;
|
||||
import org.xmlbeam.io.XBFileIO;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@Order(100)
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
class MavenBuildSystem implements BuildSystem {
|
||||
|
||||
private static final String POM_XML = "pom.xml";
|
||||
|
||||
private final Workspace workspace;
|
||||
private final ProjectionFactory projectionFactory;
|
||||
private final Logger logger;
|
||||
private final MavenRuntime mvn;
|
||||
private final DeploymentProperties properties;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.build.BuildSystem#updateProjectDescriptors(org.springframework.data.release.model.ModuleIteration, org.springframework.data.release.model.TrainIteration, org.springframework.data.release.model.Phase)
|
||||
*/
|
||||
@Override
|
||||
public ModuleIteration updateProjectDescriptors(ModuleIteration module, UpdateInformation information) {
|
||||
|
||||
PomUpdater updater = new PomUpdater(logger, information, module.getProject());
|
||||
|
||||
if (updater.isBuildProject()) {
|
||||
|
||||
updateBom(information);
|
||||
updateParentPom(information);
|
||||
|
||||
} else {
|
||||
|
||||
execute(workspace.getFile(POM_XML, updater.getProject()), pom -> {
|
||||
|
||||
updater.updateDependencyProperties(pom);
|
||||
updater.updateParentVersion(pom);
|
||||
updater.updateRepository(pom);
|
||||
});
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.build.BuildSystem#triggerDistributionBuild(org.springframework.data.release.model.ModuleIteration)
|
||||
*/
|
||||
@Override
|
||||
public ModuleIteration triggerDistributionBuild(ModuleIteration module) {
|
||||
|
||||
Project project = module.getProject();
|
||||
|
||||
if (BUILD.equals(project)) {
|
||||
return module;
|
||||
}
|
||||
|
||||
if (!isMavenProject(project)) {
|
||||
logger.log(project, "Skipping project as no pom.xml could be found in the working directory!");
|
||||
return module;
|
||||
}
|
||||
|
||||
logger.log(project, "Triggering distribution build…");
|
||||
|
||||
ArtifactVersion version = ArtifactVersion.of(module);
|
||||
|
||||
String profile = "-Pdistribute";
|
||||
|
||||
if (version.isMilestoneVersion()) {
|
||||
profile = profile.concat(",milestone");
|
||||
} else if (version.isReleaseVersion()) {
|
||||
profile = profile.concat(",release");
|
||||
}
|
||||
|
||||
mvn.execute(project, "clean", "deploy", "-DskipTests", profile);
|
||||
|
||||
logger.log(project, "Successfully finished distribution build!");
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
private void updateBom(UpdateInformation updateInformation) {
|
||||
|
||||
TrainIteration iteration = updateInformation.getIteration();
|
||||
|
||||
logger.log(BUILD, "Updating BOM pom.xml…");
|
||||
|
||||
execute(workspace.getFile("bom/pom.xml", BUILD), pom -> {
|
||||
|
||||
for (ModuleIteration module : iteration.getModulesExcept(BUILD)) {
|
||||
|
||||
ArtifactVersion version = updateInformation.getProjectVersionToSet(module.getProject());
|
||||
|
||||
logger.log(BUILD, "%s", module);
|
||||
|
||||
pom.setDependencyManagementVersion(new MavenArtifact(module).getArtifactId(), version);
|
||||
|
||||
module.getProject().doWithAdditionalArtifacts(
|
||||
additionalArtifact -> pom.setDependencyManagementVersion(additionalArtifact.getArtifactId(), version));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateParentPom(UpdateInformation information) {
|
||||
|
||||
// Fix version of shared resources to to-be-released version.
|
||||
execute(workspace.getFile("parent/pom.xml", BUILD), ParentPom.class, pom -> {
|
||||
|
||||
logger.log(BUILD, "Setting shared resources version to %s.", information.getParentVersionToSet());
|
||||
pom.setSharedResourcesVersion(information.getParentVersionToSet());
|
||||
|
||||
logger.log(BUILD, "Setting releasetrain property to %s.", information.getReleaseTrainVersion());
|
||||
pom.setReleaseTrain(information.getReleaseTrainVersion());
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isMavenProject(ModuleIteration module) {
|
||||
|
||||
Project project = module.getProject();
|
||||
|
||||
if (!isMavenProject(project)) {
|
||||
logger.log(module, "No pom.xml file found, skipping project.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers building the distribution artifacts for all Maven projects of the given {@link Train}.
|
||||
*
|
||||
* @param iteration
|
||||
* @throws Exception
|
||||
*/
|
||||
public void triggerDistributionBuild(TrainIteration iteration) throws Exception {
|
||||
|
||||
ExecutionUtils.run(iteration, module -> {
|
||||
|
||||
Project project = module.getProject();
|
||||
|
||||
if (BUILD.equals(project)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isMavenProject(project)) {
|
||||
logger.log(project, "Skipping project as no pom.xml could be found in the working directory!");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log(project, "Triggering distribution build…");
|
||||
|
||||
ArtifactVersion version = ArtifactVersion.of(module);
|
||||
|
||||
String profile = "-Pdistribute";
|
||||
|
||||
if (version.isMilestoneVersion()) {
|
||||
profile = profile.concat(",milestone");
|
||||
} else if (version.isReleaseVersion()) {
|
||||
profile = profile.concat(",release");
|
||||
}
|
||||
|
||||
mvn.execute(project, "clean", "deploy", "-DskipTests", profile);
|
||||
|
||||
logger.log(project, "Successfully finished distribution build!");
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.build.BuildSystem#prepareVersion(org.springframework.data.release.model.ModuleIteration, org.springframework.data.release.model.Phase)
|
||||
*/
|
||||
@Override
|
||||
public ModuleIteration prepareVersion(ModuleIteration module, Phase phase) {
|
||||
|
||||
Project project = module.getProject();
|
||||
UpdateInformation information = new UpdateInformation(module.getTrainIteration(), phase);
|
||||
|
||||
mvn.execute(project, "versions-set",
|
||||
"-DnewVersion=".concat(information.getProjectVersionToSet(project).toString()));
|
||||
|
||||
if (BUILD.equals(project)) {
|
||||
|
||||
mvn.execute(project, "versions-set", //
|
||||
"-DnewVersion=".concat(information.getReleaseTrainVersion()), //
|
||||
"-DgroupId=org.springframework.data", //
|
||||
"-DartifactId=spring-data-releasetrain");
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.build.BuildSystem#deploy(org.springframework.data.release.model.ModuleIteration)
|
||||
*/
|
||||
@Override
|
||||
public DeploymentInformation deploy(ModuleIteration module) {
|
||||
|
||||
Assert.notNull(module, "Module must not be null!");
|
||||
|
||||
DeploymentInformation information = new DeploymentInformation(module, properties);
|
||||
|
||||
List<String> arguments = new ArrayList<>();
|
||||
arguments.add("clean");
|
||||
arguments.add("deploy");
|
||||
arguments.add("-Prelease");
|
||||
|
||||
arguments.add("-DskipTests");
|
||||
|
||||
arguments.add("-Dartifactory.server=".concat(properties.getServer().getUri()));
|
||||
arguments.add("-Dartifactory.staging-repository=".concat(properties.getStagingRepository()));
|
||||
arguments.add("-Dartifactory.username=".concat(properties.getUsername()));
|
||||
arguments.add("-Dartifactory.password=".concat(properties.getPassword()));
|
||||
arguments.add("-Dartifactory.build-name=\"".concat(information.getBuildName()).concat("\""));
|
||||
arguments.add("-Dartifactory.build-number=".concat(information.getBuildNumber()));
|
||||
|
||||
mvn.execute(module.getProject(), arguments);
|
||||
|
||||
return information;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.plugin.core.Plugin#supports(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean supports(Project project) {
|
||||
return isMavenProject(project);
|
||||
}
|
||||
|
||||
private void updateVersion(ModuleIteration iteration, File workingDirectory) {
|
||||
|
||||
ArtifactVersion version = ArtifactVersion.of(iteration);
|
||||
|
||||
mvn.execute(iteration.getProject(), "versions-set", "-DnewVersion=".concat(version.toString()));
|
||||
}
|
||||
|
||||
private boolean isMavenProject(Project project) {
|
||||
return workspace.getFile(POM_XML, project).exists();
|
||||
}
|
||||
|
||||
private void execute(File file, Consumer<Pom> callback) {
|
||||
execute(file, Pom.class, callback);
|
||||
}
|
||||
|
||||
private <T extends Pom> void execute(File file, Class<T> type, Consumer<T> callback) {
|
||||
|
||||
XBFileIO io = projectionFactory.io().file(file);
|
||||
|
||||
try {
|
||||
|
||||
T pom = (T) io.read(type);
|
||||
callback.accept(pom);
|
||||
io.write(pom);
|
||||
|
||||
} catch (Exception o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2015 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.build;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Maven configuration properties.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Slf4j
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "maven")
|
||||
class MavenProperties {
|
||||
|
||||
private File mavenHome;
|
||||
private File localRepository;
|
||||
private Map<String, String> plugins;
|
||||
|
||||
/**
|
||||
* Configures the local Maven repository location to use. In case the given folder does not already exists it's
|
||||
* created.
|
||||
*
|
||||
* @param localRepository must not be {@literal null} or empty.
|
||||
*/
|
||||
public void setLocalRepository(String localRepository) {
|
||||
|
||||
Assert.hasText(localRepository, "Local repository must not be null!");
|
||||
|
||||
log.info("Using {} as local Maven repository!", localRepository);
|
||||
|
||||
this.localRepository = new File(localRepository.replace("~", System.getProperty("user.home")));
|
||||
|
||||
if (!this.localRepository.exists()) {
|
||||
this.localRepository.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully-qualified plugin goal for the given local one.
|
||||
*
|
||||
* @param goal must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
public String getFullyQualifiedPlugin(String goal) {
|
||||
|
||||
Assert.hasText(goal, "Goal must not be null or empty!");
|
||||
return plugins.containsKey(goal) ? plugins.get(goal) : goal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2015 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.build;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
|
||||
import org.apache.maven.shared.invoker.DefaultInvoker;
|
||||
import org.apache.maven.shared.invoker.InvocationResult;
|
||||
import org.apache.maven.shared.invoker.Invoker;
|
||||
import org.apache.maven.shared.invoker.MavenInvocationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.io.OsOperations;
|
||||
import org.springframework.data.release.io.Workspace;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
class MavenRuntime {
|
||||
|
||||
private final Invoker invoker;
|
||||
private final Workspace workspace;
|
||||
private final OsOperations os;
|
||||
private final Logger logger;
|
||||
private final MavenProperties properties;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MavenRuntime} for the given {@link Workspace} and Maven home.
|
||||
*
|
||||
* @param workspace must not be {@literal null}.
|
||||
* @param os must not be {@literal null}.
|
||||
* @param logger must not be {@literal null}.
|
||||
* @param properties must not be {@literal null}.
|
||||
*/
|
||||
@Autowired
|
||||
public MavenRuntime(Workspace workspace, OsOperations os, Logger logger, MavenProperties properties) {
|
||||
|
||||
this.workspace = workspace;
|
||||
this.os = os;
|
||||
this.logger = logger;
|
||||
this.properties = properties;
|
||||
|
||||
this.invoker = new DefaultInvoker();
|
||||
this.invoker.setMavenHome(properties.getMavenHome());
|
||||
this.invoker.setOutputHandler(line -> log.info(line));
|
||||
this.invoker.setErrorHandler(line -> log.info(line));
|
||||
|
||||
File localRepository = properties.getLocalRepository();
|
||||
|
||||
if (localRepository != null) {
|
||||
this.invoker.setLocalRepositoryDirectory(localRepository);
|
||||
}
|
||||
}
|
||||
|
||||
public void execute(Project project, String... arguments) {
|
||||
execute(project, Arrays.asList(arguments));
|
||||
}
|
||||
|
||||
public void execute(Project project, List<String> arguments) {
|
||||
|
||||
DefaultInvocationRequest request = new DefaultInvocationRequest();
|
||||
request.setJavaHome(os.getJavaHome());
|
||||
request.setShellEnvironmentInherited(true);
|
||||
request.setBaseDirectory(workspace.getProjectDirectory(project));
|
||||
|
||||
List<String> goals = new ArrayList<>();
|
||||
goals.add(properties.getFullyQualifiedPlugin(arguments.get(0)));
|
||||
goals.addAll(arguments.subList(1, arguments.size()));
|
||||
|
||||
request.setGoals(goals);
|
||||
|
||||
logger.log(project, "Executing mvn %s", goals.stream().collect(Collectors.joining(" ")));
|
||||
|
||||
try {
|
||||
|
||||
InvocationResult result = invoker.execute(request);
|
||||
|
||||
if (result.getExitCode() != 0) {
|
||||
throw new RuntimeException(result.getExecutionException());
|
||||
}
|
||||
|
||||
} catch (MavenInvocationException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
package org.springframework.data.release.build;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.xmlbeam.annotation.XBValue;
|
||||
@@ -24,6 +24,9 @@ import org.xmlbeam.annotation.XBWrite;
|
||||
*/
|
||||
public interface ParentPom extends Pom {
|
||||
|
||||
@XBWrite("/project/properties/releasetrain")
|
||||
void setReleaseTrain(@XBValue String releaseTrain);
|
||||
|
||||
@XBWrite("/project/profiles/profile[id=\"distribute\"]/dependencies/dependency/version")
|
||||
void setSharedResourcesVersion(@XBValue ArtifactVersion value);
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
package org.springframework.data.release.build;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.xmlbeam.annotation.XBRead;
|
||||
@@ -26,13 +26,16 @@ import org.xmlbeam.annotation.XBWrite;
|
||||
public interface Pom {
|
||||
|
||||
@XBRead("/project")
|
||||
Artifact getArtifactId();
|
||||
Artifact getArtifact();
|
||||
|
||||
@XBRead("/project/version")
|
||||
String getRawVersion();
|
||||
|
||||
@XBRead("/project/version")
|
||||
ArtifactVersion getVersion();
|
||||
|
||||
@XBWrite("/project/version")
|
||||
void setVersion(String version);
|
||||
void setVersion(ArtifactVersion version);
|
||||
|
||||
@XBWrite("/project/parent/version")
|
||||
void setParentVersion(ArtifactVersion version);
|
||||
@@ -73,12 +76,20 @@ public interface Pom {
|
||||
public interface Artifact {
|
||||
|
||||
@XBRead("child::groupId")
|
||||
String getGroupId();
|
||||
GroupId getGroupId();
|
||||
|
||||
@XBRead("child::artifactId")
|
||||
String getArtifactId();
|
||||
|
||||
@XBRead("child::version")
|
||||
String getVersion();
|
||||
|
||||
default String getArtifactPath() {
|
||||
return "/".concat(getGroupId().asPath()).concat("/").concat(getArtifactId());
|
||||
}
|
||||
|
||||
default String getPath() {
|
||||
return getArtifactPath().concat(getVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2015 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.build;
|
||||
|
||||
import static org.springframework.data.release.model.Phase.*;
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.UpdateInformation;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
class PomUpdater {
|
||||
|
||||
private final Logger logger;
|
||||
private final UpdateInformation information;
|
||||
private final @Getter Project project;
|
||||
|
||||
public boolean isBuildProject() {
|
||||
return BUILD.equals(project);
|
||||
}
|
||||
|
||||
public void updateArtifactVersion(Pom pom) {
|
||||
|
||||
ArtifactVersion version = information.getProjectVersionToSet(project);
|
||||
logger.log(project, "Updated project version to %s.", version);
|
||||
pom.setVersion(version);
|
||||
}
|
||||
|
||||
public void updateDependencyProperties(Pom pom) {
|
||||
|
||||
project.getDependencies().forEach(dependency -> {
|
||||
|
||||
String dependencyProperty = dependency.getDependencyProperty();
|
||||
|
||||
if (pom.getProperty(dependencyProperty) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArtifactVersion version = information.getProjectVersionToSet(dependency);
|
||||
|
||||
logger.log(project, "Updating %s dependency version property %s to %s.", dependency.getFullName(),
|
||||
dependencyProperty, version);
|
||||
pom.setProperty(dependencyProperty, version);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the version of the parent project in the given {@link Pom}.
|
||||
*
|
||||
* @param pom must not be {@literal null}.
|
||||
*/
|
||||
public void updateParentVersion(Pom pom) {
|
||||
|
||||
Assert.notNull(pom, "Pom must not be null!");
|
||||
|
||||
ArtifactVersion version = information.getParentVersionToSet();
|
||||
|
||||
logger.log(project, "Updating Spring Data Build Parent version to %s.", version);
|
||||
pom.setParentVersion(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the repository section in the given {@link Pom}.
|
||||
*
|
||||
* @param pom must not be {@literal null}.
|
||||
*/
|
||||
public void updateRepository(Pom pom) {
|
||||
|
||||
Assert.notNull(pom, "Pom must not be null!");
|
||||
|
||||
String message = "Switching to Spring repository %s (%s).";
|
||||
Repository repository = information.getRepository();
|
||||
|
||||
if (PREPARE.equals(information.getPhase())) {
|
||||
|
||||
logger.log(project, message, repository.getId(), repository.getUrl());
|
||||
|
||||
pom.setRepositoryId(repository.getSnapshotId(), repository.getId());
|
||||
pom.setRepositoryUrl(repository.getId(), repository.getUrl());
|
||||
|
||||
} else {
|
||||
|
||||
logger.log(project, message, repository.getSnapshotId(), repository.getSnapshotUrl());
|
||||
|
||||
pom.setRepositoryId(repository.getId(), repository.getSnapshotId());
|
||||
pom.setRepositoryUrl(repository.getSnapshotId(), repository.getSnapshotUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,35 +13,35 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
package org.springframework.data.release.build;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
|
||||
@Value
|
||||
public class Repository {
|
||||
|
||||
private static final String ID_BASE = "spring-libs-";
|
||||
private static final String BASE = "https://repo.spring.io/libs-";
|
||||
|
||||
private final String id;
|
||||
private final String url;
|
||||
String id, url;
|
||||
|
||||
public Repository(Iteration iteration) {
|
||||
this.id = iteration.isPublic() ? "spring-libs-release" : "spring-libs-milestone";
|
||||
this.url = iteration.isPublic() ? BASE.concat("release") : BASE.concat("milestone");
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
Assert.notNull(iteration, "Iteration must not be null!");
|
||||
|
||||
this.id = ID_BASE.concat(iteration.isPublic() ? "release" : "milestone");
|
||||
this.url = BASE.concat(iteration.isPublic() ? "release" : "milestone");
|
||||
}
|
||||
|
||||
public String getSnapshotId() {
|
||||
return "spring-libs-snapshot";
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
return ID_BASE.concat("snapshot");
|
||||
}
|
||||
|
||||
public String getSnapshotUrl() {
|
||||
@@ -45,8 +45,9 @@ public class IssueTrackerCommands implements CommandMarker {
|
||||
private final Credentials credentials;
|
||||
|
||||
/**
|
||||
* @param tracker
|
||||
* @param environment
|
||||
* @param tracker must not be {@literal null}.
|
||||
* @param jira must not be {@literal null}.
|
||||
* @param environment must not be {@literal null}.
|
||||
*/
|
||||
@Autowired
|
||||
public IssueTrackerCommands(PluginRegistry<IssueTracker, Project> tracker, JiraConnector jira,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -19,35 +19,39 @@ import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.docs.DocumentationOperations;
|
||||
import org.springframework.data.release.CliComponent;
|
||||
import org.springframework.data.release.build.BuildOperations;
|
||||
import org.springframework.data.release.deployment.DeploymentInformation;
|
||||
import org.springframework.data.release.deployment.DeploymentOperations;
|
||||
import org.springframework.data.release.git.GitOperations;
|
||||
import org.springframework.data.release.git.VersionTags;
|
||||
import org.springframework.data.release.gradle.GradleOperations;
|
||||
import org.springframework.data.release.maven.MavenOperations;
|
||||
import org.springframework.data.release.misc.ReleaseOperations;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Phase;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
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;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@CliComponent
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
public class ReleaseCommands implements CommandMarker {
|
||||
|
||||
private final MavenOperations maven;
|
||||
private final GradleOperations gradle;
|
||||
private final GitOperations git;
|
||||
private final ReleaseOperations misc;
|
||||
private final DocumentationOperations docs;
|
||||
private final DeploymentOperations deployment;
|
||||
private final BuildOperations build;
|
||||
|
||||
@CliCommand("release predict")
|
||||
public String predictTrainAndIteration() throws Exception {
|
||||
@@ -64,20 +68,6 @@ public class ReleaseCommands implements CommandMarker {
|
||||
findFirst().map(Train::getName).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the distribution of release artifacts for all projects.
|
||||
*
|
||||
* @param trainName
|
||||
* @param iterationName
|
||||
* @throws Exception
|
||||
*/
|
||||
@CliCommand("release distribute")
|
||||
public void distribute(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
|
||||
|
||||
git.checkout(iteration);
|
||||
maven.triggerDistributionBuild(iteration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the release of the given iteration of the given train.
|
||||
*
|
||||
@@ -92,22 +82,73 @@ public class ReleaseCommands implements CommandMarker {
|
||||
|
||||
misc.prepareChangelogs(iteration);
|
||||
misc.updateResources(iteration);
|
||||
docs.updateDockbookIncludes(iteration);
|
||||
|
||||
maven.updatePom(iteration, Phase.PREPARE);
|
||||
gradle.updateProject(iteration, Phase.PREPARE);
|
||||
build.updateProjectDescriptors(iteration, Phase.PREPARE);
|
||||
|
||||
git.commit(iteration, "Prepare %s.", null);
|
||||
git.commit(iteration, "Prepare %s.");
|
||||
}
|
||||
|
||||
@CliCommand(value = "release build")
|
||||
public void buildRelease(@CliOption(key = "", mandatory = true) TrainIteration iteration, //
|
||||
@CliOption(key = "project", mandatory = false) String projectName) throws Exception {
|
||||
|
||||
if (projectName != null) {
|
||||
|
||||
Project project = Projects.byName(projectName);
|
||||
ModuleIteration module = iteration.getModule(project);
|
||||
|
||||
DeploymentInformation information = build.performRelease(module);
|
||||
deployment.promote(information);
|
||||
|
||||
} else {
|
||||
|
||||
List<DeploymentInformation> deploymentInformation = build.performRelease(iteration);
|
||||
git.commit(iteration, "Release version %s.");
|
||||
deploymentInformation.forEach(deployment::promote);
|
||||
|
||||
build.prepareVersions(iteration, Phase.CLEANUP);
|
||||
git.commit(iteration, "Prepare next development iteration.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Concludes the release of the given {@link TrainIteration}.
|
||||
*
|
||||
* @param iteration
|
||||
* @throws Exception
|
||||
*/
|
||||
@CliCommand(value = "release conclude")
|
||||
public void conclude(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
|
||||
|
||||
Assert.notNull(iteration, "Train iteration must not be null!");
|
||||
|
||||
// Tag release
|
||||
git.tagRelease(iteration);
|
||||
|
||||
maven.updatePom(iteration, Phase.CLEANUP);
|
||||
gradle.updateProject(iteration, Phase.CLEANUP);
|
||||
// Prepare master branch
|
||||
build.updateProjectDescriptors(iteration, Phase.CLEANUP);
|
||||
git.commit(iteration, "After release cleanups.");
|
||||
|
||||
git.commit(iteration, "After release cleanups.", null);
|
||||
// Prepare maintenance branches
|
||||
git.checkout(iteration);
|
||||
git.createMaintenanceBranches(iteration);
|
||||
|
||||
build.updateProjectDescriptors(iteration, Phase.MAINTENANCE);
|
||||
build.prepareVersions(iteration, Phase.MAINTENANCE);
|
||||
git.commit(iteration, "Prepare next development iteration.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the distribution of release artifacts for all projects.
|
||||
*
|
||||
* @param trainName
|
||||
* @param iterationName
|
||||
* @throws Exception
|
||||
*/
|
||||
@CliCommand("release distribute")
|
||||
public void distribute(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
|
||||
|
||||
git.checkout(iteration);
|
||||
build.distributeResources(iteration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,6 @@ public class TrainIterationConverter implements Converter<TrainIteration> {
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.deployment;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* A client to interact with Artifactory.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
class ArtifactoryClient {
|
||||
|
||||
private final RestOperations template;
|
||||
private final Logger logger;
|
||||
private final DeploymentProperties properties;
|
||||
|
||||
/**
|
||||
* Triggers the promotion of the artifacts identified by the given {@link DeploymentInformation}.
|
||||
*
|
||||
* @param information must not be {@literal null}.
|
||||
*/
|
||||
public void promote(DeploymentInformation information) {
|
||||
|
||||
Assert.notNull(information, "DeploymentInformation must not be null!");
|
||||
|
||||
ModuleIteration module = information.getModule();
|
||||
URI uri = properties.getServer().getPromotionResource(information);
|
||||
|
||||
logger.log(module, "Promoting %s %s from %s to %s.", information.getBuildName(), information.getBuildNumber(),
|
||||
properties.getStagingRepository(), information.getTargetRepository());
|
||||
|
||||
try {
|
||||
template.postForEntity(uri, new PromotionRequest(information.getTargetRepository()), String.class);
|
||||
} catch (HttpClientErrorException o_O) {
|
||||
handle(o_O, module);
|
||||
}
|
||||
}
|
||||
|
||||
private void handle(HttpClientErrorException o_O, ModuleIteration module) {
|
||||
|
||||
try {
|
||||
|
||||
logger.log(module, "Promotion failed!");
|
||||
|
||||
Errors errors = new ObjectMapper().readValue(o_O.getResponseBodyAsByteArray(), Errors.class);
|
||||
errors.getErrors().forEach(error -> logger.log(module, error));
|
||||
errors.getMessages().forEach(message -> logger.log(module, message));
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteArtifacts(DeploymentInformation information) {
|
||||
template.delete(properties.getServer().getDeleteBuildResource(information));
|
||||
}
|
||||
|
||||
@Value
|
||||
private static class PromotionRequest {
|
||||
String targetRepo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.deployment;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Configuration to set up deployment components.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
class DeploymentConfiguration {
|
||||
|
||||
@Autowired DeploymentProperties properties;
|
||||
|
||||
@Bean
|
||||
public ArtifactoryClient client(Logger logger) {
|
||||
return new ArtifactoryClient(artifactoryRestTemplate(), logger, properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestTemplate artifactoryRestTemplate() {
|
||||
|
||||
RestTemplate template = new RestTemplate();
|
||||
template.setInterceptors(Arrays.asList(new AuthenticatingClientHttpRequestInterceptor(properties.getApiKey())));
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class AuthenticatingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private final @NonNull String apiKey;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.http.client.ClientHttpRequestInterceptor#intercept(org.springframework.http.HttpRequest, byte[], org.springframework.http.client.ClientHttpRequestExecution)
|
||||
*/
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
|
||||
throws IOException {
|
||||
|
||||
request.getHeaders().add("X-Api-Key", apiKey);
|
||||
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.deployment;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
|
||||
/**
|
||||
* Information about a deployment.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class DeploymentInformation {
|
||||
|
||||
private static UriTemplate REPOSITORY_TEMPLATE = new UriTemplate(
|
||||
"artifactory::default::{server};build.number={buildNumber};build.name={buildName}");
|
||||
|
||||
private final @Getter @NonNull ModuleIteration module;
|
||||
private final @NonNull DeploymentProperties properties;
|
||||
|
||||
/**
|
||||
* Returns a unique build number for this particular deployment.
|
||||
*/
|
||||
private final @Getter String buildNumber = String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC));
|
||||
|
||||
/**
|
||||
* Returns the name of the build.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getBuildName() {
|
||||
return module.getProject().getFullName().concat(" - Release");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the repository to deploy to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getTargetRepository() {
|
||||
return properties.getRepositoryPrefix()
|
||||
.concat(module.getIteration().isPublic() ? "libs-release-local" : "libs-milestone-local");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full URL to be used as deployment target.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDeploymentTargetUrl() {
|
||||
|
||||
Map<String, Object> parameters = new HashMap<>();
|
||||
parameters.put("server", properties.getStagingRepositoryUrl());
|
||||
parameters.putAll(getBuildInfoParameters());
|
||||
|
||||
return REPOSITORY_TEMPLATE.expand(parameters).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Map} to expand a URI template to access the build information.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> getBuildInfoParameters() {
|
||||
|
||||
Map<String, Object> parameters = new HashMap<>();
|
||||
parameters.put("buildNumber", buildNumber);
|
||||
parameters.put("buildName", getBuildName());
|
||||
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.deployment;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Deployment functionality.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
public class DeploymentOperations {
|
||||
|
||||
private final ArtifactoryClient client;
|
||||
|
||||
/**
|
||||
* Promotes the artifacts identified by the given {@link DeploymentInformation}.
|
||||
*
|
||||
* @param information must not be {@literal null}.
|
||||
*/
|
||||
public void promote(DeploymentInformation information) {
|
||||
|
||||
Assert.notNull(information, "DeploymentInformation must not be null!");
|
||||
|
||||
client.promote(information);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.deployment;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "deployment")
|
||||
public class DeploymentProperties {
|
||||
|
||||
/**
|
||||
* The Artifactory host.
|
||||
*/
|
||||
private Server server;
|
||||
|
||||
/**
|
||||
* The deployer's username.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* The deployer's password.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* The repository to deploy the artifacts to.
|
||||
*/
|
||||
private String stagingRepository;
|
||||
|
||||
private String repositoryPrefix = "";
|
||||
|
||||
public String getStagingRepository() {
|
||||
return repositoryPrefix.concat(stagingRepository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URI of the staging repository.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getStagingRepositoryUrl() {
|
||||
return server.getUri().toString().concat("/").concat(stagingRepository);
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Server {
|
||||
|
||||
private static final String PROMOTION_RESOURCE = "/api/build/promote/{buildName}/{buildNumber}";
|
||||
private static final String DELETE_BUILD_RESOURCE = "/api/build/{buildName}?buildNumbers={buildNumber}&artifacts=1";
|
||||
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* Returns the URI to the resource that a promotion can be triggered at.
|
||||
*
|
||||
* @param information must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public URI getPromotionResource(DeploymentInformation information) {
|
||||
|
||||
Assert.notNull(information, "DeploymentInformation must not be null!");
|
||||
|
||||
return new UriTemplate(uri.concat(PROMOTION_RESOURCE)).expand(information.getBuildInfoParameters());
|
||||
}
|
||||
|
||||
public URI getDeleteBuildResource(DeploymentInformation information) {
|
||||
|
||||
return new UriTemplate(uri.concat(DELETE_BUILD_RESOURCE)).expand(information.getBuildInfoParameters());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2015 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.deployment;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Data
|
||||
public class Errors {
|
||||
|
||||
private List<Error> errors = new ArrayList<>();
|
||||
private List<Message> messages = new ArrayList<>();
|
||||
|
||||
public List<Error> getErrors(Errors this) {
|
||||
return errors;
|
||||
}
|
||||
|
||||
@Data
|
||||
static class Error {
|
||||
|
||||
private String message;
|
||||
private int status;
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s - %s", status, message);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
static class Message {
|
||||
|
||||
private String level, message;
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s - %s", level, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.release.docs;
|
||||
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -24,7 +25,6 @@ import org.springframework.data.release.git.GitProject;
|
||||
import org.springframework.data.release.git.Tag;
|
||||
import org.springframework.data.release.git.VersionTags;
|
||||
import org.springframework.data.release.io.Workspace;
|
||||
import org.springframework.data.release.io.Workspace.LineCallback;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
@@ -34,7 +34,7 @@ import org.springframework.stereotype.Component;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
public class DocumentationOperations {
|
||||
|
||||
private static final String INDEX_LOCATION = "/src/docbkx/index.xml";
|
||||
@@ -61,16 +61,12 @@ public class DocumentationOperations {
|
||||
continue;
|
||||
}
|
||||
|
||||
workspace.processFile(INDEX_LOCATION, project, new LineCallback() {
|
||||
workspace.processFile(INDEX_LOCATION, project, (line, number) -> {
|
||||
|
||||
@Override
|
||||
public String doWith(String line, long number) {
|
||||
boolean isInclude = line.contains("xi:include");
|
||||
boolean containsGitRepo = line.contains(gitProject.getRepositoryName());
|
||||
|
||||
boolean isInclude = line.contains("xi:include");
|
||||
boolean containsGitRepo = line.contains(gitProject.getRepositoryName());
|
||||
|
||||
return isInclude && containsGitRepo ? line.replace(previousTag.toString(), newTag.toString()) : line;
|
||||
}
|
||||
return isInclude && containsGitRepo ? line.replace(previousTag.toString(), newTag.toString()) : line;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.release.git;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.release.model.IterationVersion;
|
||||
import org.springframework.data.release.model.Version;
|
||||
import org.springframework.data.release.model.VersionAware;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -27,8 +29,8 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
class Branch {
|
||||
|
||||
public static final Branch MASTER = new Branch("master");
|
||||
@@ -43,17 +45,30 @@ class Branch {
|
||||
*/
|
||||
public static Branch from(IterationVersion iterationVersion) {
|
||||
|
||||
Assert.notNull(iterationVersion, "Iteration versoin must not be null!");
|
||||
Assert.notNull(iterationVersion, "Iteration version must not be null!");
|
||||
|
||||
Version version = iterationVersion.getVersion();
|
||||
|
||||
if (iterationVersion.getIteration().isServiceIteration()) {
|
||||
return new Branch(version.toString().concat(".x"));
|
||||
if (iterationVersion.isServiceIteration()) {
|
||||
return from((VersionAware) iterationVersion);
|
||||
}
|
||||
|
||||
return MASTER;
|
||||
}
|
||||
|
||||
public static Branch from(VersionAware versioned) {
|
||||
return from(versioned.getVersion());
|
||||
}
|
||||
|
||||
private static Branch from(Version version) {
|
||||
return from(version.toString().concat(".x"));
|
||||
}
|
||||
|
||||
private static Branch from(String name) {
|
||||
|
||||
int slashIndex = name.lastIndexOf('/');
|
||||
|
||||
return new Branch(slashIndex != -1 ? name.substring(slashIndex + 1) : name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.data.release.git;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.release.jira.Ticket;
|
||||
|
||||
/**
|
||||
@@ -29,7 +31,7 @@ public class Commit {
|
||||
|
||||
private final Ticket ticket;
|
||||
private final String summary;
|
||||
private final String details;
|
||||
private final Optional<String> details;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -42,10 +44,10 @@ public class Commit {
|
||||
|
||||
builder.append(ticket.getId()).append(" - ").append(summary).append("\n");
|
||||
|
||||
if (details != null) {
|
||||
details.ifPresent(it -> {
|
||||
builder.append("\n");
|
||||
builder.append(details).append("\n");
|
||||
}
|
||||
builder.append(it).append("\n");
|
||||
});
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,12 @@ public class GitCommands implements CommandMarker {
|
||||
|
||||
private final GitOperations git;
|
||||
|
||||
@CliCommand("git checkout")
|
||||
@CliCommand("git co train")
|
||||
public void checkout(@CliOption(key = "", mandatory = true) Train train) throws Exception {
|
||||
git.checkout(train);
|
||||
}
|
||||
|
||||
@CliCommand("git co")
|
||||
public void checkout(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
|
||||
git.checkout(iteration);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -19,8 +19,8 @@ import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.eclipse.jgit.api.CheckoutCommand;
|
||||
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
|
||||
@@ -86,14 +86,49 @@ public class GitOperations {
|
||||
|
||||
logger.log(module, "git reset --hard origin/%s", branch);
|
||||
|
||||
git.reset().//
|
||||
setMode(ResetType.HARD).//
|
||||
setRef("origin/".concat(branch.toString())).//
|
||||
call();
|
||||
reset(git, branch.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks out all projects of the given {@link TrainIteration}.
|
||||
*
|
||||
* @param iteration
|
||||
* @throws Exception
|
||||
*/
|
||||
public void checkout(Train train) {
|
||||
|
||||
update(train);
|
||||
|
||||
ExecutionUtils.run(train, module -> {
|
||||
|
||||
try (Git git = new Git(getRepository(module.getProject()))) {
|
||||
|
||||
Branch branch = Branch.from(module);
|
||||
CheckoutCommand command = git.checkout().setName(branch.toString());
|
||||
|
||||
if (!branchExists(module.getProject(), branch)) {
|
||||
|
||||
logger.log(module.getProject(), "git checkout -b %s --track origin/%s", branch, branch);
|
||||
command.setCreateBranch(true).//
|
||||
setStartPoint("origin/".concat(branch.toString())).//
|
||||
call();
|
||||
|
||||
} else {
|
||||
|
||||
logger.log(module.getProject(), "git checkout %s", branch);
|
||||
command.call();
|
||||
}
|
||||
|
||||
logger.log(module.getProject(), "git reset --hard origin/%s", branch);
|
||||
reset(git, branch.toString());
|
||||
}
|
||||
});
|
||||
|
||||
logger.log(train, "Successfully checked out projects.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks out all projects of the given {@link TrainIteration}.
|
||||
*
|
||||
@@ -120,7 +155,7 @@ public class GitOperations {
|
||||
|
||||
logger.log(module, "git checkout %s", tag);
|
||||
|
||||
git.checkout().setStartPoint(tag.toString());
|
||||
git.checkout().setStartPoint(tag.toString()).call();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -197,12 +232,13 @@ public class GitOperations {
|
||||
if (workspace.hasProjectDirectory(project)) {
|
||||
|
||||
logger.log(project, "Found existing repository %s. Obtaining latest changes…", repositoryName);
|
||||
logger.log(project, "git checkout master && git reset --hard && git fetch --tags && git pull origin master");
|
||||
logger.log(project,
|
||||
"git checkout master && git reset --hard origin/master && git fetch --tags && git pull origin master");
|
||||
|
||||
checkout(project, Branch.MASTER);
|
||||
|
||||
git.reset().setMode(ResetType.HARD).call();
|
||||
git.fetch().setTagOpt(TagOpt.FETCH_TAGS);
|
||||
reset(git, "master");
|
||||
git.fetch().setTagOpt(TagOpt.FETCH_TAGS).call();
|
||||
git.pull().call();
|
||||
|
||||
} else {
|
||||
@@ -256,6 +292,18 @@ public class GitOperations {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits all changes currently made to all modules of the given {@link TrainIteration}. The summary can contain a
|
||||
* single {@code %s} placeholder which the version of the current module will get replace into.
|
||||
*
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @param summary must not be {@literal null} or empty.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void commit(TrainIteration iteration, String summary) throws Exception {
|
||||
commit(iteration, summary, Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits all changes currently made to all modules of the given {@link TrainIteration}. The summary can contain a
|
||||
* single {@code %s} placeholder which the version of the current module will get replace into.
|
||||
@@ -265,7 +313,7 @@ public class GitOperations {
|
||||
* @param details can be {@literal null} or empty.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void commit(TrainIteration iteration, String summary, String details) throws Exception {
|
||||
public void commit(TrainIteration iteration, String summary, Optional<String> details) throws Exception {
|
||||
|
||||
Assert.notNull(iteration, "Train iteration must not be null!");
|
||||
Assert.hasText(summary, "Summary must not be null or empty!");
|
||||
@@ -273,19 +321,22 @@ public class GitOperations {
|
||||
ExecutionUtils.run(iteration, module -> commit(module, expandSummary(summary, module, iteration), details));
|
||||
}
|
||||
|
||||
private static String expandSummary(String summary, ModuleIteration module, TrainIteration iteration) {
|
||||
|
||||
if (!summary.contains("%s")) {
|
||||
return summary;
|
||||
}
|
||||
|
||||
return String.format(summary,
|
||||
ArtifactVersion.of(module).toString().concat(String.format(" (%s)", iteration.toString())));
|
||||
/**
|
||||
* Commits the given files for the given {@link ModuleIteration} using the given summary for the commit message. If no
|
||||
* files are given, all pending changes are committed.
|
||||
*
|
||||
* @param module must not be {@literal null}.
|
||||
* @param summary must not be {@literal null} or empty.
|
||||
* @param files can be empty.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void commit(ModuleIteration module, String summary, File... files) throws Exception {
|
||||
commit(module, summary, Optional.empty(), files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits the given files for the given {@link ModuleIteration} using the given summary and details for the commit
|
||||
* message. If no files are given, all pending changes are commited.
|
||||
* message. If no files are given, all pending changes are committed.
|
||||
*
|
||||
* @param module must not be {@literal null}.
|
||||
* @param summary must not be {@literal null} or empty.
|
||||
@@ -293,7 +344,7 @@ public class GitOperations {
|
||||
* @param files can be empty.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void commit(ModuleIteration module, String summary, String details, File... files) throws Exception {
|
||||
public void commit(ModuleIteration module, String summary, Optional<String> details, File... files) throws Exception {
|
||||
|
||||
Assert.notNull(module, "Module iteration must not be null!");
|
||||
Assert.hasText(summary, "Summary must not be null or empty!");
|
||||
@@ -318,6 +369,55 @@ public class GitOperations {
|
||||
}
|
||||
}
|
||||
|
||||
public void checkout(Project project, Branch branch) throws Exception {
|
||||
|
||||
try (Git git = new Git(getRepository(project))) {
|
||||
|
||||
Ref ref = git.getRepository().getRef(branch.toString());
|
||||
CheckoutCommand checkout = git.checkout().setName(branch.toString());
|
||||
|
||||
if (ref == null) {
|
||||
|
||||
checkout.setCreateBranch(true).//
|
||||
setUpstreamMode(SetupUpstreamMode.TRACK).//
|
||||
setStartPoint("origin/".concat(branch.toString()));
|
||||
}
|
||||
|
||||
checkout.call();
|
||||
}
|
||||
}
|
||||
|
||||
public void createMaintenanceBranches(TrainIteration iteration) throws Exception {
|
||||
|
||||
checkout(iteration);
|
||||
|
||||
ExecutionUtils.run(iteration, module -> {
|
||||
Branch branch = createMaintenanceBranch(module);
|
||||
checkout(module.getProject(), branch);
|
||||
});
|
||||
}
|
||||
|
||||
private Branch createMaintenanceBranch(ModuleIteration module) throws Exception {
|
||||
|
||||
try (Git git = new Git(getRepository(module.getProject()))) {
|
||||
|
||||
Branch branch = Branch.from(module);
|
||||
git.branchCreate().setName(branch.toString()).call();
|
||||
|
||||
return branch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ObjectId} of the commit that is considered the release commit. It is identified by the summary
|
||||
* starting with the release ticket identifier, followed by a dash separated by spaces and the key word
|
||||
* {@code Release}. To prevent skimming through the entire Git history, we expect such a commit to be found within the
|
||||
* 50 most recent commits.
|
||||
*
|
||||
* @param module
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private ObjectId getReleaseHash(ModuleIteration module) throws Exception {
|
||||
|
||||
Project project = module.getProject();
|
||||
@@ -329,9 +429,7 @@ public class GitOperations {
|
||||
|
||||
for (RevCommit commit : git.log().setMaxCount(50).call()) {
|
||||
|
||||
String summary = commit.getShortMessage();
|
||||
|
||||
if (summary.startsWith(trigger)) {
|
||||
if (commit.getShortMessage().startsWith(trigger)) {
|
||||
return commit.getId();
|
||||
}
|
||||
}
|
||||
@@ -351,36 +449,17 @@ public class GitOperations {
|
||||
*/
|
||||
private Tag findTagFor(Project project, ArtifactVersion version) {
|
||||
|
||||
return StreamSupport.stream(getTags(project).spliterator(), false).//
|
||||
return getTags(project).stream().//
|
||||
filter(tag -> tag.toArtifactVersion().map(it -> it.equals(version)).orElse(false)).//
|
||||
findFirst().orElseThrow(() -> new IllegalArgumentException(
|
||||
String.format("No tag found for version %s of project %s!", version, project)));
|
||||
}
|
||||
|
||||
public void checkout(Project project, Branch branch) throws Exception {
|
||||
|
||||
try (Git git = new Git(getRepository(project))) {
|
||||
|
||||
Ref ref = git.getRepository().getRef(branch.toString());
|
||||
CheckoutCommand checkout = git.checkout().setName(branch.toString());
|
||||
|
||||
if (ref == null) {
|
||||
|
||||
checkout.setCreateBranch(true).//
|
||||
setUpstreamMode(SetupUpstreamMode.TRACK).//
|
||||
setStartPoint("origin/".concat(branch.toString()));
|
||||
}
|
||||
|
||||
checkout.call();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Repository getRepository(Project project) throws IOException {
|
||||
return FileRepositoryBuilder.create(workspace.getFile(".git", project));
|
||||
}
|
||||
|
||||
public void clone(Project project) throws Exception {
|
||||
private void clone(Project project) throws Exception {
|
||||
|
||||
Git git = Git.cloneRepository().//
|
||||
setURI(getGitProject(project).getProjectUri()).//
|
||||
@@ -390,4 +469,23 @@ public class GitOperations {
|
||||
git.checkout().setName(Branch.MASTER.toString()).//
|
||||
call();
|
||||
}
|
||||
|
||||
private boolean branchExists(Project project, Branch branch) {
|
||||
|
||||
try (Git git = new Git(getRepository(project))) {
|
||||
|
||||
return git.getRepository().getRef(branch.toString()) != null;
|
||||
|
||||
} catch (Exception o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
|
||||
private static void reset(Git git, String name) throws Exception {
|
||||
git.reset().setMode(ResetType.HARD).setRef("origin/".concat(name)).call();
|
||||
}
|
||||
|
||||
private static String expandSummary(String summary, ModuleIteration module, TrainIteration iteration) {
|
||||
return summary.contains("%s") ? String.format(summary, module.getMediumVersionString()) : summary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,4 +57,8 @@ public class GitProperties {
|
||||
public CredentialsProvider getCredentials() {
|
||||
return new UsernamePasswordCredentialsProvider(username, password);
|
||||
}
|
||||
|
||||
public String getAuthenticationHeader() {
|
||||
return username.concat(":").concat(password);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.release.Streamable;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -31,7 +32,7 @@ import org.springframework.util.Assert;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public class VersionTags implements Iterable<Tag> {
|
||||
public class VersionTags implements Streamable<Tag> {
|
||||
|
||||
private final List<Tag> tags;
|
||||
|
||||
|
||||
@@ -1,139 +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.gradle;
|
||||
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.io.Workspace;
|
||||
import org.springframework.data.release.io.Workspace.LineCallback;
|
||||
import org.springframework.data.release.maven.Repository;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Phase;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Gradle specific operations.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
public class GradleOperations {
|
||||
|
||||
private static final String BUILD_GRADLE = "build.gradle";
|
||||
private static final String GRADLE_PROPERTIES = "gradle.properties";
|
||||
private static final String COMMONS_PROPERTY = "springDataCommonsVersion";
|
||||
private static final String BUILD_PROPERTY = "springDataBuildVersion";
|
||||
|
||||
private final Workspace workspace;
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* Updates all Gradle projects contained in the release.
|
||||
*
|
||||
* @param iteration
|
||||
* @param phase
|
||||
* @throws Exception
|
||||
*/
|
||||
public void updateProject(TrainIteration iteration, final Phase phase) throws Exception {
|
||||
|
||||
final Repository repository = new Repository(iteration.getIteration());
|
||||
final ArtifactVersion commonsVersion = iteration.getModuleVersion(COMMONS);
|
||||
final ArtifactVersion buildVersion = iteration.getModuleVersion(BUILD);
|
||||
|
||||
for (ModuleIteration module : iteration.getModulesExcept(BUILD)) {
|
||||
|
||||
final Project project = module.getProject();
|
||||
|
||||
if (!isGradleProject(project)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
workspace.processFile(GRADLE_PROPERTIES, project, new LineCallback() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.io.Workspace.LineCallback#doWith(java.lang.String, long)
|
||||
*/
|
||||
@Override
|
||||
public String doWith(String line, long number) {
|
||||
|
||||
if (line.contains(COMMONS_PROPERTY)) {
|
||||
|
||||
ArtifactVersion version = phase.equals(Phase.PREPARE) ? commonsVersion
|
||||
: commonsVersion.getNextDevelopmentVersion();
|
||||
|
||||
logger.log(project, "Setting Spring Data Commons version in %s to %s.", GRADLE_PROPERTIES, version);
|
||||
return String.format("%s=%s", COMMONS_PROPERTY, version);
|
||||
}
|
||||
|
||||
if (line.contains(BUILD_PROPERTY)) {
|
||||
|
||||
ArtifactVersion version = phase.equals(Phase.PREPARE) ? buildVersion
|
||||
: buildVersion.getNextDevelopmentVersion();
|
||||
|
||||
logger.log(project, "Setting Spring Data Build version in %s to %s.", GRADLE_PROPERTIES, version);
|
||||
return String.format("%s=%s", BUILD_PROPERTY, version);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
});
|
||||
|
||||
workspace.processFile(BUILD_GRADLE, project, new LineCallback() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.io.Workspace.LineCallback#doWith(java.lang.String, long)
|
||||
*/
|
||||
@Override
|
||||
public String doWith(String line, long number) {
|
||||
|
||||
String snapshotUrl = repository.getSnapshotUrl();
|
||||
String releaseUrl = repository.getUrl();
|
||||
String message = "Switching to Spring repository %s";
|
||||
|
||||
switch (phase) {
|
||||
case CLEANUP:
|
||||
logger.log(project, message, snapshotUrl);
|
||||
return line.contains(releaseUrl) ? line.replace(releaseUrl, snapshotUrl) : line;
|
||||
case PREPARE:
|
||||
default:
|
||||
logger.log(project, message, releaseUrl);
|
||||
return line.contains(snapshotUrl) ? line.replace(snapshotUrl, releaseUrl) : line;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given project is a Gradle project (checks for the presence of a build.gradle file).
|
||||
*
|
||||
* @param project
|
||||
* @return
|
||||
*/
|
||||
private boolean isGradleProject(Project project) {
|
||||
return workspace.getFile(BUILD_GRADLE, project).exists();
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.release.io;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
@@ -35,22 +33,35 @@ import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of {@link OsCommandOperations} interface.
|
||||
* Implementation of {@link OsOperations} interface.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @author Oliver Gierke
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
class CommonsExecOsCommandOperations implements OsCommandOperations {
|
||||
class CommonsExecOsCommandOperations implements OsOperations {
|
||||
|
||||
private static final Map<String, String> ENVIRONMENT = new HashMap<>();
|
||||
|
||||
private final Workspace workspace;
|
||||
private final Logger logger;
|
||||
private final File javaHome;
|
||||
|
||||
@Autowired
|
||||
public CommonsExecOsCommandOperations(Workspace workspace, Logger logger, IoProperties properties) throws Exception {
|
||||
|
||||
this.workspace = workspace;
|
||||
this.logger = logger;
|
||||
this.javaHome = detectJavaHome(properties);
|
||||
|
||||
Assert.isTrue(javaHome.exists(), String.format("Java home %s does not exist!", javaHome.getAbsolutePath()));
|
||||
|
||||
ENVIRONMENT.put("JAVA_HOME", javaHome.getAbsolutePath());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -133,20 +144,24 @@ class CommonsExecOsCommandOperations implements OsCommandOperations {
|
||||
new CommandResult(resultHandler.getExitValue(), writer.toString(), resultHandler.getException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@code JAVA_HOME} to the ENVIRONMENT variables looking up the path to a Java 7.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
// @PostConstruct
|
||||
public void initialize() throws Exception {
|
||||
public File getJavaHome() {
|
||||
return javaHome;
|
||||
}
|
||||
|
||||
String javaHome = executeCommand("/usr/libexec/java_home -F -v 1.8 -a x86_64 -d64").get().getOutput();
|
||||
private File detectJavaHome(IoProperties properties) throws Exception {
|
||||
|
||||
if (javaHome.endsWith("\n")) {
|
||||
javaHome = javaHome.substring(0, javaHome.length() - 1);
|
||||
File javaHome = properties.getJavaHome();
|
||||
|
||||
if (javaHome != null) {
|
||||
return javaHome;
|
||||
}
|
||||
|
||||
ENVIRONMENT.put("JAVA_HOME", javaHome);
|
||||
String javaHomePath = executeCommand("/usr/libexec/java_home -F -v 1.8 -a x86_64 -d64").get().getOutput();
|
||||
|
||||
if (javaHomePath.endsWith("\n")) {
|
||||
javaHomePath = javaHomePath.substring(0, javaHomePath.length() - 1);
|
||||
}
|
||||
|
||||
return new File(javaHomePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,17 +30,19 @@ import org.springframework.stereotype.Component;
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "io")
|
||||
public class IoProperties {
|
||||
class IoProperties {
|
||||
|
||||
private String workDir;
|
||||
private File workDir, javaHome;
|
||||
|
||||
public void setWorkDir(String workDir) {
|
||||
|
||||
this.workDir = workDir.replace("~", System.getProperty("user.home"));
|
||||
log.info(String.format("Using %s as working directory!", workDir));
|
||||
this.workDir = new File(workDir.replace("~", System.getProperty("user.home")));
|
||||
}
|
||||
|
||||
public File getWorkDir() {
|
||||
return new File(workDir);
|
||||
public void setJavaHome(String javaHome) {
|
||||
|
||||
log.info(String.format("Using %s as Java home!", javaHome));
|
||||
this.workDir = new File(javaHome.replace("~", System.getProperty("user.home")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.release.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@@ -26,7 +27,7 @@ import org.springframework.data.release.model.Project;
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface OsCommandOperations {
|
||||
public interface OsOperations {
|
||||
|
||||
/**
|
||||
* Attempts the execution of a commands and delegates the output to the standard logger.
|
||||
@@ -41,4 +42,6 @@ public interface OsCommandOperations {
|
||||
Future<CommandResult> executeWithOutput(String command, Project project) throws IOException;
|
||||
|
||||
String executeForResult(String command, Project project) throws Exception;
|
||||
|
||||
File getJavaHome();
|
||||
}
|
||||
@@ -15,17 +15,23 @@
|
||||
*/
|
||||
package org.springframework.data.release.io;
|
||||
|
||||
import static org.springframework.data.release.utils.StreamUtils.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -44,6 +50,7 @@ public class Workspace {
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
private final IoProperties ioProperties;
|
||||
private final ResourcePatternResolver resolver;
|
||||
|
||||
/**
|
||||
* Returns the current working directory.
|
||||
@@ -93,7 +100,23 @@ public class Workspace {
|
||||
return new File(getProjectDirectory(project), name);
|
||||
}
|
||||
|
||||
public boolean processFile(String filename, Project project, LineCallback callback) throws Exception {
|
||||
public Stream<File> getFiles(String pattern, Project project) {
|
||||
|
||||
File projectDirectory = getProjectDirectory(project);
|
||||
String patternToLookup = String.format("file:%s/%s", projectDirectory.getAbsolutePath(), pattern);
|
||||
|
||||
try {
|
||||
return Arrays.stream(resolver.getResources(patternToLookup)).map(wrap(Resource::getFile));
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean processFiles(String pattern, Project project, LineCallback callback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean processFile(String filename, Project project, LineCallback callback) {
|
||||
|
||||
File file = getFile(filename, project);
|
||||
|
||||
@@ -115,9 +138,13 @@ public class Workspace {
|
||||
builder.append(result).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
writeContentToFile(filename, project, builder.toString());
|
||||
|
||||
} catch (Exception o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
|
||||
writeContentToFile(filename, project, builder.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,6 @@ class GitHubIssue {
|
||||
}
|
||||
|
||||
public boolean isReleaseTicket(ModuleIteration module) {
|
||||
return title.contains("Release") && title.contains(module.getVersionString());
|
||||
return title.contains("Release") && title.contains(module.getShortVersionString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,18 +18,20 @@ package org.springframework.data.release.jira;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.data.release.git.GitProject;
|
||||
import org.springframework.data.release.git.GitProperties;
|
||||
import org.springframework.data.release.git.GitServer;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
@@ -39,16 +41,16 @@ import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Tracker;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
@RequiredArgsConstructor
|
||||
class GitHubIssueTracker implements IssueTracker {
|
||||
|
||||
private static final String MILESTONE_URI = "https://api.github.com/repos/spring-projects/{repoName}/milestones?state={state}";
|
||||
@@ -59,6 +61,7 @@ class GitHubIssueTracker implements IssueTracker {
|
||||
|
||||
private final RestOperations operations;
|
||||
private final Logger logger;
|
||||
private final GitProperties properties;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -112,7 +115,9 @@ class GitHubIssueTracker implements IssueTracker {
|
||||
parameters.put("repoName", repositoryName);
|
||||
parameters.put("id", milestone.getNumber());
|
||||
|
||||
return operations.exchange(URI_TEMPLATE, HttpMethod.GET, null, ISSUES_TYPE, parameters).getBody();
|
||||
return operations
|
||||
.exchange(URI_TEMPLATE, HttpMethod.GET, new HttpEntity<>(getAuthenticationHeaders()), ISSUES_TYPE, parameters)
|
||||
.getBody();
|
||||
}
|
||||
|
||||
private GitHubMilestone findMilestone(ModuleIteration module, String repositoryName) {
|
||||
@@ -127,13 +132,13 @@ class GitHubIssueTracker implements IssueTracker {
|
||||
|
||||
logger.log(module, "Looking up milestone from %s…", milestoneUri);
|
||||
|
||||
List<GitHubMilestone> exchange = operations
|
||||
.exchange(MILESTONE_URI, HttpMethod.GET, null, MILESTONES_TYPE, parameters).getBody();
|
||||
List<GitHubMilestone> exchange = operations.exchange(MILESTONE_URI, HttpMethod.GET,
|
||||
new HttpEntity<>(getAuthenticationHeaders()), MILESTONES_TYPE, parameters).getBody();
|
||||
|
||||
GitHubMilestone milestone = null;
|
||||
|
||||
for (GitHubMilestone candidate : exchange) {
|
||||
if (candidate.getTitle().contains(module.getVersionString())) {
|
||||
if (candidate.getTitle().contains(module.getShortVersionString())) {
|
||||
milestone = candidate;
|
||||
}
|
||||
}
|
||||
@@ -144,7 +149,19 @@ class GitHubIssueTracker implements IssueTracker {
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format("No milestone found containing %s!", module.getVersionString()));
|
||||
throw new IllegalStateException(String.format("No milestone found containing %s!", module.getShortVersionString()));
|
||||
}
|
||||
|
||||
private HttpHeaders getAuthenticationHeaders() {
|
||||
|
||||
byte[] encodedAuth = Base64.getEncoder()
|
||||
.encode(properties.getAuthenticationHeader().getBytes(Charset.forName("US-ASCII")));
|
||||
String authHeader = "Basic " + new String(encodedAuth);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Authorization", authHeader);
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -23,10 +23,13 @@ import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.data.release.git.GitProperties;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.plugin.core.config.EnablePluginRegistries;
|
||||
import org.springframework.plugin.core.OrderAwarePluginRegistry;
|
||||
import org.springframework.plugin.core.PluginRegistry;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
@@ -37,15 +40,18 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
@PropertySource(value = "file:jira.properties", ignoreResourceNotFound = true)
|
||||
@EnablePluginRegistries({ IssueTracker.class })
|
||||
class JiraConfiguration {
|
||||
class IssueTrackerConfiguration {
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager() {
|
||||
return new ConcurrentMapCacheManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PluginRegistry<IssueTracker, Project> issueTrackers(List<? extends IssueTracker> plugins) {
|
||||
return OrderAwarePluginRegistry.create(plugins);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ObjectMapper jacksonObjectMapper() {
|
||||
|
||||
@@ -69,4 +75,14 @@ class JiraConfiguration {
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Jira jira(Logger logger) {
|
||||
return new Jira(restTemplate(), logger);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GitHubIssueTracker github(Logger logger, GitProperties properties) {
|
||||
return new GitHubIssueTracker(restTemplate(), logger, properties);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
@@ -40,15 +39,13 @@ import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
@RequiredArgsConstructor
|
||||
class Jira implements JiraConnector {
|
||||
|
||||
private static final String JIRA_HOST = "https://jira.spring.io";
|
||||
|
||||
@@ -17,10 +17,7 @@ package org.springframework.data.release.jira;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
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.Train;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
@@ -28,16 +25,7 @@ import org.springframework.data.release.model.Train;
|
||||
@Value
|
||||
class JiraVersion {
|
||||
|
||||
private final Module module;
|
||||
private final Train train;
|
||||
private final Iteration iteration;
|
||||
|
||||
public JiraVersion(ModuleIteration moduleIteration) {
|
||||
|
||||
this.module = moduleIteration.getModule();
|
||||
this.iteration = moduleIteration.getIteration();
|
||||
this.train = moduleIteration.getTrain();
|
||||
}
|
||||
private ModuleIteration module;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -45,15 +33,6 @@ class JiraVersion {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
Iteration iteration = this.iteration.isInitialIteration() && module.hasCustomFirstIteration() ? module
|
||||
.getCustomFirstIteration() : this.iteration;
|
||||
|
||||
if (iteration.isServiceIteration()) {
|
||||
return String.format("%s.%s (%s %s)", module.getVersion(), iteration.getBugfixValue(), train.getName(),
|
||||
iteration.getName());
|
||||
}
|
||||
|
||||
return String.format("%s %s (%s)", module.getVersion(), iteration.getName(), train.getName());
|
||||
return module.getMediumVersionString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ package org.springframework.data.release.jira;
|
||||
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -1,251 +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.maven;
|
||||
|
||||
import static org.springframework.data.release.model.Phase.*;
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
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.ModuleIteration;
|
||||
import org.springframework.data.release.model.Phase;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.data.release.utils.ExecutionUtils;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.xmlbeam.ProjectionFactory;
|
||||
import org.xmlbeam.io.XBFileIO;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
|
||||
public class MavenOperations {
|
||||
|
||||
private static final String POM_XML = "pom.xml";
|
||||
|
||||
private final Workspace workspace;
|
||||
private final ProjectionFactory projectionFactory;
|
||||
private final OsCommandOperations os;
|
||||
private final Logger logger;
|
||||
|
||||
public Pom getMavenProject(Project project) throws IOException {
|
||||
|
||||
File file = workspace.getFile(POM_XML, project);
|
||||
return projectionFactory.io().file(file).read(Pom.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the POM files for all Maven projects contained in the iteration:
|
||||
* <ol>
|
||||
* <li>Updates the BOM POM.</li>
|
||||
* <li>Updates the dependency version to Spring Data Commons to the current release version for all projects depending
|
||||
* on it.</li>
|
||||
* <li>Switches to the Spring release Maven repository.</li>
|
||||
* </ol>
|
||||
* If {@link Phase} is {@link Phase#CLEANUP} the changes will be rolled back.
|
||||
*
|
||||
* @param iteration must not be {@literal null}.
|
||||
* @param phase must not be {@literal null}.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void updatePom(TrainIteration iteration, final Phase phase) throws Exception {
|
||||
|
||||
Assert.notNull(iteration, "Train iteration must not be null!");
|
||||
Assert.notNull(phase, "Phase must not be null!");
|
||||
|
||||
updateBomPom(iteration, phase);
|
||||
|
||||
final Repository repository = new Repository(iteration.getIteration());
|
||||
final ArtifactVersion buildVersion = iteration.getModuleVersion(BUILD);
|
||||
final ArtifactVersion nextBuildVersion = buildVersion.getNextDevelopmentVersion();
|
||||
|
||||
// Fix version of shared resources to to-be-released version.
|
||||
execute(workspace.getFile("parent/pom.xml", BUILD), new PomCallback<ParentPom>() {
|
||||
|
||||
@Override
|
||||
public void doWith(ParentPom pom) {
|
||||
pom.setSharedResourcesVersion(phase.equals(PREPARE) ? buildVersion : nextBuildVersion);
|
||||
}
|
||||
});
|
||||
|
||||
for (ModuleIteration module : iteration.getModulesExcept(BUILD)) {
|
||||
|
||||
final Project project = module.getProject();
|
||||
|
||||
if (!isMavenProject(project)) {
|
||||
logger.log(module, "No pom.xml file found, skipping project.");
|
||||
continue;
|
||||
}
|
||||
|
||||
execute(workspace.getFile(POM_XML, project), new PomCallback<Pom>() {
|
||||
|
||||
@Override
|
||||
public void doWith(Pom pom) {
|
||||
|
||||
for (Project dependency : project.getDependencies()) {
|
||||
|
||||
String dependencyProperty = dependency.getDependencyProperty();
|
||||
|
||||
if (pom.getProperty(dependencyProperty) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ArtifactVersion dependencyVersion = iteration.getModuleVersion(dependency);
|
||||
ArtifactVersion version = CLEANUP.equals(phase) ? dependencyVersion.getNextDevelopmentVersion()
|
||||
: dependencyVersion;
|
||||
|
||||
logger.log(project, "Updating %s dependency version property %s to %s.", dependency.getFullName(),
|
||||
dependencyProperty, version);
|
||||
pom.setProperty(dependencyProperty, version);
|
||||
}
|
||||
|
||||
ArtifactVersion version = CLEANUP.equals(phase) ? nextBuildVersion : buildVersion;
|
||||
logger.log(project, "Updating Spring Data Build Parent version to %s.", version);
|
||||
pom.setParentVersion(version);
|
||||
|
||||
updateRepository(project, pom, repository, phase);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(TrainIteration iteration) throws Exception {
|
||||
|
||||
ExecutionUtils.run(iteration, module -> {
|
||||
|
||||
Project project = module.getProject();
|
||||
|
||||
if (BUILD.equals(project)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isMavenProject(project)) {
|
||||
logger.log(project, "Skipping project as no pom.xml could be found in the working directory!");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log(project, "Triggering distribution build…");
|
||||
|
||||
ArtifactVersion version = ArtifactVersion.of(module);
|
||||
|
||||
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, module.getProject()).get();
|
||||
|
||||
if (result.hasError()) {
|
||||
throw result.getException();
|
||||
}
|
||||
|
||||
logger.log(project, "Successfully finished distribution build!");
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isMavenProject(Project project) {
|
||||
return workspace.getFile(POM_XML, project).exists();
|
||||
}
|
||||
|
||||
private void updateBomPom(final TrainIteration iteration, final Phase phase) throws Exception {
|
||||
|
||||
File bomPomFile = workspace.getFile("bom/pom.xml", BUILD);
|
||||
|
||||
logger.log(BUILD, "Updating BOM pom.xml…");
|
||||
|
||||
execute(bomPomFile, new PomCallback<Pom>() {
|
||||
|
||||
@Override
|
||||
public void doWith(Pom pom) {
|
||||
|
||||
for (ModuleIteration module : iteration.getModulesExcept(BUILD)) {
|
||||
|
||||
Artifact artifact = new Artifact(module);
|
||||
ArtifactVersion version = artifact.getVersion();
|
||||
version = PREPARE.equals(phase) ? version : version.getNextDevelopmentVersion();
|
||||
|
||||
logger.log(BUILD, "%s", module);
|
||||
|
||||
pom.setDependencyManagementVersion(artifact.getArtifactId(), version);
|
||||
|
||||
for (String additionalArtifact : module.getProject().getAdditionalArtifacts()) {
|
||||
pom.setDependencyManagementVersion(additionalArtifact, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateRepository(Project project, Pom pom, Repository repository, Phase phase) {
|
||||
|
||||
String message = "Switching to Spring repository %s (%s).";
|
||||
|
||||
if (PREPARE.equals(phase)) {
|
||||
|
||||
logger.log(project, message, repository.getId(), repository.getUrl());
|
||||
|
||||
pom.setRepositoryId(repository.getSnapshotId(), repository.getId());
|
||||
pom.setRepositoryUrl(repository.getId(), repository.getUrl());
|
||||
|
||||
} else {
|
||||
|
||||
logger.log(project, message, repository.getSnapshotId(), repository.getSnapshotUrl());
|
||||
|
||||
pom.setRepositoryId(repository.getId(), repository.getSnapshotId());
|
||||
pom.setRepositoryUrl(repository.getSnapshotId(), repository.getSnapshotUrl());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Pom> void execute(File file, PomCallback<T> callback) throws Exception {
|
||||
|
||||
XBFileIO io = projectionFactory.io().file(file);
|
||||
Class<?> typeArgument = GenericTypeResolver.resolveTypeArgument(callback.getClass(), PomCallback.class);
|
||||
|
||||
T pom = (T) io.read(typeArgument);
|
||||
callback.doWith(pom);
|
||||
io.write(pom);
|
||||
}
|
||||
|
||||
private interface PomCallback<T extends Pom> {
|
||||
public void doWith(T pom);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import java.util.Set;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.git.GitOperations;
|
||||
import org.springframework.data.release.io.Workspace;
|
||||
import org.springframework.data.release.io.Workspace.LineCallback;
|
||||
import org.springframework.data.release.jira.Changelog;
|
||||
import org.springframework.data.release.jira.IssueTracker;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
@@ -77,27 +76,23 @@ public class ReleaseOperations {
|
||||
|
||||
for (String location : CHANGELOG_LOCATIONS) {
|
||||
|
||||
boolean processed = workspace.processFile(location, module.getProject(), new LineCallback() {
|
||||
boolean processed = workspace.processFile(location, module.getProject(), (line, number) -> {
|
||||
|
||||
@Override
|
||||
public String doWith(String line, long number) {
|
||||
if (line.startsWith("=")) {
|
||||
|
||||
if (line.startsWith("=")) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(line).append("\n\n");
|
||||
builder.append(changelog.toString());
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(line).append("\n\n");
|
||||
builder.append(changelog.toString());
|
||||
|
||||
return builder.toString();
|
||||
} else {
|
||||
return line;
|
||||
}
|
||||
return builder.toString();
|
||||
} else {
|
||||
return line;
|
||||
}
|
||||
});
|
||||
|
||||
if (processed) {
|
||||
|
||||
git.commit(module, "Updated changelog.", null);
|
||||
git.commit(module, "Updated changelog.");
|
||||
|
||||
logger.log(module.getProject(), "Updated changelog %s.", location);
|
||||
}
|
||||
@@ -107,25 +102,14 @@ public class ReleaseOperations {
|
||||
|
||||
public void updateResources(TrainIteration iteration) throws Exception {
|
||||
|
||||
for (final ModuleIteration module : iteration) {
|
||||
iteration.stream().forEach(module -> {
|
||||
|
||||
boolean processed = workspace.processFile("src/main/resources/notice.txt", module.getProject(),
|
||||
new LineCallback() {
|
||||
|
||||
@Override
|
||||
public String doWith(String line, long number) {
|
||||
|
||||
if (number != 0) {
|
||||
return line;
|
||||
}
|
||||
|
||||
return module.toString();
|
||||
}
|
||||
});
|
||||
(line, number) -> number != 0 ? line : module.toString());
|
||||
|
||||
if (processed) {
|
||||
logger.log(module, "Updated notice.txt.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2015 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.
|
||||
@@ -13,30 +13,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
package org.springframework.data.release.model;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Module;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
class MavenProject {
|
||||
@Value(staticConstructor = "of")
|
||||
public class ArtifactCoordinate {
|
||||
|
||||
private final Module module;
|
||||
String groupId, artifactId;
|
||||
|
||||
public String getGroupId() {
|
||||
return "org.springframework.data";
|
||||
}
|
||||
public static ArtifactCoordinate from(String coordinate) {
|
||||
|
||||
public String getArtifactId() {
|
||||
return String.format("spring-data-%s", module.getProject().getName().toLowerCase());
|
||||
}
|
||||
|
||||
public ArtifactVersion getReleaseVersion() {
|
||||
return ArtifactVersion.of(module.getVersion());
|
||||
String[] parts = coordinate.split(":");
|
||||
return new ArtifactCoordinate(parts[0], parts[1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2015 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.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ArtifactCoordinates {
|
||||
|
||||
public static ArtifactCoordinates NONE = forGroupId("org.springframework.data");
|
||||
|
||||
private final String groupId;
|
||||
private final @Getter(AccessLevel.PACKAGE) List<ArtifactCoordinate> coordinates;
|
||||
|
||||
public static ArtifactCoordinates forGroupId(String groupId) {
|
||||
return new ArtifactCoordinates(groupId, new ArrayList<>());
|
||||
}
|
||||
|
||||
public ArtifactCoordinates artifacts(String... artifactIds) {
|
||||
|
||||
return new ArtifactCoordinates(groupId,
|
||||
Arrays.stream(artifactIds)//
|
||||
.map(artifactId -> ArtifactCoordinate.of(groupId, artifactId))//
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public ArtifactCoordinates artifact(ArtifactCoordinate coordinate) {
|
||||
|
||||
List<ArtifactCoordinate> artifacts = new ArrayList<>(coordinates);
|
||||
artifacts.add(coordinate);
|
||||
|
||||
return new ArtifactCoordinates(groupId, artifacts);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,9 +20,9 @@ package org.springframework.data.release.model;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface IterationVersion {
|
||||
|
||||
Version getVersion();
|
||||
public interface IterationVersion extends VersionAware {
|
||||
|
||||
Iteration getIteration();
|
||||
|
||||
boolean isServiceIteration();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.springframework.util.Assert;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
public class Module {
|
||||
public class Module implements VersionAware {
|
||||
|
||||
private final Project project;
|
||||
private final Version version;
|
||||
|
||||
@@ -27,8 +27,14 @@ import lombok.RequiredArgsConstructor;
|
||||
public class ModuleIteration implements IterationVersion {
|
||||
|
||||
private final @Getter Module module;
|
||||
private final Iteration iteration;
|
||||
private final @Getter Train train;
|
||||
private final @Getter TrainIteration trainIteration;
|
||||
|
||||
/**
|
||||
* @return the train
|
||||
*/
|
||||
public Train getTrain() {
|
||||
return trainIteration.getTrain();
|
||||
}
|
||||
|
||||
public ProjectKey getProjectKey() {
|
||||
return module.getProject().getKey();
|
||||
@@ -52,20 +58,33 @@ public class ModuleIteration implements IterationVersion {
|
||||
* @see org.springframework.data.release.model.IterationVersion#getIteration()
|
||||
*/
|
||||
public Iteration getIteration() {
|
||||
return this.iteration.isInitialIteration() && this.module.hasCustomFirstIteration() ? module
|
||||
.getCustomFirstIteration() : this.iteration;
|
||||
|
||||
return trainIteration.getIteration().isInitialIteration() && this.module.hasCustomFirstIteration()
|
||||
? module.getCustomFirstIteration() : this.trainIteration.getIteration();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.model.IterationVersion#isServiceIteration()
|
||||
*/
|
||||
@Override
|
||||
public boolean isServiceIteration() {
|
||||
return getIteration().isServiceIteration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link String} representation of the logical version of the {@link ModuleIteration}.
|
||||
* Returns the {@link String} representation of the logical version of the {@link ModuleIteration}. This will
|
||||
* abbreviate trailing zeros and not include the release train name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getVersionString() {
|
||||
public String getShortVersionString() {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(ArtifactVersion.of(this).toShortString());
|
||||
|
||||
Iteration iteration = trainIteration.getIteration();
|
||||
|
||||
if (!iteration.isServiceIteration()) {
|
||||
builder.append(" ").append(iteration.getName());
|
||||
}
|
||||
@@ -73,12 +92,41 @@ public class ModuleIteration implements IterationVersion {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String getMediumVersionString() {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(ArtifactVersion.of(this).toShortString());
|
||||
|
||||
Iteration iteration = trainIteration.getIteration();
|
||||
|
||||
if (iteration.isServiceIteration()) {
|
||||
builder.append(" (").append(trainIteration.toString());
|
||||
} else {
|
||||
builder.append(" ").append(iteration.getName()).append(" (");
|
||||
builder.append(trainIteration.getTrain().getName());
|
||||
}
|
||||
|
||||
return builder.append(")").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link String} representation of the logical version of the {@link ModuleIteration}. This will use the
|
||||
* technical version string and append the train iteration.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getFullVersionString() {
|
||||
|
||||
String result = ArtifactVersion.of(this).toString();
|
||||
return result.concat(" (").concat(trainIteration.toString()).concat(")");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s", module.getProject().getFullName(), getVersionString());
|
||||
return String.format("%s %s", module.getProject().getFullName(), getShortVersionString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2016 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.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.data.release.Streamable;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class Modules implements Streamable<Module> {
|
||||
|
||||
private final Collection<Module> modules;
|
||||
|
||||
public Iterator<Module> iterator() {
|
||||
return modules.iterator();
|
||||
}
|
||||
}
|
||||
@@ -20,5 +20,5 @@ package org.springframework.data.release.model;
|
||||
*/
|
||||
public enum Phase {
|
||||
|
||||
PREPARE, CLEANUP;
|
||||
PREPARE, CLEANUP, MAINTENANCE;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -35,17 +35,18 @@ public class Project {
|
||||
private final @Getter String name;
|
||||
private final @Getter List<Project> dependencies;
|
||||
private final Tracker tracker;
|
||||
private final @Getter List<String> additionalArtifacts;
|
||||
private final @Getter ArtifactCoordinates additionalArtifacts;
|
||||
|
||||
Project(String key, String name, List<Project> dependencies) {
|
||||
this(key, name, Tracker.JIRA, dependencies, Collections.emptyList());
|
||||
this(key, name, Tracker.JIRA, dependencies, ArtifactCoordinates.NONE);
|
||||
}
|
||||
|
||||
Project(String key, String name, List<Project> dependencies, List<String> additionalArtifacts) {
|
||||
Project(String key, String name, List<Project> dependencies, ArtifactCoordinates additionalArtifacts) {
|
||||
this(key, name, Tracker.JIRA, dependencies, additionalArtifacts);
|
||||
}
|
||||
|
||||
Project(String key, String name, Tracker tracker, List<Project> dependencies, List<String> additionalArtifacts) {
|
||||
Project(String key, String name, Tracker tracker, List<Project> dependencies,
|
||||
ArtifactCoordinates additionalArtifacts) {
|
||||
|
||||
this.key = new ProjectKey(key);
|
||||
this.name = name;
|
||||
@@ -66,6 +67,10 @@ public class Project {
|
||||
return "springdata.".concat(name.toLowerCase());
|
||||
}
|
||||
|
||||
public void doWithAdditionalArtifacts(Consumer<ArtifactCoordinate> consumer) {
|
||||
additionalArtifacts.getCoordinates().forEach(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current project depends on the given one.
|
||||
*
|
||||
@@ -75,6 +80,7 @@ public class Project {
|
||||
public boolean dependsOn(Project project) {
|
||||
|
||||
Assert.notNull(project, "Project must not be null!");
|
||||
return dependencies.contains(project);
|
||||
|
||||
return dependencies.stream().anyMatch(dependency -> dependency.equals(project) || dependency.dependsOn(project));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.release.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.jgrapht.graph.DefaultDirectedGraph;
|
||||
import org.jgrapht.graph.DefaultEdge;
|
||||
import org.jgrapht.traverse.TopologicalOrderIterator;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -30,26 +36,60 @@ public class Projects {
|
||||
|
||||
static {
|
||||
|
||||
BUILD = new Project("DATABUILD", "Build", Tracker.GITHUB, Collections.emptyList(), Collections.emptyList());
|
||||
BUILD = new Project("DATABUILD", "Build", Tracker.GITHUB, Collections.emptyList(),
|
||||
ArtifactCoordinates.forGroupId("org.springframework.data.build")
|
||||
.artifacts("spring-data-build-parent", "spring-data-build-resources")
|
||||
.artifact(ArtifactCoordinate.of("org.springframework.data", "spring-data-releasetrain")));
|
||||
COMMONS = new Project("DATACMNS", "Commons", Arrays.asList(BUILD));
|
||||
JPA = new Project("DATAJPA", "JPA", Arrays.asList(COMMONS));
|
||||
MONGO_DB = new Project("DATAMONGO", "MongoDB", Arrays.asList(COMMONS),
|
||||
Arrays.asList("spring-data-mongodb-cross-store", "spring-data-mongodb-log4j"));
|
||||
ArtifactCoordinates.NONE.artifacts("spring-data-mongodb-cross-store", "spring-data-mongodb-log4j"));
|
||||
NEO4J = new Project("DATAGRAPH", "Neo4j", Arrays.asList(COMMONS));
|
||||
SOLR = new Project("DATASOLR", "Solr", Arrays.asList(COMMONS));
|
||||
COUCHBASE = new Project("DATACOUCH", "Couchbase", Arrays.asList(COMMONS));
|
||||
CASSANDRA = new Project("DATACASS", "Cassandra", Arrays.asList(COMMONS), Arrays.asList("spring-cql"));
|
||||
CASSANDRA = new Project("DATACASS", "Cassandra", Arrays.asList(COMMONS),
|
||||
ArtifactCoordinates.NONE.artifacts("spring-cql"));
|
||||
ELASTICSEARCH = new Project("DATAES", "Elasticsearch", Arrays.asList(COMMONS));
|
||||
REDIS = new Project("DATAREDIS", "Redis", Collections.emptyList());
|
||||
GEMFIRE = new Project("SGF", "Gemfire", Arrays.asList(COMMONS));
|
||||
|
||||
REST = new Project("DATAREST", "REST", Arrays.asList(COMMONS, JPA, MONGO_DB, NEO4J, GEMFIRE, SOLR, CASSANDRA),
|
||||
Arrays.asList("spring-data-rest-core", "spring-data-rest-core", "spring-data-rest-hal-browser"));
|
||||
ArtifactCoordinates.NONE.artifacts("spring-data-rest-core", "spring-data-rest-core",
|
||||
"spring-data-rest-hal-browser"));
|
||||
|
||||
KEY_VALUE = new Project("DATAKV", "KeyValue", Arrays.asList(COMMONS));
|
||||
ENVERS = new Project("DATAENV", "Envers", Arrays.asList(JPA, COMMONS));
|
||||
ENVERS = new Project("DATAENV", "Envers", Tracker.GITHUB, Arrays.asList(JPA, COMMONS), ArtifactCoordinates.NONE);
|
||||
|
||||
PROJECTS = Arrays.asList(BUILD, COMMONS, JPA, MONGO_DB, NEO4J, SOLR, COUCHBASE, CASSANDRA, ELASTICSEARCH, REDIS,
|
||||
GEMFIRE, REST, KEY_VALUE, ENVERS);
|
||||
List<Project> projects = Arrays.asList(BUILD, COMMONS, JPA, MONGO_DB, NEO4J, SOLR, COUCHBASE, CASSANDRA,
|
||||
ELASTICSEARCH, REDIS, GEMFIRE, REST, KEY_VALUE, ENVERS);
|
||||
|
||||
DefaultDirectedGraph<Project, DefaultEdge> graph = new DefaultDirectedGraph<>(DefaultEdge.class);
|
||||
|
||||
projects.forEach(project -> {
|
||||
|
||||
graph.addVertex(project);
|
||||
|
||||
project.getDependencies().forEach(dependency -> {
|
||||
graph.addEdge(project, dependency);
|
||||
});
|
||||
});
|
||||
|
||||
Iterator<Project> iterator = new TopologicalOrderIterator<>(graph);
|
||||
List<Project> intermediate = new ArrayList<>(projects.size());
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
intermediate.add(iterator.next());
|
||||
}
|
||||
|
||||
Collections.reverse(intermediate);
|
||||
|
||||
PROJECTS = Collections.unmodifiableList(intermediate);
|
||||
}
|
||||
|
||||
public static Project byName(String name) {
|
||||
|
||||
return PROJECTS.stream().//
|
||||
filter(project -> project.getName().equalsIgnoreCase(name)).//
|
||||
findFirst().orElseThrow(() -> new IllegalArgumentException("No project named %s available!"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ public class ReleaseTrains {
|
||||
EVANS = DIJKSTRA.next("Evans", Transition.MINOR);
|
||||
FOWLER = EVANS.next("Fowler", Transition.MINOR);
|
||||
GOSLING = FOWLER.next("Gosling", Transition.MINOR, new Module(KEY_VALUE, "1.0"));
|
||||
HOPPER = GOSLING.next("Hopper", Transition.MINOR, new Module(NEO4J, "4.1"), new Module(COUCHBASE, "2.1"),
|
||||
new Module(ENVERS, "1.0"));
|
||||
HOPPER = GOSLING.next("Hopper", Transition.MINOR, new Module(SOLR, "2.0"), new Module(ENVERS, "1.0"),
|
||||
new Module(NEO4J, "4.1"), new Module(COUCHBASE, "2.1"));
|
||||
|
||||
// Trains
|
||||
|
||||
|
||||
@@ -23,13 +23,13 @@ import lombok.Value;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.release.Streamable;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -37,23 +37,20 @@ import org.springframework.util.Assert;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
public class Train implements Iterable<Module> {
|
||||
public class Train implements Streamable<Module> {
|
||||
|
||||
private final String name;;
|
||||
private final Collection<Module> modules;
|
||||
private final Modules modules;
|
||||
private final Iterations iterations;
|
||||
|
||||
public Train(String name, Module... modules) {
|
||||
|
||||
this.name = name;
|
||||
this.modules = Arrays.asList(modules);
|
||||
this.iterations = Iterations.DEFAULT;
|
||||
this(name, Arrays.asList(modules));
|
||||
}
|
||||
|
||||
public Train(String name, Collection<Module> modules) {
|
||||
|
||||
this.name = name;
|
||||
this.modules = Collections.unmodifiableCollection(modules);
|
||||
this.modules = new Modules(modules);
|
||||
this.iterations = Iterations.DEFAULT;
|
||||
}
|
||||
|
||||
@@ -66,6 +63,12 @@ public class Train implements Iterable<Module> {
|
||||
return modules.iterator();
|
||||
}
|
||||
|
||||
public boolean contains(Project project) {
|
||||
|
||||
return modules.stream().//
|
||||
anyMatch(module -> module.getProject().equals(project));
|
||||
}
|
||||
|
||||
public Module getModule(String name) {
|
||||
|
||||
return modules.stream().//
|
||||
@@ -98,7 +101,7 @@ public class Train implements Iterable<Module> {
|
||||
return modules.stream().//
|
||||
filter(module -> module.hasName(moduleName)).//
|
||||
findFirst().//
|
||||
map(module -> new ModuleIteration(module, iteration, this)).//
|
||||
map(module -> new ModuleIteration(module, new TrainIteration(this, iteration))).//
|
||||
orElseThrow(
|
||||
() -> new IllegalArgumentException(String.format("No module found with module name %s!", moduleName)));
|
||||
}
|
||||
@@ -113,7 +116,8 @@ public class Train implements Iterable<Module> {
|
||||
|
||||
return modules.stream().//
|
||||
filter(module -> !exclusionList.contains(module.getProject())).//
|
||||
map(module -> new ModuleIteration(module, iteration, this)).//
|
||||
map(module -> new ModuleIteration(module, new TrainIteration(this, iteration))).//
|
||||
sorted().//
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -125,7 +129,7 @@ public class Train implements Iterable<Module> {
|
||||
|
||||
Module module = getModule(project);
|
||||
|
||||
return ArtifactVersion.of(new ModuleIteration(module, iteration, this));
|
||||
return ArtifactVersion.of(new ModuleIteration(module, new TrainIteration(this, iteration)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,12 +18,15 @@ package org.springframework.data.release.model;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.release.Streamable;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
public class TrainIteration implements Iterable<ModuleIteration> {
|
||||
public class TrainIteration implements Streamable<ModuleIteration> {
|
||||
|
||||
private final Train train;
|
||||
private final Iteration iteration;
|
||||
@@ -49,16 +52,29 @@ public class TrainIteration implements Iterable<ModuleIteration> {
|
||||
return train.getModuleIteration(iteration, project.getName());
|
||||
}
|
||||
|
||||
public Iterable<ModuleIteration> getModulesExcept(Project... exclusions) {
|
||||
public List<ModuleIteration> getModulesExcept(Project... exclusions) {
|
||||
return train.getModuleIterations(iteration, exclusions);
|
||||
}
|
||||
|
||||
public boolean contains(Project project) {
|
||||
return train.contains(project);
|
||||
}
|
||||
|
||||
public ModuleIteration getPreviousIteration(ModuleIteration module) {
|
||||
|
||||
Iteration previousIteration = train.getIterations().getPreviousIteration(iteration);
|
||||
return train.getModuleIteration(previousIteration, module.getProject().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version string to be used for the train iteration.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String toVersionString() {
|
||||
return toString().replace(' ', '-');
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
@@ -67,4 +83,5 @@ public class TrainIteration implements Iterable<ModuleIteration> {
|
||||
public String toString() {
|
||||
return String.format("%s %s", train.getName(), iteration.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.springframework.data.release.model;
|
||||
|
||||
import static org.springframework.data.release.model.Projects.*;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.release.build.Repository;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to expose update information for a given {@link TrainIteration} and phase.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class UpdateInformation {
|
||||
|
||||
private final @NonNull @Getter TrainIteration iteration;
|
||||
private final @NonNull @Getter Phase phase;
|
||||
|
||||
/**
|
||||
* Returns the {@link ArtifactVersion} to be set for the given {@link Project}.
|
||||
*
|
||||
* @param dependency must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public ArtifactVersion getProjectVersionToSet(Project dependency) {
|
||||
|
||||
Assert.notNull(dependency, "Project must not be null!");
|
||||
|
||||
ArtifactVersion dependencyVersion = iteration.getModuleVersion(dependency);
|
||||
|
||||
switch (phase) {
|
||||
case PREPARE:
|
||||
return dependencyVersion;
|
||||
case CLEANUP:
|
||||
return dependencyVersion.getNextDevelopmentVersion();
|
||||
case MAINTENANCE:
|
||||
return dependencyVersion.getNextBugfixVersion();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Unexpected phase detected " + phase + " detected!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ArtifactVersion} to be set for the parent reference.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public ArtifactVersion getParentVersionToSet() {
|
||||
|
||||
ArtifactVersion version = iteration.getModuleVersion(BUILD);
|
||||
|
||||
switch (phase) {
|
||||
case PREPARE:
|
||||
return version;
|
||||
case CLEANUP:
|
||||
return version.getNextDevelopmentVersion();
|
||||
case MAINTENANCE:
|
||||
return version.getNextBugfixVersion();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Unexpected phase detected " + phase + " detected!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Repository} to use (milestone or release).
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public Repository getRepository() {
|
||||
return new Repository(iteration.getIteration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version {@link String} to be used to describe the release train.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public String getReleaseTrainVersion() {
|
||||
|
||||
switch (phase) {
|
||||
case PREPARE:
|
||||
return iteration.toVersionString();
|
||||
case CLEANUP:
|
||||
case MAINTENANCE:
|
||||
return iteration.getTrain().getName().concat("-BUILD-SNAPSHOT");
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Unexpected phase detected " + phase + " detected!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2015 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 VersionAware {
|
||||
|
||||
Version getVersion();
|
||||
}
|
||||
@@ -19,8 +19,8 @@ import java.util.Collection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.data.release.Streamable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -35,15 +35,15 @@ public class ExecutionUtils {
|
||||
* all executions to complete before returning. Exceptions being thrown in the {@link ConsumerWithException} will be
|
||||
* converted into {@link RuntimeException}s.
|
||||
*
|
||||
* @param iterable must not be {@literal null}.
|
||||
* @param streamable must not be {@literal null}.
|
||||
* @param consumer must not be {@literal null}.
|
||||
*/
|
||||
public static <T> void run(Iterable<T> iterable, ConsumerWithException<T> consumer) {
|
||||
public static <T> void run(Streamable<T> streamable, ConsumerWithException<T> consumer) {
|
||||
|
||||
Assert.notNull(iterable, "Iterable must not be null!");
|
||||
Assert.notNull(streamable, "Streamable must not be null!");
|
||||
Assert.notNull(consumer, "Consumer must not be null!");
|
||||
|
||||
StreamSupport.stream(iterable.spliterator(), false).//
|
||||
streamable.stream().//
|
||||
map(it -> CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
consumer.accept(it);
|
||||
@@ -55,19 +55,19 @@ public class ExecutionUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given {@link Function} for each element in the given {@link Iterable} in parallel waiting for all
|
||||
* Runs the given {@link Function} for each element in the given {@link Streamable} in parallel waiting for all
|
||||
* executions to complete before returning the results.
|
||||
*
|
||||
* @param iterable must not be {@literal null}.
|
||||
* @param streamable must not be {@literal null}.
|
||||
* @param function must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static <T, S> Collection<S> runAndReturn(Iterable<T> iterable, Function<T, S> function) {
|
||||
public static <T, S> Collection<S> runAndReturn(Streamable<T> streamable, Function<T, S> function) {
|
||||
|
||||
Assert.notNull(iterable, "Iterable must not be null!");
|
||||
Assert.notNull(streamable, "Iterable must not be null!");
|
||||
Assert.notNull(function, "Consumer must not be null!");
|
||||
|
||||
return StreamSupport.stream(iterable.spliterator(), false).//
|
||||
return streamable.stream().//
|
||||
map(it -> CompletableFuture.supplyAsync(() -> function.apply(it))).//
|
||||
collect(Collectors.toList()).//
|
||||
stream().//
|
||||
|
||||
@@ -32,23 +32,23 @@ public class Logger {
|
||||
|
||||
private final java.util.logging.Logger LOGGER = HandlerUtils.getLogger(getClass());
|
||||
|
||||
public void log(ModuleIteration module, String template, Object... args) {
|
||||
public void log(ModuleIteration module, Object template, Object... args) {
|
||||
log(module.getProject(), template, args);
|
||||
}
|
||||
|
||||
public void log(Project project, String template, Object... args) {
|
||||
public void log(Project project, Object template, Object... args) {
|
||||
log(project.getName(), template, args);
|
||||
}
|
||||
|
||||
public void log(TrainIteration iteration, String template, Object... args) {
|
||||
public void log(TrainIteration iteration, Object template, Object... args) {
|
||||
log(iteration.toString(), template, args);
|
||||
}
|
||||
|
||||
public void log(Train train, String template, Object... args) {
|
||||
public void log(Train train, Object template, Object... args) {
|
||||
log(train.getName(), template, args);
|
||||
}
|
||||
|
||||
private void log(String context, String template, Object... args) {
|
||||
LOGGER.info(String.format(PREFIX_TEMPLATE, context, String.format(template, args)));
|
||||
private void log(String context, Object template, Object... args) {
|
||||
LOGGER.info(String.format(PREFIX_TEMPLATE, context, String.format(template.toString(), args)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2016 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.utils;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface StreamUtils {
|
||||
|
||||
public static <T, S> Function<T, S> wrap(FunctionWithException<T, S> function) {
|
||||
return it -> {
|
||||
try {
|
||||
return function.apply(it);
|
||||
} catch (Exception o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public interface FunctionWithException<T, S> {
|
||||
S apply(T source) throws Exception;
|
||||
}
|
||||
}
|
||||
@@ -1 +1,12 @@
|
||||
io.work-dir=~/temp/spring-data-shell
|
||||
|
||||
maven.release-command=install -DskipTests
|
||||
|
||||
#maven.plugins.deploy=org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy
|
||||
maven.plugins.versions-set=org.codehaus.mojo:versions-maven-plugin:2.2:set
|
||||
maven.plugins.artifactory-deploy=org.jfrog.buildinfo:artifactory-maven-plugin:2.4.0:publish
|
||||
|
||||
deployment.server.uri=https://repo.spring.io
|
||||
deployment.staging-repository=libs-staging-local
|
||||
deployment.username=buildmaster
|
||||
#deployment.password <- local
|
||||
@@ -23,7 +23,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ActiveProfiles({ "test", "local" })
|
||||
@ActiveProfiles({ "local", "test" })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = Application.class)
|
||||
public abstract class AbstractIntegrationTests {}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2016 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;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ApplicationTests extends AbstractIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void bootstrapsApplication() {}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.release.maven.Artifact;
|
||||
import org.springframework.data.release.build.MavenArtifact;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
@@ -32,7 +32,7 @@ public class ArtifactUnitTests {
|
||||
@Test
|
||||
public void testname() {
|
||||
|
||||
Artifact artifact = new Artifact(ReleaseTrains.DIJKSTRA.getModuleIteration(Iteration.M1, "JPA"));
|
||||
MavenArtifact artifact = new MavenArtifact(ReleaseTrains.DIJKSTRA.getModuleIteration(Iteration.M1, "JPA"));
|
||||
|
||||
assertThat(artifact.getArtifactId(), is("spring-data-jpa"));
|
||||
assertThat(artifact.getVersion(), is(ArtifactVersion.of("1.6.0.M1")));
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.release.maven;
|
||||
package org.springframework.data.release.build;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -21,8 +21,16 @@ import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.release.AbstractIntegrationTests;
|
||||
import org.springframework.data.release.git.GitOperations;
|
||||
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.Phase;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.data.release.model.UpdateInformation;
|
||||
import org.xmlbeam.ProjectionFactory;
|
||||
import org.xmlbeam.io.XBFileIO;
|
||||
|
||||
@@ -33,6 +41,8 @@ public class MavenIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
@Autowired Workspace workspace;
|
||||
@Autowired ProjectionFactory projection;
|
||||
@Autowired MavenBuildSystem maven;
|
||||
@Autowired GitOperations git;
|
||||
|
||||
@Test
|
||||
public void modifiesParentPomCorrectly() throws IOException {
|
||||
@@ -42,7 +52,7 @@ public class MavenIntegrationTests extends AbstractIntegrationTests {
|
||||
ParentPom pom = io.read(ParentPom.class);
|
||||
pom.setSharedResourcesVersion(ArtifactVersion.of("1.2.0.RELEASE"));
|
||||
|
||||
// System.out.println(projection.asString(pom));
|
||||
System.out.println(projection.asString(pom));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -57,4 +67,17 @@ public class MavenIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
// System.out.println(projection.asString(pom));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testname() throws Exception {
|
||||
|
||||
git.update(ReleaseTrains.HOPPER);
|
||||
|
||||
TrainIteration iteration = new TrainIteration(ReleaseTrains.HOPPER, Iteration.M1);
|
||||
ModuleIteration build = iteration.getModule(Projects.BUILD);
|
||||
UpdateInformation information = new UpdateInformation(iteration, Phase.PREPARE);
|
||||
|
||||
maven.updateProjectDescriptors(build, information);
|
||||
maven.prepareVersion(build, Phase.PREPARE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.deployment;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.AbstractIntegrationTests;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
|
||||
/**
|
||||
* Integration test for {@link DeploymentInformation}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DeploymentInformationIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
@Autowired DeploymentProperties properties;
|
||||
|
||||
@Test
|
||||
public void createsDeploymentInformation() {
|
||||
|
||||
TrainIteration iteration = new TrainIteration(ReleaseTrains.HOPPER, Iteration.M1);
|
||||
ModuleIteration buildModule = iteration.getModule(Projects.BUILD);
|
||||
|
||||
DeploymentInformation information = new DeploymentInformation(buildModule, properties);
|
||||
|
||||
assertThat(information.getDeploymentTargetUrl(), containsString(properties.getServer().getUri().toString()));
|
||||
assertThat(information.getBuildName(), is("Spring Data Build - Release"));
|
||||
assertThat(information.getTargetRepository(), is("test-libs-milestone-local"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2015 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.deployment;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.AbstractIntegrationTests;
|
||||
import org.springframework.data.release.build.BuildOperations;
|
||||
import org.springframework.data.release.git.GitOperations;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Phase;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.data.release.model.Train;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DeploymentOperationsIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
@Autowired GitOperations git;
|
||||
@Autowired BuildOperations build;
|
||||
@Autowired DeploymentOperations deployment;
|
||||
@Autowired ArtifactoryClient client;
|
||||
|
||||
@Test
|
||||
public void testname() {
|
||||
|
||||
Train train = ReleaseTrains.HOPPER;
|
||||
ModuleIteration buildModule = train.getModuleIteration(Iteration.M1, "build");
|
||||
|
||||
git.update(train);
|
||||
build.prepareVersion(buildModule, Phase.PREPARE);
|
||||
|
||||
DeploymentInformation information = build.buildAndDeployRelease(buildModule);
|
||||
|
||||
try {
|
||||
deployment.promote(information);
|
||||
} finally {
|
||||
client.deleteArtifacts(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,9 @@ public class ModuleIterationUnitTests {
|
||||
TrainIteration iteration = new TrainIteration(ReleaseTrains.DIJKSTRA, Iteration.M1);
|
||||
ModuleIteration module = iteration.getModule(Projects.JPA);
|
||||
|
||||
assertThat(module.getVersionString(), is("1.6 M1"));
|
||||
assertThat(module.getShortVersionString(), is("1.6 M1"));
|
||||
assertThat(module.getMediumVersionString(), is("1.6 M1 (Dijkstra)"));
|
||||
assertThat(module.getFullVersionString(), is("1.6.0.M1 (Dijkstra M1)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -40,6 +42,8 @@ public class ModuleIterationUnitTests {
|
||||
TrainIteration iteration = new TrainIteration(ReleaseTrains.DIJKSTRA, Iteration.SR1);
|
||||
ModuleIteration module = iteration.getModule(Projects.JPA);
|
||||
|
||||
assertThat(module.getVersionString(), is("1.6.1"));
|
||||
assertThat(module.getShortVersionString(), is("1.6.1"));
|
||||
assertThat(module.getMediumVersionString(), is("1.6.1 (Dijkstra SR1)"));
|
||||
assertThat(module.getFullVersionString(), is("1.6.1.RELEASE (Dijkstra SR1)"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2015 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 static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ProjectUnitTests {
|
||||
|
||||
@Test
|
||||
public void testname() {
|
||||
|
||||
List<Project> projects = new ArrayList<>(Projects.PROJECTS);
|
||||
// Collections.reverse(projects);
|
||||
// Collections.sort(projects);
|
||||
|
||||
projects.stream().map(Project::getName).forEach(System.out::println);
|
||||
|
||||
System.out.println();
|
||||
|
||||
assertThat(projects.get(0), is(Projects.BUILD));
|
||||
assertThat(projects.get(1), is(Projects.COMMONS));
|
||||
}
|
||||
}
|
||||
@@ -22,4 +22,13 @@ public class SimpleIterationVersion implements IterationVersion {
|
||||
|
||||
private final Version version;
|
||||
private final Iteration iteration;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.model.IterationVersion#isServiceIteration()
|
||||
*/
|
||||
@Override
|
||||
public boolean isServiceIteration() {
|
||||
return iteration.isServiceIteration();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,18 @@ public class TrainsUnitTest {
|
||||
public void addsNewlyAddedModule() {
|
||||
assertThat(ReleaseTrains.HOPPER.getModule(Projects.ENVERS), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testname() {
|
||||
|
||||
Iterable<ModuleIteration> iterations = ReleaseTrains.HOPPER.getModuleIterations(Iteration.M1);
|
||||
|
||||
for (ModuleIteration iteration : iterations) {
|
||||
System.out.println(iteration);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
iterations.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2015 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 static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link UpdateInformation}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class UpdateInformationUnitTests {
|
||||
|
||||
TrainIteration hopperM1 = new TrainIteration(ReleaseTrains.HOPPER, Iteration.M1);
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullTrainIteration() {
|
||||
new UpdateInformation(null, Phase.CLEANUP);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullPhase() {
|
||||
new UpdateInformation(hopperM1, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exposesMilestoneRepositoryForMilestone() {
|
||||
assertThat(new UpdateInformation(hopperM1, Phase.PREPARE).getRepository().getId(), is("spring-libs-milestone"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exposesReleaseRepositoryForGA() {
|
||||
|
||||
Arrays.asList(Iteration.GA, Iteration.SR1).forEach(iteration -> {
|
||||
TrainIteration trainIteration = new TrainIteration(ReleaseTrains.HOPPER, iteration);
|
||||
assertThat(new UpdateInformation(trainIteration, Phase.PREPARE).getRepository().getId(),
|
||||
is("spring-libs-release"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculatesProjectVersionToSetCorrectly() {
|
||||
|
||||
UpdateInformation updateInformation = new UpdateInformation(hopperM1, Phase.PREPARE);
|
||||
assertThat(updateInformation.getProjectVersionToSet(Projects.JPA).toString(), is("1.10.0.M1"));
|
||||
|
||||
updateInformation = new UpdateInformation(hopperM1, Phase.CLEANUP);
|
||||
assertThat(updateInformation.getProjectVersionToSet(Projects.JPA).toString(), is("1.10.0.BUILD-SNAPSHOT"));
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,14 @@
|
||||
io.work-dir=~/temp/shell-test
|
||||
# Logging
|
||||
logging.level.org.springframework=WARN
|
||||
logging.level.org.springframework.data.release=INFO
|
||||
logging.level.org.springframework.web.client=TRACE
|
||||
|
||||
# Workspace
|
||||
io.work-dir=~/temp/shell-test
|
||||
|
||||
# Maven
|
||||
maven.localRepository=~/temp/.m2/repository
|
||||
|
||||
# Deployment
|
||||
deployment.server.uri=https://repo.spring.io
|
||||
deployment.repository-prefix=test-
|
||||
|
||||
Reference in New Issue
Block a user