diff --git a/plugin/src/main/java/com/github/gmazzo/gocd/BuildWatcherPlugin.java b/plugin/src/main/java/com/github/gmazzo/gocd/BuildWatcherPlugin.java index 00673ab..a780a6d 100644 --- a/plugin/src/main/java/com/github/gmazzo/gocd/BuildWatcherPlugin.java +++ b/plugin/src/main/java/com/github/gmazzo/gocd/BuildWatcherPlugin.java @@ -2,7 +2,11 @@ import com.github.gmazzo.gocd.email.EmailNotifier; import com.github.gmazzo.gocd.model.Message; -import com.github.gmazzo.gocd.model.api.*; +import com.github.gmazzo.gocd.model.api.PipelineInstance; +import com.github.gmazzo.gocd.model.api.PluginSettings; +import com.github.gmazzo.gocd.model.api.StageResult; +import com.github.gmazzo.gocd.model.api.StageStatus; +import com.github.gmazzo.gocd.model.api.ValidateConfiguration; import com.github.gmazzo.gocd.slack.SlackNotifier; import com.google.gson.Gson; import com.thoughtworks.go.plugin.api.GoApplicationAccessor; @@ -20,15 +24,46 @@ import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -import static com.github.gmazzo.gocd.model.api.PluginSettings.*; +import javax.xml.bind.DatatypeConverter; + +import static com.github.gmazzo.gocd.model.api.PluginSettings.PLACEHOLDER_LABEL; +import static com.github.gmazzo.gocd.model.api.PluginSettings.PLACEHOLDER_PIPELINE; +import static com.github.gmazzo.gocd.model.api.PluginSettings.PLACEHOLDER_PIPELINE_COUNTER; +import static com.github.gmazzo.gocd.model.api.PluginSettings.PLACEHOLDER_STAGE; +import static com.github.gmazzo.gocd.model.api.PluginSettings.PLACEHOLDER_STAGE_COUNTER; +import static com.github.gmazzo.gocd.model.api.PluginSettings.PLACEHOLDER_STATE_CURRENT; +import static com.github.gmazzo.gocd.model.api.PluginSettings.PLACEHOLDER_STATE_PREVIOUS; +import static com.github.gmazzo.gocd.model.api.PluginSettings.PLACEHOLDER_USER; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_EMAIL_AUTH_PASSWORD; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_EMAIL_AUTH_USER; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_EMAIL_CC; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_EMAIL_FROM; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_EMAIL_SMTP_PORT; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_EMAIL_SMTP_SERVER; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_EMAIL_SMTP_SSL; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_MESSAGE_PIPE_BROKEN; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_MESSAGE_PIPE_FIXED; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_MESSAGE_PIPE_STILL_BROKEN; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_SERVER_API_PASSWORD; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_SERVER_API_USERNAME; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_SERVER_BASE_URL; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_SLACK_API_TOKEN; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_SLACK_BOT_IMAGE; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_SLACK_BOT_USERNAME; +import static com.github.gmazzo.gocd.model.api.PluginSettings.SETTING_SLACK_CHANNEL; import static com.github.gmazzo.utils.HttpUtils.response; import static com.github.gmazzo.utils.IOUtils.readStream; import static com.github.gmazzo.utils.MapUtils.map; -import static com.github.gmazzo.utils.StringUtils.*; -import static java.lang.Integer.parseInt; +import static com.github.gmazzo.utils.StringUtils.capitalize; +import static com.github.gmazzo.utils.StringUtils.extractEmail; +import static com.github.gmazzo.utils.StringUtils.isBlank; @Extension public class BuildWatcherPlugin implements GoPlugin { @@ -125,41 +160,30 @@ private void handleStageStatus(StageStatus.Pipeline pipeline) { StageResult currentResult = pipeline.stage.result; - LOGGER.info("Starting execution of the handleStageStatus() method"); - if (currentResult.isFinal()) { PipelineInstance currentInstance = getPipelineInstance(settings, pipeline.name, pipeline.counter); PipelineInstance previousInstance = getPipelineInstance(settings, pipeline.name, pipeline.counter - 1); StageResult previousResult = getPreviousStageResult(previousInstance, pipeline.stage.name); - - Set users = new LinkedHashSet<>(); - relevantMaterialRevisions(currentInstance).forEach( - $ -> users.addAll(getMaterialUsers($.modifications)) - ); - LOGGER.info("Number of users found: " + users.size()); - + String userEmail = getMaterialUser(currentInstance); String changesResume = getChangesResume(currentInstance); - - users.forEach(userEmail -> { - LOGGER.info("userEmail: " + userEmail); - - Message message = getMessage(settings, userEmail, pipeline, currentResult, previousResult, changesResume); - LOGGER.info("handleStageStatus: userEmail=" + userEmail + ", current=" + currentResult + - ", previous=" + previousResult + ", message=" + message); - if (message != null) { - // sends the notification - getNotifiers(settings).forEach(n -> { - try { - n.sendMessage(userEmail, message); - - } catch (Exception e) { - LOGGER.error("sendMessage failed: notifier=" + n + - ", userEmail=" + userEmail + ", current=" + currentResult + - ", previous=" + previousResult + ", message=" + message, e); - } - }); - } - }); + Message message = getMessage(settings, userEmail, pipeline, currentResult, previousResult, changesResume); + + LOGGER.info("handleStageStatus: userEmail=" + userEmail + ", current=" + currentResult + + ", previous=" + previousResult + ", message=" + message); + + if (message != null) { + // sends the notification + getNotifiers(settings).forEach(n -> { + try { + n.sendMessage(userEmail, message); + + } catch (Exception e) { + LOGGER.error("sendMessage failed: notifier=" + n + + ", userEmail=" + userEmail + ", current=" + currentResult + + ", previous=" + previousResult + ", message=" + message, e); + } + }); + } } else { LOGGER.info("Ignoring non final state: stage=" + @@ -188,51 +212,14 @@ private PipelineInstance getPipelineInstance(PluginSettings settings, String nam } } - private List relevantMaterialRevisions(PipelineInstance instance) { - Map> materialRevisions = instance.buildCause.revisions.stream() - .collect(Collectors.partitioningBy(r -> Objects.equals(r.material.type, "Pipeline"))); - - LOGGER.info("Starting execution of the relevantMaterialRevisions() method"); - - LOGGER.info("Printing out all relevant material revisions..."); - - LOGGER.info("Printing out type: pipeline..."); - materialRevisions.get(true).forEach(m -> LOGGER.info(m.material.fingerprint)); - - LOGGER.info("Printing out type: !pipeline..."); - materialRevisions.get(false).forEach(m -> LOGGER.info(m.material.fingerprint)); - - List res = new LinkedList<>(materialRevisions.get(false)); - - if (materialRevisions.get(false).size() == 0 && materialRevisions.get(true).size() > 0) { - LOGGER.info("Only able to find pipeline material revisions, processing parents..."); - - materialRevisions.get(true) - .forEach( - $ -> getPipelinesFromModifications($).forEach(p -> res.addAll(relevantMaterialRevisions(p))) - ); - } - - return res; - } - - private List getPipelinesFromModifications(PipelineInstance.MaterialRevision materialRevision) { - PluginSettings settings = getSettings(); - - return materialRevision.modifications.stream() - .filter($ -> !Objects.equals($.revision, "")) - .map($ -> extractPipelineAndCounter($.revision)) - .filter(Objects::nonNull) - .map($ -> getPipelineInstance(settings, $.get("pipeline"), parseInt($.get("counter")))) - .collect(Collectors.toList()); - } - - private List getMaterialUsers(List modifications) { - return modifications.stream() - .filter(m -> m.emailAddress != null || m.userName != null) + private String getMaterialUser(PipelineInstance instance) { + return instance.buildCause.revisions.stream() + .flatMap(m -> m.modifications.stream()) + .sorted((a, b) -> -Long.compare(a.modifiedTime, b.modifiedTime)) + .findFirst() .map(m -> m.emailAddress != null ? m.emailAddress : extractEmail(m.userName)) - .filter(Objects::nonNull) - .collect(Collectors.toList()); + .filter($ -> $ != null) + .orElseThrow(() -> new IllegalArgumentException("No modifications found for material!")); } private StageResult getPreviousStageResult(PipelineInstance instance, String stage) { @@ -246,7 +233,7 @@ private StageResult getPreviousStageResult(PipelineInstance instance, String sta private String getChangesResume(PipelineInstance instance) { return instance.buildCause.revisions.stream() .flatMap($ -> $.modifications.stream()) - .map($ -> "Material changed:\n\tRevision: " + $.revision + ($.comment != null ? "\n\tComment: " + $.comment : "") + ($.userName != null ? "\n\tUsername: " + $.userName : "")) + .map($ -> $.revision + ":\n" + $.comment + " - " + $.userName) .collect(Collectors.joining("\n\n")); } @@ -275,7 +262,7 @@ private Message getMessage(PluginSettings settings, String userEmail, StageStatu '/' + pipeline.stage.name + '/' + pipeline.stage.counter; } if (!isBlank(message)) { - String text = "\n" + message.replaceAll(PLACEHOLDER_USER, userEmail) + String text = message.replaceAll(PLACEHOLDER_USER, userEmail) .replaceAll(PLACEHOLDER_PIPELINE, pipeline.name) .replaceAll(PLACEHOLDER_PIPELINE_COUNTER, String.valueOf(pipeline.counter)) .replaceAll(PLACEHOLDER_STAGE, pipeline.stage.name) diff --git a/plugin/src/main/java/com/github/gmazzo/gocd/email/EmailNotifier.java b/plugin/src/main/java/com/github/gmazzo/gocd/email/EmailNotifier.java index bc31332..20dd50f 100644 --- a/plugin/src/main/java/com/github/gmazzo/gocd/email/EmailNotifier.java +++ b/plugin/src/main/java/com/github/gmazzo/gocd/email/EmailNotifier.java @@ -61,25 +61,30 @@ public void sendMessage(String userEmail, Message message) { private String buildHtml(Message message) { StringBuilder tags = new StringBuilder(); + boolean col2 = false; int rowSpan = 1; for (Message.Tag tag : message.tags) { - if (rowSpan > 1) { + col2 |= !tag.isShort; + if (col2) { tags.append(""); + rowSpan++; + col2 = !tag.isShort; + + } else { + col2 = true; } tags.append(""); tags.append(escapeHtml3(tag.name)); tags.append("
"); - tags.append(escapeHtml3(tag.value).replace("\n", "
").replace("\t", "    ")); + tags.append(escapeHtml3(tag.value)); tags.append(""); - - rowSpan++; } StringBuilder sb = new StringBuilder(); - sb.append("
"); + sb.append("
"); sb.append(escapeHtml3(message.text)); - sb.append("
 
modifications; - @SerializedName("changed") - public boolean changed; - } - - public static class Material { - @SerializedName("fingerprint") - public String fingerprint; - - @SerializedName("description") - public String description; - - @SerializedName("id") - public Integer id; - - @SerializedName("type") - public String type; } public static class Modification { diff --git a/plugin/src/main/java/com/github/gmazzo/utils/StringUtils.java b/plugin/src/main/java/com/github/gmazzo/utils/StringUtils.java index 9b3dfe0..dfc2cab 100644 --- a/plugin/src/main/java/com/github/gmazzo/utils/StringUtils.java +++ b/plugin/src/main/java/com/github/gmazzo/utils/StringUtils.java @@ -1,6 +1,5 @@ package com.github.gmazzo.utils; -import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -20,18 +19,4 @@ public static String extractEmail(String text) { return m.find() ? m.group() : null; } - public static HashMap extractPipelineAndCounter(String text) { - String[] parts = text.split("/"); - - if (parts.length < 2) { - return null; - } - - HashMap res = new HashMap<>(); - res.put("pipeline", parts[0]); - res.put("counter", parts[1]); - - return res; - } - }