Cake Build vs VSTS

Cake Build system has an integration point with most build systems like Team City, AppVeyor, Bamboo, etc. But there is not much for Visual Studio Team Services (VSTS). There is a Cake Build Task that facilitates execution of Cake script on VSTS build agent, basically a wrapper around build.ps1.

But if you need to reach into any of the VSTS build process variables or call any of their API – you are on your own. And we are migrating our grand-project to be built on Cake and with VSTS.

And one of the pain points were NuGet feeds. We are consuming private nuget feed from VSTS and we are pushing a NuGet package into a private VSTS feed. Both of these actions require feed authentication. And VSTS authentication is painful.

Cake Package Restore From Private VSTS Feed

To restore packages in Cake you have NuGetRestore method and you do something like this:

Task("Restore-NuGet-Packages")
    .Does(() =>
    {
        Information("Starting Nuget Restore");

        var settings = new NuGetRestoreSettings()
        {
            ConfigFile = "./src/NuGet.config", 
        };
        NuGetRestore("./src/MyProject.sln", settings);
    });

This composes a command line arguments and executes nuget.exe with the parameters. Because your feed is protected by password you need to authenticate. VSTS feeds have magic authentication barrier and documentation is less than optimal for cases where build server is involved. The gist of it all – you need to generate Personal Authentication Token and save it in Nuget.config file.

Personal Authentication Tokens (PAT) are like alternative passwords for your account with limited permissions. Once you have your PAT, add your feed and credentials to your nuget.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
  </solution>
  <activePackageSource>
    <add key="All" value="(Aggregate source)" />
  </activePackageSource>
  <packageSources>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
    <add key="MyVSTS" value="https://MyCompany.pkgs.visualstudio.com/_packaging/MyFeed/nuget/v2" />
  </packageSources>
  <disabledPackageSources />
   <packageSourceCredentials>
    <MyVSTS>
      <add key="Username" value="MyUsername" />
      <add key="ClearTextPassword" value="MyPersonalAccessToken" />
    </MyVSTS>
  </packageSourceCredentials>
</configuration>

Make sure your personal access token has only minimal permissions because you are going to check it into your source control. For packaging restore you need only “Packaging (read)“.

Run your Cake build script locally, make sure it runs and restores packages – before executing the build – empty your packages folder. Then check it in and execute the process on in VSTS build agent.

Here I hit a wall – everything worked locally perfectly. But once I got to the VSTS build agent, I could not restore the packages – there was an authentication error. To fix this I had to downgrade to nuget feed version 2. That was a mind-bogging issue that took forever to fix. I even checked nuget.exe version installed on VSTS agent and one used by Cake.exe – version numbers were the same, yet there was a problem. I actually did not get down to the actual source of the problem – there was enough time wasted on that issue.

Anyway, VSTS does not seem to be working with nuget v3 properly yet.

Cake Push Nuget to VSTS Private Feed

THERE IS A BETTER WAY TO PUBLISH. READ THIS

Another issue I run into was publishing a NuGet package into a VSTS feed. VSTS documentation says I need to provide -ApiKey VSTS when I push a nuget. Huh??? Not quite so, but close enough.

Again, you need to generate the Personal Authentication Token and add it into nuget.config. Because I was pushing to a different feed I now have 2 nuget feeds in my nuget.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
  </solution>
  <activePackageSource>
    <add key="All" value="(Aggregate source)" />
  </activePackageSource>
  <packageSources>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
    <add key="VSTSMyCompany" value="https://MyCompany.pkgs.visualstudio.com/_packaging/MyFeed/nuget/v2" />
    <add key="VSTSMyCompanyApplications" value="https://MyCompany.pkgs.visualstudio.com/_packaging/MyCompanyApplications/nuget/v2" />
  </packageSources>
  <disabledPackageSources />
   <packageSourceCredentials>
    <VSTSMyCompany>
      <add key="Username" value="MyUsername" />
      <add key="ClearTextPassword" value="YourPersonalAcessToken" />
    </VSTSMyCompany>
    <VSTSMyCompanyApplications>
        <add key="Username" value="MyUsername" />
        <add key="ClearTextPassword" value="YourPersonalAcessToken" />
    </VSTSMyCompanyApplications>
  </packageSourceCredentials>
</configuration>

Your Personal Access Token now needs write permissions to your packages: “Packaging (read and write)”.

And your Cake task will look like this:

Task("Publish-Nuget")
    .Does(() => 
    {
        var package = "./src/MyApp/bin/release/MyApp.nupkg";
        Information("Pushing package {0}", package);

        NuGetPush(package, new NuGetPushSettings 
            { 
                Source ="VSTSMyCompanyApplications",
                ApiKey = "VSTS", 
                ConfigFile = "./src/NuGet.config", 
                Verbosity = NuGetVerbosity.Detailed,
            });
    });

For my case I push results of builds into Applications feed, but if you don’t do this – you only need to have one source recorded in your nuget.config. And make sure value for Source = "VSTSMyCompanyApplications" matches the source name in nuget.config. Verbosity is not mandatory here, but I had so much trouble with it – I’ll leave it in just in case. And don’t forget to specify ApiKey = "VSTS" – the process won’t work without it.

Again, as with package restore, everything worked locally great. But as soon as I checked it in and executed that on VSTS build agent, I got The remote server returned an error: (405) Method Not Allowed.. The fix was to again downgrade nuget protocol to version 2. Again I decided it is not important to actually figure out the reasons behind the issue.

So far these have been the biggest issues I hit with Cake and VSTS. And it only seems to be happening on actual VSTS build agent. So I’m not sure where to report the bug – it is not really Cake issue because it works locally, it is sort of VSTS issue, but I can push/restore packages OK when I use nuget.exe directly without Cake. I wish you, my dear reader, not to hit this kind of road-blocks.

Enjoy your Cake!