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:
which when executed
will open up the O2 Platform C# REPL script environment:
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.
Here is an another way to see it the Location and CodeBase:
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)
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:
A couple seconds after the commit and push, TeamCity will detect the change, and will trigger the build workflow:
And looking at the BuildLog, we can see that the Assembly’s CodeBase and Location actually point to the same location
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:
Once we have that code, we can transform it into a unit test:
which will now run ok locally, if ga.js is the same:
and fail if they are not the same (I added a couple spaces to the local ga.js to test the fail behaviour)
Next, let’s commit the changes to GitHub:
Push it to master:
TeamCity will detect the GitHub push (it checks every 60 seconds):
Run the workflow:
Humm, which failed:
A look at the logs shows that this is CRLF mis-match problem:
Which can be solved using the fixCRLF extension method:
And finally, after commiting and pushing that change; TeamCity will trigger the Workflow, and the test will pass:
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.