[sdkman] rework how packager and announcer work together. Resolves #319

This commit is contained in:
Andres Almiray
2021-07-30 01:16:39 +02:00
parent 061e34eefa
commit ae0bd21030
16 changed files with 196 additions and 34 deletions

View File

@@ -24,9 +24,9 @@ import org.jreleaser.model.announcer.spi.Announcer;
import org.jreleaser.model.announcer.spi.AnnouncerBuilder;
import org.jreleaser.model.announcer.spi.AnnouncerBuilderFactory;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@@ -90,7 +90,7 @@ public class Announcers {
Announcers.class.getClassLoader()).spliterator(), false)
.collect(Collectors.toMap(AnnouncerBuilderFactory::getName, AnnouncerBuilderFactory::getBuilder));
Map<String, Announcer> announcers = new LinkedHashMap<>();
Map<String, Announcer> announcers = new TreeMap<>();
builders.forEach((name, builder) -> {
if (null != model.getAnnounce().findAnnouncer(name)) {
announcers.put(name, builder.configureWith(context).build());

View File

@@ -44,6 +44,7 @@ public class Sdkman extends AbstractTool implements TimeoutAware {
private String consumerToken;
private int connectTimeout;
private int readTimeout;
private boolean published;
public Sdkman() {
super(NAME);
@@ -58,6 +59,7 @@ public class Sdkman extends AbstractTool implements TimeoutAware {
this.consumerToken = sdkman.consumerToken;
this.connectTimeout = sdkman.connectTimeout;
this.readTimeout = sdkman.readTimeout;
this.published = sdkman.published;
}
public String getResolvedConsumerKey() {
return Env.resolve(SDKMAN_CONSUMER_KEY, consumerKey);
@@ -135,6 +137,14 @@ public class Sdkman extends AbstractTool implements TimeoutAware {
this.readTimeout = readTimeout;
}
public boolean isPublished() {
return published;
}
public void setPublished(boolean published) {
this.published = published;
}
@Override
protected void asMap(boolean full, Map<String, Object> props) {
props.put("candidate", candidate);

View File

@@ -38,7 +38,7 @@ public class SdkmanAnnouncer extends AbstractAnnouncer {
private String consumerToken;
private String candidate;
private String releaseNotesUrl;
private boolean major = true;
private Sdkman.Command command;
public SdkmanAnnouncer() {
super(NAME);
@@ -50,7 +50,7 @@ public class SdkmanAnnouncer extends AbstractAnnouncer {
this.consumerToken = sdkman.consumerToken;
this.candidate = sdkman.candidate;
this.releaseNotesUrl = sdkman.releaseNotesUrl;
this.major = sdkman.major;
this.command = sdkman.command;
}
@Override
@@ -98,12 +98,29 @@ public class SdkmanAnnouncer extends AbstractAnnouncer {
this.releaseNotesUrl = releaseNotesUrl;
}
public Sdkman.Command getCommand() {
return command;
}
public void setCommand(Sdkman.Command command) {
this.command = command;
}
public void setCommand(String str) {
this.command = Sdkman.Command.of(str);
}
public boolean isCommandSet() {
return command != null;
}
public boolean isMajor() {
return major;
return command == Sdkman.Command.MAJOR;
}
public void setMajor(boolean major) {
this.major = major;
System.out.println("announce.sdkman.major has been deprecated since 0.6.0 and will be removed in the future. Use announce.sdkman.command instead");
this.command = major? Sdkman.Command.MAJOR: Sdkman.Command.MINOR;
}
@Override
@@ -112,6 +129,6 @@ public class SdkmanAnnouncer extends AbstractAnnouncer {
props.put("consumerToken", isNotBlank(getResolvedConsumerToken()) ? HIDE : UNSET);
props.put("candidate", candidate);
props.put("releaseNotesUrl", releaseNotesUrl);
props.put("major", major);
props.put("command", command);
}
}

View File

@@ -17,7 +17,9 @@
*/
package org.jreleaser.model.validation;
import org.jreleaser.model.Active;
import org.jreleaser.model.JReleaserContext;
import org.jreleaser.model.Sdkman;
import org.jreleaser.model.SdkmanAnnouncer;
import org.jreleaser.util.Errors;
@@ -31,6 +33,12 @@ import static org.jreleaser.util.StringUtils.isBlank;
*/
public abstract class SdkmanAnnouncerValidator extends Validator {
public static void validateSdkmanAnnouncer(JReleaserContext context, SdkmanAnnouncer sdkman, Errors errors) {
// activate if there are any active distributions with Sdkman packager enabled
context.getModel().getActiveDistributions().stream()
.filter(d -> d.getSdkman().isEnabled())
.findFirst()
.ifPresent(distribution -> sdkman.setActive(Active.ALWAYS));
if (!sdkman.resolveEnabled(context.getModel().getProject())) return;
if (!context.getModel().getRelease().getGitService().isReleaseSupported()) {
sdkman.disable();
@@ -64,15 +72,10 @@ public abstract class SdkmanAnnouncerValidator extends Validator {
sdkman.disable();
}
validateTimeout(sdkman);
if (null == sdkman.getCommand()) {
sdkman.setCommand(Sdkman.Command.MAJOR);
}
context.getModel().getActiveDistributions().stream()
.filter(d -> d.getSdkman().isEnabled())
.findFirst()
.ifPresent(distribution -> {
errors.configuration("announce.sdkman and distribution." +
distribution.getName() +
".sdkman are mutually exclusive. Please remove one of them.");
});
validateTimeout(sdkman);
}
}

View File

@@ -33,6 +33,7 @@ import static org.jreleaser.model.Sdkman.SDKMAN_CONSUMER_KEY;
import static org.jreleaser.model.Sdkman.SDKMAN_CONSUMER_TOKEN;
import static org.jreleaser.model.validation.DistributionsValidator.validateArtifactPlatforms;
import static org.jreleaser.model.validation.ExtraPropertiesValidator.mergeExtraProperties;
import static org.jreleaser.util.Constants.MAGIC_SET;
import static org.jreleaser.util.StringUtils.isBlank;
/**
@@ -44,6 +45,10 @@ public abstract class SdkmanValidator extends Validator {
JReleaserModel model = context.getModel();
Sdkman parentTool = model.getPackagers().getSdkman();
boolean toolSet = tool.isActiveSet();
boolean parentToolSet = parentTool.isActiveSet();
tool.getExtraProperties().put(MAGIC_SET, toolSet && parentToolSet);
if (!tool.isActiveSet() && parentTool.isActiveSet()) {
tool.setActive(parentTool.getActive());
}
@@ -103,6 +108,14 @@ public abstract class SdkmanValidator extends Validator {
public static void postValidateSdkman(JReleaserContext context, Errors errors) {
Map<String, List<Distribution>> map = context.getModel().getDistributions().values().stream()
.peek(distribution -> {
if (distribution.getSdkman().getExtraProperties().containsKey(MAGIC_SET)) {
boolean set = (boolean) distribution.getSdkman().getExtraProperties().remove(MAGIC_SET);
if (set) {
context.getModel().getAnnounce().getSdkman().getExtraProperties().put(MAGIC_SET, set);
}
}
})
.filter(d -> d.isEnabled() && d.getSdkman().isEnabled())
.collect(groupingBy(d -> d.getSdkman().getCandidate()));

View File

@@ -89,7 +89,7 @@ public class SdkmanToolProcessor extends AbstractToolProcessor<Sdkman> {
switch (sdkman.getCommand()) {
case MAJOR:
context.getLogger().info("Announcing major release of '{}' candidate", candidate);
context.getLogger().info("publishing major release of '{}' candidate", candidate);
MajorReleaseSdkmanCommand.builder(context.getLogger())
.connectTimeout(sdkman.getConnectTimeout())
.readTimeout(sdkman.getReadTimeout())
@@ -100,11 +100,12 @@ public class SdkmanToolProcessor extends AbstractToolProcessor<Sdkman> {
.platforms(platforms)
.releaseNotesUrl(releaseNotesUrl)
.dryrun(context.isDryrun())
.skipAnnounce(true)
.build()
.execute();
break;
case MINOR:
context.getLogger().info("Announcing minor release of '{}' candidate", candidate);
context.getLogger().info("publishing minor release of '{}' candidate", candidate);
MinorReleaseSdkmanCommand.builder(context.getLogger())
.connectTimeout(sdkman.getConnectTimeout())
.readTimeout(sdkman.getReadTimeout())
@@ -115,10 +116,13 @@ public class SdkmanToolProcessor extends AbstractToolProcessor<Sdkman> {
.platforms(platforms)
.releaseNotesUrl(releaseNotesUrl)
.dryrun(context.isDryrun())
.skipAnnounce(true)
.build()
.execute();
break;
}
sdkman.setPublished(true);
} catch (SdkmanException e) {
throw new ToolProcessingException(e);
}

View File

@@ -25,6 +25,8 @@ public interface Constants {
String UNSET = "**unset**";
String HIDE = "************";
String MAGIC_SET = "__MAGIC_SET__";
// General
String KEY_ZONED_DATE_TIME_NOW = "__ZonedDateTime_now__";
String KEY_TIMESTAMP = "timestamp";

View File

@@ -36,4 +36,8 @@ interface SdkmanAnnouncer extends Announcer {
Property<String> getReleaseNotesUrl()
Property<Boolean> getMajor()
Property<org.jreleaser.model.Sdkman.Command> getCommand()
void setCommand(String str)
}

View File

@@ -26,6 +26,8 @@ import org.jreleaser.model.SdkmanAnnouncer
import javax.inject.Inject
import static org.jreleaser.util.StringUtils.isNotBlank
/**
*
* @author Andres Almiray
@@ -38,6 +40,7 @@ class SdkmanAnnouncerImpl extends AbstractAnnouncer implements org.jreleaser.gra
final Property<String> candidate
final Property<String> releaseNotesUrl
final Property<Boolean> major
final Property<org.jreleaser.model.Sdkman.Command> command
@Inject
SdkmanAnnouncerImpl(ObjectFactory objects) {
@@ -49,6 +52,13 @@ class SdkmanAnnouncerImpl extends AbstractAnnouncer implements org.jreleaser.gra
major = objects.property(Boolean).convention(Providers.notDefined())
}
@Override
void setCommand(String str) {
if (isNotBlank(str)) {
command.set(org.jreleaser.model.Sdkman.Command.of(str.trim()))
}
}
@Override
@Internal
boolean isSet() {
@@ -57,7 +67,8 @@ class SdkmanAnnouncerImpl extends AbstractAnnouncer implements org.jreleaser.gra
consumerToken.present ||
candidate.present ||
releaseNotesUrl.present ||
major.present
major.present ||
command.present
}
SdkmanAnnouncer toModel() {
@@ -67,6 +78,7 @@ class SdkmanAnnouncerImpl extends AbstractAnnouncer implements org.jreleaser.gra
if (consumerToken.present) sdkman.consumerToken = consumerToken.get()
if (candidate.present) sdkman.candidate = candidate.get()
if (releaseNotesUrl.present) sdkman.releaseNotesUrl = releaseNotesUrl.get()
if (command.present) sdkman.command = command.get()
sdkman.major = major.getOrElse(true)
sdkman
}

View File

@@ -29,6 +29,7 @@ public class SdkmanAnnouncer extends AbstractAnnouncer {
private String candidate;
private String releaseNotesUrl;
private boolean major = true;
private Sdkman.Command command;
void setAll(SdkmanAnnouncer sdkman) {
super.setAll(sdkman);
@@ -37,6 +38,7 @@ public class SdkmanAnnouncer extends AbstractAnnouncer {
this.candidate = sdkman.candidate;
this.releaseNotesUrl = sdkman.releaseNotesUrl;
this.major = sdkman.major;
this.command = sdkman.command;
}
public String getConsumerKey() {
@@ -79,12 +81,33 @@ public class SdkmanAnnouncer extends AbstractAnnouncer {
this.major = major;
}
public Sdkman.Command getCommand() {
return command;
}
public void setCommand(Sdkman.Command command) {
this.command = command;
}
public void setCommand(String str) {
this.command = Sdkman.Command.of(str);
}
public String resolveCommand() {
return command != null ? command.name() : null;
}
public boolean isCommandSet() {
return command != null;
}
@Override
public boolean isSet() {
return super.isSet() ||
isNotBlank(consumerKey) ||
isNotBlank(consumerToken) ||
isNotBlank(candidate) ||
isNotBlank(releaseNotesUrl);
isNotBlank(releaseNotesUrl) ||
null != command;
}
}

View File

@@ -554,6 +554,7 @@ public final class JReleaserModelConverter {
a.setCandidate(sdkman.getCandidate());
a.setReleaseNotesUrl(sdkman.getReleaseNotesUrl());
a.setMajor(sdkman.isMajor());
a.setCommand(sdkman.resolveCommand());
return a;
}

View File

@@ -50,6 +50,7 @@ abstract class AbstractSdkmanCommand implements SdkmanCommand {
static class Builder<S extends Builder<S>> {
protected final JReleaserLogger logger;
protected boolean dryrun;
protected boolean skipAnnounce;
protected String consumerKey;
protected String consumerToken;
protected String candidate;
@@ -72,6 +73,11 @@ abstract class AbstractSdkmanCommand implements SdkmanCommand {
return self();
}
public S skipAnnounce(boolean skipAnnounce) {
this.skipAnnounce = skipAnnounce;
return self();
}
/**
* The SDK consumer key
*/

View File

@@ -31,6 +31,7 @@ import static org.jreleaser.util.StringUtils.requireNonBlank;
* @since 0.1.0
*/
public class MajorReleaseSdkmanCommand extends AbstractSdkmanCommand {
private final boolean skipAnnounce;
private final String hashtag;
private final String releaseNotesUrl;
private final Map<String, String> platforms = new LinkedHashMap<>();
@@ -44,18 +45,20 @@ public class MajorReleaseSdkmanCommand extends AbstractSdkmanCommand {
String candidate,
String version,
boolean dryrun,
boolean skipAnnounce,
String hashtag,
String releaseNotesUrl,
Map<String, String> platforms) {
super(logger, apiHost, connectTimeout, readTimeout, consumerKey, consumerToken, candidate, version, dryrun);
this.hashtag = hashtag;
this.skipAnnounce = skipAnnounce;
this.releaseNotesUrl = releaseNotesUrl;
this.platforms.putAll(platforms);
}
@Override
public void execute() throws SdkmanException {
sdkman.majorRelease(candidate, version, platforms, hashtag, releaseNotesUrl);
sdkman.majorRelease(candidate, version, platforms, hashtag, releaseNotesUrl, skipAnnounce);
}
public static Builder builder(JReleaserLogger logger) {
@@ -149,6 +152,7 @@ public class MajorReleaseSdkmanCommand extends AbstractSdkmanCommand {
candidate,
version,
dryrun,
skipAnnounce,
hashtag,
releaseNotesUrl,
platforms);

View File

@@ -31,6 +31,7 @@ import static org.jreleaser.util.StringUtils.requireNonBlank;
* @since 0.1.0
*/
public class MinorReleaseSdkmanCommand extends AbstractSdkmanCommand {
private final boolean skipAnnounce;
private final String hashtag;
private final String releaseNotesUrl;
private final Map<String, String> platforms = new LinkedHashMap<>();
@@ -44,10 +45,12 @@ public class MinorReleaseSdkmanCommand extends AbstractSdkmanCommand {
String candidate,
String version,
boolean dryrun,
boolean skipAnnounce,
String hashtag,
String releaseNotesUrl,
Map<String, String> platforms) {
super(logger, apiHost, connectTimeout, readTimeout, consumerKey, consumerToken, candidate, version, dryrun);
this.skipAnnounce = skipAnnounce;
this.hashtag = hashtag;
this.releaseNotesUrl = releaseNotesUrl;
this.platforms.putAll(platforms);
@@ -55,7 +58,7 @@ public class MinorReleaseSdkmanCommand extends AbstractSdkmanCommand {
@Override
public void execute() throws SdkmanException {
sdkman.minorRelease(candidate, version, platforms, hashtag, releaseNotesUrl);
sdkman.minorRelease(candidate, version, platforms, hashtag, releaseNotesUrl, skipAnnounce);
}
public static Builder builder(JReleaserLogger logger) {
@@ -149,6 +152,7 @@ public class MinorReleaseSdkmanCommand extends AbstractSdkmanCommand {
candidate,
version,
dryrun,
skipAnnounce,
hashtag,
releaseNotesUrl,
platforms);

View File

@@ -127,10 +127,11 @@ public class Sdkman {
String version,
String url,
String hashtag,
String releaseNotesUrl) throws SdkmanException {
String releaseNotesUrl,
boolean skipAnnounce) throws SdkmanException {
Map<String, String> platforms = new LinkedHashMap<>();
platforms.put("UNIVERSAL", url);
majorRelease(candidate, version, platforms, hashtag, releaseNotesUrl);
majorRelease(candidate, version, platforms, hashtag, releaseNotesUrl, skipAnnounce);
}
public void majorRelease(String candidate,
@@ -138,19 +139,21 @@ public class Sdkman {
String platform,
String url,
String hashtag,
String releaseNotesUrl) throws SdkmanException {
String releaseNotesUrl,
boolean skipAnnounce) throws SdkmanException {
Map<String, String> platforms = new LinkedHashMap<>();
platforms.put(platform, url);
majorRelease(candidate, version, platforms, hashtag, releaseNotesUrl);
majorRelease(candidate, version, platforms, hashtag, releaseNotesUrl, skipAnnounce);
}
public void majorRelease(String candidate,
String version,
Map<String, String> platforms,
String hashtag,
String releaseNotesUrl) throws SdkmanException {
String releaseNotesUrl,
boolean skipAnnounce) throws SdkmanException {
release(candidate, version, platforms);
announce(candidate, version, hashtag, releaseNotesUrl);
if (!skipAnnounce) announce(candidate, version, hashtag, releaseNotesUrl);
setDefault(candidate, version);
}
@@ -158,10 +161,11 @@ public class Sdkman {
String version,
String url,
String hashtag,
String releaseNotesUrl) throws SdkmanException {
String releaseNotesUrl,
boolean skipAnnounce) throws SdkmanException {
Map<String, String> platforms = new LinkedHashMap<>();
platforms.put("UNIVERSAL", url);
minorRelease(candidate, version, platforms, hashtag, releaseNotesUrl);
minorRelease(candidate, version, platforms, hashtag, releaseNotesUrl, skipAnnounce);
}
public void minorRelease(String candidate,
@@ -169,19 +173,21 @@ public class Sdkman {
String platform,
String url,
String hashtag,
String releaseNotesUrl) throws SdkmanException {
String releaseNotesUrl,
boolean skipAnnounce) throws SdkmanException {
Map<String, String> platforms = new LinkedHashMap<>();
platforms.put(platform, url);
minorRelease(candidate, version, platforms, hashtag, releaseNotesUrl);
minorRelease(candidate, version, platforms, hashtag, releaseNotesUrl, skipAnnounce);
}
public void minorRelease(String candidate,
String version,
Map<String, String> platforms,
String hashtag,
String releaseNotesUrl) throws SdkmanException {
String releaseNotesUrl,
boolean skipAnnounce) throws SdkmanException {
release(candidate, version, platforms);
announce(candidate, version, hashtag, releaseNotesUrl);
if (!skipAnnounce) announce(candidate, version, hashtag, releaseNotesUrl);
}
private void wrap(Runnable runnable) throws SdkmanException {

View File

@@ -20,12 +20,15 @@ package org.jreleaser.sdk.sdkman;
import org.jreleaser.model.Artifact;
import org.jreleaser.model.Distribution;
import org.jreleaser.model.JReleaserContext;
import org.jreleaser.model.Sdkman;
import org.jreleaser.model.announcer.spi.AnnounceException;
import org.jreleaser.model.announcer.spi.Announcer;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import static org.jreleaser.util.Constants.MAGIC_SET;
import static org.jreleaser.util.MustacheUtils.applyTemplate;
import static org.jreleaser.util.StringUtils.isBlank;
import static org.jreleaser.util.StringUtils.isNotBlank;
@@ -54,6 +57,56 @@ public class SdkmanAnnouncer implements Announcer {
@Override
public void announce() throws AnnounceException {
Map<String, Distribution> distributions = context.getModel().getActiveDistributions().stream()
.filter(d -> d.getSdkman().isEnabled())
.filter(d -> d.getSdkman().isPublished())
.collect(Collectors.toMap(distribution -> {
Sdkman sdkman = distribution.getSdkman();
return isNotBlank(sdkman.getCandidate()) ? sdkman.getCandidate().trim() : context.getModel().getProject().getName();
}, distribution -> distribution));
Boolean set = (Boolean) context.getModel().getAnnounce().getSdkman().getExtraProperties().remove(MAGIC_SET);
if (distributions.isEmpty() && (set != null && !set)) {
announceProject();
return;
}
boolean failures = false;
for (Map.Entry<String, Distribution> e : distributions.entrySet()) {
String candidate = e.getKey();
Distribution distribution = e.getValue();
Sdkman sdkman = distribution.getSdkman();
Map<String, Object> props = context.props();
props.putAll(distribution.props());
String releaseNotesUrl = applyTemplate(sdkman.getReleaseNotesUrl(), props);
String command = sdkman.getCommand().name().toLowerCase();
context.getLogger().info("announcing {} release of '{}' candidate", command, candidate);
try {
AnnounceSdkmanCommand.builder(context.getLogger())
.connectTimeout(sdkman.getConnectTimeout())
.readTimeout(sdkman.getReadTimeout())
.consumerKey(context.isDryrun() ? "**UNDEFINED**" : sdkman.getResolvedConsumerKey())
.consumerToken(context.isDryrun() ? "**UNDEFINED**" : sdkman.getResolvedConsumerToken())
.candidate(candidate)
.version(context.getModel().getProject().getVersion())
.releaseNotesUrl(releaseNotesUrl)
.dryrun(context.isDryrun())
.build()
.execute();
} catch (SdkmanException x) {
context.getLogger().warn(x.getMessage().trim());
failures = true;
}
}
if (failures) {
throw new AnnounceException("Failed to announce some candidates.");
}
}
private void announceProject() throws AnnounceException {
org.jreleaser.model.SdkmanAnnouncer sdkman = context.getModel().getAnnounce().getSdkman();
Map<String, String> platforms = new LinkedHashMap<>();