One of my aims with my GiftList project is to build sensible CI/CD support processes to enable easy deployments as I continue to develop the API. In addition, one of my aims is to move away from pure mobile dev and return to my roots as a backend developer while maintaining my strong focus on solid development techniques and processes.
Setting up the build
The first step was to setup the build such that I could confirm that I didnt miss a build error with a given checkin. VSO makes this incredibly easy using the Build Solution task; just remember to have it follow a Nuget Restore task.
I always recommend using individual build configurations for each build type, it just makes it easier to be more selective as you move through the process. I use to recommend this as a way to change your connection string at each stage but, this is falling out of practice as Cloud can hold your credentials and do the replacement for you. Such an approach maintains the “wall” between development and production so the credentials for Production are known only by the cloud and select individuals.
Adding the Unit Tests
So apart from adding the unit tests (128 as of this writing) which took me a month after I had completed a majority of the API code. But honestly, this worked out well as going back and adding the unit tests found a few bugs that I would have otherwise missed.
In terms of organization I have always been a big fan of the “give an instance … verify …” pattern where you attempt to construct logical sentences describing what is being tested with the class name and method name. Example:
given an instance of itemcontroller call getitems verify bad request is returned if id is empty guid
This allows the first portion of this to describe the general action being tested which is calls to getitems on the itemcontroller. The second portion indicates what test case we are exploring, bad request is returned if id guid is empty in this case. This approach enables good organization when you have hundreds and hundreds of tests. It also helps prevent accidental duplication.
Now, once I added the tests I needed to instruct VSO to actually run those tests as part of the build. To do this, you need to tell the task WHERE tests are located. Tests CAN be added as part of your projects but this means this code will get added to all versions of the assembly (you could remove it with a PreProcessor directive) which would inflate the overall size of the application. My preference here is to add new assemblies with a .Test suffix. I then instruct my other build profiles to NOT build these beyond development.
Once you do this, configuring the VSO tasks is rather easy. Here is a screenshot of mine:
Remember, the default setting in Visual Studio is that the DLL name matches the project name, so this works here. The ** means recursive.
Truth is, even with this your tests will not run if you are not using MSTest. In my case, I was using NUnit and I needed to ensure I had the TestAdapter Nuget package referenced (there are two versions, one for 2.x and one for 3.x – use the one correct one for your version).
Now I have 128/128 tests passing.
Let’s deploy it
So this proved to be the most difficult part for me, but it gets to be easy for you now. First, make sure you are publishing your artifacts using the Publish Artifacts task. Documentation here is kind of sparse but what you want to do is publish your output directory (mine is /bin) to a staging directory which we can use for a release.
Here is what my task looks like. The key here is the Artifact Type which I have set to Server which indicates the artifact is stored on the build server. The artifact name will represent the directory, remember it for the next step.
Ok, so it used to be that when you ran your builds if you also wanted to deploy you would code that as part of the steps. While it works, it is actually not a good strategy since it made built processes less reusable. In seeing that Microsoft has now added a second section called Releases. Releases contain you release workflows, they are independant of your Build workflows.
I am still exploring this environment but, it appears to be full featured and allows signoff for builds. For my example, I just want to deploy to my Dev environment whenever the build changes. All this takes is the Deploy Azure App Service task. Here is my configuration:
Most of this is simply selectable, very easy. Once you authorize the task it can pull your subscriptions and from that it can get your App Service instances. Really the hardest part was the Package or Folder bit, which once I got the Publish working worked great. Here is an example of what the … brings up if your Publish is working properly.
Very easy. You notice the lowest folder matches the Artifact Name from the Publish.
All in all, very easy to set this up. WIthout the time to add all of my unit tests, probably took me 2hrs tops to create this process end to end while doing other things. Hat’s off to Microsoft, cant wait to see what is coming next.