Support the repository attribute in package metadata in Octopus Deploy - octopus-deploy

OctoPack / Octo.exe currently does not support the latest nuget XSD spec, and fails to run when newer elements are used in the nuspec:
Octopus-deploy Version : Octopus 3.14.1
Repro steps:
Create a new nuspec file with all the defaults and inside it add a repository element inside the metadata element. Example:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<repository type="git" url="https://github.com/user/repo" />
</metadata>
</package>
Run OctoPack or Octo.exe with the pack command, and the following error will be shown:
error OCTONUGET: The element 'metadata' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd'; has invalid child element 'repository' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd'. List of possible elements expected: 'iconUrl, references, contentFiles, title, summary, description, dependencies, language, releaseNotes, frameworkAssemblies, developmentDependency, packageTypes, licenseUrl, serviceable, tags, copyright' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd'. This validation error occurred in a 'repository' element.

Related

Create nuget containing shared project properties - automatic references

We would like to create a nuget that contains an msbuild properties (.props) file. We do this by creating a nuspec which as the following MIL (most important line) :
<files>
<file src="SharedProperties.props" target="build\SharedProperties.props" />
</files>
How can we change our .nuspec definition so that a project (.csproj) that references this nuget will automatically include the property file ("like" line 3 in this snippet):
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\Shared\SharedProperties.props" />
(Is this even possible ?)
That is a feature of the nuget package design. And nuget has the automatic import targets mechanism. See this document.
The tip is that you should name the targets or props file to <package_id>.props or targets and then pack the file into build folder. That is all.
For an example, I created a lib project and then use this nuspec file to pack:
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>test_A</id>
<version>1.0.0</version>
<title>me</title>
<authors>me</authors>
......
</metadata>
<files>
<file src="test_A.props" target="build" />
</files>
</package>
If my package is called test_A.1.0.0.nupkg, the file should be named as test_A.props file.
Then, when you install the nuget package into a new project, you can check the <new project>.csproj file, the props file is added automatically during the nuget installation.
If you use PackageReference nuget management format to install the nuget package, the file is added under obj\xxx.csproj.nuget.g.props or obj\xxx.csproj.nuget.g.targets file:
For new-sdk project, that also work. If you create a new-sdk class library project, you could use this into csproj file to pack it:
<None Include="<packages_id>.props" Pack="true" PackagePath="build">
When you finish it, install the new package into new-sdk main project, you will find that the props file has imported automatically under obj\xxx.csproj.nuget.g.props file.
According to the documentation the ".props" file should be automatically added to the beginning of a .csproj as an import (a .targets file should go to the end). However, for the new sdk-style projects this doesn't seem to work?

Creating multitarget nuget package with .nuspec

I have specified multitargeting in my .csproj
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
When I am using below script, then my package has dependencies and it is expected result:
dotnet pack --output nupkgs $ProjectPath -c:Release
The problem is when I also want to use .nuspec file with some information about package:
dotnet pack --output nupkgs $ProjectPath -c:Release -p:NuspecFile=$NuspecFile
With .nuspec file the package has no dependencies and I can install it only in netstandard2.0...
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>xyz</id>
<version>1.2011.4</version>
<title>xyz</title>
<authors>xyz</authors>
<projectUrl>xyz</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>xyz</description>
<copyright>xyz</copyright>
</metadata>
</package>
Should I add something to this .nuspec to have a package with target dependencies? I have read about tag, but to be honest I cannot find example how to configure it.
Given that you are using an SDK based projects, I'd strongly discourage using a nuspec unless your scenario cannot be satisfied because of it's complexity.
The automatic package generation with project file through dotnet.exe pack does much of the compatibility work for you.
If you really need to go with a nuspec, you should add dependency groups like defined here:
https://learn.microsoft.com/en-us/nuget/reference/nuspec#dependency-groups.
Make sure you add the relevant framework.
Example
<group targetFramework=".NETFramework4.7.2">
<dependency id="PackageA" version="1.2.3" />
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="PackageB" version="4.5.6" />
</group>
Note that you need to add a dependency group for the specific frameworks you support.

Prevent content files to be added on Nuget restore

We have some executables which we need to create our setups. So we have packed
the external dependencies which are some .exe files into a nuget package. But on NuGet restore they are added to project root.
How can we achieve this ?
Have searched around but haven't found any solution so far.
Since we use nuspec file, this is what i have it as:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>VCRedistributable</id>
<version>$version$</version>
<title>VCRedistributable</title>
<authors>--</authors>
<owners>--</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>InstallVCRedistributable assemblies</description>
<contentFiles>
<files include="**" exclude="**" buildAction="None" copyToOutput="false"
/>
</contentFiles>
</metadata>
<files>
<file src="VC\x86\*.*" target="content\x86" />
<file src="VC\x64\*.*" target="content\x64" />
</files>
Any ideas ?
Prevent content files to be added on Nuget restore
You should target to the tools folder instead of content folder.
So, your .nupsec file should be:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>VCRedistributable</id>
<version>$version$</version>
<title>VCRedistributable</title>
<authors>--</authors>
<owners>--</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>InstallVCRedistributable assemblies</description>
</metadata>
<files>
<file src="VC\x86\*.*" target="tools\x86" />
<file src="VC\x64\*.*" target="tools\x64" />
</files>
</package>
That because the content directory is a convention-based working directory, which contents are copied to the project root:
Convention-based working directory:
Besides, if you nuget package just include external some .exe files, you do not have to add the contentFiles label, this label is used for the content file for packagereference.
<contentFiles>
<files include="**" exclude="**" buildAction="None" copyToOutput="false"
/>
</contentFiles>
If you are interested in, you can check this document for some more details.
Update:
Is it good convention to create our own folder structure other than
NuGet defined since based on the tools folder description from above
it seems they will be accessible via Package Manager Console.
Of course, you can use your own folder structure other than NuGet defined. But you need to notice that there will be a limit to do this. You can NOT just include your own folder structure, you need also need add a NuGet defined folder structure in your .nuspec, otherwise, nuget will install failed with the error like:
Could not install package 'MyCustomPackage 1.0.0'. You are trying to
install this package into a project that targets
'.NETFramework,Version=v4.6.1', but the package does not contain any
assembly references or content files that are compatible with that
framework.
Because nuget did not detect that you added assembly references or content files to the project.
Hope this helps.

