Using VSTS Wildcards for .NET Core projects

On our Thinktecture Research Retreat I had the chance to have a deeper look at the Visual Studio Team System (VSTS), especially in regards to VSTS and its Build / CI System. Right on the first steps with it I ran into an issue with the VSTS wildcards for .NET Core projects.

The Issue with VSTS Wildcards

I wanted to build and publish NuGet packages for a .NET Core library project after all unit tests passed. So for the VSTS build I chose the .NET Core template, that comes with the tasks to call the dotnet CLI with restore, build, test and publish the project.

Since I wanted to create and push NuGet packages instead of creating a project with the dotnet publish command I changed the publish task to call dotnet pack instead. The problem with that was that the default project search pattern for the .NET Core CLI commands is **/*.csproj. With that pattern, the build created (and pushed) a NuGet package for all projects. Including my test project, which is something you usually don’t want to do, because who wants to install a test project with NuGet? 😉

Since that pattern seemed like a normal globbing pattern, I tried to simply exclude my test project from that, but sadly the next build did not pick up any of my projects for packing. Since I worked quite a bit with gulp tasks previously and usually know my way around globs, I found that a bit irritating. I tried several different syntaxes, but none of them worked out.

The journey

First I tried to to find some official documentation from Microsoft on the VSTS task wildcards. Sadly I wasn’t able to find one, which was quite discouraging. So I asked Google for some more ideas. In a blog post from Léon Bouqiet he explains the TFS 2015 build task wildcard format. Since VSTS and TFS are very similar (in fact, TFS is a version of VSTS you can install on premises), I hoped this would help.

Update 2017-07-22: I now know why I wasn’t able to find the official documentation during my searches. There is quite a disconnect between the terms used on the VSTS UI (“Projects”, “Paths”, “Wildcards”) and the terms used in the documentation (“File matching patterns reference”). I just didn’t come up with the correct search terms, as they were nowhere on the UI.

Strangely enough, also none of his search patterns worked. The syntax described in his post reminded me a bit of the file patterns used in JetBrains TeamCity server. Since I know my way around TeamCity build configs quite well, I tried multiple variations of each scheme, with and without variables for the full patch. I tried them separated by semi-colons or by new lines, with different orders etc., but none of them yielded the expected result. Every version I tried led to one of two possible results: Either no or all projects were packaged.

At this stage I was quite a bit frustrated. Luckily my boss knows someone who knows someone and so we could direct that question to some people who know quite a bit more about VSTS than what was available on online resources.

Already the first answer that came back was a big hint in the correct direction.

The rabbit hole

This response hinted me to the fact, that the VSTS tasks are open source on GitHub. Which, by the way, is awesomesauce. He linked me to the repository of the .NET Core CLI tasks. There I searched my way through the dependencies of that project where the actual file matching is implemented. Working through the code I found the correct way of how the pattern should look like.

Using VSTS Wildcards for .NET Core projects

First and foremost, there are currently at least two different versions in VSTS for wildcard file matching. The one explained in the aforementioned blog post is the ‘legacy’ version and no longer widely supported. Besides that any task is a custom extension, so it is possible that other tasks use different globbing libraries and bring their own pattern matching variation with them.

To give the answer away, this is the pattern that includes the projects, but excludes all test projects:

*.csproj
!*Tests*.csproj

Despite what other sites may say, for the .NET CLI Tasks the patterns need to be separated by new lines and not be semi-colons. Also, the exclusion operator is the exclamation mark and not the -: operator.

Conclusion

Astonishingly this is a very simple, straightforward pattern. However given previous experience with other globbing syntax and pretty much all online references pointing to the ‘legacy’ patterns that is similar to TeamCity´s this really isn’t the intuitive way.

Getting used to VSTS Wildcards in build tasks, especially for .NET Core projects, takes a bit of time when you are used to other globbing syntaxes. It would have helped a lot when the VSTS UI would have provided a link to the most recent documentation. However, having the source code of the VSTS Wildcards search pattern evaluation in the build tasks at hand is an invaluable resource.

By the way, after I figured all that out another response to our question turned up with a link to the official documentation. That verified my findings were correct. It seems my google foo wasn’t so strong in the first place.

Update 2017-07-22:

The team at Microsoft got in touch with me after this post, which is pretty awesome! Indeed they want to add a link to the official documentation page right from the info box. This will help a lot, because it removes the need to search for help on the patterns in the first place.