Continuous Integration in Munich

November 23, 2011 on 3:57 pm | In Uncategorized | No Comments

Hardy Erlinger, the head of .NET Developers Group München, has just confirmed my session in Munich, Germany. I will be speaking about Continuous Integration in .NET at January 17th. The meeting will take place probably as usual in Firma TESIS at Baierbrunner Str. 15, 81379 München. Start 18:00. Details will be available at the group website www.munichdot.net. Acha, the talk will be in German!

More on “Continuous Integration in .NET”

November 11, 2011 on 2:46 pm | In Continuous Integration, DotNet | No Comments

I’ve recently got the sales report from Manning about my book “Continuous Integration in .NET”. I’m very happy to report it sells quite well!

And speaking about the book. My friend Mateusz Łoskot send me an excerpt from the ACCU discussion board discussing my book. Here it is:

> Interesting you mention the Manning books on Dependency Injection and Continuous Integration… is there really a whole books-worth of stuff in each of those topics??

If you are in the .NET world then then ‘Continuous Integration in
.NET’ is really worth the time invested. It covers most of commonly
used tools (CC.NET, MSBuild & Team System, TeamCity). Goes over
integration of unit testing, code metrics, analyse tools, source
control and these like (if I recall correctly there is a section on
building installation package and getting you DB related changes under
CI as well).

However, it lack some obscure topics (e.g. I would really like to
facilitate Hudson, Maven and Sonar, but I don’t even recall a word on
these also NAnt isn’t presented too well).

Even thought, if you are just starting with CI I would give it a go.

You could skip it if you already have some CI in house and just need
to improve / extend what it offers. It’s alway nice to have a look
around, but I find hands-on experience much more important in this
area.

So be my guest!

Adventures with certificates, 2-way-SSL and WCF

September 8, 2011 on 8:43 pm | In DotNet, Windows | No Comments

I’ve recently dived deep into WCF and security. To be exact I’ve tinkered with something that is called 2-Way–SSL a little. It’s a quite complex topic and I will try to summarize what I’ve learned.

1. Issuing certificates

Resources: http://msdn.microsoft.com/en-us/library/ff648902.aspx and http://msdn.microsoft.com/en-us/library/aa386968%28v=vs.85%29.aspx

System: Windows 7

To start you will have to have a certificate. Essentially you have two options if you don’t have one yet:

a) getting one from a CA (Certification Authority),

b) issuing one for yourself.

While choosing the way to go, keep in mind what do you need it for. The whole point of certificates is they need to be trusted. For your development its sufficient you trust yourself, but if you want to sing the SSL communication from your website or sign the emails you send you will need something more. For some purposes a free certificate from issuer like COMODO, CAcert or StartSSL are sufficient. They will only verify that you own the domain and/or email. If you need more thorough verification you will have to pay (from tenths to thousands of dollars).

If you are .NET developer sitting on Windows (sometimes mutually exclusive – cheers to Mono developers), you can use tool called MakeCert. You will find it in Visual Studio Command Prompt. To create usable certificate you will have to act like a CA yourself. So as a fist step you will have to issue a certificate for your CA. You can do it like that:

makecert -n "CN=MkCA" -r MkCA.cer -sv MkCA.pvk

Add a password for your private key (or choose to use none). This command will create a certificate *.cer and a file containing the private key *.pvk. The certificate needs to be added to “Trusted Root Certification Authorities” store. To do so, start the Microsoft Management Console (execute mmc.exe) and from in menu go to File –> Add/Remove Snap-in… and choose Certificates. Press Add > button and choose to manage the certificates in Computer account and on Local computer. Then press Ok.

Navigate to Console root –> Certificates (Local computer) –> Trusted Root Certification Authorities and from the context menu choose All Tasks –> Import…

image

Find the *.cer file you created using MakeCert and add it to the certification store.

Congratulations from now on you trust the certificates issued by the CA you’ve just created. Now you need a certificate combined with private key to secure the communication from the server. To do so you have to issue following commands

makecert -n "CN=localhost" -ic MkCA.cer -iv MkCA.pvk -sv MkServer.pvk MkServer.cer

