Native NuGet Support in TeamCity

A few months ago, Scott Hanselman gave a session at TechEd US were he showed some new features we were working on for TeamCity, in order to provide first class support for NuGet. He later blogged about it here.

Instead of delaying until the next release of TeamCity, this feature (like many), has been developed as a plug-in. Eugene, who has been working on it, announced the availability of a first build a few weeks ago. After some initial trials and changes, I decided to setup YouTrackSharp to automate the publishing of the NuGet package. It was surprisingly easy as you’ll see.

1. Installing the Plug-in

If your project is running on TeamCity at Codebetter.com, you can skip to Step 3, since it’s already installed and configured. If not, then grab the latest build from our public TeamCity server. Place the zip file into the plugins folder of your TeamCity installation and restart the server.

2. Configuring the NuGet version

Once the server is running, and agents updated (automated procedure), you then need to tell TeamCity what NuGet version you want to use. The plug-in knows about the nuget.org feed to it can grab the latest version of the command line tool directly. Click on Administration | Server Configuration. If the plug-in installed correctly, you should now have a new Tab called NuGet:

AdminPanelNuGet

Click on the “Install additional versions of the NuGet.exe Command Line”. TeamCity will read from the feed and display available versions to you in the dialog box. Select the version you want and click Install:

NuGetVersion

Pull, Pack, Publish

The plug-in offers three main operations:

  • Pulling NuGet packages required to build your project
  • Creating NuGet packages
  • Publishing Packages

In my case, I want to create the package and publish it. To give you a general idea of my build process, here’s the outline of the build steps:

BuildOverview

The NuGet related steps are 3 and 4. Step 1 simply builds the project by building the solution file. Step 2 runs the MSpec tests.

3. Building the package

This step is for building the actual package. We create a new Build Step in our project and select NuGet Packages Pack. This will give us the following configuration screen:

Step3

As you can see, the configuration is pretty straightforward. Notice that in the Specification file, we can also provide a csproj file as opposed to a NuGet spec file. The advantage to this is that we do not have to redefine information such as version number and copyright information in the spec file. If you’re not familiar with this feature, check out David Ebbo’s post.

I’ve also checked the option to Include Sources and Symbols. This is also explained in David Ebbo’s post and it’s for publishing the sources to Symbolsource. Additional command line parameters (if required) can be passed in the Additional Commandline arguments. If you want to make this a release build, you can also do this by defining Configuration=Release in the Properties field.

Finally I’ve specified the Build number of the package using the TeamCity variable %build.number% which auto increments on each build, and is also used by another feature of TeamCity new in 6.5 which is called the AssemblyPatcher, which I’ll show you as the last step.

4. Publishing the package

The next step is to publish the package. As before, we need to add a Build Step and select NuGet Packages Publish.

BuildStep4

This step is even easier to configure. By convention it uses nuget.org as the destination to publish the package. If you have your own NuGet server then fill in the address in the Packages Sources field. If you’re using nuget.org, leave it blank. You need to provide your API key which is stored in a password protected field and finally indicate which packages you want published. Here you can list each package individually or use wildcards. [Note: relative paths are allowed but at the time of writing this post, there was an issue and I was using the full path. This should be fixed soon].

If you want to publish to multiple sources, all you need to do is add another step. Note however that we did not have to specify an extra step to publish the sources to symbolsource.org. TeamCity will follow NuGet’s convention and do this for you automatically.

5. AssemblyInfo Patcher

Although this step is optional I recommend you use it. The AssemblyInfo Patcher is a new Build Feature added to TeamCity which temporarily patches all your projects AssemblyInfo.cs files to update the version number, and then reverts it back after the build is complete. This allows your build number, artifacts, packages and assemblies to all have the same version number. Adding this option is as simple as selecting it from the main project configuration screen:

AssemblyPatcher

That’s it. There’s nothing more to it. With a few simple build steps we have now fully automated packaging and publishing NuGet packages. As I mentioned initially, if you’ve got your project on CodeBetter, you already have this feature enabled. If you’re running your own server, just download the plugin and set it up. It’s very simple.

Try it out and please give us your feedback!

This entry was posted in News and Events and tagged , . Bookmark the permalink.

