Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

allow message to be configured

Allow the message sent into the Campfire channel to be configured.
The permitted substitutions are in the config documentation. The
default message replicates the message currently displayed by
version 2.6 of the plugin.
  • Loading branch information...
commit b988e554d6636fd6f94042e62b783fedf0cf3130 1 parent 5690b37
Tom Dyas tdyas authored
114 src/main/java/hudson/plugins/campfire/CampfireNotifier.java
View
@@ -9,19 +9,24 @@
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
+import org.kohsuke.stapler.DataBoundConstructor;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
+import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.Map;
public class CampfireNotifier extends Notifier {
private Campfire campfire;
private Room room;
private String hudsonUrl;
+ private String notificationTemplate;
private boolean smartNotify;
private boolean sound;
@@ -51,6 +56,14 @@ public String getConfiguredToken() {
}
}
+ public String getConfiguredNotificationTemplate() {
+ if ( DESCRIPTOR.getNotificationTemplate().equals(notificationTemplate) ) {
+ return null;
+ } else {
+ return notificationTemplate;
+ }
+ }
+
@Extension
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
@@ -61,18 +74,54 @@ public CampfireNotifier() {
initialize();
}
- public CampfireNotifier(String subdomain, String token, String room, String hudsonUrl, boolean ssl, boolean smartNotify, boolean sound) {
+ @DataBoundConstructor
+ public CampfireNotifier(String subdomain, String token, String room, String hudsonUrl, String notificationTemplate,
+ boolean ssl, boolean smartNotify, boolean sound) {
super();
- initialize(subdomain, token, room, hudsonUrl, ssl, smartNotify, sound);
+ initialize(subdomain, token, room, hudsonUrl, notificationTemplate, ssl, smartNotify, sound);
}
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.BUILD;
}
- private void publish(AbstractBuild<?, ?> build) throws IOException {
- checkCampfireConnection();
- Result result = build.getResult();
+ private String interpolate(String base, Map<String, String> context) {
+ StringBuilder builder = new StringBuilder();
+ int pos = 0;
+
+ while (pos < base.length()) {
+ int startIndex = base.indexOf("%", pos);
+ if (startIndex >= 0) {
+ builder.append(base.substring(pos, startIndex));
+
+ int endIndex = base.indexOf("%", startIndex + 1);
+
+ if (endIndex > 0) {
+ String key = base.substring(startIndex + 1, endIndex).trim();
+ if (key.length() > 0) {
+ String value = context.get(key);
+ if (value == null) {
+ value = "";
+ }
+ builder.append(value);
+ } else {
+ builder.append("%");
+ }
+ pos = endIndex + 1;
+ } else {
+ // should error out here but quick and dirty for now
+ builder.append("%");
+ pos = startIndex + 1;
+ }
+ } else {
+ builder.append(base.substring(pos));
+ pos = base.length();
+ }
+ }
+ return builder.toString();
+ }
+
+ private String computeChangeString(AbstractBuild<?, ?> build) {
String changeString = "No changes";
if (!build.hasChangeSetComputed()) {
changeString = "Changes not determined";
@@ -112,16 +161,53 @@ private void publish(AbstractBuild<?, ?> build) throws IOException {
changeString = commitMsg + " - " + entry.getAuthor().toString();
}
}
+ return changeString;
+ }
+
+ private Map<String, String> buildContextFor(AbstractBuild<?, ?> build) {
+ HashMap<String, String> context = new HashMap<String, String>();
+
+ context.put("PROJECT_NAME", build.getProject().getName());
+ context.put("PROJECT_DISPLAY_NAME", build.getProject().getDisplayName());
+ context.put("PROJECT_FULL_NAME", build.getProject().getFullName());
+ context.put("PROJECT_FULL_DISPLAY_NAME", build.getProject().getFullDisplayName());
+
+ context.put("BUILD_DISPLAY_NAME", build.getDisplayName());
+
+ Result result = build.getResult();
String resultString = result.toString();
- if (!smartNotify && result == Result.SUCCESS) resultString = resultString.toLowerCase();
- String message = build.getProject().getName() + " " + build.getDisplayName() + " \"" + changeString + "\": " + resultString;
- if (hudsonUrl != null && hudsonUrl.length() > 1 && (smartNotify || result != Result.SUCCESS)) {
- message = message + " (" + hudsonUrl + build.getUrl() + ")";
+ context.put("RESULT", resultString);
+ if (!smartNotify && result == Result.SUCCESS) {
+ context.put("SMART_RESULT", resultString.toLowerCase());
+ } else {
+ context.put("SMART_RESULT", resultString);
+ }
+
+ context.put("CHANGES", computeChangeString(build));
+
+ if (hudsonUrl != null && hudsonUrl.length() > 1) {
+ context.put("BUILD_URL", hudsonUrl + build.getUrl());
+ }
+
+ return context;
+ }
+
+ private void publish(AbstractBuild<?, ?> build) throws IOException {
+ checkCampfireConnection();
+
+ if (notificationTemplate == null || notificationTemplate.trim().length() == 0) {
+ return;
}
+
+ Map<String, String> context = buildContextFor(build);
+
+ String message = interpolate(notificationTemplate, context);
+
room.speak(message);
+
if (sound) {
String message_sound;
- if ("FAILURE".equals(resultString)) {
+ if ("FAILURE".equals(build.getResult().toString())) {
message_sound = "trombone";
} else {
message_sound = "rimshot";
@@ -151,16 +237,20 @@ private void checkCampfireConnection() {
}
private void initialize() {
- initialize(DESCRIPTOR.getSubdomain(), DESCRIPTOR.getToken(), room.getName(), DESCRIPTOR.getHudsonUrl(), DESCRIPTOR.getSsl(), DESCRIPTOR.getSmartNotify(), DESCRIPTOR.getSound());
+ initialize(DESCRIPTOR.getSubdomain(), DESCRIPTOR.getToken(), room.getName(), DESCRIPTOR.getHudsonUrl(),
+ DESCRIPTOR.getNotificationTemplate(), DESCRIPTOR.getSsl(), DESCRIPTOR.getSmartNotify(),
+ DESCRIPTOR.getSound());
}
- private void initialize(String subdomain, String token, String roomName, String hudsonUrl, boolean ssl, boolean smartNotify, boolean sound) {
+ private void initialize(String subdomain, String token, String roomName, String hudsonUrl, String notificationTemplate,
+ boolean ssl, boolean smartNotify, boolean sound) {
campfire = new Campfire(subdomain, token, ssl);
this.room = campfire.findRoomByName(roomName);
if ( this.room == null ) {
throw new RuntimeException("Room '" + roomName + "' not found - verify name and room permissions");
}
this.hudsonUrl = hudsonUrl;
+ this.notificationTemplate = notificationTemplate;
this.smartNotify = smartNotify;
this.sound = sound;
}
24 src/main/java/hudson/plugins/campfire/DescriptorImpl.java
View
@@ -10,11 +10,14 @@
import java.util.logging.Logger;
public class DescriptorImpl extends BuildStepDescriptor<Publisher> {
+ private static final String DEFAULT_NOTIFICATION_TEMPLATE = "%PROJECT_NAME% %BUILD_DISPLAY_NAME% (%CHANGES%): %SMART_RESULT% (%BUILD_URL%)";
+
private boolean enabled = false;
private String subdomain;
private String token;
private String room;
private String hudsonUrl;
+ private String notificationTemplate = DEFAULT_NOTIFICATION_TEMPLATE;
private boolean ssl;
private boolean smartNotify;
private boolean sound;
@@ -25,6 +28,10 @@ public DescriptorImpl() {
load();
}
+ public String getDefaultNotificationTemplate() {
+ return DEFAULT_NOTIFICATION_TEMPLATE;
+ }
+
public boolean isEnabled() {
return enabled;
}
@@ -45,6 +52,10 @@ public String getHudsonUrl() {
return hudsonUrl;
}
+ public String getNotificationTemplate() {
+ return notificationTemplate;
+ }
+
public boolean getSsl() {
return ssl;
}
@@ -69,6 +80,7 @@ public Publisher newInstance(StaplerRequest req, JSONObject formData) throws For
String projectSubdomain = req.getParameter("campfireSubdomain");
String projectToken = req.getParameter("campfireToken");
String projectRoom = req.getParameter("campfireRoom");
+ String projectNotificationTemplate = req.getParameter("campfireNotificationTemplate");
if ( projectRoom == null || projectRoom.trim().length() == 0 ) {
projectRoom = room;
}
@@ -78,8 +90,12 @@ public Publisher newInstance(StaplerRequest req, JSONObject formData) throws For
if ( projectSubdomain == null || projectSubdomain.trim().length() == 0 ) {
projectSubdomain = subdomain;
}
+ if ( projectNotificationTemplate == null || projectNotificationTemplate.trim().length() == 0 ) {
+ projectNotificationTemplate = notificationTemplate;
+ }
try {
- return new CampfireNotifier(projectSubdomain, projectToken, projectRoom, hudsonUrl, ssl, smartNotify, sound);
+ return new CampfireNotifier(projectSubdomain, projectToken, projectRoom, hudsonUrl,
+ projectNotificationTemplate, ssl, smartNotify, sound);
} catch (Exception e) {
String message = "Failed to initialize campfire notifier - check your campfire notifier configuration settings: " + e.getMessage();
LOGGER.log(Level.WARNING, message, e);
@@ -96,11 +112,15 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti
if ( hudsonUrl != null && !hudsonUrl.endsWith("/") ) {
hudsonUrl = hudsonUrl + "/";
}
+ notificationTemplate = req.getParameter("campfireNotificationTemplate");
+ if (notificationTemplate == null || notificationTemplate.trim().length() == 0) {
+ notificationTemplate = DEFAULT_NOTIFICATION_TEMPLATE;
+ }
ssl = req.getParameter("campfireSsl") != null;
smartNotify = req.getParameter("campfireSmartNotify") != null;
sound = req.getParameter("campfireSound") != null;
try {
- new CampfireNotifier(subdomain, token, room, hudsonUrl, ssl, smartNotify, sound);
+ new CampfireNotifier(subdomain, token, room, hudsonUrl, notificationTemplate, ssl, smartNotify, sound);
} catch (Exception e) {
String message = "Failed to initialize campfire notifier - check your global campfire notifier configuration settings: " + e.getMessage();
LOGGER.log(Level.WARNING, message, e);
5 src/main/resources/hudson/plugins/campfire/CampfireNotifier/config.jelly
View
@@ -12,4 +12,9 @@
<f:entry title="Project Room Name" description="Optional. Use to send notifications to a room other than the default (${descriptor.getRoom()})" help="${rootURL}/plugin/campfire/help-projectConfig-room.html">
<f:textbox name="campfireRoom" value="${instance.getConfiguredRoomName()}"/>
</f:entry>
+ <f:entry title="Project Notification Message Template" description="Optional. Override the message sent to the Campfire room other than the default (${descriptor.getNotificationTemplate()})."
+ help="${rootURL}/plugin/campfire/help-projectConfig-notificationTemplate.html">
+ <f:textbox name="campfireNotificationTemplate" value="${instance.getConfiguredNotificationTemplate()}" />
+ </f:entry>
+
</j:jelly>
3  src/main/resources/hudson/plugins/campfire/CampfireNotifier/global.jelly
View
@@ -24,6 +24,9 @@
<f:entry title="Hudson Url" help="${rootURL}/plugin/campfire/help-globalConfig-hudsonUrl.html">
<f:textbox name="campfireHudsonUrl" value="${descriptor.getHudsonUrl()}" />
</f:entry>
+ <f:entry title="Notification Message Template" help="${rootURL}/plugin/campfire/help-globalConfig-notificationTemplate.html">
+ <f:textbox name="campfireNotificationTemplate" value="${descriptor.getNotificationTemplate()}" default="${descriptor.defaultNotificationTemplate}" />
+ </f:entry>
<f:entry title="SSL" help="${rootURL}/plugin/campfire/help-globalConfig-ssl.html">
<f:checkbox name="campfireSsl" checked="${descriptor.getSsl()}" />
</f:entry>
17 src/main/webapp/help-globalConfig-notificationTemplate.html
View
@@ -0,0 +1,17 @@
+<div>
+ <p>Optionally specify the template used to construct the notifications sent to the Campfire room.</p>
+ <p>Supported replacements:</p>
+ <ul>
+ <li>%PROJECT_NAME% -- Name of the Jenkins project</li>
+ <li>%PROJECT_DISPLAY_NAME% -- Display name of the Jenkins project</li>
+ <li>%PROJECT_FULL_NAME% -- Full name of the Jenkins project (includes names of parent projects)</li>
+ <li>%PROJECT_FULL_DISPLAY_NAME% -- Full display name of the Jenkins project (includes display names of parent projects)</li>
+ <li>%BUILD_DISPLAY_NAME% -- Display name for a particular build</li>
+ <li>%RESULT% -- Result of a particular build (capitalized)</li>
+ <li>%SMART_RESULT% -- Result of a particular build (capitalized except for "success")</li>
+ <li>%CHANGES% -- Brief description of the changes in the build</li>
+ <li>%BUILD_URL% -- URL for a particular build</li>
+ <li>%% -- Bare % character</li>
+ </ul>
+ <p>Default: %PROJECT_NAME% %BUILD_DISPLAY_NAME% (%CHANGES%): %SMART_RESULT% (%BUILD_URL%)</p>
+</div>
18 src/main/webapp/help-projectConfig-notificationTemplate.html
View
@@ -0,0 +1,18 @@
+<div>
+ <p>Optionally specify the template used to construct the notifications sent to the Campfire room, if
+ different than the global notification template.</p>
+ <p>Supported replacements:</p>
+ <ul>
+ <li>%PROJECT_NAME% -- Name of the Jenkins project</li>
+ <li>%PROJECT_DISPLAY_NAME% -- Display name of the Jenkins project</li>
+ <li>%PROJECT_FULL_NAME% -- Full name of the Jenkins project (includes names of parent projects)</li>
+ <li>%PROJECT_FULL_DISPLAY_NAME% -- Full display name of the Jenkins project (includes display names of parent projects)</li>
+ <li>%BUILD_DISPLAY_NAME% -- Display name for a particular build</li>
+ <li>%RESULT% -- Result of a particular build (capitalized)</li>
+ <li>%SMART_RESULT% -- Result of a particular build (capitalized except for "success")</li>
+ <li>%CHANGES% -- Brief description of the changes in the build</li>
+ <li>%BUILD_URL% -- URL for a particular build</li>
+ <li>%% -- Bare % character</li>
+ </ul>
+ <p>Default: %PROJECT_NAME% %BUILD_DISPLAY_NAME% (%CHANGES%): %SMART_RESULT% (%BUILD_URL%)</p>
+</div>
Please sign in to comment.
Something went wrong with that request. Please try again.