pvk2pfx -pvk MkServer.pvk -spc MkServer.cer -pfx MkServer.pfx

The fist one will create a private key file and a certificate under your certificate authority MkCA issuer for “localhost” computer. The second one will create *.pfx file that contains both the certificate and the private key (and it can be protected by a symmetric key – a password – to assign one use the –po switch to pvk2pfx). The *.pfx file is necessary to secure the communication. The server will send the certificate (containing among other information’s a server public key) to the client. The client will encrypt a random number using the server public key and send it back to the server. This number will become a symmetric key used by both parties to encrypt the communication.

2. Securing the IIS communication using SSL

Now when you have the the *.pfx ready you can secure the IIS Web Site. To do so do the following:

1. Open IIS Manager (start InetMgr.exe or go to Control Panel –> Administrative Tools –> Internet Information Services (IIS) Manager)

2. Go to server node (root node with the name of your computer) and open “Server Certificates

image

3. From Actions choose Import …

image

4. Pick the *.pfx file you’ve created and enter password (if you used one).

5. Create a new Web Site (or use the default one if you like to secure it) and from Action choose Bindings…

image

5. Choose binding type https and newly imported SSL certificate.

image

Voila the website supports now secure communication.

Lets talk a little about the client (browser) configuration. While in IIS Manager with focus on the newly created web site choose Browse *:443 (https) from the Actions pane (or navigate to the website by typing the URL in the browser address)

image

As you can see there is a problem with the certificate. It’s because the browser tried to verify the issuer of the server certificate and failed. It failed because the issuer is not trusted.

image

As you can remember you’ve added your certificate authority key to the computer storage. But it’s not enough the browser uses the Current User certificate store. So you will have to add the certificate authority once again to user storage. Use the mmc.exe again. Add Certificates snap-in but choose “My user account” this time. Then add the CA certificate as described in section 1.

Note: if the certificate keeps disappearing (why? I don’t know – id did on my machine) from the store please experiment with the storage. Choose Registry or Local Storage as showed below.

image

Restart the browser and the problem report will be gone. The communication is encrypted. The certificate is trusted.

3. 2-Way-SSL

The term “2-Way-SSL” is sometimes used to describe the scenario where both the server and the client need to verify each other. It means that not only the server must present the certificate. The client need to do accordingly.

On IIS it can be achieved by setting the client certificate requirement in the “SSL Settings” of the web site or web application.

image

Set the Require SSL and choose to require client certificates.

image

From now on you will get the HTTP Error 403.7 – Forbidden if you will try to get the resource in the browser.

image

It’s because you don’t have the client certificate ready on the client side. Lets fix it. We will need a *.pfx file one again. Lets create one.

makecert -n "CN=marcin" -ic MkCA.cer -iv MkCA.pvk -sv MkClient.pvk MkClient.cer

pvk2pfx -pvk MkClient.pvk -spc MkClient.cer -pfx MkClient.pfx

With the *.pfx file ready you should add it to Personal –> Certificates in the Local Computer. Now the client will be able to present the client certificate and accomplish the 2-Way-SSL.

4. WCF and 2-Way-SSL

Ressources: http://www.codeproject.com/KB/WCF/wcfcertificates.aspx and http://www.codeproject.com/KB/WCF/WCFSSL.aspx

It’s now time to glue the pieces together. Lets configure WCF service to use the client certificates to communicate with the server.

I have used a simple service that took a string as a parameter and returned it back to the client. I named the service EchoService, I used wsHttpBinding to secure the communication on the transport level (it secures the whole communication as opposed to only securing the messages if you use Mosseage mode). The binding configuration looked like this:

   1: <bindings>

   2:   <wsHttpBinding>

   3:     <binding name="WSHttpBinding_IEchoService">

   4:       <security mode="Transport">

   5:         <transport clientCredentialType="Certificate"></transport>

   6:       </security>

   7:     </binding>

   8:   </wsHttpBinding>

   9: </bindings>

