Automate everything

I'm a huge fan of automation. I don't like repeating things and I don't like doing everything manually. Everything can be automated - code generation, deployments and migrations. You can script how your application is being built, how it is being packed and how to notify everyone interested in this fact. After few months of work it saves even days of your priceless time. You can hardly believe in that? Let's see(all below examples are real functionalities prepared for my side-project):

  • Using command line to generate modules or features in your application

Most applications are based on very simple CRUD modules, which allow users to manage the data. No one likes to write such code - just query the database, do some validation, return a success or an error. Such modules or features, developed by many devs, tend to evolve into some kind of "an-app-inside-an-app" - everyone uses different conventions, code is formatted differently, the very same functionalities are structured using different patterns. Even when you are creating an application on your own, you sometimes change your style and approach. To get rid of this problem I've created a simple command line tool, which creates whole feature structure using only given feature name(of course it generates both handlers for API and AngularJS controllers and factories). I think, it saves me about one hour of writing the same code all over again per each feature. I have around 20 features so far.

  • Generating AngularJS factories based on requests data using Fody

It's a similar feature to previous one but it extends it rather than overrides it. When I have my structure created, it is obvious, that in some point in the future, I will have to add something new to my features. Because requests, which are a part of my API, are also used by factories in AngularJS(at least in terms of URL structure/HTTP verb), I don't want to change something in my JS code each time server-side code changes. That's why I'm using Fody(or Mono.Cecil if you wish) to generate this kind of client-side code.

  • Notifying users about new deployment/delivery using EventStore

I wanted to notify each user about the fact, that a new version of the application has been delivered. Because I extensively use TeamCity and psake, I decided, that my build script should just send an event to EventStore, which will be processed and respective action will be taken. I don't think about it, it just happens.

  •  Packing and deploying application using TeamCity + psake

Although I haven't got Octopus yet, I really wanted to pack and deploy my application automatically. It's the biggest problem for most companies - automate your deployment/delivery process so human factor is minimized. I decided, that everything necessary can be zipped by psake and just deployed to the destination server. Because psake is basically PowerShell, I was able to shut down the old version of my application, deploy new version and start it much faster, than doing it manually. No mistake is possible.

  • Creating issues in YouTrack automatically when not handled exception occurs

This is something unusual, but I realized that it's a real pain in the ass. Working with your client can be difficult sometimes, especially when you're trying to get some details about error he or she mentioned. Yes, you have logs and some general idea what was the flow but sometimes, you need a whole context. You can implement audit of each operation performed in you application(and this is not a bad idea). I decided to do something more interesting from my point of view - to automatically report an issue in my YouTrack when a HTTP 500 error occurs. It saves my time, it saves my client's time and that makes him happy.

Personally I think, that automating things - in development, in your process, in management - is a great opportunity to try and test your ideas. Initially you have to invest some time in making all those things, but after few months, when you just write

--create -featureName=Foo

instead of writing boilerplate code again and again, you will now it was worth it.

Making your application's version more descriptive with Stamp.Fody and TeamCity

Problem

Sometimes you want to display an application's version visible somewhere, so it is easy to determine, which version has been recently deployed. In .NET application the easiest way is to get a version number from the one of the following attributes:

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

The problem is, that in the world of automatic builds and deployments, changing those values is cumbersome and error-prone. Of course you can shape your delivery process in a way, that will allow manual version changes - but we should avoid such actions if possible, shouldn't we?

Solution

Assuming that you use some kind of a build server, getting all necessary data(in my particular case - build number and SHA of a commit) can be pretty easy or very difficult. To be honest, it would be possible to create a whole functionality, I'm talking about, relying solely on TeamCity. The thing is, that the more your build server knows, the harder it gets to version it.

Because of all above concerns I decided to change the concept a little. The best idea I came up with was to get all necessary info directly from the .git folder of my solution after the build. Because I'd already had working psake build script, the easiest thing to do seemed to use some Powershell magic and fetch all what I needed using it. However, why should I extend my script when there is already a better solution?

Stamp.Fody

Yes, there is a weaver, which allows you to automate work needed to embed some Git info in application's version info. The best thing about it is, that it is completely transparent - all it needs is installed Fody in your solution.

Stamp's concept is pretty simple - it checks whether there is an AssemblyInformationalVersionAttribute attribute added to your assembly and if it is - it replaces predefined tokens used as a version's info using data found in your solution's .git folder:

[assembly: AssemblyInformationalVersion("%version%-%shorthash%-%branch%")]

In the above example it is possible to get following result - 1.0.0.0-0772a13a-develop. More tokens are listed on the weaver's GitHub page.

We have some Git info in application's version - what about getting a build number and combining all those values?

TeamCity & psake

As I mentioned before, I use a psake script to handle all build-related tasks. This lets me version all steps required during building an application. Because Stamp takes care of getting the Git info, the only thing left is to combine it somehow with a build number provided by TeamCity.

The very first thing needed here is to pass a build number parameter to a psake script. To do that, you have to go to the build steps of your project and find the one, which executes psake. There, in the script source area, you probably have something similar to:

Import-Module .\.tools\psake.4.4.2\tools\psake.psm1
Invoke-Psake .\build.ps1

All you need is to add a parameter using -parameters switch:

Import-Module .\.tools\psake.4.4.2\tools\psake.psm1
Invoke-Psake .\build.ps1 -parameters @{tcBuildNumer=%build.number%}

Now each build will pass its number to our script. Next todo is to create a function in Powershell, which will obtain generated application's version from an assembly:

function Assembly-GetVersion($file) {    
    $version = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($file).ProductVersion;
    return $version;
}

The last thing is to use above function and generate a new application's version number, which will be much more informative:

Task ExtractVersion {
    $assemblyVersion = Assembly-GetVersion "path_to_your_assembly"
    $majorVersion, $minorVersion, $buildNumber, $revision = $assemblyVersion.split('.', 4)
    $version = "$majorVersion.$minorVersion.$tcBuildNumber.$revision"
    
    New-Item "path_to_the_base_directory\version.json" -type file -value "{`"Version`": `"$version`"}"
}

Note that above syntax is correct using Powershell 4.0 - if you have a different version, some changes would be required. What is more - I am generating a version.json file, which can be requested by your front-end and displayed(e.g. using Angular):

var version = $http.get('version.json');
version.success(function (res) {
     $scope.appVersion = res.Version;
});

Summary

By using mentioned tools you can easily generate an application's version, which will easily tell you and your client what version has been deployed. It can be especially helpful when dealing with multiple environments + automatic deployments(e.g. using Octopus Deploy) during development phase - it is easy to determine whether correct version of an application is being tested and used.