How to "inject" NuGet package in Jenkins CI build job - visual-studio

So here is the case: We have a web application which can be deployed for different customers. The web application can be extended by different modules per customer. The modules are created as NuGet packages and contain the DLLs together with static files like e.g. HTML, CSS, JS, ASMX...
As not all customers use the same modules and the base web application shall be as sleek as possible, the web application project itself doesn't know anything about the modules. Instead a Jenkins build job is available for each customer. In this build job the packages.config file will be modified to add the NuGet package entry for the wanted module. Then we do a nuget.exe restore and a nuget.exe update (to ensure it's on the latest version) for the module NuGet package. After this we use msbuild and Octopack to build and deploy the web application.
All of this works great for the DLLs included in the modules NuGet package and for the web.config transformations (done via web.config.install.xdt), but unfortunately it doesn't work for the static files included in the modules NuGet package :(
I assume that this is the case due to the missing references in the web applications .csproj file!? So the static files are actually copied to the correct locations, but are not added to the final Octopack Nuget package as they are not recognized as project content.
As far as I have researched till now this is nothing we can solve using the NuGet CLI itself, but are there any other options maybe? The Package Manager Console is only available within the powershell context of Visual Studio, right? (Update-Package -Reinstall would be perfect I guess)
Any other ideas?

We found the following solution (Octopack to win!). Instead of relying solely on NuGet, we use an option provided by Octopack which is OctoPackEnforceAddingFiles=true. This tells Octopack to not only add the project files to the resulting NuGet package (as it would normally do), but on top of this add files/folders listed in the <files> section defined in a .nuspec file you added to the project. See: http://docs.octopusdeploy.com/display/OD/Using+OctoPack#UsingOctoPack-IncludingadditionalfilesusingaNuSpecfile(.nuspec)
So our base project only has the nuspec file with an empty <files> section. The module then includes XDT files to tranform the nuspec file on (un)install to configure the additional files/folders which shall be added by Octopack. This way they don't have to be part of the csproj file.
I would love to see this option to handle the <files> section as an inclusive list of additional files (instead of either csproj or files section) be added to the nuget cli as well.

Related

How to exclude some directories from imported nuget package in a Xamarin (VS) project

I'm working on a mobile application in xamarin, which uses certain third party nuget package, and I would like to prevent some of the directories from that nuget package being included in final release, but I can't find any information on how to exclude specific files/folders from an imported, third party nuget package.
(specifically I would like some of the localisation folders from the package not being copied to the output directory)
I'm using package reference format.
The solution is to add a post-build step with a simple bash command removing all of the unwanted directories.

After Installing Microsoft.PowerShell.SDK a "runtimes" folder is added to my project

I added the Microsoft.PowerShell.SDK NuGet package to my project and these folders appeared in it.
Why does it happen?
NuGet 4.0+ with PackageReference supports content files. Content files are used to include artifacts like text files, XML files, images or even C# or VB code in a package that are are included with a predefined build action into the consuming project, optionally with a specific copy action.
The Microsoft.PowerShell.SDK package defines the content folders ref and runtimes that contain psd1, ps1xml files that are included with build action None in your project. They are copied to the output directory if newer. Visual Studio shows them with that little blue link arrow so that you know that they are referenced and not created in your own project.
Below you see the internal structure of the package. The path of the files inside of the package is given by /contentFiles/{codeLanguage}/{TargetFrameworkMoniker}, where any is like a wildcard.
Note that if you install the Microsoft.PowerShell.SDK package in an older project type that uses packages.config you will not see them, because content files are not supported there.

Difference between adding a Reference and adding a Nuget package to a project in Visual Studio