To keep the things simple I’ve turned off the publication of metadata off. The services and behaviors looked like this:

   1: <services>

   2:   <service name="WcfServiceLib.EchoService">

   3:     <endpoint address="" binding="wsHttpBinding"

   4:             bindingConfiguration="WSHttpBinding_IEchoService" 

   5:             contract="WcfServiceLib.IEchoService">

   6:     </endpoint>

   7:   </service>

   8: </services>

   9: <behaviors>

  10:   <serviceBehaviors>

  11:     <behavior>

  12:       <serviceMetadata httpGetEnabled="False"/>

  13:       <serviceDebug includeExceptionDetailInFaults="True" />

  14:     </behavior>

  15:   </serviceBehaviors>

  16: </behaviors>

On the client side of things the configuration needs to be extended with a behaviors section like that one:

   1: <behaviors>

   2:         <endpointBehaviors>

   3:           <behavior name="clientCertificateConf">

   4:             <clientCredentials>

   5:               <clientCertificate findValue="8516165A77364EDA28853CAAAD6197C5158E80A4"

   6:               storeLocation="CurrentUser"

   7:               x509FindType="FindByThumbprint" />

   8:             </clientCredentials>

   9:           </behavior>

  10:         </endpointBehaviors>

  11:       </behaviors>

It tells the client to use the client credentials taken from a CurrenUser certificate store and to search for the certificate using a given thumbprint (findValue). You can find the thumbprint in the certificate details tab.

image

Note if you get a “Invalid hexadecimal string format” from System.IdentityModel you will need to type the thumbprint by hand into the config file instead of copying it into the file. Oh, not ask why. Don’t forget do delete and add the quotation marks too Puszczam oczko

The rest of the client configuration is easy. wsHttpBinding like the one you used on the server plus gathering everything together in client configuration block.

   1: <client>

   2:   <endpoint address="https://localhost/Wcf2WaySsl/Echo.svc" 

   3:             binding="wsHttpBinding"

   4:             bindingConfiguration="WSHttpBinding_IEchoService"

   5:             contract="EchoServiceReference.IEchoService"

   6:             behaviorConfiguration="clientCertificateConf"

   7:           name="WSHttpBinding_IEchoService">

   8:   </endpoint>

   9: </client>

You are done.

You can always configure the client by code like that:

   1: // Configure binding with transport level certificate security

   2: WSHttpBinding binding = new WSHttpBinding();

   3: binding.Security.Mode = SecurityMode.Transport;

   4: binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

   5:  

   6: EndpointAddress endptadr = new EndpointAddress("https://localhost/Wcf2WaySsl/Echo.svc");

   7:  

   8: // Configure client by code

   9: using (EchoServiceReference.EchoServiceClient client = new EchoServiceReference.EchoServiceClient(binding, endptadr))

  10: {

  11:     

  12:     // Configure client certificate

  13:     client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser,

  14:         StoreName.My, X509FindType.FindByThumbprint,

  15:         "8516165A77364EDA28853CAAAD6197C5158E80A4");

  16:  

  17:     client.Echo("Test");

  18: }

5. Great finale

Keep in mind that the whole process is a bit tricky. It’s easy to make mistake so be careful and check if:

1. the certificate status you use is “This certificate is OK.”,

image

If not check if the CA is among the trusted root certification authorities. Beware of disappearing certificates Puszczam oczko

2. the “Issued To” field of the server certificate matches the name of the server you are using (localhost in my case),

3. If you are testing the SSL configuration using another browser then IE keep in mind that it can use its own certificate store and not the default windows one (Firefox does, Chrome not).

4. you can easily test the services with tools like soapUI. To set it up to use client certificates go to Preferences and set it up like this:

image

I had to create a *.pfx file WITH password to make it work.

Then if the server is configured to transport level security you can simply send a XML request to it to check if everything works fine.

Happy coding!

Visual Studio 2010 Professional and Hudson / Jenkins CI and FxCop

June 15, 2011 on 9:03 am | In Continuous Integration, DotNet, MSBuild | No Comments

 

