Continuous Integration with Hudson, ColdFusion, and MXUnit: Advanced Notification Control

Saturday, August 29, 2009

In an earlier post, I wrote about configuring notifications with Hudson. This is a follow-up post to demonstrate how to set up even more fine-grained notification control using the Hudson Email Extension Plugin.

In a nutshell, this provides granular control over:

  • Who receives notifications at any event: build instability, build failure, return to stability, continuing failure, etc.
  • The subject of the notifications that are sent
  • The content of notifications that are sent

By default, as of this writing, Hudson’s email notifications are fairly basic. It will notify either a specified list of recipients or “culprits” when a build fails. It will contain a generic subject and message, basically indicating that a build failed, but with no details.

The Email Extension Plugin: What it gets you

The Email Extension Plugin will enable you to control the content of the subject and message to make them more meaningful, in addition to the more granular controls I mentioned above.

Here’s what your “Configure Project” screen will look like once you install the plugin:


Notice from this screenshot how you can add notifications on different triggers: “Unstable”, “Still Failing”, etc. You can specify who should receive messages for all of the available events. You can add a new event by selecting one of the available options in the “Add a trigger” Select list.

Once you do so, you get checkboxes for the recipients to select. In addition, you get fields for controlling the subject and message. You can specify all manner of variables in there. My current setup at work for message content is:




With these variables, on the events I have specified, I get to see what tests have failed and what code changes have happened since the last build. Other variables are available to you. As per Hudson’s conventions, simply click on the (?) icon beside the configuration to get all the details for how to use the plugin. Here’s a sample of what you currently get in the Help:


My Take

I wrote before about how Hudson can significantly aide in noise control. I think this plugin gets you even further. Consider the “default case”: you get a notification that a build failed. Now you have to go research why it failed. This means going to your Hudson URL, checking the failed tests, and determining responsibility. However, with the plugin, I believe determining responsibility cuts out a few steps: it lets you see a) what tests failed and b) what code changed in a single email. All the information you and your team need to assign responsibility is, potentially, in a single communication.

So what? I think the answer to that question resides squarely in the answer to another question: how much do you value your time?

How to Install

You install this plugin just like you install other Hudson plugins, thank God (I Love Hudson. I wish all software I worked with were as easy to extend.)

  1. click the Hudson link, “Manage Hudson”, “Manage Plugins”
  2. in the “available” tab, select “Hudson Email Extension Plugin”
  3. select it, and click checkboxes and OK buttons until it’s installed. Restart Hudson

Once it’s installed, you go into your project configuration and now you have more “Advanced” buttons and such in the Notifications area than you had before. From there, it’s a matter of selecting your triggers and what you want to happen on those triggers.


If you want even more noise control, and more meaningful communication, take the few minutes to install the Hudson Email Extension Plugin.

Continuous Integration with Hudson, ColdFusion, and MXUnit: Failing builds for failing tests

