├── .gitignore ├── src └── main │ ├── webapp │ ├── help-globalConfig-ssl.html │ ├── help-globalConfig-token.html │ ├── help.html │ ├── help-globalConfig-sounds.html │ ├── help-globalConfig-room.html │ ├── help-projectConfig-room.html │ ├── help-globalConfig-hudsonUrl.html │ ├── help-globalConfig-subdomain.html │ └── help-globalConfig-smartNotify.html │ ├── java │ └── hudson │ │ └── plugins │ │ └── campfire │ │ ├── PluginImpl.java │ │ ├── Room.java │ │ ├── DescriptorImpl.java │ │ ├── Campfire.java │ │ └── CampfireNotifier.java │ └── resources │ ├── index.jelly │ └── hudson │ └── plugins │ └── campfire │ └── CampfireNotifier │ ├── config.jelly │ └── global.jelly ├── README.markdown └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.*~ 2 | *.swp 3 | .project 4 | target 5 | -------------------------------------------------------------------------------- /src/main/webapp/help-globalConfig-ssl.html: -------------------------------------------------------------------------------- 1 |
2 |

Use SSL to connect to Campfire?

3 |
-------------------------------------------------------------------------------- /src/main/java/hudson/plugins/campfire/PluginImpl.java: -------------------------------------------------------------------------------- 1 | package hudson.plugins.campfire; 2 | 3 | import hudson.Plugin; 4 | 5 | public class PluginImpl extends Plugin { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/webapp/help-globalConfig-token.html: -------------------------------------------------------------------------------- 1 |
2 |

The API authentication token to be used to send notifications to Campfire. You can copy this from the settings page within Campfire.

3 |
-------------------------------------------------------------------------------- /src/main/webapp/help.html: -------------------------------------------------------------------------------- 1 |
2 | Send build notifications to a Campfire chat room.
3 | The campfire notifier is configured globally, but you can customize the room name per-project. 4 |
5 | -------------------------------------------------------------------------------- /src/main/webapp/help-globalConfig-sounds.html: -------------------------------------------------------------------------------- 1 |
2 |

Play sounds in addition to build success and failure messages:

3 |
8 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ## Campfire notifier plugin for Jenkins 2 | 3 | --- 4 | 5 | This fork has merged back to the offical Jenkins repository at 6 | [https://github.com/jenkinsci/campfire-plugin](https://github.com/jenkinsci/campfire-plugin). 7 | 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 6 |
7 | This plugin is a Campfire bot that can publish build statusses to Campfire rooms. 8 |
-------------------------------------------------------------------------------- /src/main/webapp/help-globalConfig-room.html: -------------------------------------------------------------------------------- 1 |
2 |

Enter the name of the room to which notifications should be sent. Note that this is the name of the 3 | room, not the id number, e.g. "Dev Team". You can customize the room name per-project, but should always 4 | enter a default here.

5 |
6 | -------------------------------------------------------------------------------- /src/main/webapp/help-projectConfig-room.html: -------------------------------------------------------------------------------- 1 |
2 |

Enter the name of the room to which notifications for this project should be sent, 3 | if different to the default room configured in the global campfire notifier settings. 4 | Note that this is the name of the room, not the id number, e.g. "Dev Team".

5 |
6 | -------------------------------------------------------------------------------- /src/main/webapp/help-globalConfig-hudsonUrl.html: -------------------------------------------------------------------------------- 1 |
2 |

Optionally specify the URL for your Hudson installation, e.g. http://yourhost.yourdomain/hudson/. 3 | This value will be used to generate links back to Hudson from Campfire and should end with a forward slash.

4 |

This is necessary because Hudson cannot reliably detect such a URL from within itself.

5 |
-------------------------------------------------------------------------------- /src/main/webapp/help-globalConfig-subdomain.html: -------------------------------------------------------------------------------- 1 |
2 |

The subdomain for your Campfire account (strictly the leaf node of the fully qualified host name). 3 | This value is used to build the URL used when interacting with the Campfire API. For example, if your 4 | Campfire URL is "http://mysubdomain.campfirenow.com", the subdomain setting should be "mysubdomain".

5 |
-------------------------------------------------------------------------------- /src/main/webapp/help-globalConfig-smartNotify.html: -------------------------------------------------------------------------------- 1 |
2 |

When checked, build notifications will be posted to Campfire only if: 3 |

    4 |
  1. there was no previous build, or
  2. 5 |
  3. if there was a failure, or
  4. 6 |
  5. if previous build failed and the current build succeeded.
  6. 7 |
8 | In other words, notifications won't be sent for successful builds unless the last build was not successful. 9 |

10 |
-------------------------------------------------------------------------------- /src/main/resources/hudson/plugins/campfire/CampfireNotifier/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/hudson/plugins/campfire/Room.java: -------------------------------------------------------------------------------- 1 | package hudson.plugins.campfire; 2 | 3 | import java.io.IOException; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Date; 7 | 8 | public class Room { 9 | private transient Campfire campfire; 10 | private String name; 11 | private String id; 12 | 13 | public Room(Campfire cf, String name, String id) { 14 | super(); 15 | this.campfire = cf; 16 | this.name = name; 17 | this.id = id; 18 | } 19 | 20 | public String getName() { 21 | return this.name; 22 | } 23 | 24 | public String getId() { 25 | return this.id; 26 | } 27 | 28 | public void speak(String message) throws IOException { 29 | campfire.post("room/" + id + "/speak.xml", "TextMessage" + message + ""); 30 | } 31 | 32 | public void play(String sound) throws IOException { 33 | campfire.post("room/" + id + "/speak.xml", "SoundMessage" + sound + ""); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/resources/hudson/plugins/campfire/CampfireNotifier/global.jelly: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.jvnet.hudson.plugins 6 | plugin 7 | 1.319 8 | ../pom.xml 9 | 10 | org.jvnet.hudson.plugins 11 | campfire 12 | hpi 13 | 2.4.2 14 | Jenkins Campfire Plugin 15 | A build status notifier that sends notifications to Campfire rooms 16 | http://wiki.jenkins-ci.org/display/JENKINS/Campfire+Plugin 17 | 18 | MIT licenseAll source code is under the MIT license. 19 | 20 | 21 | scm:git:git://github.com/thickpaddy/jenkins_campfire_plugin.git 22 | scm:git:git@github.com:thickpaddy/jenkins_campfire_plugin.git 23 | http://github.com/thickpaddy/jenkins_campfire_plugin 24 | 25 | 26 | 27 | org.jvnet.hudson.main 28 | maven-plugin 29 | 30 | 31 | commons-httpclient 32 | commons-httpclient 33 | 3.1-rc1 34 | 35 | 36 | 37 | 38 | jenslukowski 39 | Jens Lukowski 40 | jens.lukowski@softwareschneiderei.de 41 | Softwareschneiderei GmbH 42 | http://www.softwareschneiderei.de 43 | 44 | 45 | thickpaddy 46 | Mark Woods 47 | https://github.com/thickpaddy 48 | 49 | 50 | jkrall 51 | Joshua Krall 52 | https://github.com/jkrall 53 | 54 | 55 | bgreenlee 56 | Brad Greenlee 57 | https://github.com/bgreenlee 58 | 59 | 60 | hpoydar 61 | Henry Poydar 62 | https://github.com/hpoydar 63 | 64 | 65 | mortice 66 | Tom Stuart 67 | https://github.com/mortice 68 | 69 | 70 | dbriones 71 | Dante Briones 72 | https://github.com/dbriones 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/main/java/hudson/plugins/campfire/DescriptorImpl.java: -------------------------------------------------------------------------------- 1 | package hudson.plugins.campfire; 2 | 3 | import hudson.model.AbstractProject; 4 | import hudson.tasks.BuildStepDescriptor; 5 | import hudson.tasks.Publisher; 6 | import net.sf.json.JSONObject; 7 | import org.kohsuke.stapler.StaplerRequest; 8 | 9 | import java.util.logging.Level; 10 | import java.util.logging.Logger; 11 | 12 | public class DescriptorImpl extends BuildStepDescriptor { 13 | private boolean enabled = false; 14 | private String subdomain; 15 | private String token; 16 | private String room; 17 | private String hudsonUrl; 18 | private boolean ssl; 19 | private boolean smartNotify; 20 | private boolean sound; 21 | private static final Logger LOGGER = Logger.getLogger(DescriptorImpl.class.getName()); 22 | 23 | public DescriptorImpl() { 24 | super(CampfireNotifier.class); 25 | load(); 26 | } 27 | 28 | public boolean isEnabled() { 29 | return enabled; 30 | } 31 | 32 | public String getSubdomain() { 33 | return subdomain; 34 | } 35 | 36 | public String getToken() { 37 | return token; 38 | } 39 | 40 | public String getRoom() { 41 | return room; 42 | } 43 | 44 | public String getHudsonUrl() { 45 | return hudsonUrl; 46 | } 47 | 48 | public boolean getSsl() { 49 | return ssl; 50 | } 51 | 52 | public boolean getSmartNotify() { 53 | return smartNotify; 54 | } 55 | 56 | public boolean getSound() { 57 | return sound; 58 | } 59 | 60 | public boolean isApplicable(Class aClass) { 61 | return true; 62 | } 63 | 64 | /** 65 | * @see hudson.model.Descriptor#newInstance(org.kohsuke.stapler.StaplerRequest) 66 | */ 67 | @Override 68 | public Publisher newInstance(StaplerRequest req, JSONObject formData) throws FormException { 69 | String projectRoom = req.getParameter("roomName"); 70 | if ( projectRoom == null || projectRoom.trim().length() == 0 ) { 71 | projectRoom = room; 72 | } 73 | try { 74 | return new CampfireNotifier(subdomain, token, projectRoom, hudsonUrl, ssl, smartNotify, sound); 75 | } catch (Exception e) { 76 | String message = "Failed to initialize campfire notifier - check your campfire notifier configuration settings: " + e.getMessage(); 77 | LOGGER.log(Level.WARNING, message, e); 78 | throw new FormException(message, e, ""); 79 | } 80 | } 81 | 82 | @Override 83 | public boolean configure(StaplerRequest req, JSONObject json) throws FormException { 84 | subdomain = req.getParameter("campfireSubdomain"); 85 | token = req.getParameter("campfireToken"); 86 | room = req.getParameter("campfireRoom"); 87 | hudsonUrl = req.getParameter("campfireHudsonUrl"); 88 | if ( hudsonUrl != null && !hudsonUrl.endsWith("/") ) { 89 | hudsonUrl = hudsonUrl + "/"; 90 | } 91 | ssl = req.getParameter("campfireSsl") != null; 92 | smartNotify = req.getParameter("campfireSmartNotify") != null; 93 | sound = req.getParameter("campfireSound") != null; 94 | try { 95 | new CampfireNotifier(subdomain, token, room, hudsonUrl, ssl, smartNotify, sound); 96 | } catch (Exception e) { 97 | String message = "Failed to initialize campfire notifier - check your global campfire notifier configuration settings: " + e.getMessage(); 98 | LOGGER.log(Level.WARNING, message, e); 99 | throw new FormException(message, e, ""); 100 | } 101 | save(); 102 | return super.configure(req, json); 103 | } 104 | 105 | /** 106 | * @see hudson.model.Descriptor#getDisplayName() 107 | */ 108 | @Override 109 | public String getDisplayName() { 110 | return "Campfire Notification"; 111 | } 112 | 113 | /** 114 | * @see hudson.model.Descriptor#getHelpFile() 115 | */ 116 | @Override 117 | public String getHelpFile() { 118 | return "/plugin/campfire/help.html"; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/hudson/plugins/campfire/Campfire.java: -------------------------------------------------------------------------------- 1 | package hudson.plugins.campfire; 2 | 3 | import org.apache.commons.httpclient.Credentials; 4 | import org.apache.commons.httpclient.HttpClient; 5 | import org.apache.commons.httpclient.UsernamePasswordCredentials; 6 | import org.apache.commons.httpclient.auth.AuthScope; 7 | import org.apache.commons.httpclient.methods.GetMethod; 8 | import org.apache.commons.httpclient.methods.PostMethod; 9 | import org.apache.commons.httpclient.methods.StringRequestEntity; 10 | import org.w3c.dom.Document; 11 | import org.w3c.dom.Node; 12 | import org.w3c.dom.NodeList; 13 | import org.xml.sax.InputSource; 14 | import org.xml.sax.SAXException; 15 | 16 | import javax.xml.parsers.DocumentBuilder; 17 | import javax.xml.parsers.DocumentBuilderFactory; 18 | import javax.xml.parsers.ParserConfigurationException; 19 | import javax.xml.xpath.*; 20 | import java.io.IOException; 21 | import java.io.StringReader; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | public class Campfire { 26 | private HttpClient client; 27 | private String subdomain; 28 | private String token; 29 | private boolean ssl; 30 | 31 | public Campfire(String subdomain, String token, boolean ssl) { 32 | super(); 33 | this.subdomain = subdomain; 34 | this.token = token; 35 | this.ssl = ssl; 36 | client = new HttpClient(); 37 | Credentials defaultcreds = new UsernamePasswordCredentials(token, "x"); 38 | client.getState().setCredentials(new AuthScope(getHost(), -1, AuthScope.ANY_REALM), defaultcreds); 39 | client.getParams().setAuthenticationPreemptive(true); 40 | client.getParams().setParameter("http.useragent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16"); 41 | } 42 | 43 | protected String getHost() { 44 | return this.subdomain + ".campfirenow.com"; 45 | } 46 | 47 | protected String getProtocol() { 48 | if (this.ssl) { return "https://"; } 49 | return "http://"; 50 | } 51 | 52 | public int post(String url, String body) { 53 | PostMethod post = new PostMethod(getProtocol() + getHost() + "/" + url); 54 | post.setRequestHeader("Content-Type", "application/xml"); 55 | try { 56 | post.setRequestEntity(new StringRequestEntity(body, "application/xml", "UTF8")); 57 | return client.executeMethod(post); 58 | } catch (IOException e) { 59 | throw new RuntimeException(e); 60 | } finally { 61 | post.releaseConnection(); 62 | } 63 | } 64 | 65 | public String get(String url) { 66 | GetMethod get = new GetMethod(getProtocol() + getHost() + "/" + url); 67 | get.setFollowRedirects(true); 68 | get.setRequestHeader("Content-Type", "application/xml"); 69 | try { 70 | client.executeMethod(get); 71 | verify(get.getStatusCode()); 72 | return get.getResponseBodyAsString(); 73 | } catch (IOException e) { 74 | throw new RuntimeException(e); 75 | } finally { 76 | get.releaseConnection(); 77 | } 78 | } 79 | 80 | public boolean verify(int returnCode) { 81 | if (returnCode != 200) { 82 | throw new RuntimeException("Unexpected response code: " + Integer.toString(returnCode)); 83 | } 84 | return true; 85 | } 86 | 87 | private List getRooms(){ 88 | String body = get("rooms.xml"); 89 | 90 | List rooms; 91 | try { 92 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 93 | factory.setNamespaceAware(true); 94 | DocumentBuilder builder = factory.newDocumentBuilder(); 95 | StringReader reader = new StringReader(body); 96 | InputSource inputSource = new InputSource( reader ); 97 | Document doc = builder.parse(inputSource); 98 | 99 | XPath xpath = XPathFactory.newInstance().newXPath(); 100 | XPathExpression roomExpr = xpath.compile("//room"); 101 | XPathExpression nameExpr = xpath.compile(".//name"); 102 | XPathExpression idExpr = xpath.compile(".//id"); 103 | 104 | NodeList roomNodeList = (NodeList) roomExpr.evaluate(doc, XPathConstants.NODESET); 105 | rooms = new ArrayList(); 106 | for (int i = 0; i < roomNodeList.getLength(); i++) { 107 | Node roomNode = roomNodeList.item(i); 108 | String name = ((NodeList) nameExpr.evaluate(roomNode, XPathConstants.NODESET)).item(0).getFirstChild().getNodeValue(); 109 | String id = ((NodeList) idExpr.evaluate(roomNode, XPathConstants.NODESET)).item(0).getFirstChild().getNodeValue(); 110 | rooms.add(new Room(this, name.trim(), id.trim())); 111 | } 112 | } catch (ParserConfigurationException e) { 113 | throw new RuntimeException(e); 114 | } catch (SAXException e) { 115 | throw new RuntimeException(e); 116 | } catch (IOException e) { 117 | throw new RuntimeException(e); 118 | } catch (XPathExpressionException e) { 119 | throw new RuntimeException(e); 120 | } 121 | return rooms; 122 | } 123 | 124 | public Room findRoomByName(String name) { 125 | for (Room room : getRooms()) { 126 | if (room.getName().equals(name)) { 127 | return room; 128 | } 129 | } 130 | return null; 131 | } 132 | 133 | private Room createRoom(String name) { 134 | verify(post("rooms.xml", "" + name + "")); 135 | return findRoomByName(name); 136 | } 137 | 138 | public Room findOrCreateRoomByName(String name) { 139 | Room room = findRoomByName(name); 140 | if (room != null) { 141 | return room; 142 | } 143 | return createRoom(name); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/hudson/plugins/campfire/CampfireNotifier.java: -------------------------------------------------------------------------------- 1 | package hudson.plugins.campfire; 2 | 3 | import hudson.Extension; 4 | import hudson.Launcher; 5 | import hudson.model.AbstractBuild; 6 | import hudson.model.BuildListener; 7 | import hudson.model.Result; 8 | import hudson.scm.ChangeLogSet; 9 | import hudson.tasks.BuildStepMonitor; 10 | import hudson.tasks.Notifier; 11 | 12 | import java.io.BufferedReader; 13 | import java.io.File; 14 | import java.io.FileReader; 15 | import java.io.IOException; 16 | import java.lang.reflect.Method; 17 | import java.util.logging.Level; 18 | import java.util.logging.Logger; 19 | 20 | public class CampfireNotifier extends Notifier { 21 | 22 | private transient Campfire campfire; 23 | private Room room; 24 | private String hudsonUrl; 25 | private boolean smartNotify; 26 | private boolean sound; 27 | 28 | // getter for project configuration.. 29 | // Configured room name should be null unless different from descriptor/global room name 30 | public String getConfiguredRoomName() { 31 | if ( DESCRIPTOR.getRoom().equals(room.getName()) ) { 32 | return null; 33 | } else { 34 | return room.getName(); 35 | } 36 | } 37 | 38 | @Extension 39 | public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); 40 | 41 | private static final Logger LOGGER = Logger.getLogger(CampfireNotifier.class.getName()); 42 | 43 | public CampfireNotifier() { 44 | super(); 45 | initialize(); 46 | } 47 | 48 | public CampfireNotifier(String subdomain, String token, String room, String hudsonUrl, boolean ssl, boolean smartNotify, boolean sound) { 49 | super(); 50 | initialize(subdomain, token, room, hudsonUrl, ssl, smartNotify, sound); 51 | } 52 | 53 | public BuildStepMonitor getRequiredMonitorService() { 54 | return BuildStepMonitor.BUILD; 55 | } 56 | 57 | private void publish(AbstractBuild build) throws IOException { 58 | checkCampfireConnection(); 59 | Result result = build.getResult(); 60 | String changeString = "No changes"; 61 | if (!build.hasChangeSetComputed()) { 62 | changeString = "Changes not determined"; 63 | } else if (build.getChangeSet().iterator().hasNext()) { 64 | ChangeLogSet changeSet = build.getChangeSet(); 65 | ChangeLogSet.Entry entry = build.getChangeSet().iterator().next(); 66 | // note: iterator should return recent changes first, but GitChangeSetList currently reverses the log entries 67 | if (changeSet.getClass().getSimpleName().equals("GitChangeSetList")) { 68 | String exceptionLogMsg = "Workaround to obtain latest commit info from git plugin failed"; 69 | try { 70 | // find the sha for the first commit in the changelog file, and then grab the corresponding entry from the changeset, yikes! 71 | String changeLogPath = build.getRootDir().toString() + File.separator + "changelog.xml"; 72 | String sha = getCommitHash(changeLogPath); 73 | if (!"".equals(sha)) { 74 | Method getIdMethod = entry.getClass().getDeclaredMethod("getId"); 75 | for(ChangeLogSet.Entry nextEntry : build.getChangeSet()) { 76 | if ( ( (String)getIdMethod.invoke(entry) ).compareTo(sha) != 0 ) entry = nextEntry; 77 | } 78 | } 79 | } catch ( IOException e ){ 80 | LOGGER.log(Level.WARNING, exceptionLogMsg, e); 81 | } catch ( NoSuchMethodException e ) { 82 | LOGGER.log(Level.WARNING, exceptionLogMsg, e); 83 | } catch ( IllegalAccessException e ) { 84 | LOGGER.log(Level.WARNING, exceptionLogMsg, e); 85 | } catch ( SecurityException e ) { 86 | LOGGER.log(Level.WARNING, exceptionLogMsg, e); 87 | } catch ( Exception e ) { 88 | throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage(), e); 89 | } 90 | } 91 | String commitMsg = entry.getMsg().trim(); 92 | if (!"".equals(commitMsg)) { 93 | if (commitMsg.length() > 47) { 94 | commitMsg = commitMsg.substring(0, 46) + "..."; 95 | } 96 | changeString = commitMsg + " - " + entry.getAuthor().toString(); 97 | } 98 | } 99 | String resultString = result.toString(); 100 | if (!smartNotify && result == Result.SUCCESS) resultString = resultString.toLowerCase(); 101 | String message = build.getProject().getName() + " " + build.getDisplayName() + " \"" + changeString + "\": " + resultString; 102 | if (hudsonUrl != null && hudsonUrl.length() > 1 && (smartNotify || result != Result.SUCCESS)) { 103 | message = message + " (" + hudsonUrl + build.getUrl() + ")"; 104 | } 105 | room.speak(message); 106 | if (sound) { 107 | String message_sound; 108 | if ("FAILURE".equals(resultString)) { 109 | message_sound = "trombone"; 110 | } else { 111 | message_sound = "rimshot"; 112 | } 113 | room.play(message_sound); 114 | } 115 | } 116 | 117 | private String getCommitHash(String changeLogPath) throws IOException { 118 | String sha = ""; 119 | BufferedReader reader = new BufferedReader(new FileReader(changeLogPath)); 120 | String line; 121 | while((line = reader.readLine()) != null) { 122 | if (line.matches("^commit [a-zA-Z0-9]+$")) { 123 | sha = line.replace("commit ", ""); 124 | break; 125 | } 126 | } 127 | reader.close(); 128 | return sha; 129 | } 130 | 131 | private void checkCampfireConnection() { 132 | if (campfire == null) { 133 | initialize(); 134 | } 135 | } 136 | 137 | private void initialize() { 138 | initialize(DESCRIPTOR.getSubdomain(), DESCRIPTOR.getToken(), room.getName(), DESCRIPTOR.getHudsonUrl(), DESCRIPTOR.getSsl(), DESCRIPTOR.getSmartNotify(), DESCRIPTOR.getSound()); 139 | } 140 | 141 | private void initialize(String subdomain, String token, String roomName, String hudsonUrl, boolean ssl, boolean smartNotify, boolean sound) { 142 | campfire = new Campfire(subdomain, token, ssl); 143 | this.room = campfire.findRoomByName(roomName); 144 | if ( this.room == null ) { 145 | throw new RuntimeException("Room '" + roomName + "' not found - verify name and room permissions"); 146 | } 147 | this.hudsonUrl = hudsonUrl; 148 | this.smartNotify = smartNotify; 149 | this.sound = sound; 150 | } 151 | 152 | @Override 153 | public boolean perform(AbstractBuild build, Launcher launcher, 154 | BuildListener listener) throws InterruptedException, IOException { 155 | // If SmartNotify is enabled, only notify if: 156 | // (1) there was no previous build, or 157 | // (2) the current build did not succeed, or 158 | // (3) the previous build failed and the current build succeeded. 159 | if (smartNotify) { 160 | AbstractBuild previousBuild = build.getPreviousBuild(); 161 | if (previousBuild == null || 162 | build.getResult() != Result.SUCCESS || 163 | previousBuild.getResult() != Result.SUCCESS) 164 | { 165 | publish(build); 166 | } 167 | } else { 168 | publish(build); 169 | } 170 | return true; 171 | } 172 | } 173 | --------------------------------------------------------------------------------