Automatically add project dependency metadata to manually created nuspec file

When I nuget pack a web project I want to specify custom unpack locations for content and maintain project dependency metadata.
Given the following manually created example nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>Web.MyApp</id>
<version>1.0</version>
<title>Web.MyApp</title>
<authors>Chris</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Nuget package containing files for Web.MyApp</description>
<releaseNotes>release notes</releaseNotes>
<copyright>Copyright Chris 2017</copyright>
<tags />
<dependencies />
</metadata>
<files>
<file src="bin\**\*.*" target="bin" />
<file src="views\**\*.*" target="views" />
<file src="content\" target="content" />
<file src="scripts\" target="scripts" />
<file src="Global.asax" target="" />
<file src="*.config" target="" />
</files>
</package>
This allows me to specify custom unpack locations for bin, content, sprint folders etc but I want the project dependency metadata to be automatically maintained. I don't want to edit the nupsec each time a new dependency is referenced.
As an attempt to resolve this problem I tried to nuget pack the csproj file instead of the nuspec. This maintained the dependency metadata however it made specifying content unpack locations much trickier. I can do the following:
<Content Include="Content\dist\images\brand-logo.svg">
<Pack>true</Pack>
<PackagePath>Content\Content\dist</PackagePath>
</Content>
But I couldn't find an elegant solution for the bin folder. I just feel like I'm doing something fundamentally wrong.
So my question is, how can I automatically maintain project dependency metadata when creating a nuget package from a manually created nuspec file?
The pack command I am using:
..\tools\nuget\nuget.exe pack $project + ".nuspec" -IncludeReferencedProjects -
Properties Configuration=Release -Verbosity quiet -NonInteractive -
OutputDirectory "$packagedirectory" -Version $buildVersion -Symbols
Automatically add project dependency metadata to manually created nuspec file
If I understand you correct, I am afraid you have already automatically add project dependency metadata to manually created .nuspec file. You just need to rebuild the project and re-pack the .nuspec file.
When you include the referenced files with wildcard, it will contain the new added project references:
<file src="bin\**\*.*" target="bin" />
Add a new project reference to the project, then re-build the project, the dll file of referenced project will be copied to the \bin folder, So we just need to re-pack the .nuspec file, the referenced project metadata will included in the new created package.
For example, add a Atest reference project to Web.MyApp project, then rebuild the project and re-pack the .nuspec file:
If I misunderstand you, please let me know for free.

XmlUpdate task not updating my XML file

I have the following task in an MSBuild script:
<XmlUpdate
Namespace="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"
XmlFileName="$(PackageDir)\temp\OddEnds.Testing\OddEnds.Testing.nuspec"
XPath="/package/metadata/version"
Value="%(OddEndsTestingAsmInfo.Version)" />
which is supposed to update an empty version node in a NuGet specification file with the assembly version. My .nuspec file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance">
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<id>OddEnds</id>
<authors>Tomas Lycken</authors>
<!-- Here's the node I want to update -->
<version></version>
<owners>Tomas Lycken</owners>
<description>Odd ends and bits that I might need in any project.</description>
</metadata>
</package>
I believe the XPath pointer /package/metadata/version points to the right node (since if I change it to something else, it complains about not finding the node) yet the output says 0 node(s) selected for update.
What am I missing?
You may need to include the namespace in your xpath string.
Check out this blog post: http://www.lesnikowski.com/blog/index.php/update-nuspec-version-from-msbuild/
You can also try //*:version. This will select all version elements regardless of namespace.
I had exactly the same problem with NuGet, XmlUpdate, MSBuild and XPath.
In the end I switched to the NuGetPack task of the MSBuild Community Tasks project.
(Note that the NuGet tasks are (at least for right now) only available in the Nightly Build)
Adding the version number to your NuGet package via MSBuild using this task would then look somehow like the following snippet:
<Target Name="NuGet">
<GetAssemblyIdentity AssemblyFiles="$(BuildCompileDirectory)\$(AssemblyName).dll">
<Output TaskParameter="Assemblies" ItemName="AssemblyIdentities"/>
</GetAssemblyIdentity>
<NuGetPack
ToolPath="$(ToolsDirectory)"
WorkingDirectory="$(BuildCompileDirectory)"
File="$(SrcDirectory)\$(SolutionName).nuspec"
Version="%(AssemblyIdentities.Version)"/>
</Target>
Hope that helps!
Your task would need to look like this:
<XmlUpdate
Prefix="xmlsucks"
Namespace="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"
XmlFileName="$(PackageDir)\temp\OddEnds.Testing\OddEnds.Testing.nuspec"
XPath="/xmlsucks:package/xmlsucks:metadata/xmlsucks:version"
Value="%(OddEndsTestingAsmInfo.Version)" />
Feel free to change the prefix to whatever derogatory term you would like to use :-)

Resources