I have a VS (2015) project. I see there's a "References" section in the Solution Explorer view of my project that includes things like System.Core. I'm assuming these are .dlls that have been added to the project?
I can also right-click on the project file (again in the Solution Explorer) and select the option to "Manage NuGet Packages". I know the NuGet allows me to add external code to my project (e.g. external .dlls and associated files).
What's the difference between adding a reference to my project and adding a .nupkg to my project? Is it just that .nupkg can contain a whole bunch of other things aside from a .dll (e.g. documentation)? Why would I use one or the other?
What's the difference between adding a reference to my project and
adding a .nupkg to my project?
NuGet essentially does not differ from manually adding references, and ultimately adds references to the project. It is a tool that automatically adds assemblies to us and manages them, effectively improving the efficiency of our development projects.
For more details, you can check the document about nuget:
Put simply, a NuGet package is a single ZIP file with the .nupkg extension that contains compiled code (DLLs), other files related to that code, and a descriptive manifest that includes information like the package's version number. Developers with code to share create packages and publish them to a public or private host. Package consumers obtain those packages from suitable hosts, add them to their projects, and then call a package's functionality in their project code. NuGet itself then handles all of the intermediate details.
Because NuGet supports private hosts alongside the public nuget.org host, you can use NuGet packages to share code that's exclusive to an organization or a work group. You can also use NuGet packages as a convenient way to factor your own code for use in nothing but your own projects. In short, a NuGet package is a shareable unit of code, but does not require nor imply any particular means of sharing.
.
Is it just that .nupkg can contain a whole bunch of other things aside
from a .dll (e.g. documentation)?
Yes, NuGet package could include specify files in the package.
Why would I use one or the other?
Nuget provides several additional benefits:
it automatically configures your projects by adding references to the
necessary assemblies, creating and adding project files (e.g.
configuration), etc.
it provides package updates
it does all of this very conveniently
I'm sure that once you use it, you'll realize that it has many benefits.
Check Why use NuGet for more details.
Hope this helps.

Where does Visual Studio is referring the actual NuGet referenced DLL?

