MonthDecember 2014

Continuous delivery, NuGet package generation and integration with TFS build server

Continuous Integration is getting more important and more popular and that is a good thing!
A couple of days ago, I was automating the NuGet package generation process. NuGet packages can be used for deployments to environments.

NuGet integrates in your solution when package restore is enabled.

enable-package-restore

This adds the following files to the .nuget folder in your solution:

  • NuGet.exe
  • NuGet.targets
  • NuGet.config

It also adds an import command for the NuGet.targets file to the project file:

<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />

One target of the targets file is BuildPackage. This target can be triggered by running the following msbuild command from the command line:


msbuild mysolution.sln /t:Build /p:BuildPackage=true

This will create a NuGet package for all projects which have imported the NuGet.targets file.
The following files will automatically be added to the NuGet package:

  • The project assembly
  • Files with build action set to content

For simple projects, this behavior is fine. The NuGet package holds the exact content of the project.
In my case, this was not really what I wanted. I wanted one NuGet package for multiple projects and the content files had to be placed in a different structure and location.

That’s when a nuspec file comes to the rescue!

The NuSpec file is the manifest file for NuGet packages. This file holds all information required for the NuGet packages, for example;

  • Package meta data (name, author, copyright, etc.)
  • Dependencies
  • Included Files

For a complete reference of the nuspec file, see http://docs.nuget.org/docs/reference/nuspec-reference.

I added a reference to the assembly1 and assembly2 project and added a nuspec file to the root of the project.
In the nspec file, I added the required assemblies and content files. The nuspec files section looked something like:

  <files>
    <file src="bin\assembly1.dll" target="lib\net40" />
    <file src="bin\assembly2.dll" target="lib\net40" />
    <file src="..\assembly1\Scripts\**\*.*" target="Content\Scripts" />
    <file src="..\assembly2\Scripts\**\*.*" target="Content\Scripts" />
  </files>

I ran the msbuild command on my dev environment and a package was created successfully and contained all files.
It also contains the dll of the NuGet project itself. This is not what I wanted.
I created a naming convention for all NuGet projects, the projects end with NuGet. This gives me the option to exclude the *nuget.dlls from the packages. This can be added to the build command I will describe later in this post.

Files added to the Content folder of a NuGet package are installed on the root of the target the project (the project which the NuGet package is installed to).
Assemblies added to the lib folder will be referenced in the target project. A subfolder in the lib folder can be used for providing different assemblies for a framework (.Net 3.5, .Net 4, etc).

I configured the TFS build server to run the same command and started a build.
The build failed, because NuGet could not find some of the referenced files in the files section of the nuspec file.
When I used RDP to login to the build server, I noticed that the output folder (binaries folder as it is called in the TFS build workflow template) is changed by TFS. It does not use the bin folder of every project, but it changes it to a different folder.
That is why bin\assembly1.dll and bin\assembly2.dll could not be found.

Creating packages should work on both dev environment and on the build server, so referencing the absolute output path on the build server is not an option.
The output folder is stored in the OutDir parameter. This parameter needs to be available in the nuspec file. This can be achieved by adding it to the properties list of the build command.
The build command is stored in the targets file, add “OutDir=$(OutDir.Trim(‘\\’))\\” to the property parameter of the build command. You can also exclude files by adding an Exclude parameter. This is what I have done to exclude the *Nuget.dll files.
The updated BuildCommand is as follows:

<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform);OutDir=$(OutDir.Trim('\\'))\\" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols -Exclude **\*NuGet.dll</BuildCommand>

It is now possible to use the OutDir variable in the nuspec file:

  <files>
    <file src="$OutDir$assembly1.dll" target="lib\net40" />
    <file src="$OutDir$assembly2.dll" target="lib\net40" />
    <file src="..\assembly1\Scripts\**\*.*" target="Content\Scripts" />
    <file src="..\assembly2\Scripts\**\*.*" target="Content\Scripts" />
  </files>

This solves the output issue on the build server and the build still works on the dev environment.

Creating a circular bitmap in Android in C#

A while ago, I was looking for a way to change a bitmap into a circular bitmap.
There are a lot of good examples on the internet, but none of them completely met my requirements.
So I used one of them as base to create my own helper for creating a circular bitmap.

public static Bitmap CreateRoundedBitmap(Bitmap bitmap, int padding)
{
    Bitmap output = Bitmap.CreateBitmap(bitmap.Width, bitmap.Height, Bitmap.Config.Argb8888);
    var canvas = new Canvas(output);

    var paint = new Paint();
    var rect = new Rect(0, 0, bitmap.Width, bitmap.Height);
    var rectF = new RectF(rect);

    paint.AntiAlias = true;
    canvas.DrawARGB(0, 0, 0, 0);
    canvas.DrawOval(rectF, paint);
    paint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.SrcIn));

    canvas.DrawBitmap(bitmap, rect, rect, paint);
    return output;
}

I’m not a fan of static methods, but when no context is used, I’m not that bothered.

A border can be added by drawing a second oval with a stroke width and a color property set to the paint instance.

 var rect2 = new Rect(padding, padding, bitmap.Width - padding, bitmap.Height - padding);
 var p = new Paint();
 p.Color = Color.White;
 p.StrokeWidth = 10;
 p.AntiAlias = true;
 canvas.DrawOval(new RectF(rect2), p);
 

This example creates a white border around the circular bitmap.

In my app, I use a lot of white circular bitmaps. To keep the code as DRY as possible, I created another helper method for creating white bitmaps.

public static Bitmap CreateWhiteBitmap(int width = 160, int height = 160)
{
    var bitmap = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
    Canvas c = new Canvas(bitmap);
    c.DrawColor(Color.White);
    c.Save();
    return bitmap;
}

Another static. Still can’t be bothered, because no context is used.
I do like to point out that statics can be very dangerous. When statics are used as repositories to read static variables, files or whatever kind of data, remember to at least always use locks, but even better… just don’t use statics!!

Now let’s bring it all together.

In my activity, I use the following code to create a bitmap, change it to a circular bitmap and add it to an ImageView (with id “Image” in my Layout file):

var bitmap = BitmapHelper.CreateWhiteBitmap();
bitmap = BitmapHelper.CreateRoundedBitmap(bitmap, 10);
var imageView = view.FindViewById<ImageView>(Resource.Id.Image);
imageView.SetImageBitmap(bitmap);

That’s it! Hope this helps!