#7 - Added support to update project information on spring.io.
This commit introduces a command "sagan update …" to take a comma-separated list of release train names that are supported. The implementation will find the latest releases by inspecting the Git tags and the creating the necessary project metadata information. The code will then wipe the existing metadata and PUT the current information to the server.
This commit is contained in:
@@ -22,6 +22,7 @@ import lombok.Getter;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -34,8 +35,8 @@ public class MavenArtifact {
|
||||
|
||||
private static final GroupId GROUP_ID = GroupId.of("org.springframework.data");
|
||||
|
||||
private final ModuleIteration module;
|
||||
private final Repository repository;
|
||||
private final Project project;
|
||||
private final @Getter Repository repository;
|
||||
private final @Getter ArtifactVersion version;
|
||||
|
||||
/**
|
||||
@@ -47,11 +48,22 @@ public class MavenArtifact {
|
||||
|
||||
Assert.notNull(module, "Module iteration must not be null!");
|
||||
|
||||
this.module = module;
|
||||
this.project = module.getModule().getProject();
|
||||
this.repository = new Repository(module.getIteration());
|
||||
this.version = ArtifactVersion.of(module);
|
||||
}
|
||||
|
||||
public MavenArtifact(Project project, ArtifactVersion version) {
|
||||
|
||||
this.project = project;
|
||||
this.repository = new Repository(version);
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return GROUP_ID.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Maven artifact identifier.
|
||||
*
|
||||
@@ -59,8 +71,9 @@ public class MavenArtifact {
|
||||
*/
|
||||
public String getArtifactId() {
|
||||
|
||||
String artifactId = String.format("spring-data-%s", module.getProject().getName().toLowerCase());
|
||||
return REST.equals(module.getProject()) ? artifactId.concat("-webmvc") : artifactId;
|
||||
String artifactId = String.format("spring-data-%s", project.getName().toLowerCase());
|
||||
|
||||
return REST.equals(project) ? artifactId.concat("-webmvc") : artifactId;
|
||||
}
|
||||
|
||||
public ArtifactVersion getNextDevelopmentVersion() {
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.release.build;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -40,6 +41,14 @@ public class Repository {
|
||||
this.url = BASE.concat(iteration.isPublic() ? "release" : "milestone");
|
||||
}
|
||||
|
||||
public Repository(ArtifactVersion version) {
|
||||
|
||||
String suffix = getSuffixFor(version);
|
||||
|
||||
this.id = ID_BASE.concat(suffix);
|
||||
this.url = BASE.concat(suffix);
|
||||
}
|
||||
|
||||
public String getSnapshotId() {
|
||||
return ID_BASE.concat("snapshot");
|
||||
}
|
||||
@@ -47,4 +56,21 @@ public class Repository {
|
||||
public String getSnapshotUrl() {
|
||||
return BASE.concat("snapshot");
|
||||
}
|
||||
|
||||
private static String getSuffixFor(ArtifactVersion version) {
|
||||
|
||||
if (version.isSnapshotVersion()) {
|
||||
return "snapshot";
|
||||
}
|
||||
|
||||
if (version.isMilestoneVersion()) {
|
||||
return "milestone";
|
||||
}
|
||||
|
||||
if (version.isReleaseVersion()) {
|
||||
return "release";
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Unsupported ArtifactVersion %s!", version));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,22 +18,17 @@ package org.springframework.data.release.issues;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.release.Streamable;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.data.release.utils.ListWrapperCollector;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -115,56 +110,6 @@ public class Tickets implements Streamable<Ticket> {
|
||||
* @return
|
||||
*/
|
||||
public static Collector<? super Ticket, ?, Tickets> toTicketsCollector() {
|
||||
|
||||
return new Collector<Ticket, List<Ticket>, Tickets>() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#supplier()
|
||||
*/
|
||||
@Override
|
||||
public Supplier<List<Ticket>> supplier() {
|
||||
return ArrayList::new;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#accumulator()
|
||||
*/
|
||||
@Override
|
||||
public BiConsumer<List<Ticket>, Ticket> accumulator() {
|
||||
return List::add;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#combiner()
|
||||
*/
|
||||
@Override
|
||||
public BinaryOperator<List<Ticket>> combiner() {
|
||||
return (left, right) -> {
|
||||
left.addAll(right);
|
||||
return left;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#finisher()
|
||||
*/
|
||||
@Override
|
||||
public Function<List<Ticket>, Tickets> finisher() {
|
||||
return tickets -> new Tickets(tickets);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#characteristics()
|
||||
*/
|
||||
@Override
|
||||
public Set<Characteristics> characteristics() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
};
|
||||
return ListWrapperCollector.collectInto(Tickets::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.release.model;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -35,7 +36,7 @@ public class ArtifactVersion implements Comparable<ArtifactVersion> {
|
||||
SNAPSHOT_SUFFIX);
|
||||
|
||||
private final Version version;
|
||||
private final String suffix;
|
||||
private final @Getter String suffix;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ArtifactVersion} from the given logical {@link Version}.
|
||||
@@ -102,6 +103,10 @@ public class ArtifactVersion implements Comparable<ArtifactVersion> {
|
||||
return new ArtifactVersion(version, iteration.getName());
|
||||
}
|
||||
|
||||
public boolean isVersionWithin(Version version) {
|
||||
return this.version.toMajorMinorBugfix().startsWith(version.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the release version for the current one.
|
||||
*
|
||||
@@ -138,6 +143,14 @@ public class ArtifactVersion implements Comparable<ArtifactVersion> {
|
||||
return suffix.matches(MILESTONE_SUFFIX);
|
||||
}
|
||||
|
||||
public boolean isSnapshotVersion() {
|
||||
return suffix.matches(SNAPSHOT_SUFFIX);
|
||||
}
|
||||
|
||||
public boolean isBugFixVersion() {
|
||||
return isReleaseVersion() && !version.toMajorMinorBugfix().endsWith("0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next development version to be used for the current release version, which means next minor for GA
|
||||
* versions and next bug fix for service releases. Will return the current version as snapshot otherwise.
|
||||
@@ -172,6 +185,19 @@ public class ArtifactVersion implements Comparable<ArtifactVersion> {
|
||||
return suffix.equals(SNAPSHOT_SUFFIX) ? this : new ArtifactVersion(version, SNAPSHOT_SUFFIX);
|
||||
}
|
||||
|
||||
public String getReleaseTrainSuffix() {
|
||||
|
||||
if (isSnapshotVersion() || isMilestoneVersion()) {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
if (isBugFixVersion()) {
|
||||
return "SR" + version.getBugfix();
|
||||
}
|
||||
|
||||
return "GA";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||
|
||||
@@ -31,6 +31,8 @@ import org.springframework.util.Assert;
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class Password implements Masked {
|
||||
|
||||
public static Password NONE = new Password("");
|
||||
|
||||
@Getter(AccessLevel.NONE) String value;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.springframework.data.release.model;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -11,6 +13,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Getter
|
||||
public class Version implements Comparable<Version> {
|
||||
|
||||
private final int major;
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
import net.minidev.json.JSONArray;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
/**
|
||||
* Sagan client to interact with the Sagan instance defined through {@link SaganProperties}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||
class DefaultSaganClient implements SaganClient {
|
||||
|
||||
RestOperations operations;
|
||||
SaganProperties properties;
|
||||
Logger logger;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.sagan.SaganClient#getProjectMetadata(org.springframework.data.release.sagan.MaintainedVersion)
|
||||
*/
|
||||
@Override
|
||||
public String getProjectMetadata(MaintainedVersion version) {
|
||||
|
||||
URI resource = properties.getProjectMetadataResource(version);
|
||||
|
||||
logger.log(version.getProject(), "Getting project metadata for version %s from %s…", version.getVersion(),
|
||||
resource);
|
||||
|
||||
return operations.getForObject(resource, String.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.sagan.SaganClient#getProjectMetadata(org.springframework.data.release.model.Project)
|
||||
*/
|
||||
@Override
|
||||
public String getProjectMetadata(Project project) {
|
||||
|
||||
URI resource = properties.getProjectMetadataResource(project);
|
||||
|
||||
logger.log(project, "Getting project metadata from %s…", resource);
|
||||
|
||||
return operations.getForObject(resource, String.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.sagan.SaganClient#updateProjectMetadata(org.springframework.data.release.model.Project, java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public void updateProjectMetadata(Project project, MaintainedVersions versions) {
|
||||
|
||||
URI resource = properties.getProjectMetadataResource(project);
|
||||
|
||||
String versionsString = versions.stream()//
|
||||
.map(MaintainedVersion::getVersion)//
|
||||
.map(Object::toString) //
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
logger.log(project, "Updating project metadata to %s via %s…", versionsString, resource);
|
||||
|
||||
// Delete all existing versions first
|
||||
Arrays.stream(JsonPath.compile("$..version").<JSONArray> read(getProjectMetadata(project)).toArray())//
|
||||
.map(version -> properties.getProjectMetadataResource(project, version.toString()))//
|
||||
.peek(uri -> logger.log(project, "Deleting existing project metadata at %s…", uri)) //
|
||||
.forEach(uri -> operations.delete(uri));
|
||||
|
||||
logger.log(project, "Writing project metadata for versions %s!", versionsString);
|
||||
|
||||
// Write new ones
|
||||
List<ProjectMetadata> payload = versions.stream() //
|
||||
.map(version -> new ProjectMetadata(version, versions)) //
|
||||
.collect(Collectors.toList());
|
||||
|
||||
operations.put(resource, payload);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
|
||||
/**
|
||||
* Dummy implementation of {@link SaganClient} to just dump the request payloads into {@link System#out} instead of
|
||||
* communicating with a real server.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||
class DummySaganClient implements SaganClient {
|
||||
|
||||
Logger logger;
|
||||
ObjectWriter mapper;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.sagan.SaganClient#updateProjectMetadata(org.springframework.data.release.model.Project, org.springframework.data.release.sagan.MaintainedVersions)
|
||||
*/
|
||||
@Override
|
||||
public void updateProjectMetadata(Project project, MaintainedVersions versions) {
|
||||
|
||||
logger.log(project, "Updating released version on Sagan to %s!", versions);
|
||||
|
||||
List<ProjectMetadata> payload = versions.stream() //
|
||||
.map(it -> new ProjectMetadata(it, versions)) //
|
||||
.collect(Collectors.toList());
|
||||
|
||||
try {
|
||||
System.out.println(mapper.writeValueAsString(payload));
|
||||
} catch (JsonProcessingException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.sagan.SaganClient#getProjectMetadata(org.springframework.data.release.sagan.MaintainedVersion)
|
||||
*/
|
||||
@Override
|
||||
public String getProjectMetadata(MaintainedVersion version) {
|
||||
|
||||
try {
|
||||
return mapper.writeValueAsString(new ProjectMetadata(version, MaintainedVersions.of(version)));
|
||||
} catch (JsonProcessingException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.release.sagan.SaganClient#getProjectMetadata(org.springframework.data.release.model.Project)
|
||||
*/
|
||||
@Override
|
||||
public String getProjectMetadata(Project project) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents a maintained project version to be represented in Sagan.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value(staticConstructor = "of")
|
||||
class MaintainedVersion implements Comparable<MaintainedVersion> {
|
||||
|
||||
Project project;
|
||||
ArtifactVersion version;
|
||||
Train train;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MaintainedVersion} representing the snaphot version of the given {@link Module} and
|
||||
* {@link Train}.
|
||||
*
|
||||
* @param module must not be {@literal null}.
|
||||
* @param train must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static MaintainedVersion snapshot(Module module, Train train) {
|
||||
|
||||
Assert.notNull(module, "Module must not be null!");
|
||||
Assert.notNull(train, "Train must not be null!");
|
||||
|
||||
ArtifactVersion snapshotVersion = ArtifactVersion.of(module.getVersion()).getSnapshotVersion();
|
||||
|
||||
return MaintainedVersion.of(module.getProject(), snapshotVersion, train);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Stream} of {@link MaintainedVersion} that are related to the current one. In case the current one
|
||||
* is not a snapshot version in the first place, the next development version is added, too.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Stream<MaintainedVersion> all() {
|
||||
return version.isSnapshotVersion() ? Stream.of(this) : Stream.of(nextDevelopmentVersion(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link MaintainedVersion} for the next development version of the current one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
MaintainedVersion nextDevelopmentVersion() {
|
||||
return MaintainedVersion.of(project, version.getNextDevelopmentVersion(), train);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(MaintainedVersion o) {
|
||||
return Comparator.comparing(MaintainedVersion::getVersion).compare(this, o);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return String.format("%s - %s - %s", project.getName(), train.getName(), version);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.sagan;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Wrapper type for a {@link List} of {@link MaintainedVersion}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ToString
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
class MaintainedVersions implements Streamable<MaintainedVersion> {
|
||||
|
||||
private final List<MaintainedVersion> versions;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MaintainedVersions} with the given {@link MaintainedVersion}s in descending order (more recent
|
||||
* versions first).
|
||||
*
|
||||
* @param versions must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
static MaintainedVersions of(List<MaintainedVersion> versions) {
|
||||
|
||||
return new MaintainedVersions(versions.stream()//
|
||||
.sorted(Comparator.reverseOrder())//
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MaintainedVersions} with the given {@link MaintainedVersion}s in descending order (more recent
|
||||
* versions first).
|
||||
*
|
||||
* @param versions must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
static MaintainedVersions of(MaintainedVersion... versions) {
|
||||
return MaintainedVersions.of(Arrays.asList(versions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link MaintainedVersion} is the main version of the current set.
|
||||
*
|
||||
* @param version must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
boolean isMainVersion(MaintainedVersion version) {
|
||||
|
||||
if (!version.getVersion().isReleaseVersion()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return versions.stream() //
|
||||
.map(it -> it.getVersion()) //
|
||||
.filter(ArtifactVersion::isReleaseVersion) //
|
||||
.findFirst() //
|
||||
.map(it -> it.equals(version.getVersion())) //
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<MaintainedVersion> iterator() {
|
||||
return versions.iterator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.data.release.build.MavenArtifact;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
/**
|
||||
* Simple value object to create payloads to update project metadata in Sagan.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
class ProjectMetadata {
|
||||
|
||||
private static String DOCS_BASE = "https://docs.spring.io/spring-data/%s/docs/{version}";
|
||||
private static String DOCS = DOCS_BASE.concat("/reference/html/");
|
||||
private static String JAVADOC = DOCS_BASE.concat("/api");
|
||||
|
||||
private final MaintainedVersions versions;
|
||||
private final MaintainedVersion version;
|
||||
private final MavenArtifact artifact;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ProjectMetadata} instace from the given {@link MaintainedVersion} in the context of the
|
||||
* {@link MaintainedVersions}.
|
||||
*
|
||||
* @param version must not be {@literal null}.
|
||||
* @param versions must not be {@literal null}.
|
||||
*/
|
||||
public ProjectMetadata(MaintainedVersion version, MaintainedVersions versions) {
|
||||
|
||||
Assert.notNull(version, "MaintainedVersion must not be null!");
|
||||
Assert.notNull(versions, "MaintainedVersions must not be null!");
|
||||
|
||||
this.version = version;
|
||||
this.versions = versions;
|
||||
this.artifact = new MavenArtifact(version.getProject(), version.getVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the release status used on Sagan.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getReleaseStatus() {
|
||||
|
||||
ArtifactVersion artifactVersion = version.getVersion();
|
||||
|
||||
if (artifactVersion.isReleaseVersion()) {
|
||||
return "GENERAL_AVAILABILITY";
|
||||
}
|
||||
|
||||
if (artifactVersion.isMilestoneVersion()) {
|
||||
return "PRERELEASE";
|
||||
}
|
||||
|
||||
if (artifactVersion.isSnapshotVersion()) {
|
||||
return "SNAPSHOT";
|
||||
}
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the group identifier of the release.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getGroupId() {
|
||||
return artifact.getGroupId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the artifact identifier.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getArtifactId() {
|
||||
|
||||
if (Projects.BUILD.equals(version.getProject())) {
|
||||
return "spring-data-releasetrain";
|
||||
}
|
||||
|
||||
return artifact.getArtifactId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the version is the most current one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Boolean getCurrent() {
|
||||
return versions.isMainVersion(version) ? true : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference documentation URL for non-snapshot versions and not the build project.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getRefDocUrl() {
|
||||
|
||||
return version.getVersion().isSnapshotVersion() || Projects.BUILD.equals(version.getProject()) //
|
||||
? "" //
|
||||
: String.format(DOCS, version.getProject().getName().toLowerCase(Locale.US));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JavaDoc URL for non-snapshot versions and not the build project.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getApiDocUrl() {
|
||||
|
||||
return version.getVersion().isSnapshotVersion() || Projects.BUILD.equals(version.getProject()) //
|
||||
? "" //
|
||||
: String.format(JAVADOC, version.getProject().getName().toLowerCase(Locale.US));
|
||||
}
|
||||
|
||||
public Repository getRepository() {
|
||||
return new Repository();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the version to use. For the build project thats the release train name, for everything else the artifact
|
||||
* version.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getVersion() {
|
||||
|
||||
if (Projects.BUILD.equals(version.getProject())) {
|
||||
return String.format("%s-%s", version.getTrain().getName(), version.getVersion().getReleaseTrainSuffix());
|
||||
}
|
||||
|
||||
return version.getVersion().toString();
|
||||
}
|
||||
|
||||
public class Repository {
|
||||
|
||||
public String getId() {
|
||||
return artifact.getRepository().getId();
|
||||
}
|
||||
|
||||
public boolean isSnapshotsEnabled() {
|
||||
return version.getVersion().isSnapshotVersion();
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return artifact.getRepository().getUrl();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
String result = "Spring ";
|
||||
|
||||
if (version.getVersion().isMilestoneVersion()) {
|
||||
return result.concat("Milestones");
|
||||
}
|
||||
|
||||
if (version.getVersion().isReleaseVersion()) {
|
||||
return result.concat("Releases");
|
||||
}
|
||||
|
||||
if (isSnapshotsEnabled()) {
|
||||
return result.concat("Snapshots");
|
||||
}
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import org.springframework.data.release.model.Project;
|
||||
|
||||
/**
|
||||
* Interface to abstract the actual interaction with the Sagan server.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
interface SaganClient {
|
||||
|
||||
/**
|
||||
* Returns the project metadata for the given {@link MaintainedVersion}.
|
||||
*
|
||||
* @param version must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
String getProjectMetadata(MaintainedVersion version);
|
||||
|
||||
/**
|
||||
* Returns all project release metadata for the given {@link Project}.
|
||||
*
|
||||
* @param project must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
String getProjectMetadata(Project project);
|
||||
|
||||
/**
|
||||
* Updates the project metadata for the given {@link Project} to the given {@link MaintainedVersions}.
|
||||
*
|
||||
* @param project must not be {@literal null}.
|
||||
* @param versions must not be {@literal null}.
|
||||
*/
|
||||
void updateProjectMetadata(Project project, MaintainedVersions versions);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.release.CliComponent;
|
||||
import org.springframework.data.release.TimedCommand;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Operations for Sagan interaction.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@CliComponent
|
||||
@RequiredArgsConstructor
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||
class SaganCommands extends TimedCommand {
|
||||
|
||||
SaganOperations sagan;
|
||||
|
||||
@CliCommand("sagan update")
|
||||
public void updateProjectInformation(@CliOption(key = "", mandatory = true) String trains) {
|
||||
|
||||
sagan.updateProjectMetadata(Stream.of(trains.split(","))//
|
||||
.map(train -> ReleaseTrains.getTrainByName(train)) //
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
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.git.GitOperations;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
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 for the Sagan interaction subsystem.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
class SaganConfiguration {
|
||||
|
||||
@Autowired SaganProperties properties;
|
||||
@Autowired Logger logger;
|
||||
|
||||
@Bean
|
||||
public SaganOperations saganOperations(GitOperations operations) {
|
||||
return new SaganOperations(operations, saganClient(), logger);
|
||||
}
|
||||
|
||||
@Bean
|
||||
SaganClient saganClient() {
|
||||
|
||||
return new DefaultSaganClient(saganRestTemplate(), properties, logger);
|
||||
// return new DummySaganClient(logger, new ObjectMapper().writerWithDefaultPrettyPrinter());
|
||||
}
|
||||
|
||||
@Bean
|
||||
RestTemplate saganRestTemplate() {
|
||||
|
||||
RestTemplate template = new RestTemplate();
|
||||
template.setInterceptors(Arrays.asList(new AuthenticatingClientHttpRequestInterceptor(properties)));
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class AuthenticatingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private final @NonNull SaganProperties properties;
|
||||
|
||||
/*
|
||||
* (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(HttpHeaders.AUTHORIZATION, properties.getCredentials().toString());
|
||||
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.release.git.GitOperations;
|
||||
import org.springframework.data.release.git.Tag;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.data.release.model.Version;
|
||||
import org.springframework.data.release.utils.ListWrapperCollector;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||
class SaganOperations {
|
||||
|
||||
private static final List<Project> TO_FILTER = Arrays.asList(Projects.COMMONS, //
|
||||
Projects.GEODE, //
|
||||
Projects.KEY_VALUE);
|
||||
|
||||
GitOperations git;
|
||||
SaganClient client;
|
||||
Logger logger;
|
||||
|
||||
/**
|
||||
* Updates the project metadata for the modules in the given release {@link Train}s.
|
||||
*
|
||||
* @param trains must not be {@literal null}.
|
||||
*/
|
||||
void updateProjectMetadata(Train... trains) {
|
||||
|
||||
Assert.notNull(trains, "Trains must not be null!");
|
||||
|
||||
updateProjectMetadata(Arrays.asList(trains));
|
||||
}
|
||||
|
||||
void updateProjectMetadata(List<Train> trains) {
|
||||
|
||||
Assert.notNull(trains, "Trains must not be null!");
|
||||
|
||||
findVersions(trains).forEach(client::updateProjectMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link MaintainedVersions} grouped by {@link Project} for the given release {@link Train}.
|
||||
*
|
||||
* @param trains must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
Map<Project, MaintainedVersions> findVersions(Train... trains) {
|
||||
|
||||
Assert.notNull(trains, "Trains must not be null!");
|
||||
|
||||
return findVersions(Arrays.asList(trains));
|
||||
}
|
||||
|
||||
Map<Project, MaintainedVersions> findVersions(List<Train> trains) {
|
||||
|
||||
Assert.notNull(trains, "Trains must not be null!");
|
||||
|
||||
return trains.stream() //
|
||||
.flatMap(train -> train.stream()//
|
||||
.filter(module -> !TO_FILTER.contains(module.getProject())) //
|
||||
.map(module -> getLatestVersion(module, train)) //
|
||||
.flatMap(MaintainedVersion::all)) //
|
||||
.collect(
|
||||
Collectors.groupingBy(it -> it.getProject(), ListWrapperCollector.collectInto(MaintainedVersions::of)));
|
||||
}
|
||||
|
||||
private MaintainedVersion getLatestVersion(Module module, Train train) {
|
||||
|
||||
Project project = module.getProject();
|
||||
|
||||
MaintainedVersion version = git.getTags(project).stream()//
|
||||
.filter(tag -> matches(tag, module.getVersion())) //
|
||||
.sorted(Comparator.reverseOrder()) //
|
||||
.findFirst() //
|
||||
.flatMap(tag -> tag.toArtifactVersion()) //
|
||||
.map(it -> MaintainedVersion.of(module.getProject(), it, train)) //
|
||||
.orElseGet(() -> MaintainedVersion.snapshot(module, train));
|
||||
|
||||
logger.log(project, "Found version %s for train %s!", version.getVersion(), train.getName());
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link Tag} is one that logically belongs to the given version.
|
||||
*
|
||||
* @param tag must not be {@literal null}.
|
||||
* @param version must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static boolean matches(Tag tag, Version version) {
|
||||
|
||||
return tag.toArtifactVersion()//
|
||||
.map(it -> it.isVersionWithin(version))//
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import lombok.Setter;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.data.release.model.Password;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.utils.HttpBasicCredentials;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
|
||||
/**
|
||||
* Configuration properties for the Sagan instance to talk to.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "sagan")
|
||||
class SaganProperties {
|
||||
|
||||
private static String SAGAN_PROJECT_METADATA = "https://spring.io/project_metadata/{project}/releases";
|
||||
private static String SAGAN_PROJECT_VERSION_METADATA = SAGAN_PROJECT_METADATA.concat("/{version}");
|
||||
|
||||
@Setter String key;
|
||||
|
||||
/**
|
||||
* Returns the {@link HttpBasicCredentials} to be used when talking to the server.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
HttpBasicCredentials getCredentials() {
|
||||
return new HttpBasicCredentials(key, Password.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URI to the resource exposing the project metadata for the given {@link Project}.
|
||||
*
|
||||
* @param project must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
URI getProjectMetadataResource(Project project) {
|
||||
|
||||
Assert.notNull(project, "Project must not be null!");
|
||||
|
||||
return new UriTemplate(SAGAN_PROJECT_METADATA).expand(getProjectPathSegment(project));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URI to the resource exposing the project metadata for the given {@link Project} and version
|
||||
* {@link String}.
|
||||
*
|
||||
* @param project must not be {@literal null}.
|
||||
* @param version must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
URI getProjectMetadataResource(Project project, String version) {
|
||||
|
||||
Assert.notNull(project, "Project must not be null!");
|
||||
Assert.hasText(version, "Version must not be null!");
|
||||
|
||||
return new UriTemplate(SAGAN_PROJECT_VERSION_METADATA).expand(getProjectPathSegment(project), version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link URI} to the resource exposing the project metadata for the given {@link MaintainedVersion}.
|
||||
*
|
||||
* @param version must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
URI getProjectMetadataResource(MaintainedVersion version) {
|
||||
return getProjectMetadataResource(version.getProject(), version.getVersion().toString());
|
||||
}
|
||||
|
||||
private static String getProjectPathSegment(Project project) {
|
||||
return Projects.BUILD.equals(project) ? "spring-data" : project.getFolderName();
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.release.utils;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -28,8 +29,8 @@ import org.springframework.data.release.model.Password;
|
||||
@Value
|
||||
public class HttpBasicCredentials {
|
||||
|
||||
private final String username;
|
||||
private final Password password;
|
||||
private final @NonNull String username;
|
||||
private final @NonNull Password password;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2017 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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collector;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class to easily create a {@link Collector} to create a collection wrapper type.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class ListWrapperCollector<T, S> implements Collector<T, List<T>, S> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Collector} to eventually apply the given function to turn the {@link List} of elements into a
|
||||
* wrapper type.
|
||||
*
|
||||
* @param function must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static <T, S> ListWrapperCollector<T, S> collectInto(Function<List<T>, S> function) {
|
||||
|
||||
Assert.notNull(function, "Finisher function must not be null!");
|
||||
|
||||
return new ListWrapperCollector<T, S>() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#finisher()
|
||||
*/
|
||||
@Override
|
||||
public Function<List<T>, S> finisher() {
|
||||
return function;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#supplier()
|
||||
*/
|
||||
@Override
|
||||
public Supplier<List<T>> supplier() {
|
||||
return ArrayList::new;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#accumulator()
|
||||
*/
|
||||
@Override
|
||||
public BiConsumer<List<T>, T> accumulator() {
|
||||
return List::add;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#combiner()
|
||||
*/
|
||||
@Override
|
||||
public BinaryOperator<List<T>> combiner() {
|
||||
return (left, right) -> {
|
||||
left.addAll(right);
|
||||
return left;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#characteristics()
|
||||
*/
|
||||
@Override
|
||||
public Set<Characteristics> characteristics() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MaintainedVersion}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MaintainedVersionUnitTests {
|
||||
|
||||
@Test
|
||||
public void newerVersionIsOrderedFirst() {
|
||||
|
||||
MaintainedVersion ingalls = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.13.0.RELEASE"),
|
||||
ReleaseTrains.INGALLS);
|
||||
MaintainedVersion hopper = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.12.0.RELEASE"),
|
||||
ReleaseTrains.HOPPER);
|
||||
|
||||
assertThat(ingalls.compareTo(hopper)).isGreaterThan(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MaintainedVersions}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MaintainedVersionsUnitTests {
|
||||
|
||||
@Test
|
||||
public void considersMostRecentReleaseVersionTheMainOne() {
|
||||
|
||||
MaintainedVersion ingalls = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.13.0.RELEASE"),
|
||||
ReleaseTrains.INGALLS);
|
||||
MaintainedVersion hopper = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.12.0.RELEASE"),
|
||||
ReleaseTrains.HOPPER);
|
||||
|
||||
MaintainedVersions versions = MaintainedVersions.of(ingalls, hopper);
|
||||
|
||||
assertThat(versions.isMainVersion(ingalls)).isTrue();
|
||||
assertThat(versions.isMainVersion(hopper)).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
|
||||
/**
|
||||
* Tests for serialization of {@link ProjectMetadata}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ProjectMetadataSerializationTests {
|
||||
|
||||
@Test
|
||||
public void serializesMaintainedVersionsIntoProjectMetadata() throws Exception {
|
||||
|
||||
ObjectWriter mapper = new ObjectMapper().writerWithDefaultPrettyPrinter();
|
||||
|
||||
MaintainedVersion kay = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("2.0.0.RC1"), ReleaseTrains.KAY);
|
||||
MaintainedVersion ingalls = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.13.5.RELEASE"),
|
||||
ReleaseTrains.INGALLS);
|
||||
MaintainedVersion ingallsSnapshot = ingalls.nextDevelopmentVersion();
|
||||
MaintainedVersion hopper = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.12.8.RELEASE"),
|
||||
ReleaseTrains.HOPPER);
|
||||
|
||||
MaintainedVersions versions = MaintainedVersions.of(kay, ingalls, ingallsSnapshot, hopper);
|
||||
|
||||
System.out.println(mapper.writeValueAsString(new ProjectMetadata(kay, versions)));
|
||||
System.out.println(mapper.writeValueAsString(new ProjectMetadata(ingallsSnapshot, versions)));
|
||||
System.out.println(mapper.writeValueAsString(new ProjectMetadata(ingalls, versions)));
|
||||
System.out.println(mapper.writeValueAsString(new ProjectMetadata(hopper, versions)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2017 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.sagan;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.AbstractIntegrationTests;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
import org.springframework.data.release.model.ReleaseTrains;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link SaganOperations}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SaganOperationsIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
@Autowired SaganOperations sagan;
|
||||
@Autowired SaganClient client;
|
||||
|
||||
@Test
|
||||
public void detectVersionsToUpdate() {
|
||||
|
||||
sagan.findVersions(ReleaseTrains.LOVELACE, ReleaseTrains.KAY, ReleaseTrains.INGALLS, ReleaseTrains.HOPPER)
|
||||
.forEach((project, versions) -> {
|
||||
|
||||
System.out.println(project.getName());
|
||||
System.out.println("-----");
|
||||
|
||||
versions.forEach(version -> {
|
||||
|
||||
String output = version.toString();
|
||||
System.out.println(versions.isMainVersion(version) ? output.concat(" (main release)") : output);
|
||||
});
|
||||
|
||||
System.out.println();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVersions() {
|
||||
sagan.updateProjectMetadata(ReleaseTrains.KAY, ReleaseTrains.INGALLS, ReleaseTrains.HOPPER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateJpa() {
|
||||
|
||||
MaintainedVersions versions = sagan.findVersions(ReleaseTrains.KAY, ReleaseTrains.INGALLS, ReleaseTrains.HOPPER)
|
||||
.get(Projects.JPA);
|
||||
|
||||
System.out.println(versions);
|
||||
|
||||
client.updateProjectMetadata(Projects.JPA, versions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getJpa() {
|
||||
System.out.println(client.getProjectMetadata(Projects.JPA));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateBuild() {
|
||||
|
||||
MaintainedVersions versions = sagan.findVersions(ReleaseTrains.KAY, ReleaseTrains.INGALLS, ReleaseTrains.HOPPER)
|
||||
.get(Projects.BUILD);
|
||||
|
||||
client.updateProjectMetadata(Projects.BUILD, versions);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user