34 Responses to Native NuGet Support in TeamCity

  1. Emil Åström says:

    This would be of great use but unfortunately we can’t get it to work in our TeamCity installation. Our build agent gets is disconnected after we install the plugin and refuses to come back online.

    Any ideas on what might cause this?

    Thanks in advance,

    Emil

  2. hazzik says:

    It ublished my API in general public! Stupid tool!

  3. Hadi Hariri says:

    @Emil,

    Can you please contact teamcity-feedback@jetbrains.com?

    @Hazzik,

    Excuse me?

  4. Dave Baxter says:

    This is a great idea and perfect for our setup… but I’m hitting a roadblock. I’ve tried a number of configurations for the nuspec file and I still can’t seem to get past the following error:

    [pack] Version string portion was too short or too long.

    I’ve tried static values pointing to the nuspec file explicitly, and tried the tokens in the nuspec when pointing to the csproj. Same result in all instances.

    Any help is appreciated.

  5. Hadi Hariri says:

    @Dave,

    Can you please email me (hadi at jetbrains dot com) screenshots of your configuration so we can take a look?

    Thanks.

  6. Artem Fedorenko says:

    Is is possible to configure packaging step to package several projects thus creating several .nupkg files? That is to provide several files in “Specification File” field.

  7. Hadi Hariri says:

    @Artem,

    New version already supports that.

  8. Christopher Johannsen says:

    Was there any resolution to @Emil’s issue as we are experiencing the same issue.

  9. Eugene says:

    @Emil, @Christopher
    The issue with agent upgrade was recently fixed. Please check you use newer version of plugin.

    @Dave,
    NuGet does not allow version like “1″. Change build configuration version number to something like “1.0.{0}.2″ and it start to work. You find the pattern at “General” tab of build configuration administration. Another way to do it is to change version number in “NuGet Packages Pack” build runner

  10. Eric says:

    How can one publish to a local feed?
    I have a network share folder where I can push/publish packages.
    I tried to entering the Name of the feed but Visual Studio fails to find the source.

    Any advice or pointers please?

  11. Eric says:

    TeamCity is calling this on the command line:

    C:TeamCityBuildAgenttoolsNuGet.CommandLine.1.5.21005.9019.nupkgtoolsNuGet.exe push c:teamcitybuildagentworkbfafc0461f80358eoutputMyPackage.1.0.0.0.nupkg %teamcity_nuget_api_key_1234567890123% -CreateOnly -Source “My Local Packages”

    but says “The specified source ‘C:Packages’ is invalid. Please provide a valid source.

    How can I set a source that points to a local/network share?

  12. Hadi Hariri says:

    @Eric,

    I’ll try and see what the syntax is. Meanwhile you could merely just copy the file locally if you’re reading off of a drive.

  13. Eric says:

    Yes, thanks. Still can’t get this to work… but will just have to manually copy the files for now.

  14. Hadi Hariri says:

    @Eric,

    Wanted to check if we had a built-in support for this, which we don’t. NuGet AFAIK does not allow direct publishing to folder either. So you’ll just have to copy.

  15. Eric says:

    oh that’s a shame, will this feature get added in future releases?

  16. Maxim Shoshin says:

    I’m tring to enable NuGet plugin on the environment without internet access.
    Therefore I can’t install NuGet.exe command line via web interface. Could you explain me how can I do it manually?

  17. Eugene Petrenko says:

    Maxim, I created an issue for your problem at http://youtrack.jetbrains.net/issue/TW-19365. Please find a workaround there.

  18. Sky says:

    Almost!

    This is very very good.
    Working with our in house Lib.sln that contains various *.csproj’s, I got it to package one of the projects by pointing Nuget directly at a *.nuspec that I checked in alongside the *.csproj. The pros is that I have control, and it doesn’t double MsBuild …the con is that it’s very very manual.

    I then tried the method you demonstrated — pointing Nuget at the *.csproj instead. But ran into trouble. The issue in our case is that the when Nuget invokes MSBuild, MSBuild can’t resolve the path to the NuGet.Target.

    I believe The reason for this is some of the solution’s projects are nested deeper than one down from the *.sln (eg: [checkoutdir]XAct.CoreXAct.CoreXAct.Core.csproj), and NuGet doesn’t use the Checkout dir, but instead decides the *.sln will be in directory one up from the *.csproj it knows about. As there is no .nuget folder there, it fails.

    I tried the following:
    Adding Property:SolutionDir=%env….% to the CommandLine args — but I think those are used by Nuget, not MSBuild (so nothing changes).
    Adding Property:SolutionDir=%env….% to the Properties — but it doesn’t like the ‘:’

    I does work if I manually put a *.nuget folder in the [checkoutdir]XAct.Core — but that is not a maintainable strategy going forward.

    WOuld you have any other suggestion I could try?

    By the way — is there a way to invoke it against the Csproj, without it causing a second invoking of MSBuild (double Build) as it’s already been called by the initial build of the Solution?– that would solve two issues in one go, no?

    Thank you,
    Sky

  19. Sky says:

    Addendum…
    It always like that…as one describes a problem to someone else things go ‘ping’. I just updated Properties to contain:

    Configuration=Debug
    SolutionDir=%system.teamcity.build.checkoutDir%

    And I got a different error:

    [11:25:30]: [Step 2/2] pack: Create NuGet package from xact.corexact.corexact.core.csproj
    [11:25:30]: [pack] An item with the same key has already been added.
    [11:25:30]: [pack] Process exited with code 1
    [11:25:30]: [Step 2/2] Step CS.FF.XAct.Lib:XAct.Core NuGet Pakage (NuGet Packages Pack) failed
    [11:25:30]: Build finished

    No idea (yet) what that means (not http://bit.ly/ulrHeY)…but at least the error has changed, and I’m back on the hunt for a solution :-)

  20. Hadi Hariri says:

    @Sky,

    Its a bit hard to decipher the issue here on the blog post. Could you please send an email to teamcity-feedback@jetbrains.com and we can try and help you there?

    Thanks

  21. Matt says:

    Is it safe to assume that this would only work with TeamCity running on a Windows server? We’ve currently put the TeamCity server on a linux machine, with our agents running windows.

  22. Hadi Hariri says:

    @Matt

    You still need NuGet to be able to create packages.

  23. Matt says:

    @Hadi — To be clear, creating packages happens in TeamCity Server, rather than in TeamCity Agent, right?

  24. Hadi Hariri says:

    @Matt,

    Sorry Matt. I didn’t read the part about the agents being .NET. You should be OK then in that sense.

  25. tcmaster says:

    What about the performance, is there any kind of caching? I mean if I refer to several packages and each build will pull it out from nuget.org it will slow down my build process several times.

  26. Eugene says:

    tcmaster,
    TeamCity does not provide NuGet.org caching. If you like, you may re-publish all referred packages to the local feed. Please feed free to post an issue to the issue tracker for that.

  27. Frank Quednau says:

    Just wondering…did anybody get this to work?

    I have the same problem as sky has.

    If you use package restore, which is now in-built into nuget, the msbuild step runs fine.
    For whatever reason in the “pack” step, the SolutionDir in the csproj file now “loses” one directory and tries to find the .nugetNuget.targets file at a wrong position.

    Trying to specify the SolutionDir to Nuget leads to an exception in nuget. For this I have filed an issue on Nuget (http://nuget.codeplex.com/workitem/1907)

    FOr those who got this working: How?

  28. Hadi Hariri says:

    @Frank

    Can you send us some screenshots of your config to teamcity-feedback@jetbrains.com? We can see what the problem is.

    Thanks.

  29. Prasanna says:

    Hi,
    I have installed the nuget plugin and restarted the teamcity server. However, I do not see the NuGet version listed in the “server Configuration” tab. I see that the nuget files are unpacked after the restart.

    “There are 0 NuGets installed”
    Download Nuget

    What am i missing in the setup procedure?

    Regards
    Prasanna

    PS: I cannot download from nuget.org directly due to firewall restrictions

  30. Gleb says:

    Hello, I tried to configure TC to pull some NuGet packages from NuGet.org before building my project and I keep getting an error that it can’t find repositories.config in my solution folder. I’m using .NET 4 and VS2010.
    I configured 4 build steps – download NuGet packages, Build, Run unit-tests and then check for code duplications. However, when I trigger the build, I can’t even get past first build step. I configured TC to download missing NuGet packages. When I run the build, TC says “Failed to find repositories.config at {here_is_my_solution_path}”.
    I understand that the problem is I use this VS feature called Enable NuGet package restore – so, there is no such file as repositories.config in my solution folder as it’s hidden in .sln file as far as I know. I understand that’s why TC can’t find repositories.config and build is failing. So, how am I supposed to configure TC then?

  31. Eugene Petrenko says:

    Gleb,
    Please vote for http://youtrack.jetbrains.com/issue/TW-20525

    The issue is that TeamCity’s NuGet packages installer implementation uses repositories.config to find all packages.config files to download packages from.
    As workaround you may check-in only packages/packages.config file into VCS.

  32. Gleb says:

    Great to know you’re aware of that.

  33. Jos Krause says:

    Is there anyway to specify that the AssemblyInfo patcher only touches a specific path? We have a “1-assemblyinfo-to-rule-them-all” setup where only the AssemblyInfo.cs in our ./BuildScripts/ folder needs to be updated to ensure all other projects share the same file and thus version.

    Right now this patcher is taking over a minute to update all the AssemblyInfo.cs files and it’s slowing down the build so much that I cannot really use this feature right now.

    Thanks in advance!

  34. Eugene Petrenko says:

    Please vote for http://youtrack.jetbrains.com/issue/TW-20158

    You may try to specify configuration parameter “”teamcity.assemblyInfoPatcher.scanDepth” to limit assemblyInfo.cs files search depth. Default value is 9

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>