Randy posted this question to the MXUnit group, and I wanted to expand a bit on it with a full code sample. His question:
"My question now is about the proper way to fail a unit test. Before I was just using haltonerror attribute to stop my unit tests. But now with Hudson I found I can't do that because I won't get the error logs. So, my question is, what is the 'best' way to fail the build when you are using it as a depends for a commit and still get the unit report that Hudson is looking for?"
By default, if you don't set MXUnit task's "haltonerror" property to true, then all tests will run, and if you pass JUnit XML to Hudson, Hudson will read it, see that tests failed (but the build didn't fail), and it'll record the build as a "warning". Here's what a warning looks like in Hudson. Note the link to “Test Result”, which you can drill down into to get all the details.
But if you use haltonerror, the MXUnit task essentially does a cfthrow, and tells the build to stop right now; consequently the JUnit task won’t run, so you get no useful messages about why the build failed. What Randy wants is to retain the ability to “fail” the build, but also to get the JUnit report messages. Here’s what happens if haltonerror is set to true. Note no link for Test Results. With a build like this, all you know is that “it failed”, but you do not know why. This is useless.

It’s time to talk about this notion of “failing” the build.  What Randy wants to do is to stop other things from happening if his tests fail. For example, maybe he wants to stop the process that FTPs the bits to the prod server; or perhaps he wants to not package the app for deployment if the tests fail. In these cases, haltonerror is usually a fine way to go. But since he’s doing continuous integration, and he wants proper recording of all that happens, he can’t do that. So what’s a boy to do?
Simple. But first, let’s look at a real-world task that runs tests, runs the JUnit report, and then emails stuff. I’ll use MXUnit’s own build file as an example:
<target name="runTests" depends="init,update">

<!-- load the current version of the package-summary file; this way, we can put it at the end of the email we send so that
comparing test the aggregate test results is easy; makes it simpler to see if any test failures crept in -->
<loadfile property="currentresultshtml" srcFile="${junit.out.dir.html}/mxunit/tests/package-summary.html" failonerror="false" />

<delete dir="${junit.out.dir.html}" />
<delete dir="${output.dir}" />
<mkdir dir="${junit.out.dir.html}" />
<mkdir dir="${output.dir}" />

<!-- get the server, port, and webroot properties from the antrunner file; this way
each developer can have their own version of the properties file with different
values depending on their setup -->
<property file="${antrunner.file}" />

<mxunittask server="${server}" port="${port}" defaultrunner="/mxunit/runner/HttpAntRunner.cfc" outputdir="${output.dir}" verbose="true" testResultsSummary="my.summary">
<directory remoteMethod="run" path="${webroot}\mxunit\tests\framework" packageName="mxunit.tests.framework" componentPath="mxunit.tests.framework" recurse="false" includes="*.cfc" excludes="" />
<directory remoteMethod="run" path="${webroot}\mxunit\tests\runner" packageName="mxunit.tests.runner" componentPath="mxunit.tests.runner" recurse="false" includes="*.cfc" excludes="" />

<!-- create nice pretty report -->
<junitreport todir="${junit.out.dir.html}">
<fileset dir="${output.dir}">
<include name="*.xml" />
<report format="frames" todir="${junit.out.dir.html}" styledir="${style.dir}" />

<!-- Read the properties files we generated 
<property file="${output.dir}/my.summary" />
<echoproperties />

<!-- now load the version we just created; this will be the first set of results in the email we send -->
<loadfile property="resultshtml" srcFile="${junit.out.dir.html}/mxunit/tests/package-summary.html" />
<loadfile property="resultscss" srcFile="${junit.out.dir.html}/stylesheet.css" />

<!—other stuff omitted for brevity -->

The important thing here is that no matter what, all the steps after the MXUnit task will run since the haltonerror attribute isn’t set. So how do I get all that stuff to run, but then fail the build  if tests fail (or error)?

1) You set the failureproperty attribute on the MXUnit task

2) You then call the ant built-in <fail> task, with a conditional.

So, in my example above, here’s what I’d do:

<mxunittask …[omitted for brevity] testResultsSummary="my.summary" failureproperty="testsfailed">




<fail if="testsfailed" message="Failing the build because tests failed"/>

If tests fail (or error), the MXUnit ant task will set the property named “testsfailed”. Then, the ant fail task will run because if=”testsfailed” will be true, since the “if” statement of an ant task runs if the property is set, not whether the property itself evaluates to true. Thus, with these two small changes to the build file, we get all the reporting we want via JUnit report but also a failure that prevents further processing.

Here’s the “overview” result in Hudson. Note that it has the data for failed tests, which we can then drill down into to get the goods.


CFUnited 2009 Part II – Day 1 Session Recap

Monday, August 24, 2009

Rather than try to put out an end-of-day recap post after each day of CFUnited, I decided to go drinking and smoking stogies instead. In retrospect, this was the correct decision. Now, however, it’s time to pay the piper. Fortunately, I took copious notes during all the sessions I attended (at least, the ones worth taking notes on) and so I’d like to give the highlights of some of the sessions. I will not attempt to cover them all nor will I attempt to provide a post that lets someone live vicariously. Consider this the day 1 highlight reel.