Visual Studio 2010 Premium and Ultimate do have the code analysis feature build in. What this feature does is static code analysis of your source code (or IL to be specific). Unfortunately the Professional edition lacks the build in integration (no Analysis tab in the project properties). Here is a way to easily integrate Visual Studio 2010 Professional with FxCop. FxCop is a standalone Code Analysis version that comes together with “Microsoft Windows SDK for Windows 7 and .NET Framework 4 Version 7.1”. Actually if you download and install the SDK you will get the FxCop installer in %ProgramFiles%\Microsoft SDKs\Windows\v7.1\Bin\FXCop. You will have to install it from there (yeah installer in a installer ;) .

Here is how to built it into Visual Studio 2010 and into continuous integration process. First of all, I like to have all the assets in my repository. So I went and copied all the FxCop files into the tools/FxCop directory into the repository. I didn’t wanted to use the FxCop project files (they add unnecessary friction with editing the file – sometimes on runtime). I decided to go the command line way all the way. The easiest solution is to define all the rules you want to obey in the ruleset file. Ruleset file is a XML file that looks like this:

   1: <?xml version="1.0" encoding="utf-8"?>

   2: <RuleSet Name="Codefusion Rules" Description="This is the Codefusion rule set." ToolsVersion="10.0">

   3:   <Localization ResourceAssembly="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.dll" ResourceBaseName="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.Localized">

   4:     <Name Resource="ExtendedDesignGuidelineRules_Name" />

   5:     <Description Resource="ExtendedDesignGuidelineRules_Description" />

   6:   </Localization>

   7:   <IncludeAll Action="Error" />

   8:   <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">

   9:     <Rule Id="CA1000" Action="Warining" />

  10:   </Rules>

  11: </RuleSet>

The example above states that all the rules (IncludeAll) are threated as errors with one exception being a Warning (<Rule Id=…). You can define the rules as you wish. Fortunately Visual Studio 2010 Professional has the build in editor for the ruleset files. Using this editor you can easily choose the rules to obey (or not).

image

When you are done with the ruleset place it somewhere in your repository and define post build event like this one:

image

The text for the post build event is:

if $(ConfigurationName) == Release $(SolutionDir)Codefusion.Common\Tools\FxCop\FxCopCmd.exe /file:$(SolutionDir)S000.Basic\bin\$(ConfigurationName)\Codefusion.S000.Basic.dll /ruleset:=$(SolutionDir)Codefusion.Common\FxCopRules\CodefusionRules.ruleset /rulesetdirectory:$(SolutionDir)Codefusion.Common\Tools\FxCop\Rules /console

This way if you compile the project in Release mode you will get all the rules defined in ruleset file checked. You will see the violations in the Error List area. You can still jump to the line where violation occurs by double-clicking the line with report.

