2013-10-09

NuGet 2.7 Package Restore with Team Foundation Service

Team Foundation Service

The best thing about Team Foundation Service is that they have a free plan for up to 5 users. I've been using it to experiment on, rather than screwing up an on-premise Team Foundation Server. TF Service also supports Git for version control, which is ton better than the legacy TFVC. TF Server supports Git in the 2013 product version, currently in RC, and it will be RTM later this month. I've been using Visual Studio 2013 RC to play with the Build part of TF Service, currently in "preview". It provides a hosted build controller that you can use to do builds on build agents.

NuGet 2.7 Package Restore

NuGet 2.7 introduced a new and much better way to doing package restore. Even better, NuGet 2.7 is on the hosted build servers and can be used to restore all the packages referenced by a solution before msbuild is kicked off. I modified the default Git build template so that package restore works.

I modified the GitTemplate.xaml so that after:
<mtbag:GitPull DisplayName="Pull sources from Git repo" CleanRepository="[CleanRepository]" />
I added:
<mtbwa:InvokeProcess DisplayName="NuGet Package Restore" FileName="C:\Program Files\Microsoft Team Foundation Server 12.0\Tools\NuGet.exe" Arguments="Restore" WorkingDirectory="C:\a\src" />
After that, the packages were restored. To get the output to show up, I had to add more:
      <mtbwa:InvokeProcess DisplayName="NuGet Package Restore" FileName="C:\Program Files\Microsoft Team Foundation Server 12.0\Tools\NuGet.exe" Arguments="Restore" WorkingDirectory="C:\a\src">
        <mtbwa:InvokeProcess.OutputDataReceived>
          <ActivityAction x:TypeArguments="x:String">
            <ActivityAction.Argument>
              <DelegateInArgument x:TypeArguments="x:String" Name="stdout" />
            </ActivityAction.Argument>
            <mtbwa:WriteBuildMessage Message="[stdout]" Importance="[Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High]" />
          </ActivityAction>
        </mtbwa:InvokeProcess.OutputDataReceived>
        <mtbwa:InvokeProcess.ErrorDataReceived>
          <ActivityAction x:TypeArguments="x:String">
            <ActivityAction.Argument>
              <DelegateInArgument x:TypeArguments="x:String" Name="stderr" />
            </ActivityAction.Argument>
            <mtbwa:WriteBuildError Message="[stderr]" />
          </ActivityAction>
        </mtbwa:InvokeProcess.ErrorDataReceived>
      </mtbwa:InvokeProcess>
A bit more will have to be done in order to fail the build if the restore fails. It looks like you have to hook into the ResultCode of the InvokeProcess and then throw if the exit code is not 0. Programming in XAML isn't fun, which is why you see me restoring FAKE. I hope to experiment and see what TFS + FAKE integration might get us.