Session 1: CSI: Who killed ColdFusion?

This was an hour-long advertisement for FusionAnalytics, a now-in-beta product from Intergral, the same fine folk who bring you FusionReactor and FusionDebug. My one word reaction: Sold.

OK, calling it an hour-long ad is a bit cynical, I admit. Along the way, they did show a bunch of information that you could get if you diligently pored over logs, monitored the app closely, and were otherwise more anal about performance monitoring than anyone has time to be. Essentially, for me, FusionAnalytics does this work for you. It automates the monkey work… and I love things that automate monkey work. The Intergral guys did a great job of weaving good application-building advice in with a session on how their tool can help.

A few of the things I’m looking forward to playing with when this thing goes public enough that I can get my hands on it:

  • “Suspect code” graph: drilldown into chart shwoing what requests were running and how they affected resources (cpu, memory)
  • Long running requests: drill into the page, shows sql if there was any. shows attributes passed. shows the processor being sucked up by this request
  • graph for showing patterns you might not have expected: bots, spiders, etc
  • jdbc graphs: most apps should have a nice wave form where queries are concerned; this graph will help you see spikes in query usage, which can show where queries are tying up requests or even the entire application
  • graphs to help you solve the “why does this app always go down at 9:00 AM?” problem

And tons more. If you can get your hands on a beta, do so. It’s impressive. Hey, Intergral, I gave you my card (it’s the one with the babyshit brown and puke green colors)…why haven’t you called? I gotta get me some of this stuff!

Session 2: Design for Developers – Dave Powell

Description and Materials are here

I attended this session on a whim. In fact, that’s how this year’s CFUnited kind of went for me… I just picked stuff in between sessions rather than following the plan I made for myself. I don’t know why that was. I guess I was feeling all zen or something. I was like a birch branch in a water-witch’s hands.

I liked Dave’s approach. He showed a lot of examples, and he showed a lot of before-and-after-redesign sites. I think for even the design-hatin-est of developers, a lot of this is probably common sense. That doesn’t mean this session wasn’t valuable. Not by a long shot. It means that even if it’s common sense, why do we find it so hard to get right? I don’t know the answer to that question, but I can say that Dave’s session is one that even a few weeks out is still sticking with me.

The things I really got out of it: whitespace is critical. “Weight” is critical. Being thematically consistent is critical.

Duh, right? Yeah. Go try it on your own. Seriously. Go ahead. Uh huh. That’s what I thought. It’s f’n hard.

However, most of what Dave showed was for “new media” and other media type sites. Sites that are either advertising-based or information delivery. I wish there were a few more “boring old business app” sites and how these same lessons apply. For example, I’d like to see a session where someone says “OK, here’s this app called ‘QuickBase’, and some of you may be stuck using it b/c some douchebag executive knows a cousin of a brother who knows a guy at Intuit, and so your company spent a gazillion dollars on QB, and now you loser peons are stuck filling out timesheets every day in an app that is less usable than if you were to carve your own skin every day and write your timecards in blood. And now I’m going to show you how you might make this abomination – nay, this pox upon the state of man – not so suicide-inducing”. That’d be kind of helpful for me: take a shitty business app that us poor serverside schmucks are stuck building day in, day out, and help us make it look better.  And then please, sell it to the QuickBase.  (this is an app where I WISH that old dancing monkey would pop up, just so I’d have something to punch).

How’s that for a digression? Bottom line: great session, but I wish he’d have held my hand a teensy bit more on applying these things to the kind of ugly ass apps I have to look at every day. I am, after all, a design idiot.

Session 3: Subversion for Smarties -- Cameron Childress

Description and Materials are here

Cameron’s session was chockfull of info, from SVN 1.5 changelists to SVN Properties and how you can use them in your source code files (keyword substitution). He covered some open source projects for interacting with subversion, including the abstraction layer,, and which is a full-on, badass system for deployment building (duh). Plus a bunch of other stuff.