I've added Autofac library using NuGet and I see it in my references as shown below.
But when I check the properties [F4] of Autofac by clicking on it, it shows empty property box in Visual Studio.
Also, I don't see Autofac folder under packages folder.
I see only Package reference in .csproj file. Then how does it locates the DLL? Where is the actual DLL? I see it's automatically coming inside BIN. How does it come?
Main Issue: Locally I'm able to build the solution but same solution fails on TFS build agents. It's unable to find the NuGet reference. So where can I find DLL references? or how to push it to TFS?
As #magicandre1981 already explained, with PackageReference style package referencing (as apposed to package.config-style, also see this for more background on the differences, in case you didn't know), the packages are not located in a per-solution packages-folder, but in a central one (by default %USERPROFILE%\.nuget\packages). Albeit you can easily change the location using the NUGET_PACKAGES environment variable (which also works as a TFS Build variable, because they are provided as environment variables to build steps).
Furthermore, inside Visual Studio you see no path, because the actual path to the DLL is determined at build time. You can see part of that path in your <project-dir>\obj\project.assets.json file (which is generated during the restore target/operation), but the full path you will only see in the MSBuild logs (for example when actually calling the csc.exe executable/C# compiler or during ResolveAssembyReferences-task).
Note that for .NET Core, i.e. "SDK style" projects, the path is actually shown in properties (as are the actual DLLs in a node underneath the "package" node.
One can only assume that the integration of PackageReference in "old" projects is not fully done yet (if ever).
For comparison a PackageReference in an "old" / non-SDK-style project:
You use the new Package Reference where the NuGet files get get stored into a cache:
Solution-local packages folders are no longer used – Packages are now
resolved against the user’s cache at %userdata%\.nuget, rather than
a solution specific packages folder. This makes PackageReference
perform faster and consume less disk space by using a shared folder of
packages on your workstation.
Assume you are using TFS 2015, the NuGet Restore task name should be NuGet Installer which under Package when you add tasks.
So, if you have installed Nuget in the build machine, then you can use the task directly.
You can also custom nuget.exe for TFS 2015 build -- Just specify the Path to NuGet.exe
You can refer to Mummy's blog- Custom nuget.exe for TFS 2015 build for details.
Add a NuGet Restore task to your build so that the packages are restored.

How do I reference instead of copy js files from a Nuget package at build time in TeamCity?

I've got a packages.config file checked into source control. This specifies the exact version of the Nuget dependency I want. We have our own NuGet repository. We are creating these NuGet packages ourselves.
<packages>
<package id="Dome" version="1.0.0.19" targetFramework="net45" />
<package id="Dome.Dojo" version="1.0.0.19" targetFramework="net45" />
</packages>
These packages have some JavaScript files which when you add the Nuget package as a reference in Visual Studio are copied to the Scripts folder in the project.
I don't want to check these JS files in to source control, I just want to check in the packages.config file.
When my project builds in Team City (or when I build in Visual Studio after a fresh checkout) it doesn't copy the JS files from the NuGet package. There's a question here explaining a similar problem:
NuGet package files not being copied to project content during build
But, the solution in the answer to that question doesn't work for me; that solution uses ReInstall, which is problematic because it can automatically upgrade the version in the packages.config file (say if a dependency is specified as a >=).
The whole point of this is that I want to be able to checkout a revision from my source control, and build that version with the right dependencies AND I want to use the nice packaging features of NuGet. So, I don't want any "automatically update to the latest version during the build."
There's an issue against NuGet (http://nuget.codeplex.com/workitem/2094) about NuGet files not restoring content files. And it's Marked as Closed By Design.
Thinking about how this works a little more, it appears to me (but I'm not 100% sure) that for assemblies NuGet has a different behaviour - it doesn't copy them into the project, instead it references them from the location in the packages folder. It strikes me that js files in the NuGet package should be referenced analogous to how dlls are referenced.
Is there a way to construct a NuGet package so that it references the JS as links in the project (in a similar way to how you can add an existing File as a Link in VS)? And would this solve my problem?
If not then I'll take the advice given by Jeff Handley when closing ticked Nuget Issue 2094 mentioned above:
The option you'd have is to create a new console executable that
references NuGet.Core, and you could build a supplemental package
restore for your own use that copies package contents into the
project.
Writing my own command line tool to copy the contents does seem like I'm pushing water uphill here - am I doing something fundamentally wrong?
The underlying problem here is Visual Studio's relatively poor support of JavaScript projects and JavaScript's lack of built-in module loader.
For C#, when you install a package it adds a reference in your .csproj file to the assembly on disk. When you build, MSBuild knows to copy the thing referenced to the bin directory. Since you aren't checking in your bin directory, this all works great.
Unfortunately for JavaScript, the build system isn't nearly as matured and there aren't well defined guidelines for NuGet to follow. Ideally (IMO), Visual Studio would not run web sites directly from your source directory. Instead, when you built it would copy the JavaScript files, CSS and HTML files to a bin directory from which they would be executed. When debugging, it would map those back to the original JavaScript or TypeScript files (so if you make a change it isn't to a transient file). If that were to happen then there is now a well-defined build step and presumably a well-defined tag for JavaScript files (rather than just "content"). This means that NuGet would be able to leverage that well-defined MSBuild tag and package authors could leverage the NuGet feature to do the right thing.
Unfortunately, none of the above is true. JavaScript files are run in-place, If you did copy them to bin on build Visual Studio would do the wrong thing and editing from a debugger would edit the transient files (not the originals). NuGet therefore has no well-defined place to put files so it leaves the decision up to the package author. Package authors know that the average user is just going to be running directly from source (no build-step) so they dump files into the source folder where they must be checked in to version control.
The entire system is very archaic if you are coming from a modern ecosystem like C# where someone took time to think these things through a bit.
What you could do is create an MSBuild task that, before build, would go through all of your packages, look for content, and copy that content to the desired location. This wouldn't be terribly difficult, though would take a bit of work.
Also, package authors could include a build-task that does this in their package so that before-build all of their content was copied local. Unfortunately, if only some package authors do this then you end up with weird fragmentation where some packages need to be committed to version control and others do not.
When a package is installed into a project, NuGet in fact performs these operations,
Download the package file from source;
Install the package into the so called packages folder, which is $(SolutionDir)\packages by default;
Install the package into the project, which consists of adding references to DLLs, copying content files into the project directory etc.
When a package is restored, only the first two steps are executed. Projects will not be touched by nuget package restore. Which is why the js files in your project will not be "restored".
The only solution for now is to check in the js files in your project.
If you are the owner of the package then you could use the nuget package i've created to be able to have a folder called "Linked" in the package and have a simple Install.ps1 and Uninstall.ps1 (one liners) to add every file in the nuget package's linked folder as existing to the project.
https://github.com/baseclass/Contrib.Nuget#baseclasscontribnugetlinked
I didn't try out how publication treats linked files, the problem is debugging the Project, as the JavaScript files will be missing in the directories.
If you are using git as source control you could try my nuget package which ignores all the nuget content files and automatically restores them before building.
Step by step example in my blog: http://www.baseclass.ch/blog/Lists/Beitraege/Post.aspx?ID=9&mobile=0

Resources