Nuspec buildAction not applying to contentFiles - nuget

I've been recently trying to create a .nuspec file that attaches a .dll file as an Embedded Resource. To do so, I've used the contentFiles tag on metadata, setting the buildAction="EmbeddedResource", as described in the section Example contentFiles section on the official documentation.
Below you can see my .nuspec file content:
<package>
<metadata>
<id>MyPackage</id>
<version>1.0.0.0</version>
<title>MyPackage</title>
<authors>Matias G Henschel</authors>
<owners>Matias G Henschel</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My package description</description>
<copyright>2017</copyright>
<contentFiles>
<files include="myDllFile.dll" buildAction="EmbeddedResource" />
</contentFiles>
</metadata>
<files>
<file src="content\myDllFile.dll" target="contentFiles" />
</files>
</package>
This package correctly copies the file inside the target project, but it doesn't apply the Build Action to it, which is crucial for me.
I've also tried using a .targets file, with no success.
If you want to see more, I've also created an Issue on the GitHub page.
PS: IMHO, both documentation on contentFiles and .targets files require some rework, they aren't clear enough and .targets' lacks examples.

You also need a file entry to actually copy the file to the correct contentFiles folder:
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
…
<contentFiles>
<files include="any/any/MyEmbeddedFile.txt" buildAction="EmbeddedResource" />
</contentFiles>
</metadata>
<files>
<file src="path/to/MyEmbeddedFile.txt" target="contentFiles/any/any/MyEmbeddedFile.txt" />
</files>
</package>
Note that this will only work in NuGet 3.3+ with project.json based projects and NuGet 4+ for PackageReference based projects. For projects using this package via packages.config, you will still need to add the file to the content folder and add a custom target to make it the right item type.

Related

Why is nuget not adding my file?

I have this nuspec file:
<?xml version="1.0"?>
<package >
<metadata>
<id>My.Package</id>
<version>1.0.1.7</version>
<title>My Package</title>
<authors>My name</authors>
<owners>Mu author</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My description</description>
<releaseNotes>Release note</releaseNotes>
<copyright>Copyright 2017</copyright>
<tags>tag1 tag2</tags>
<contentFiles>
<files include="myFile.config" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="myFile.config" target=""/>
</files>
</package>
When I pack this nuspec file, my nupkg file is created and in the NuGet Package Explorer I see that myFile.config is included in my package. All well so far.
But, then, when I install this package, the dll is added to references, but myFile.config is not added to the solution.
Things I've tried without success:
- View the folder on Disk to see if myFile.config is created (not there)
- <file src="myFile.config" target="."/>
- <file src="myFile.config" target=".\"/>
I also want the file to set Copy to Output Directory: Copy always.
What am I missing here?
PS: I am working on a private nuget server.
The target needs to be content since files of the nugpkg's content subdirectory are copied to the consuming project.
Note that this only works for projects using the packages.config style of referencing NuGet packages. For PackageReference (available in VS 2017, default for .NET Core / ASP.NET Core / .NET Standard projects), there is a new contentFiles feature that includes files logically in the build process.
See NuGet's documentation on including content files for more information.

Options for placing and updating PowerShell files in Project folder using NuGet