My only complaint: too much time comparing SVN to Git. That information is important, to be sure. I just wish a bit less time were spent on it. I’d have rather had 10 minutes on SVN externals or some “OK, here’s where I wow you n00bs” info rather than this comparison. Just sayin.

Session 4: How not to code a Flex app – Jeff Tapper

Description and Materials are here

Easily one of my top 2 or 3 favorite sessions. I loved Jeff’s approach: for each chunk of code, ask the audience to figure out why the code is bad. I think sessions like this just speak to how I like to learn things. I love presentations that are at least as much Sherlock Holmes as they are School Marm. I am very glad I took notes on this session, and I really like that Jeff’s approach gave me the time to take notes. As people were trying to figure out what was wrong with the code, I was jamming out thoughts and such.

One point that stuck with me was how he showed a ridiculously convoluted event dispatch that was dizzying in its attempt at  loose coupling but which in the end resulted in even tighter coupling, less maintainability, and otherwise nice rise in the “whoever coded this is an asshole” factor. Jeff demonstrated a lot of pragmatism during his presentation, which I appreciated. Going into it, I didn’t know if it was going to be a “if you’re not using Cairngorm, you’re doing it wrong” kind of thing. It most certainly was not.

Kick. Ass. Presentation. I wish it were a day long.

My only criticism is that Jeff isn’t bald, like me. You can’t have everything, I guess.

Session 5: Living in the Cloud – Sean Corfield

Description and Materials are here

I do not have a single line of notes for Sean’s presentation. I’m not sure how to analyze that, but I will say that I feel like I probably felt as engaged in this presentation as any other. I think I was just listening really hard or something.

Sean’s hour was not spent on “how do you deploy your app to Amazon” but instead on the challenges that he faced and the questions that you must answer during your investigation of choosing cloud services. So for a code monkey or day-to-day implementer type dude, this presentation might have been kind of “eh”. But for the people responsible for making decisions like this, I believe this presentation was outstanding.

If you are in a decision-making position and you’re investigating cloud solutions, do yourself a favor: contact Sean. He’s a teddy bear, and he’s smart as hell, and he loves to talk.

One thing I definitely took away from this, and I’m not sure it was intentional but I got it all the same, was that this stuff isn’t easy, and it’s not without consequence. For those of us who deal with typical managed corporate hosting environments – lots of IT staff, lots of control over servers, etc – this is a very different world. Just seemingly simple things like “Where do I store my data?” become very different kinds of decisions from the ones many of us are used to making. Is it scary? Possibly. Is it a “run away and hide”? Hell no. Not when you have people like Sean out there talking about their experiences.



Man, by the end of day 1, I was tuckered. I wish I had another “me” to go around to all the sessions I didn’t get to see. Alas, that is not to be. Why is that? Why is the worst part about a conference that you don’t get to see all the things you want to see?

I hope some day, every session at a conference is recorded and available, ideally for all the public to see.

CFUnited 2009 Part I – Big Picture Thoughts

You’ve already heard dozens of others say it: this year’s CFUnited was outstanding. The venue, the food, the quality of sessions, the organization… all were 5-star. So I won’t belabor those points except to say thank you to Liz, Nafisa, and the rest of the Stellr group.

For Managers

If this year’s CFUnited is an indication of where this conference is going, then I say put it back at the top of your “bang-for-the-buck” list when you’re allocating training money next year.

For Developers

One thing that set this year apart from previous years is the growing amount of Flex and Air content. Obviously, many of those sessions have a CF focus (Air + CF, Connecting Flex to CF, etc), though I attended at least one Flex session that was strictly Flex. I think it’s important for developers to seek out training which might not immediately apply to their day jobs but which just might be relevant in the future. That’s why, for example, I attended Jeff Tapper’s “How not to build a Flex App” session. I do not do Flex in my day job, but this session “smelled” like something that would be useful. I took copious notes, and I was not disappointed. Andy Powell said to me in the hallways: “Flex is hard to learn, and even harder to master”. The stuff that Jeff presented falls into the “here’s how to master Flex” category. Did it apply on Monday when I got back to work? Nope. But I trust that it will some  day.