You can always suppress the messages for the rules you chosen to obey if in this particular case they don’t make sense. You can do it globally in the GlobalSuppressions.cs file. Like that:

   1: [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Codefusion")]

Or directly in the code like that:

   1: [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength")]

   2: public static string MakeMD5Hash(this string value)

   3: {

   4:     if (value == null)

   5:     {

   6:         throw new ArgumentNullException("value");

   7:     }

   8:     else if (value == string.Empty)

   9:     {

  10:         throw new ArgumentException(Resources.BasicStrings.ErrorMsgValueCannotBeEmpty + ".", "value");

  11:     }

  12:  

  13: ...

To make the suppressions work (suppressions are inline or global exceptions from the ruleset) you will have to define the compiler directive like that:

image

It will define a constant in the project file:

<DefineConstants>CODE_ANALYSIS</DefineConstants>

If you are using the continuous integration technique you can put the command similar to the one in post build event into the build project. In MSBuild it will look like this:

   1: <Target Name="Analysis" >

   2:   <Exec Command="$(MSBuildProjectDirectory)\Codefusion.Common\Tools\FxCop\FxCopCmd.exe /file:S000.Basic\bin\$(Configuration)\Codefusion.S000.Basic.dll /ruleset:=Codefusion.Common\FxCopRules\CodefusionRules.ruleset /rulesetdirectory:Codefusion.Common\Tools\FxCop\Rules /out:FxCopReport.xml /forceoutput" ContinueOnError="false" />

   3: </Target>

This way you will get get the XML file with the violations report that your CI server can interpret and thanks to the ContinueOnError=”false” attribute you will get the broken build if any of the violations will be found.

In Hudson/Jenkins you can use the Violations plug-in (you will have to install it) to show the violations in the build report. To do so you need to to configure the project like this:

image

Happy coding!

Continuous Integration in .NET – dead tree edition

March 13, 2011 on 9:12 pm | In Continuous Integration, DotNet | No Comments

Continuous Integration in .NET Author's CopiesFinally it happened. I’ve just got my author copies of “Continuous Integration in .NET” the book I coauthored. I’m very, very happy because it was a long journey and finally it happened. My first book is out. I would like to thank all the people who helped at Manning and outside. I was considering writing a longer post about the process, the ups and the downs, but I decided not to. I might return to that thought later. In a mean time if you are considering coauthoring a book with someone you don’t know think twice. If you are considering writing something together with Craig Berntson and want to know my honest opinion write to me. Hoppe you will consider this book interesting.

Hudson Continuous Integration LED message board monitor

January 2, 2011 on 8:59 pm | In Continuous Integration, DotNet | 2 Comments

Knowing the state of the build is one of the most important aspects of Continuous Integration. Team should get the information about the problems with he build as soon as possible. If the quality of source code degrades rendering the build to fail team, should jump in and fix the problem.

The most popular group of tools that make the swift reaction possible are the tray notifiers. Small programs that reside somewhere in the corner of the screen and show one of the 3 states the build server is ever in:

1. Building

2. Failed

3. Yet another successful build!

Oh, and well… not working (if the CI server is down). Some teams use emails or even SMS to inform about the broken build. Fore some it is not enough. The history of “alternative feedback mechanism” is long. It includes inventions like:

- Ambient Orb

- Read Bear Alert!

- Traffic Lights (to tell you the truth it is my favourite!)

I didn’t wanted to be worse. I wanted my won gadget. My budget was limited so I’ve picked something cheap but funny. What can be cheaper than USB toy, I thought. But finding a device that can be customized/programmed was not so easy. Most of the USB toys are dummy devices that take the 5V from the USB socket to simply power something up. But after a small research I’ve stumbled upon something interesting: LED Message Board from Dream Cheeky. I’ve asked the manufacturer about the possibility to program the device and received short but complete instruction how to use it programmatically.

LED Message Board for Hudson CI server

The LED Message Board is a HID device. HID stays for Human Interface Device – a device that can interact with humans. In my case it was the device input that should interact with my developers and show them that something is wrong on the CI server. So I’ve looked for a HID library on the net and found a nice piece of work from Mike Obrien. A .NET Framework library ready to use with any HID device. Neat!

We are using Hudson CI at CODEFUSION (my company). It has a nice XML API (next to JSON and Python API) that anyone can use of. So I had everything I needed to start coding (for fun)!

Getting Hudson CI build state

As I mentioned earlier Hudson CI exposes quite robust XML API that you can consume over HTTP as you like. To get the basic information about all available APIs substitute your Hudson URL with API like this:

http://yourserver/hudson/api

To the the the basic XML API document write api/xml:

http://yourserver/hudson/api/xml

This document holds only the subset of information’s that Hudson CI can deliver. The fist level does not contain what I needed – the information if any of the jobs defined is in broken state. Trying another depths /api/xml?depth=1I found the last buildResult in jobs that was what I needed! You can filter the returned XML using the tree parameter like this:

http://yourserver/hudson/api/xml?tree=jobs[name,lastBuild[result]]

In return I’ve got nicely formatted XML with all the data I’ve needed

<hudson>
  <job>
    <name>S000.Framework</name>
    <lastBuild>
      <result>SUCCESS</result>
    </lastBuild>
  </job>
  <job>
    <name>S001.Cfms</name>
    <lastBuild>
      <result>SUCCESS</result>
    </lastBuild>
  </job>
</hudson>

All I needed now is to get the file and parse it. One more thing I had to do before it was possible. My Hudson CI server uses the Active Directory authentication. There is access without an AD account and a proper values in Hudson security matrix. After some investigation on the HTTP communication the browser is normally performing with the server (I used Firebug – excellent Firefox plug-in for web developers) I’ve came with following code:

   1: // Non blocking lock

   2: if (Monitor.TryEnter(_TimerLocker))

   3: {

   4:     // Create web client instance

   5:     MyWebClient WebClient = null;

   6:  

   7:     try

   8:     {

   9:         WebClient = new MyWebClient();

  10:  

  11:         // Log-in in if neccessary

  12:         if (_UserName != null && _Password != null)

  13:         {

  14:             // Readc login page and dump result to dummy string

  15:             string Dump = (new StreamReader(WebClient.OpenRead(_Uri.ToString() + "loginEntry"))).ReadToEnd();

  16:  

  17:             System.Collections.Specialized.NameValueCollection Variables = new System.Collections.Specialized.NameValueCollection();

  18:             Variables.Add("j_username", _UserName);

  19:             Variables.Add("j_password", _Password);

  20:             Variables.Add("from", "/");

  21:             Variables.Add("Submit", "log in");

  22:  

  23:             WebClient.UploadValues(_Uri.ToString() + "j_acegi_security_check", "POST", Variables);

  24:         }

  25:  

  26:         StreamReader RequestReader = new StreamReader(WebClient.OpenRead(_Uri.ToString() + _HudsonFiler));

  27:         string ResponseFromServer = RequestReader.ReadToEnd();

  28:  

  29:         XElement XElement = XElement.Parse(ResponseFromServer);

  30:  

  31:         foreach (XElement Element in XElement.Elements())

  32:         {

  33:             // TODO mk from mk; meybe add project filtering

  34:             //Element.Element("name");

  35:             XElement LastBuildElement = Element.Element("lastBuild");

  36:  

  37:             if (LastBuildElement != null)

  38:             {

  39:                 XElement IsSuccessResult = LastBuildElement.Element("result");

  40:  

  41:                 if (IsSuccessResult != null && IsSuccessResult.Value.Equals("FAILURE"))

  42:                 {

  43:                     _IsOk = false;

  44:                     break;

  45:                 }

  46:             }

  47:  

  48:             _IsOk = true;

  49:         }

  50:     }

  51:     catch (Exception ex)

  52:     {

  53:         _LogProvider.Error(ex);

  54:     }

  55:     finally

  56:     {

  57:         WebClient.Dispose();

  58:         

  59:         // Exit from critical section

  60:         Monitor.Exit(_TimerLocker);

  61:     }

  62: }

  63: return _IsOk;

First, since I’m going to write a Windows Serve that periodically check Hudson CI I’m making a non blocking lock on the code I will run in a loop. If something hangs inside (like the HTTP request) the application will not run in a deadly loop that can eventually eat up all the resources. I’m using a overloaded WebClient class to perform all the operations. The overload was necessary because I have a secured Hudson CI server and the login is a little tricky in such case. Here is the code for the overloaded WebClient with cookie and changed timeout.

   1: namespace HudsonLedSygnalizer

   2: {

   3:     #region Using

   4:     using System;

   5:     using System.Net;

   6:     #endregion

   7:     internal class MyWebClient : WebClient

   8:     {

   9:         #region Private variables

  10:         private CookieContainer m_container = new CookieContainer();

  11:         #endregion

  12:  

  13:         #region Overrides

  14:         protected override WebRequest GetWebRequest(Uri address)

  15:         {

  16:             WebRequest request = base.GetWebRequest(address);

  17:             if (request is HttpWebRequest)

  18:             {

  19:                 (request as HttpWebRequest).CookieContainer = m_container;

  20:                 (request as HttpWebRequest).Timeout = 6000;

  21:             }

  22:             return request;

  23:         }

  24:         #endregion

  25:     }

  26: }

What we are about to do with it is essentially log-in like we were to log-on to the site over normal web browser. Maintaining the session by providing session cookie to the server.

The login URL is:

http://yourserver/hudson/loginEntry

You will have to read this URL to get the response cookie that needs to be maintained. The actual return is of no use to use. We are interested only in cookies. Having the cookie we can log-in. To do so you will have to send POST request to the server containing:

  1. j_username – set to the Hudson account name
  2. j_password – set to the password for the Hudson account name
  3. from – set to “\”
  4. Submit set to “log in”

If you are using AD authentication the request needs to go to:

http://yourserver/hudson/j_acegi_security_check

I was using WebClient.UploadValues to get the POST request rolling.

From now on you should be authenticated and ready to get the information about last builds from Hudson CI. To do it you will have to use the API provided by the CI server that I described earlier in this post. I was only interested if any of the build is broken. So I searched in a job for a result that contained FAILURE text. If found I knew that the CI server as a whole is in broken state and consequently it was the time to lighten up the alarm signal on the LED Message Board.

Programming LED Message Board

Every HID device has a vendor and product ID. The two numbers are unique and you need them to contact the device. The ones for LED Message Board are

private int _VentodId = 0x1d34;
private int _ProductId = 0x0013;

Getting the device is easy with the Mike Obrien HID library I mentioned earlier:

   1: private void MyDetectMessageBoard()

   2: {

   3:     HidDevice[] HidDeviceList;

   4:  

   5:     try

   6:     {

   7:  

   8:         HidDeviceList = HidDevices.Enumerate(_VentodId, _ProductId);

   9:  

  10:         if (HidDeviceList.Length > 0)

  11:         {

  12:             _MessageBoard = HidDeviceList[0];

  13:  

  14:             _MessageBoard.Open();

  15:         }

  16:     }

  17:     catch (Exception ex)

  18:     {

  19:         _LogProvider.Error(ex);

  20:     }

  21: }

What I wanted to do is to simply display a “big red blinking eye” that watches my team if something is not working well on the CI server. To display the “big red eye” you will have to send following data to the device:

   1: byte[] Packet0 = new byte[] { 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x7F, 0xFF, 0xF8, 0x3F };

   2: byte[] Packet1 = new byte[] { 0x00, 0x00, 0x02, 0xFF, 0xF0, 0x1F, 0xFF, 0xE0, 0x0F };

   3: byte[] Packet2 = new byte[] { 0x00, 0x00, 0x04, 0xFF, 0xF0, 0x1F, 0xFF, 0xF8, 0x3F };

   4: byte[] Packet3 = new byte[] { 0x00, 0x00, 0x06, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFF };

I wrote a quick Excel sheet to calculate the hex values needed for a given display pattern.

To display the signal you have to do the following:

   1: private void Timer_Elapsed(object sender, ElapsedEventArgs e)

   2: {

   3:     // Try to detect message board

   4:     if (_MessageBoard == null)

   5:     {

   6:         MyDetectMessageBoard();

   7:     }

   8:  

   9:     // Try to send the signal

  10:     if (_MessageBoard != null)

  11:     {

  12:         _MessageBoard.Write(Packet0);

  13:         _MessageBoard.Write(Packet1);

  14:         _MessageBoard.Write(Packet2);

  15:         _MessageBoard.Write(Packet3);

  16:     }

  17: }

As you can see the I’m using the Timer to display the “big red eye”. It is because the diodes are fleshing for a fraction of a second and you have to keep up refreshing them to get continuous display. I used System.Timers.Timer class to do the work. I set the interval so that the LED will flash – for a better effect.

   1: internal LedNotifier()

   2: {

   3:     // Init timer

   4:     _Timer = new Timer();

   5:     _Timer.Enabled = false;

   6:     _Timer.Interval = 1000;

   7:     _Timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);

   8:  

   9:     // Init message board

  10:     MyDetectMessageBoard();

  11:  

  12: }

We almost have all the ingredients. The last thing is a windows service. It will be very simple service that incorporates a new timer to perform periodical checks on the Hudson CI server and if necessary turning on the LEDs. I’m not providing the source code here but you can download it here:

DOWNLOAD Hudson CI LED Notifier Please write me an email to get the source code.

That’s it hope you can find any use for the information provided in that post. Here last but not least the device in motion!

 

Hudson CI LED Message Board Notifier

Continuous Integration in .NET book MEAP update

January 21, 2010 on 6:11 pm | In Uncategorized | No Comments

image There are two new chapters available at Manning MEAP site. The third one about build process automation (with MSBuild) and the forth one about choosing the right CI server (covering CCNet, TeamCity and TFS 2010).

And wow the book is third on this weeks bestselling early access titles. Juhu!

Speaking about continuous integration

January 16, 2010 on 7:09 pm | In Continuous Integration | No Comments

image I will be speaking on Wednesday (20.01.2010) in Krakow, Poland at the Karkow .NET Developers Group meeting. The session is about Continuous Integration in .NET. So if you like hear what I have to say about CI meet me at ABB ISDC, Pałac Pugetow, ul. Starowislna 13, Krakow at 18:30. I believe the attendance is free but registration is required. See you in Krakow!

Selenium RC and FitNesse as a service on Windows Server 2008

November 7, 2009 on 10:19 pm | In Continuous Integration, Windows | 2 Comments

If you are working in a team or running a continuous integration process the most comfortable way to run tools like Selenum RC Server or FitNesse is to install them as a windows service. I was doing this earlier on my old Windows Server 2003 by issuing the  instsrv.exe (to install a service) on srvany.exe (to run anything) – both from Windows Resource Kit. I had to edit the registry to provide what exactly do I wanted to run (java –jar selenium-server.jar or java –jar fitnesse.jar).

But there is no Windows Resource Kit for 2008. You might use the sc.exe and get the old srvany.exe (with compatibility issues according to Microsoft itself). It would work but why bother when there is a Non-Sucking Service Manager! All you have to do to install a service with this tool is to download it, issue a

nssm.exe install SeleniumRC

and edit this dialog box:

image

Click Install service and you are done. Selenium RC Server is installed. All you have to do is to start it. Voila!

How to make CruiseControl.NET accept SSL certificate under Windows Server 2008?

October 24, 2009 on 11:44 pm | In Continuous Integration, Windows | 1 Comment

If you are running CruiseControl.NET under the Local System account and your SVN server certificate was issued by yourself (or by VisualSVN Server) you will quickly run into trouble. Normally if you run any command on your repository you will get this information:

C:\Program Files\svn\bin>svn log https://your_server/svn/your_repository/trunk –username username –password password
Error validating server certificate for ‘https://your_server:443′:
- The certificate is not issued by a trusted authority. Use the
fingerprint to validate the certificate manually!
- The certificate hostname does not match.
Certificate information:
- Hostname: your_server
- Valid: from Sat, 26 Sep 2009 17:24:27 GMT until Tue, 24 Sep 2019 17:24:27 GMT

- Issuer: your_server
- Fingerprint: 24:8e:f6:ba:c7:a6:3f:69:32:c0:21:92:64:44:62:fe:2c:bb:b4:69
(R)eject, accept (t)emporarily or accept (p)ermanently?

If you accept you will not be bothered again. But CCNet works as a Windows Service. There is no one to make the decision. How to deal with this issue. Well earlier it was easy enough. You had to use one of the security holes and start cmd.exe in interactive mode wit at command (look here for more details). But with Windows Server 2008 it is not possible you will simply get this:

C:\Users\Administrator>time
The current time is: 23:31:11.59
Enter the new time:

C:\Users\Administrator>at 22:32 /interactive cmd.exe
Warning: Due to security enhancements, this task will run at the time
expected but not interactively.
Use schtasks.exe utility if interactive task is required (‘schtasks /?’
for details).
Added a new job with job ID = 1

How to deal with this. There is very easy solution. Set the CruiseContril.NET service “Allow to interact with desktop” flag (Start –> Control Panel –> Administrative Tools –> Services –CruiseControl.NET) like this

image

Restart the service and wait a while for this windows to appear:

image

Select show me the message.

Voila! You have command line as Local System user available. You can now issue the

C:\Program Files\svn\bin>svn log https://your_server/svn/your_repository/trunk –username username –password password
command and accept the SSL certificate permanently.

Local Service User Accepting SSL SVN certificate fir CruiseControl.NET server

From this time on you CCNet server will not have any problems with accessing your secured repository.

Next Page »

Powered by WordPress with Pool theme design by Borja Fernandez.
Text © Marcin Kawalerowicz. Hosting CODEFUSION.