Saturday, 12 January 2013

Sending messages to TeamCity and UnitTest to check if the Google Analytics file has changed

Since it is a really bad idea for websites to load Javascript files from external domains, my objective is to host the Google Analytics ga.js file directly in TeamMentor’s Javascript folder (i.e. not load ga.js from Google's server (which btw, is what most websites do)).

The only potential side-effect of hosting this file natively, is if Google changes the content of the ga.js file (where we are would be using an out-of-date version that could cause problems in the way the data is processed by Google). So to handle that case, I’m going to write a unit test to compare the 'TeamMentor hosted version' with the version at http://www.google-analytics.com/ga.js (this UnitTest needs to also be executable from TeamCity)



The first problem we have is in finding the TeamMentor’s Website folder from the UnitTests Project (we need the *.js files and not the *.dll).

Let's start by creating a UnitTest and (using the technique described here) open a C# REPL under the UnitTest Execution process:

image which when executed image  

will open up the O2 Platform C# REPL script environment:

image

In there, let's look at the UnitTests assembly, taking note of the fact that Assembly's CodeBase value has a different path from the Location value.

image

Here is an another way to see it the Location and CodeBase:

image

This means that we will be able to find the TM_Website project because that project is in a relative path from the CodeBase value (which is inside the TeamMentor.UnitTests project)

image

The interesting question is: "will this also happen in TeamCity?" (which we’re using for CI and to run the UnitTests)

So let’s put this code on out UnitTest , commit it, and see what happens at TeamCity:

image

A couple seconds after the commit and push, TeamCity will detect the change, and will trigger the build workflow:

image

And looking at the BuildLog, we can see that the Assembly’s CodeBase and Location actually point to the same location

image

Note: to create messages from an UnitTest that will show in TeamCity’s log, just write them to the Console Out (via Console.WriteLine or one of the O2’s Logging extension methods)

Now that we know that this will work in TeamCity, let’s go back to the C# REPL and write the code that will find the current copy of ga.js, download it and store in the right location:

image

Once we have that code, we can transform it into a unit test:

image

which will now run ok locally, if ga.js is the same:

image

and fail if they are not the same (I added a couple spaces to the local ga.js to test the fail behaviour)

image

Next, let’s commit the changes to GitHub:

image

Push it to master:

image

TeamCity will detect the GitHub push (it checks every 60 seconds):

image

Run the workflow:

image

Humm, which failed:

image

A look at the logs shows that this is CRLF mis-match problem:

image

Which can be solved using the fixCRLF extension method:

image

And finally, after commiting and pushing that change; TeamCity will trigger the Workflow, and the test will pass:

image

This means that if the http://www.google-analytics.com/ga.js file changes, we will be alerted by the failure of this UnitTest :)

From a security point of view, this will also prevent TeamMentor customers (including SI) from being compromised via a malicious ga.js file.