I mention this because I think when you approach a conference with a mindset of “I want to learn at least a few things that I otherwise would not investigate on my own”, then you open doors for yourself. If you just stick to “what can I learn that’s useful on Monday”, you’re limiting yourself. And what’s great about CFUnited is that it now provides enough of those opportunities to explore new technological alleyways. Kudos to Andy for bringing in such top-notch Flex speakers.

What could Improve?

Time to get critical. As a speaker, I know how much energy most presenters put into what they do. It generally requires countless hours of preparation and practice to deliver an engaging, informative presentation that audience members can apply to their day jobs. And it is emotionally exhausting (at least, for me it is). However, as a former teacher, if I learned anything during my hears at college and the years I spent in the classroom, it’s this: the least effective way to learn is to listen to other people talk about it. I don’t know what the numbers are, but I bet the “retention rate” is pretty dismal for eyes-forward sessions.

Still, maybe that’s OK. Maybe the point of going to sessions isn’t so much to learn specific things but to be inspired enough to go back to work and pick the handful of things that you want to learn more about… and then go learn them. I suppose that is, in fact, the learning model on which most conferences are based. OK, I can buy that.


What if there’s a better way? What if we take what we know about teaching and learning and apply it to the way we run conferences. You always hear people say “I get more out of the hallway conversations than I do out of the sessions themselves”. Do you know why people say that? I do: it’s because we learn more when we collaborate. When people praise the value of hallway conversations, what they’re praising is the idea that 1+1 can equal 100. It’s the social learning, the fact that together, people can combine ideas, perhaps even come to new ideas that they otherwise wouldn’t have come to all by themselves. Does it happen all the time? Of course not. Are many of these “hallway conversations” just one blowhard holding court? Sure. But I bet more often than not, you get true idea sharing. What’s more, you’re building relationships, and you’re building community.

I think we should take this and apply it to the sessions themselves. Instead of 3 full days of eyes-forward, how about making more time for collaborative sessions. Roundtables, open-space sessions, sessions that have a topic and where the attendees simply talk about their experiences and work towards shared understandings. In this approach, presenters become more facilitators than yappers.

I’m not advocating a wholesale switch from an eyes-forward approach to a completely open space conference; however, I think that it’s time to challenge the assumption that conferences are about presentations. Conference organizers and presenters must challenge themselves to make sessions less about the person at the front and more about the people in the middle. 

For attendees: Take the best session you attended, and take the worst: and now, imagine if those sessions were structured differently. What if they started off with maybe a question, and for an hour, the people in the room tried to explore that question.  What would that have done to the quality of your best and worst session? Can you picture it? And can you think of one thing you could have done to make the conference even more meaningful for you?

For speakers and organizers: People learn best when they engage. How do we create even more opportunities for deeper engagement? How do we help attendees kick even more ass when they get back to work on Monday?

CFUnited 2009: Best New Blog? God help us all

Sunday, August 23, 2009

In what was, I assure you, a complete surprise, the MXUnit blog won “best new blog of the year” at the CFUnited Community Awards.

This isn’t good. This portends terrible things. When the best the ColdFusion community has to offer in the “new” category is a  unit testing blog where the two dudes who write on it never write about unit testing and generally just go on about all manner of inane things other than ColdFusion programming – where you get posts with samurai videos and Rated-R banners and occasional talk of “truth tables” – then it’s time to consider a switch to a different language.

God help us all.

And THANKS! to the 3 people who voted for us. You guys rock! (the check’s not in the mail… we lied. You should’ve voted for Jason, suckers!).

A full list of winners is here:


(In all seriousness: we’re flattered and humbled. Thanks a million to Todd for keeping the community awards alive. If there were a category for “ColdFusion Community King”, I’d vote for you, Todd.)


