diff --git a/src/main/java/nz/co/jammehcow/jenkinsdiscord/DiscordPipelineStep.java b/src/main/java/nz/co/jammehcow/jenkinsdiscord/DiscordPipelineStep.java index 2183f68..1a9b933 100644 --- a/src/main/java/nz/co/jammehcow/jenkinsdiscord/DiscordPipelineStep.java +++ b/src/main/java/nz/co/jammehcow/jenkinsdiscord/DiscordPipelineStep.java @@ -10,7 +10,6 @@ import hudson.model.Result; import hudson.model.Run; import hudson.model.TaskListener; -import java.util.List; import javax.inject.Inject; import jenkins.model.JenkinsLocationConfiguration; import nz.co.jammehcow.jenkinsdiscord.exception.WebhookException; @@ -35,7 +34,7 @@ public class DiscordPipelineStep extends AbstractStepImpl { private String notes; private String customAvatarUrl; private String customUsername; - private List fields; + private DynamicFieldContainer dynamicFieldContainer; private boolean successful; private boolean unstable; private boolean enableArtifactsList; @@ -187,12 +186,15 @@ public String getScmWebUrl() { } @DataBoundSetter - public void setFields(List fields) { - this.fields = fields; + public void setDynamicFieldContainer(String fieldsString) { + this.dynamicFieldContainer = DynamicFieldContainer.of(fieldsString); } - public List getFields() { - return fields; + public String getDynamicFieldContainer() { + if(dynamicFieldContainer == null){ + return ""; + } + return dynamicFieldContainer.toString(); } public static class DiscordPipelineStepExecution extends AbstractSynchronousNonBlockingStepExecution { @@ -259,12 +261,8 @@ protected Void run() throws Exception { wh.setCustomUsername(step.getCustomUsername()); } - // Add all key value field pairs to the webhook by splitting them with the delimiter - if (step.fields != null) { - step.fields.stream() - .map(s -> s.split(":")) - .forEach(pair -> wh.addField(pair[0], pair[1])); - } + // Add all key value field pairs to the webhook + addDynamicFieldsToWebhook(wh); try { wh.send(); @@ -275,6 +273,18 @@ protected Void run() throws Exception { return null; } + /** + * Add all key value field pairs to the webhook + */ + private void addDynamicFieldsToWebhook(DiscordWebhook wh){ + // Early exit if we don't have any dynamicFieldContainer set + if(step.dynamicFieldContainer == null){ + return; + } + // Go through all fields and add them to the webhook + step.dynamicFieldContainer.getFields().forEach(pair -> wh.addField(pair.getKey(), pair.getValue())); + } + private String checkLimitAndTruncate(String fieldName, String value, int limit) { if (value == null) return ""; if (value.length() > limit) { diff --git a/src/main/java/nz/co/jammehcow/jenkinsdiscord/DynamicFieldContainer.java b/src/main/java/nz/co/jammehcow/jenkinsdiscord/DynamicFieldContainer.java new file mode 100644 index 0000000..44adc4c --- /dev/null +++ b/src/main/java/nz/co/jammehcow/jenkinsdiscord/DynamicFieldContainer.java @@ -0,0 +1,86 @@ +package nz.co.jammehcow.jenkinsdiscord; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author Marek Hasselder + */ +public class DynamicFieldContainer { + + private final List fields = new ArrayList<>(); + + public List getFields() { + return fields; + } + + public DynamicFieldContainer addField(String key, String value) { + fields.add(new DynamicField(key, value)); + return this; + } + + @Override + public String toString() { + // Could be optimized using >8 Java Features + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < fields.size(); i++) { + // Serialize the field using the custom toString method + builder.append(fields.get(i).toString()); + if (i + 1 < fields.size()) { + builder.append(", "); + } + } + return builder.toString(); + } + + /** + * Creates a new dynamic field container using the fieldsString. + * + * @param fieldsString the string containing the dynamic fields (key1:value1, key2:value2) + * @return a dynamic field container containing the + * @throws RuntimeException if the string is in a wrong format + */ + public static DynamicFieldContainer of(String fieldsString) { + DynamicFieldContainer fieldContainer = new DynamicFieldContainer(); + + try { + for (String s : fieldsString.split(", ")) { + String[] pair = s.split(":"); + fieldContainer.addField(pair[0], pair[1]); + } + } catch (Exception e) { + throw new RuntimeException("Dynamic fields string is in a wrong format. Using empty container as fallback"); + } + + return fieldContainer; + } + + public static class DynamicField { + + private final String key; + private final String value; + + public DynamicField(String key, String value) { + Objects.requireNonNull(key); + Objects.requireNonNull(value); + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.format("%s:%s", key, value); + } + } + + +} diff --git a/src/main/java/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher.java b/src/main/java/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher.java index e01a3e2..ba17b06 100644 --- a/src/main/java/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher.java +++ b/src/main/java/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher.java @@ -14,16 +14,15 @@ import hudson.tasks.Notifier; import hudson.tasks.Publisher; import hudson.util.FormValidation; -import java.util.List; +import java.io.IOException; +import java.util.Map; import jenkins.model.JenkinsLocationConfiguration; import nz.co.jammehcow.jenkinsdiscord.exception.WebhookException; import nz.co.jammehcow.jenkinsdiscord.util.EmbedDescription; import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; -import java.io.IOException; -import java.util.Map; - /** * Author: jammehcow. * Date: 22/04/17. @@ -38,7 +37,7 @@ public class WebhookPublisher extends Notifier { private final String notes; private final String customAvatarUrl; private final String customUsername; - private final List fields; + private DynamicFieldContainer dynamicFieldContainer; private final boolean sendOnStateChange; private final boolean sendOnlyFailed; private boolean enableUrlLinking; @@ -61,7 +60,6 @@ public WebhookPublisher( String branchName, String customAvatarUrl, String customUsername, - List fields, boolean sendOnStateFailed, boolean sendOnlyFailed, boolean enableUrlLinking, @@ -85,7 +83,6 @@ public WebhookPublisher( this.notes = notes; this.customAvatarUrl = customAvatarUrl; this.customUsername = customUsername; - this.fields = fields; this.sendLogFile = sendLogFile; this.sendStartNotification = sendStartNotification; this.scmWebUrl = scmWebUrl; @@ -111,8 +108,16 @@ public String getCustomUsername() { return this.customUsername; } - public List getFields() { - return fields; + @DataBoundSetter + public void setDynamicFieldContainer(String fieldsString) { + this.dynamicFieldContainer = DynamicFieldContainer.of(fieldsString); + } + + public String getDynamicFieldContainer() { + if(dynamicFieldContainer == null){ + return ""; + } + return dynamicFieldContainer.toString(); } public String getNotes() { @@ -199,10 +204,7 @@ public boolean prebuild(AbstractBuild build, BuildListener listener) { } wh.setDescription(new EmbedDescription(build, globalConfig, description, false, false, null).toString()); - // Add all key value field pairs to the webhook by splitting them with the delimiter - fields.stream() - .map(s -> s.split(":")) - .forEach(pair -> wh.addField(pair[0], pair[1])); + addDynamicFieldsToWebhook(dynamicFieldContainer, wh); // Send the webhook wh.send(); @@ -321,10 +323,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListener lis .toString() ); - // Add all key value field pairs to the webhook by splitting them with the delimiter - fields.stream() - .map(s -> s.split(":")) - .forEach(pair -> wh.addField(pair[0], pair[1])); + addDynamicFieldsToWebhook(dynamicFieldContainer, wh); wh.setStatus(statusColor); if (this.enableFooterInfo) @@ -340,6 +339,18 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListener lis return true; } + /** + * Add all key value field pairs to the webhook + */ + private void addDynamicFieldsToWebhook(DynamicFieldContainer dynamicFieldContainer, DiscordWebhook wh){ + // Early exit if we don't have any dynamicFieldContainer set + if(dynamicFieldContainer == null){ + return; + } + // Go through all fields and add them to the webhook + dynamicFieldContainer.getFields().forEach(pair -> wh.addField(pair.getKey(), pair.getValue())); + } + public BuildStepMonitor getRequiredMonitorService() { return BuildStepMonitor.NONE; } diff --git a/src/main/resources/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher/config.jelly b/src/main/resources/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher/config.jelly index 30f6b35..554d103 100644 --- a/src/main/resources/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher/config.jelly +++ b/src/main/resources/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher/config.jelly @@ -28,8 +28,7 @@ - - + diff --git a/src/main/resources/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher/help-dynamicFieldContainer.html b/src/main/resources/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher/help-dynamicFieldContainer.html new file mode 100644 index 0000000..016edcd --- /dev/null +++ b/src/main/resources/nz/co/jammehcow/jenkinsdiscord/WebhookPublisher/help-dynamicFieldContainer.html @@ -0,0 +1,3 @@ +
+ Field that contains key value pairs in an array in the following format `key1:value1, key2:value2, [...]` +