Andrew Kanieski

Software Architect
Passionate Programmer
Loving Husband & Father of Three

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.

Moving Work Items Made Easy

December 8, 2020

In my experiences working with enterprise implementations of Azure DevOps Server and Services I’ve found it fairly common for organizations to be able to migrate work items and other entities. Some common scenarios include:

  • Moving work items from XML Process Model to Inheritance Process Model
  • Moving work items from on-premise Azure DevOps Server to Azure DevOps Services
  • Moving work items from between process models that have different fields and requirements
  • Moving work items from many projects into a single project
  • Moving work items between projects for other reasons

Sometimes these scenarios may be simple, just move item 1 from project A to project B. But in other scenarios they can be fairly complex. For example, moving a work item from a CMMI XML Process Model to an Agile flavored Inheritance Process model. This would require field mappings from one field to another including work item type changes. As these sorts of scenarios come up it can be daunting creating a set of scripts to automate this process using the out-of-the-box REST api for Azure DevOps.

That being said I would like to introduce a project I’ve been working on the …

Azure DevOps Migration Utility.

This tool was written to create a simple user experience for migrating work items and other entities between projects in Azure DevOps. Working directly with the Azure DevOps REST api takes work. Administrators may not have the time needed to script out migrations using the REST API. This tool aims to make that experience easier.

This tool is maintained by it’s author Andrew Kanieski with the support of the community and is not an official or supported product of Microsoft. It’s design and intent does not relect the views of Microsoft.

A special thanks to the teams of people that I have worked with over the years that have lent ideas and requested features that have found their way into this tool. Together as a community we can make our work easier and more enjoyable!

UI Screenshot

Download the latest version here.

If you are looking for a feature that’s missing or need to report a bug, please follow up in our GitHub’s Issues section.

Disclaimer: This product is not a Microsoft product and support for it is handled by the community. Please keep this in mind when using it. If you encounter an issue feel free to submit a bug using the link above

Purging 'Local Versions' from Azure DevOps Server

November 3, 2020

Note: Use this at your own risk. As is best practice: Take backups and test it out in advance. This guidance may not be officially supported although it leverages existing APIs for Azure DevOps Server.

Recently I’ve had to work on a project to reduce the size of the tbl_LocalVersion table in Azure DevOps Server. This table stores metadata about Local Workspaces, Shelvesets and Server Workspaces. One way we can trim this down is by using the TFSConfig command line utility’s purgelocalversions job. This job is not documented but will essentially trim the size down on your tbl_LocalVersion table by providing you a mechanism to set a rolling window of Local Version records based on the date in which they were “Last Accessed”.

Enabling the command triggers the purge to begin immediately, and then schedules a job to run on Saturdays at 04:00 “Server Time”.

This should help keep the size of the tbl_LocalVersion down as it removes old workspaces.

The command is as follows:

Getting a glimpse of what’s being purged

If you are like me and are concerned about what exactly is going to be purged, we can take a look at the stored procedure that drives this operation, [dbo].prc_PurgeLocalVersions. You will notice that the mechanism used to identify rows for purging based on LastAccessDate. If we take this as a baseline we can build a stored procedure that allows us to view what Local Version records will be purged when the job next runs.

Take a look at the below [dbo].prc_PurgeLocalVersionsDryRun which can provide you a summary of what is slated to be purged.

Note: This stored procedure itself is not supported. It will work and has been tested with Azure DevOps Server 2019 and likely will continue to work. This of course can change with subsequent versions. Your mileage may vary.

Measuring Concurrent Jobs Over Time

July 17, 2020

If you are looking to move your Azure DevOps Server or TFS implementation to Azure DevOps Services, you will find that the licensing and pricing around concurrent job’s has changed.

First, what is a “concurrent job” anyway? In short, a job can mean a few different things in Azure DevOps, but a concurrent job relates to a discrete unit of work executed as part of a pipeline (Release or Build). That being said you may find it somewhat difficul to gauge how many concurrent pipelines you are currently using at most during the course of business.

To get a grasp of how many concurrent jobs you have consumed at most during the past year, the below query will give you a decent idea of consumption:


Migrating Work Items Across Projects, Organizations, Templates and Even Process Models

February 17, 2020

Azure Devops can be quite flexible and allow users to structure their work items to meet the needs of their favorite and preferred DevOps process. It even allows you to go fully custom if that’s your desire. But with such flexibility can come some challenges.

In order to strike a proper balance, one fundamental decision organizations need to understand is how coarse or fine grained should teams, repos, boards and developers be across Team Projects. One one side, having many team projects provides organizations with isolation that has benefits in the form of security and management. On the other hand, the more team projects an organization maintains, the more challenging it is to roll up and report on the status across all the team projects in your organization.

A great break down of how to strike this balance can be found in a blog series by a colleague and friend, Emmanuel Knafo, “One Project to Rule Them All”.

Fortunately for us, a fantastic tool has been developed by Martin Hinshelwood that makes migrating work items in and out of projects a breeze!

So if you are tasked with the process of merging many projects into one large project, or perhaps break one large project into many smaller projects, this tool is exactly what you’re looking for!

More info can be found over at their GitHub page!

Happy Coding Everyone!

Andrew Kanieski

Static Site Generators - Beauty in Simplicity

February 14, 2020

Recently I’ve had to spin up a number of blogs and simple sites for friends and customers. The process of doing basic web development has changed so much over the past 15 years! Fifteen years back I might have created a website in pure html and css, perhaps some javascript thrown in if they wanted a sparkling mouse cursor, or some background music (so kitsch!). If you went back perhaps 10 years ago, I might have spun up a website using ASP.NET Web Forms. If you asked me to building a website 7 years ago I would have created a HTML5/CSS3/Angular website.

What about today? Today I build simple websites using static site generators. In fact this site itself was written using Hugo, a super fast and robust static site generator written in GoLang. A static site generator is a tool that takes a folder of static content, blog articles written in markdown, images, Sass files, etc and converts them into flat HTML content. They can even do things like automagically crop, resize and thumbnail your photos for different display sizes.

Even better, store your site in a GitHub repo and use a service like Render to host your site, from a CDN for fast loading, for FREE.

The world of programming has truly come a long way! And boy has it gotten good!