--Marc and Bill

CFUnited 2009 “Automate Like a Rock Star” Presentation Materials

First, a HUGE thank you to the people who spent their hour with me. You could’ve gone to see Joe Rinehart, Mike Brunt, and other unbelievably awesome speakers, but you gave your time to me and for that I am truly grateful. I hope it was worth your while. If you didn’t get out of it what you expected, please let me know. I generally don’t give a presentation more than once, so this one’s in the can and in the grave, but knowing what could improve can always help me as I prepare stuff for the future.

Now then: you can get the presentation materials here. If you wanted to learn more about ANT, notice that on that same page is a link to last year’s presentation at CFUnited on ANT… it has a whole bunch of sample ANT files for doing all manner of ridiculously cool things with ANT.

For those of you bitten by the automation bug, please drop me a line as you learn more new ways to master your machine and eliminate soul-killing monkey work from your life!


The Importance of Failure and Organizational Maturity

Friday, August 14, 2009

This is me raising my voice, "If you want to be a grown-up organization, stop treating your staff like children!" Good - now I feel better. However, managers frequently echo a far different sentiment, "If they just acted more like adults, then we would treat them accordingly, but the truth is they need constant supervision or else..." Maybe these types of managers are simply responding to the same assumption by senior management. Is it possible this lack of faith, the fear, is a systemic social virus pervading organizational culture? Like, duh! So, where does this leave us? This makes an organization a stagnant environment lacking in creativity, initiative, and makes for a typical sucky place to work. I'm starting to believe that one of the most important approaches an organization can take with staff is to encourage failure. "Say, what!? Tell staff to make mistakes? That's fucked up, dude!" Really? Think about it. Failure is critical to progress and may be especially important for people in software development where there are many unknowns and rapid technology advances makes it challenging to maintain and evolve software. If we are doing only that which we already know, how can we improve and evolve our software - how can we learn anything new? Further, how can we attempt to learn these new things without experiencing failure? If failure is something to be avoided, it seems that it would be hard, if not impossible, to grow in the absence of failure. As a manager or technical leader, maybe the risk of failure should be embraced (at a minimum, suspended) rather than deterred. Maybe a metric to know whether a solution is reasonably viable is how many set-backs or fuck-ups occurred during the research or proof-of-concept phases. If the answer is 0, then that may be suspect or pure bullshit altogether. If the response was, "Well we tried X and it broke Y, and we learned something about P, so we tried R and that broke Y, too. Eventually we saw that Z was the best way today because it made A faster and subsequently Y worked as expected.", then maybe there might be some validity. I'm certainly not encouraging lower quality products - God knows we don't need more crappy software! - or a chaotic approach to problem solving. On the contrary, allowing for the exploration of alternative solutions methodically but with wide boundaries and the freedom to fail may produce a higher quality work product in the end simply because more alternatives have been explored. I wager that allowing developers to play and be creative will produce some very interesting results and I would put my own money down on the fact that would make developers want to come to work. Equally as important, giving developers your faith that they can and will come up with a decent solution instills confidence and respect all the way around and contributes to your organization's maturity. On a personal note, this is how I try to avoid the swirling vortex of mediocrity and apathy at my workplace where success and failure are deemed foes. A lot of what I do is done without official approval and I have incurred numerous political risks because of this way of thinking and action; i.e. failures. I guess management has learned to tolerate me because in the end I have have consistently delivered solutions of high quality and value. With that said, it is tiresome to be at an organization that does not embrace creative thinking or innovation. If you want what you always get, don't change what you do ... But, there are many opportunities ... For this programmer, failure is the road to success. It's kind of like a Samurai death - going knowingly towards a certain end is not negative - it's freeing. "Even if one's head were to be suddenly cut off, he should be able to do one more action with certainty" -The Hagakure Ok and now for some organizationally immature content. My favorite Samurai movie scene ever! Enjoy :-)