Using NuGet the way you should
Consuming NuGet packages, that’s what everyone does. Open source projects create NuGet packages and post them on NuGet.org. Meanwhile, all of us are still working with shared projects and fighting relative paths, versioning and so on. In this talk, we’ll use Visual Studio, NuGet and TeamCity to work with NuGet the way you should. Project references must die! Add Package Reference and good continuous integration is everything you will ever need.
1. Using NuGet
the way you should
Maarten Balliauw
@maartenballiauw
2. Who am I?
• Maarten Balliauw
• Antwerp, Belgium
• Developer Advocate, JetBrains
• Founder, MyGet
• AZUG
• Focus on web
• Big passion: Azure
• http://blog.maartenballiauw.be
• @maartenballiauw
Shameless self promotion: Pro NuGet -
http://amzn.to/pronuget2
3. Agenda
• NuGet
• File | New Project…
• The state of NuGet
• Every project is a package
• Creating packages
• Distributing packages
• Consuming packages
5. A brief NuGet introduction...
• Package management system for .NET
• Visual Studio extension, command line, console
• Simplifies incorporating 3rd party libraries
• Developer focused
• Free, open source
• Use packages from the official feed
• Publish your own packages
• Create & use your own feed
8. That was trouble!
Dependency hell
•Dependencies on NuGet packages
•Dependencies on projects
•Dependencies on file system layout
• Breaking changes in dependencies
9. “Dependencies, also in real
life, are trouble. Have you
ever had to depend on a
plumber showing up?”
- Maarten Balliauw
10. Dependencies before NuGet
• Projects in solution
•Reference in-house projects:
• Either the assemblies (typically unversioned / all 1.0.0.0)
• Either the actual project / linked files (unversioned by design)
•Reference third party assemblies (e.g. JSON.NET)
11. Dependencies with NuGet
• Projects in solution
•Reference in-house projects:
• Either the assemblies (typically unversioned / all 1.0.0.0)
• Either the actual project / linked files (unversioned by design)
•Reference third party packages (e.g. JSON.NET)
• Semantic Versioning to announce breaking changes
(happy times as long as package authors respect that)
13. The state of NuGet
Where are we, 3 years in?
•We are consumers!
• Even quite some overconsumption I dare say…
•We sort of know about Semantic Versioning
• If the mayor version changes, we’re doomed
•Are we producing?
• Some are, e.g. OSS and some companies
• Did we solve our dependency issues?
14. .NET is late to the party!
•Others have been doing package management for
decades
• Perl (CPAN.org)
• Linux (RPM/YUM/APT-GET/...)
• PHP (PEAR, Composer)
• Node (npm)
• Ruby (Gems)
•We can learn a great deal from these!
16. What are the others doing?
What was in that package.json?
•Name and version of the project
•Dependencies (and version range) of the project
• Every project is a package!
• It can have dependencies
• It can be depended on
18. Supporting componentization
• Every project is a package
• Clearly identifyable
• Proper Semantic Versioning
• Every project becomes discoverable
• Nice description, release notes, ...
• Add it to a private feed so developers can find it
•Dependencies (can) stay out of source control
•Dependencies are versioned
19. But… NuGet only has packages.config!
•Nodejs: packages.json
•Composer (PHP): composer.json
•NuGet:
• packages.config: dependencies
• <projectname>.nuspec: package description
• NuGet.config: other settings
• It’s 2-3 files in our world, but it is all there.
• Let’s become producers!
21. All we need is one file
<projectname>.nuspec
• XML file which can be generated
• nuget.exe spec
• Install-Package NuSpec && Install-Nuspec
•Run nuget.exe pack to create package
23. Think about versioning!
Enforce Explicit Semantic Versioning
• www.semver.org
Major Breaking changes
Minor Backwards compatible changes
e.g. API additions
Patch Bugfixes not affecting the API
• SemVer states intentions
• It’s the only way to
avoid dependency
versioning hell.
But not bullet-proof.
<dependency id="ExamplePackage" version="1.3.2" />
1.0 = 1.0 ≤ x
(,1.0] = x ≤ 1.0
(,1.0) = x < 1.0
[1.0] = x == 1.0
(1.0) = invalid
(1.0,) = 1.0 < x
(1.0,2.0) = 1.0 < x < 2.0
[1.0,2.0] = 1.0 ≤ x ≤ 2.0
empty = latest version
25. Which medium?
We will need a “package source” or feed
• In source control (please don’t)
• Local / network folder (slow > ~50 packages)
• NuGet.Server (slow > ~50 packages)
• NuGet Gallery (clone of www.nuget.org)
• MyGet (www.myget.org, SaaS)
• ProGet (www.inedo.com/proget)
• TeamCity NuGet artifacts (www.jetbrains.com/teamcity)
• Sonatype (www.sonatype.com/nexus)
• Artifactory (www.jfrog.com)
26. How do they get there?
•Manual upload
• As part of our continuous integration process
• All benefits of CI (e.g. testing)
• Plus reporting on which packages we are using
• Plus publishing packages for consumption
28. What did we just see?
•Creating packages using .nuspec
•NuGet configuration inheritance
•Continuous Integration on TeamCity
• How to run package restore
• How to build a package
• How to see packages that are being used
•How to consume a package
29. NuGet configuration inheritance
•Make settings common to projects!
• NuGet walks up the directory tree to find NuGet.config files
• Or even push them to developer machines
• %AppData%NuGetNuGet.config
• %ProgramData%NuGetConfig*.config
• ...
•See http://bit.ly/nuget-config-inheritance
• Configure feeds, proxy, credentials, ...
30. More recommendations…
• Don’t just update blindly
• Not everyone respects SemVer…
• It would take us back to the original problem
• Don’t autoupdate during builds
• Continuous Integration: Same Input = Same Output
• Be explicit about versioning
31. Deploying from NuGet packages
•Using a simple, handcrafted script
• Using a tool like OctopusDeploy.com
• Which is even cooler combined with Chocolatey.org
•TeamCity supports various ways of deploying (e.g.
WebDeploy)
33. Considerations
•TeamCity internal NuGet feed
• Only build artifacts
• No way to add external packages that are being used
• May not be a problem for your setup
• But maybe it is: a feed is much like source control for dependencies
• Add dependencies that are being used, NuGet.org, component
vendors, ...
• If it is, create your own feed, e.g. MyGet.org
34. Create a package source / feed
For your team or the entire organization
• That’s a cool library! And that one too!
• Avoid overconsumption by limiting packages
• May not block developers but at least the build will fail
• Your own feed will only contain packages you
know
• Keep versions under control
• Keep licensing under control
• Easy way to audit external packages in use
36. But I’m using NuGet. It’s broken!!!
http://blog.nuget.org/20141010/nuget-is-broken.
html
• Tied to Visual Studio
•Merging sucks (XML merge, yuck!)
•Updating fails often
• Disk space pollution
• Project re-targeting
•Pessimistic package version picker / fixed versions
39. Conclusions
What have we learned?
• NuGet
• File | New Project…
• The state of NuGet
• Every project is a package
• Creating packages
• Distributing packages
• Consuming packages
40. “Project references must
die. Embrace NuGet by
consuming and creating
packages. It’s a logical
evolution.”
- Maarten Balliauw
Open IniTech.TpsReports solution
Explain demo application we will be building
Explain we will skip the actual File | New Project... Because of demo purposes, but we will cover the steps right after that
Go through HomeController and the related views and model classes
Let’s add some NuGet Goodness!
Bootstrap Datepicker
ELMAH for diagnostics
Run updates! We are get-latest addicts!
Next, explain that for date formatting, we need one of our own projects. Which is located somewhere on my disk in another github repository from the framework code team enterprise architects.
Open TpsReportCoversheet.cshtml and add reference
That is awesome! Build, run and demonstrate the application.
Switch hats: become the architect and open IniTech.Framework solution
A good architect refactors! Let’s switch namespaces. And that formatter,we need a FormatterFactory for that!
Close Visual Studio. We also want to move this project in the source repository, because it is not at the best location
Switch hats again and try compiling IniTech.TpsReports solution...
What has happened! RELEASE IS TODAY! HELP! And the architect guy is in a meeting or presenting or something. PANIC!
Open IniTech.Framework solution
Run a nuget spec and show the file in action (update it and so on)
Run nuget pack to package it
Open it in NuGet Package Explorer (explain the tool!) and see what is in there
Level up: add a dependency on Newtonsoft.Json and run nuget pack again
Open in NPE again and see the dependency magically appeared!
If you do not want this, add developmentDependency=“true”
Open the IniTech.TpsReports solution
Drop the project reference and add a package source, install the framework that way
Explain how it all works and where packages can come from, folder (and NuGet.Server) are a bad idea! (BAD BAD BAD!)
Now that we are here... Create a spec, run packaging on the .csproj
Explore the package: dependencies are there, contents are in there too
Explain TeamCity (CI, project, configuration, build steps)
Let’s make sure our IniTech.Framework is packaged
Create project from URL - https://github.com/maartenba-demo/initech-nuget.git
Autodetected build steps: none in this case?
Add build step: package restore
Solution file: src/framework/IniTech.Framework/IniTech.Framework.sln
Restore mode: restore
Explain other options and their evilness (autoupdate? noooo!)
Mention because of the private feed we are using (TeamCIty itself), we want to add authentication there as well
Add build step: build solution
Solution file: src/framework/IniTech.Framework/IniTech.Framework.sln
Add build step: pack
Project file: src/framework/IniTech.Framework/IniTech.Framework/IniTech.Framework.csproj
Version: 1.0.%build.number%
Output: “artifacts” + tick publish to artifacts to make the package visible on the TeamCity NuGet feed
Run a build, see package has been created. Run a NuGet.exe list
nuget list -Source http://teamcity.balliauw.net/httpAuth/app/nuget/v1/FeedService.svc
Sources: %teamcity.nuget.feed.auth.server% and https://nuget.org/api/v2
Switch to the existing build configuration for the IniTech.TpsReports solution
Explain same setup: package restore, build, pack
Edit the package restore step and mention for this configuration we are using the TeamCity server itself as a package source, as well as NuGet.org
Run a build, see the results tabs and get an inventory of all packages consumed
Open IniTech.Framework solution, make a change, commit, build
Open the IniTech.TpsReports solution, update packages, keep working
Explain that when the framework would have a breaking change, we have to update the version number so developers will see there are breaking changes and they will have work to do when they update for the update.
How do developers know about the feeds to use?
Open the NuGet.config file, mention inheritance, mention developers will automatically have that feed available
Package restore: close the solution, delete the packages folder, open and build
Explain no need to use the Enable package restore menu anymore (in fact, it will hurt you)
If package restore fails (which happens a lot when fiddling with settings), make sure the (Aggregate Source) is selected in the NuGet.config file so ALL feeds are checked, not just one
Similar to consuming packages in Visual Studio, only command line this time
Do a nuget list -Source http://teamcity.balliauw.net/httpAuth/app/nuget/v1/FeedService.svc
Explain we can get all packages, install them, ...
We know this is a web application, so let us create a deploy.bat
Open the existing one
Explain the steps in there
Explain we are installing without version number in paths so we can more easily script something
Feel free to add database deployment in a similar way, calling into SQL Server command line
Feel free to add DevOps stuff: why not create a new Windows Azure VM using th CLI tools they have and then FTP the NuGet contents up there?
Mention this is quite archaic but it works. You have to know the project you will be deploying and that is it.
Mention we could also run this script from TeamCity, in fact we have a demo on that
Show the configuration there
Show the snapshot dependency
Show promoting build
Mention OctopusDeploy.com again, show it on screen quickly, explain it is a good companion to TeamCity:
Build on one, convention-based deployments with the other
Explain setup: instead of using the TeamCity internal feed we want to use another one
The reason for that is: we don’t want to have just our build artifacts on there, but we want to make it the only feed of thruth (much like a VCS does for sources, this feed will do so for dependencies)
Quickly create a feed on MyGet, add dependencies from the IniTech.TpsReports solution by uploading packages.config. Make sure they are mirrored.
Also configure the framework build to push there and run it.
Delete package sources in the IniTech.TpsReports solution and add our one source of thruth
All developers can now only use these approved packages + in-house artifacts that are created
Option: create an “unstable” feed to test out new versions and migrate to teh “real” feed when they get approved (there is a push upstream feature for that on MyGet)