Refactoring development

Ramblings from the trenches...

View on GitHub
                                                                                                                                         | | 15 years on and some teams don't realise that CI is mandatory.

There’s several stages of evolution with TeamCity:

With ‘feature-branch’ support now in TeamCity we only need to copy our projects when we’re creating a new version of the build system, - not when we’re creating a new branch. TC can keep an eye on a range of branches and trigger a build on the right one. This removes the need for templating and keeps things simple again.


 

properties for trunk/branch, version checkout on agent

a project should be the level at which you branch at. I.e. you can have one with ‘trunk’ in the name.

Templates are good but you can’t template build dependencies so try to keep the dependencies within one TC project.

Cake

Freightliner Just Revealed The First Real Road-Legal Autonomous Big Rig: http://truckyeah.jalopnik.com/freightliner-just-revealed-the-first-real-road-legal-au-1702382986/+AnnaleeNewitz

Given most of the cyclists killed in London are by undertaking a lorry while not being seen, these automated trucks should have a much better job of spotting them.

I wonder how few years it will be before they don’t bother with the cab. My guess is that we will see cabless road trains first in Australia.

(Just so we are clear, you should still have a truck number greater than 1 in your team even if the chances of a team member getting run over are now smaller !)
| | I thought I was doing the right thing. I had every dll branded with the branch that it was built with and the subversion revision number that the repository was up to when the build was done.

I still think there’s nothing wrong with including the branch name, but there’s distinct disadvantages to just wiring the version number to the latest revision number. If you do so you loose an important property: your artefacts change all the time. Two otherwise identical builds will appear binary different for all built dlls.

From a human / operational perspective this is a big downside. It’s great that we can aways reproduce the exact build, but ideally if I’ve not changed a dll it would be great if that dll didn’t change.

Can we have our cake and eat it?

TeamCity

I’m assuming you’re fully bought into how awesome TeamCity is as a CI server. Have a look and see how your build scores against this list.

Maintenance

1. Thou shalt not select agents based on their name.

2. DRY: Templates are your friend.

3. Favour svn / package managers over agent installs

Speed

4. No more than 50 agents per server.

5. Keep it brief

6. Always checkout on the agent

Reliability

7. Always use the Free Disk Space build feature

8. Use custom errors.

9. Be hygienic.

Above all,

10. Don't live with red.

 

If you’ve got some great CI / TeamCity tips, please share!

Obligatory infographic:

TeamCity10Commandments

Agent Management

                                                        | | TeamCity is awesome, but there's always room for improvement. Here's a great trick to help you always select the right agents...

Agent-Selection

Once you’ve got a big build farm, agent selection has challenges. How many times have we realised the tests failed because that agent didn’t have a particular package installed on it?

One technique that works very well is to have a weekly task running on all compatible agents that scans the registry for all MSI packages installed and which version numbers they are.

This is easy enough to do in PowerShell:

Get-WmiObject -Class Win32_Product

Returns the installed set of products, with the Name and Version properties being on each product.

The secret is to then write this information to the build agent’s conf\build.properties file. The agent will then disconnect from the TeamCity cluster, and a minute later will re-connect with the appropriate settings.

One slight gotcha at the moment is to try not to have any version number as part of the property name as TeamCity can’t do wildcards on property names - only on the version field.

Run as Admin

Obviously it’s strongly recommended to not have your build chain need admin privileges to run, but for some builds it may be the only way. You could subset to build agents which have admin privileges by doing something like this:

([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")

(Again, if at all possible you can de-admin your build process that’s preferable!)

Hopefully you’ll find other good uses for this technique!  
  <h2>Living with NuGet</h2>

As NuGet packages are immutable I’m really interested in using a shared package directory for NuGet as suggested here:

http://stackoverflow.com/questions/24617112/storing-nuget-packages-in-alternate-location-on-build-server

As well as time, this would save a ton of diskspace on build agents.

 

Death to Dll Hell

.Net assembly versioning has always been ‘tricky’. The GAC solves this problem but as many find out the GAC is wac. An alternative to mandatory strong naming of the world is to embed the version in the assembly name (which you bump the version number on each breaking change).

At least with Nuget this gets a bit easier when you’re then upgrading references to the next version.

Large Testbases

                                                                                                                                                                                                                                                                                     | | There's two possibilities, either you have a set of machines exactly the same or they're not. If you're using imaging then exactly the same may be possible.

If not there’s likely to be machines which don’t have every last install required to pass every test. You could be fighting a loosing battle trying to get everything installed everywhere. Instead nunit has ‘assume ‘ which allows you to check whether that component is available before running the test. If it’s not then the test is reported as inconclusive.

Using ‘Assume’s allows you to use a higher percentage of build agents and reduces the number of boring test failures.

In my book that’s a win-win that reduces the costs of keeping a large testbase on the road.

(See also selecting TeamCity BuildAgents based on installed programs)

 

Testing in the Small

Before you get to having a large test base you need to know how to test. There’s a learning curve and the more you do the better you get, but I think this guy has hit the nail on the head (it’s not really about ruby):

https://www.youtube.com/watch?v=LfmAzLAKKoc  
  There’s two possibilities, either you have a set of machines exactly the same or they’re not. If you’re using imaging then exactly the same may be possible.

If not there’s likely to be machines which don’t have every last install required to pass every test. You could be fighting a loosing battle trying to get everything installed everywhere. Instead nunit has ‘assume ‘ which allows you to check whether that component is available before running the test. If it’s not then the test is reported as inconclusive.

Using ‘Assume’s allows you to use a higher percentage of build agents and reduces the number of boring test failures.

In my book that’s a win-win that reduces the costs of keeping a large testbase on the road.