I am building a NuGet package that only contains a set of PowerShell scripts. The desired behavior is for the scripts to be placed in the project and/or solution folder, removed when the package is uninstalled, and updated when the package is updated. These scripts just need to live in the folder, and be copied to output folder (they are deploy scripts).
I've done this before using content target in a nuspec, but this does not work in netstandard/.NET Core applications (i.e., anything that uses PackageReference). The NuGet documentation mentioned the contentFiles element under the metadata element, but that also does not work with PackageReference. The only thing that I have been able to get working at all is copying the PowerShell scripts in tools/init.ps1. I have something partially working, but it doesn't handle the uninstall or upgrade path. And DTE is never fun.
Is there a way to use content files in netstandard?
If not, does there exist a sample or example of how to properly manage the NuGet lifecycle (copy file, update file, delete file)?
EDIT: This is for a console application, but it also should work in an asp.net application.
EDIT2: This is the nuspec that I have tried to do things via the contentFiles element. When I install the package, I don't see anything in project or solution.
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Test</id>
<version>1.0.0</version>
<contentFiles>
<files include="Build.ps1" buildAction="Content" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="Build.ps1" target="content" />
</files>
</package>
Thanks,
Erick
As you have noticed, NuGet packages referenced via PackageReference no longer modify the project when installing. This is also the case for .NET Framework projects using this new feature (it was made public for non-core projects in VS 2017 15.2).
The content/someScript.ps1 file is still necessary for compatibility with "classic" packages.config based project, but a new feature for PackageReference projects is contentFiles.
When packing manually using a nuspec file, copying a file on build can be done by adding a contentFiles section:
<package>
<metadata>
...
<contentFiles>
<files include="**/*.ps1" buildAction="Content" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="Build.ps1" target="content" />
<file src="Build.ps1" target="contentFiles/any/any" />
</files>
</package>
See the documentation on contentFiles for more details my example on GitHub.

Packaging a static website in Nuget

I have a static website I want to deploy using Ocotpus deploy. Octopus uses nuget packages for everything so I want to turn it into a nuget package so Octopus can deploy right from my nuget feeds.
Right now I'm using this as my nuspec file:
<?xml version="1.0"?>
<package >
<metadata>
<id>mysite</id>
<version>1.0.0</version>
<authors>Alpaca</authors>
<owners>Alpaca</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My Package description</description>
<copyright>2017</copyright>
<contentFiles>
<files include="build/**" />
</contentFiles>
</metadata>
</package>
Should I be using ContentFiles to deploy the site or is there a better way of building a package for a static website?
Better is very subjective.
If your site is in a msbuild project (static or otherwise) then plain octopack should work. Mark anything that octopack doesnt include by convention as 'Content' and it will be included.
Documentations is here: https://octopus.com/docs/packaging-applications/nuget-packages/using-octopack#UsingOctoPack-Includingwebapplicationcontentfiles
That same documentation alludes to using the 'files' section of nupsec and points to the nuspec documentation here: http://docs.nuget.org/docs/reference/nuspec-reference
We are using the nuspec files section to pack up all our common styles, ect:
<files>
<file src="**\*.*" target="" exclude="obj\*;bin\*;**\*.csproj;**\*.config;**\*.nuspec;**\*.less;**\*.json;grunfile.js"/>
</files>

NuGet include tools folder when packing from csproj

I'm trying to create a nuget package from a csproj file. This package will include an install.ps1 script in the tools folder and some files in the content folder.
However, it seems like when packing from a csproj file, nuget will pull the package information (description, tags, etc.) from the corresponding nuspec file, but not anything else. It ignores the tools folder that is in the same directory as the nuspec file as well as the content folder.
When packing this way nuget also seems to ignore files included in the contentFiles section of the nuspec file.
Is this expected behavior? If it is, is there a way for me to pack from a csproj and get the content and tools folders to be included in the package?
I realize I could just use only a nuspec file and this would work, but I have multiple packages I'm trying to build this way and managing the dependencies manually becomes a less than trivial task.
Running NuGet 3.4.4.1321
My nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$id$</title>
<authors>authors</authors>
<owners>$owners$</owners>
<projectUrl>http://dummy.url</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>the description</description>
<copyright>$copyright$</copyright>
<releaseNotes>$releaseNotes$</releaseNotes>
<contentFiles>
<files include="content\App.config.install.xdt"/>
<files include="content\App.config.uninstall.xdt"/>
<files include="temp\App.config"/>
</contentFiles>
<tags>wpf testing</tags>
</metadata>
</package>
Turns out the documentation for this confused me a bit. Content Files are not a replacement for Files. In NuGet 3, both can be used simultaneously.
Using the Files tag outside of the metadata tag in my nuspec file allowed me to specify items that go into the tools and content folder.
Updated nuspec:
<?xml version="1.0"?>
<package>
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$id$</title>
<authors>authors</authors>
<owners>$owners$</owners>
<projectUrl>http://dummy.url</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>the description</description>
<copyright>$copyright$</copyright>
<releaseNotes>$releaseNotes$</releaseNotes>
<tags>wpf testing</tags>
</metadata>
<files>
<file src="App.config.install.xdt" target="content"/>
<file src="App.config.uninstall.xdt" target="content"/>
<file src="tools\install.ps1" target="tools"/>
</files>
</package>
Hopefully this helps in case anyone else gets tripped up by the docs here.
A bit more discussion can be found in this NuGet Issue.
You could do nuget pack -Tool
Tool - Specifies that the output files of the project should be placed in the tool folder.
https://learn.microsoft.com/en-us/nuget/tools/cli-ref-pack

