Saturday, June 29, 2013

How to Add Support for a new CI Server to Siren of Shame

Siren of Shame supports eight CI servers today, but adding additional ones is pretty easy.  Read on if you you're interested in adding support for achievements, reputation, or push notifications to mobile devices to your favorite CI server.

Architecture Overview

We use a plugin model to interact with CI server's via the Managed Extensibility Framework (MEF).  The main project (SirenOfShame.csproj) looks in the \plugins directory to find class libraries (.dll's) that export classes (via MEF's ExportAttribute) that inherit from ICiEntryPoint.  Theoretically you could export multiple CiEntryPoints per assembly, but we only do one per C# project to separate concerns.

If you'd like to start with a reference project for either reading through or copying, consider checking out HudsonServices.csproj as it is one of our more mature plugins.


public interface ICiEntryPoint
ConfigureServerBase CreateConfigurationWindow(
        SirenOfShameSettings settings,
CiEntryPointSetting ciEntryPointSetting

    string Name { get; }

    string DisplayName { get; }

    WatcherBase GetWatcher(SirenOfShameSettings settings);



The ICiEntryPoint interface requires a Name and DisplayName.  Name (e.g. "Hudson") is used extensively in a user's persisted settings as an ID.  It is never displayed to a user, and should never be changed.

DisplayName (e.g. "Hudson/Jenkins") is displayed in the dropdown of available CI servers in the Add CI Server dialog and may be changed over time if necessary.

SirenOfShame calls ICiEntryPoint's CreateConfigurationWindow() when a user adds an instance of a new build definition to watch.  It should return a class that inherits from ConfigureServerBase, which in turn inherits from UserControl.  The control will be embedded in a windows forms page when a user selects the associated CI server on the add CI server dialog or goes to edit an existing CI server.  This form should be used to allow a user to connect to a CI server, select the build definitions to watch, and optionally persist a username and password.  For example:

public ConfigureServerBase CreateConfigurationWindow(
SirenOfShameSettings settings,
CiEntryPointSetting ciEntryPointSetting) {

return new ConfigureHudson(settings, this, ciEntryPointSetting);


Finally, GetWatcher() is called when the system starts watching CI servers (e.g. after adding a CI server, or on startup).  Its job is to instantiate and return a class that inherits from WatcherBase whose job is to handle polling for build status changes.  For example:

public WatcherBase GetWatcher(SirenOfShameSettings settings) {

    return new HudsonWatcher(settings, this);



Pretty must the only responsibility of WatcherBase that's important is overriding:

protected override IList<BuildStatus> GetBuildStatus();

This method is called very frequently by the rules engine (RulesEngine.cs) to check for build status changes.  It is is expected to retrieve the build definitions that the user is watching and return a BuildStatus for each one.  It could utilize a separate class, such as one that inherits from ServiceBase, like HudsonService.cs does, but this isn't strictly necessary.

The build engine is run on a background thread, to free up the UI thread, but it does call GetBuildStatus synchronously.  Consequently any long delays inside GetBuildStatus decrease the frequency that users get build statuses.  For example if the user has set the polling interval as 10 seconds and GetBuildStatus takes 10 seconds to run then the user actually gets build statuses every 20 seconds.  For this reason it might be a good idea to request build statuses for each build definition in parallel like HudsonService.cs does:

public IList<HudsonBuildStatus> GetBuildsStatuses(
string rootUrl,
string userName,
string password,
BuildDefinitionSetting[] watchedBuildDefinitions) {

    rootUrl = GetRootUrl(rootUrl);

var parallelResult = from buildDefinitionSetting in watchedBuildDefinitions
select GetBuildStatus(rootUrl, buildDefinitionSetting, userName, password);
return parallelResult.AsParallel().ToList();

At any time GetBuildStatus() can throw ServerUnavailableException to indicate that something is temporarily wrong (e.g. the web connection is down or the server is down for maintenance).  In response the main engine will notify the user and continue polling the server periodically until the situation has resolved itself.  If you choose the overload with an exception, the user will be given the opportunity to click on the error message and send the result back to us for diagnosis.

Next Steps

If you have any questions feel free to e-mail us at support at our domain name.  And once you get it working we hope you'll consider initiating a pull request from our GitHub project.

Saturday, June 1, 2013

Released 2.1.1

In the excitement of announcing My CI we forgot to announce what else is new with versions 2.1 and 2.1.1.

Merge Duplicate Users

This oft-requested feature allows you to merge two users that are actually the same person.  Frequently this occurs for those monitoring multiple CI servers.  To perform a merge right-click on the user:

Then select who to merge that user with:

Notice the caveats above.  Specifically the system will not attempt to merge any previous check-ins, reputation, achievements, or stats.  However, the system will merge these going forward.


Again, as mentioned in our previous post 2.1 enables My CI, where you can get push notifications to mobile phones, a dedicated page on our site with your build information, and e-mails about build status changes and new achievements. 

If you were a beta user of 2.1, then 2.1.1:
  • Sync's users and their reputation, achievements and stats up to My CI
  • Sync's in-progress builds

Other Features

  • Full Screen mode now displays dates as pretty dates (e.g. 5 minutes ago).
  • Improved pretty date calculations

Bugs Fixed

  • The system was excessively updating the tray icon (Issue #16)
  • Full screen mode was displaying dates with incorrect time zone (Issue  #9)
  • Fixed a bug where the Jon Skeet achievement was too easy to get (Issue #42)
  • Fixed various smaller anonymously submitted bugs including null reference exceptions

Thursday, May 30, 2013

Introducing My CI: Turn a Smart Phone Into a Siren of Shame

Today we're proud to release a new, free, service called My CI and in conjunction Siren of Shame 2.1.1 (see also our official 2.1.1 release nodes).


Continuous integration can be awesome.  It can significantly improve quality on projects.  But incorporating it into daily life for the entire team can be hard.  It ultimately only works if everyone on a team is both aware of the state of the build, and is actively engaged in fixing it when it breaks.

We built My CI to help team leads achieve both ends: generate awareness, while encouraging everyone to fix broken builds; hopefully while making things a little more fun along the way.

What Is It?

My CI is a service that you turn on from our desktop software (2.1.1 or later) to enable some new features. First, it allows anyone to turn a smart phone or tablet into a mini Siren of Shame.  Second, it enables e-mail build notifications with fun user stats and updates about new teammates' achievements.  Finally, it turns on a customized web page we host on our website that displays your team's real time build status, build history, and team member stats like reputation, achievements, CSB, and FSB.

We have a pretty new webpage on our site to describe My CI at a high level here, but read on if you're interested in details.

Turn On My CI

Enabling My CI is easy.  After you pick up the Siren of Shame 2.1.1 desktop software, create an account, open up the SoS Online settings page and turn on My CI like this:

Or, if you use Travis to monitor a Github project you can add the account directly from the My CI page and we'll monitor it for you.  The only downside is we do not yet support achievements and reputation for projects monitored from our server.

Your My CI Page

Once you've enabled My CI you can log onto and you should see something like the following:

Your builds are on the left with most recent check-in comments, author, and build status.

Notice the team members listed on the right with their baseball card stats including Consecutive Successful Builds (CSB), Fail %, # of Times Fixed Someone else's Build (FSB), Total Builds (T), Reputation, and achievement counts.

We designed this view to be something you could throw up on a projector or put on a dedicated monitor from a machine that isn't running the desktop software.  We hope your team will find the baseball card stats to be motivating and add an element of friendly competition.

If you click on a user you can view individual achievements earned:

If you click on a build from the My CI page you can view build history:

Email Notifications

Typically an e-mail from a build server is bad news.  Wouldn't it be nice if your build failed e-mails contained a silver lining?

Or wouldn't it be nice to occasionally pass on good news to your teammates?

Mobile Sirens of Shame

We saved the best for last.  We now have apps for just about every smartphone and tablet.  We have apps for

Push Notifications

Now when the build breaks we send push notifications to your device(s).  You'll get a modal dialog that pops up with who broke the build and their check-in comments.  In Android you'll get build updates to your notification area.  In Windows 8 and Windows Phone you'll get live tile updates with recent check-in details.


In iPhone, Windows Phone and Win8 if any of the builds your monitor are broken we'll throw a badge on the Siren of Shame icon to show a count of broken builds without even needing to open the app.

Build Status, Leaders, News

When you open the app you can see all of your builds.  In Android it looks like this.

You can drill down to view recent check-ins.

We also show news from the Siren of Shame leader board like this in iOS:

Or the leaders from the Siren of Shame leaderboard like this in Windows Phone.

We hope you enjoy this new service.  We've got some big plans for it in the works, so stay tuned in here, on Facebook, or on twitter.  And as always please feel free to add comments we'd love to hear your feedback.