nuspec contentFiles Example

Yesterday NuGet 3.3 was released (release notes) and there is a new contentFiles element supported (docs). However, I can't seem to get this working.
I'm using the NuGet.exe as the build process. It is updated to v3.3. I have also updated my Visual Studio to 2015 Update 1 and rebooted.
Here is my nuspec file (Hello.world.nuspec):
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata minClientVersion="3.3">
<id>Hello.world</id>
<version>1.0.0</version>
<title>Greeting library</title>
<authors>Timothy Klenke</authors>
<description>Greetings for the world</description>
</metadata>
<contentFiles>
<files include="*" />
</contentFiles>
</package>
I run from the command line using the following:
nuget.exe update -Self
nuget.exe pack Hello.world.nuspec
And I get the following:
MSBuild auto-detection: using msbuild version '14.0' from 'C:\Program Files (x86)\MSBuild\14.0\bin'. Attempting to build package from 'Hello.world.nuspec'. The element 'package' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd' has invalid child element 'contentFiles' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd'. List of possible elements expected: 'files' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd'.
I think I am running all the latest versions that should support the new contentFiles XML element, but the tools don't seem to know about it. What am I missing? I know the files include attribute is garbage, but does someone have a full example nuspec file using the new contentFiles element?
Element <contentFiles> has to be inside <metadata> according to NuSpec reference. So it should look like this:
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata minClientVersion="3.3">
<id>Hello.world</id>
<version>1.0.0</version>
<title>Greeting library</title>
<authors>Timothy Klenke</authors>
<description>Greetings for the world</description>
<contentFiles>
<files include="*" />
</contentFiles>
</metadata>
</package>
#Timothy,
You were right. It is a combination having a metadata/contentFiles element as well as a definition in the files element. I have a C# test utility library that needs to include PowerShell files in a projects output/bin folder when it is referenced using a PackageReference. I will include the XML below for you. I think you will be able to derive what you need from it.
Special Note:
Be sure to get your language and framework values right in the path (i.e. yours will something like cs/net45/YourFile.cs). I'm using any/any/MyFile.psm1 because I want the file to be treated as language and platform agnostic. If I don't, I get code analysis errors on build.
Additionally, placing the files in a 'contentFiles' directory is important.
(language and framework options defined in the .nuspec reference documentation)
https://learn.microsoft.com/en-us/nuget/reference/nuspec#including-content-files
<package>
<metadata>
<id>SomeLibrary</id>
<version>$version$</version>
<title>SomeLibrary</title>
<authors>Somebody</authors>
<owners>Somebody</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Some library that does things I enjoy.</description>
<releaseNotes />
<copyright>Copyright 2017</copyright>
<tags>PowerShell Testing</tags>
<contentFiles>
<files include="any/any/SomePS.psd1" buildAction="none" copyToOutput="true" />
<files include="any/any/SomePS.psm1" buildAction="none" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="*.dll" target="lib\net461" />
<file src="*.pdb" target="lib\net461" />
<file src="SomePS.psd1" target="contentFiles\any\any" />
<file src="SomePS.psm1" target="contentFiles\any\any" />
</files>
</package>
The "/" matters in the node. It will not work if used:
<files include="any/any/x.dll" buildAction="None" copyToOutput="true" flatten="true" />
It must be:
<files include="any\any\x.dll" buildAction="None" copyToOutput="true" flatten="true" />
But it doesn't work for .NET framework??!