Updating local nuget package on post-build event
Asked Answered
I

6

15

I have my local nuget library repository separately both for my personal and work releted class libraries.

I have created some of the nuget packages for the libraries which are no longer in development. I did this only for them because I do not know how to update them automatically as soon as my project builds.

I have figured that all the work is being done by nuget command line with Visual Studio Command Prompt. So I can easily do the work I needed (of course I would know commands perfectly and I do not !)

Basically I want the following tasks to execute on the post-build event of my project.

On project build:

  1. copying project dll into a specific folder (lib folder of the nuget package)
  2. updating nuspec file for new file version (my project is increasing the file version on every build)
  3. creating new nupkg file with new file version

Phil Haack shows some of this feature but it is still a prototype as far as I can tell.

So my requirement is the above. Has anyone else accomplished this?

Intensify answered 23/2, 2011 at 14:55 Comment(0)
L
4

Jeremy Skinner has written a blog post on how he performs automated builds of packages and uploads them to the NuGet Gallery. I think that it matches your requirements.

Basically he uses MsBuild to apply the version (with the MsBuild Community Extensions UpdateXml task) to the nuspec file and invoke the nuget.exe to package it up.

Letreece answered 25/2, 2011 at 15:4 Comment(0)
I
17

The selected solution looks like it would work but it seems like there is a simpler solution for your requirements.

You can create a nuspec file that will read data from the project's metadata. You only need to do this once with this command:

C:\<Path to project>\nuget spec

This creates 'tokens' in the spec file that will will be replaced by the project's metadata when you create the nuget package. This includes the file version. You will want to replace and because all projects are technically suppose to have them.

More details can be found here: http://docs.nuget.org/docs/creating-packages/Creating-and-Publishing-a-Package#From_a_project

Then...

For .Net Framework (old-school) projects, in you project's Post build events you can do this:

nuget pack "$(ProjectPath)"  
xcopy "$(TargetDir)*.nupkg" "<path where you are hosting your local nuget repo>" /C /Y

(assuming nuget.exe is available on your system PATH).

For .Net Core and Standard projects, nuget can't pack them (see https://github.com/NuGet/Home/issues/4491). Instead, use this as your post-build step:

dotnet pack "$(ProjectPath)" --no-build --include-source --include-symbols --output "<path where you are hosting your local nuget repo>"

Of course you can adjust the options to meet your needs. See https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-pack?tabs=netcore2x for dotnet pack command options.

Impaction answered 23/1, 2013 at 20:34 Comment(2)
You also can avoid the two step process if you want to set the output directory. Also, you may want to consider if you need to include dependencies: nuget pack "$(ProjectPath)" -outputdirectory "c:\NuGetPackages" -IncludeReferencedProjectsVirginity
This won't work for a remote NuGet feed that does not expose the package path as a share.Ptolemaist
P
7

Just in case someone else (like me) come across this ancient question - in the current era (VS2017, SDK/NugetReference format/ .NET Core / .NET Standard / Multi-target projects), where creation of NuGet package is an option in the Project Properties - so, only issue of local repository has to be solved:

If you have single-target project, to copy your .nupkg file to local NuGet repository, add Post-build event (Project properties > Build Events > Post-build event command line):

xcopy $(TargetDir)*.nupkg [path to your local nuget repository] /s

Like:

xcopy $(TargetDir)*.nupkg G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\ /s


If you have multi-target project, to copy your .nupkg file to local NuGet repository: add Post-build event (Project properties > Build Events > Post-build event command line):

xcopy $(TargetDir)..*.nupkg [path to your local nuget repository] /s

Like:

xcopy $(TargetDir)..*.nupkg G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\ /s


Update: Forget post-build events, there is a cleaner way (xcopy approach works strange for multi-target projects), just add this in project XML:

  <Target Name="CopyPackage" AfterTargets="Pack">
    <Copy SourceFiles="$(OutputPath)$(PackageId).$(PackageVersion).nupkg" DestinationFolder="G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\" />
  </Target>

Update

For newer NuGet versions, which cut off the last 0 (patch from a 0.0.0.0 version notation), you will need to regex the PackageVersion:

  <Target Name="CopyPackage" AfterTargets="Pack">
    <Copy SourceFiles="$(OutputPath)$(PackageId).$([System.Text.RegularExpressions.Regex]::Replace(&quot;$(PackageVersion)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;)).nupkg" DestinationFolder="G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\" />
  </Target>
Protect answered 21/6, 2018 at 19:39 Comment(4)
Had to modify my target to be <Target Name="CopyPackage" AfterTargets="Pack"> <Copy SourceFiles="$(ProjectDir)\bin\Release\$(PackageId).$(PackageVersion).nupkg" DestinationFolder="C:\Users\mcasas\Documents" /> </Target>Gies
Seems that the directory for *.nupkg files has changed (VS 2019, 16.4.5) It is no longer under $(OutputPath). Mike Casas provided the necessary solution (thanks!!)Unparalleled
You can deploy to a local Nuget feed at a post-build even using the $(Package) variables that @Protect found: nuget add bin\$(Configuration)\$(PackageId).$(PackageVersion).nupkg -source c:\packages. (Make sure you select 'When the build updates the project output').Pangenesis
I followed okieh and Mike and used the following (to include configuration): <Target Name="CopyPackage" AfterTargets="Pack"> <Copy SourceFiles="$(ProjectDir)\bin\$(ConfigurationName)\$(PackageId).$(PackageVersion).nupkg" DestinationFolder="c:\repos\Daas.NuGet" /> </Target>. I tried using Nick's but kept getting a nuget 9009 error. After playing with it a bit, switched to the project fix and it worked (with config since I was in Debug). VS 2019 Community, 16.8.6Sena
L
4

Jeremy Skinner has written a blog post on how he performs automated builds of packages and uploads them to the NuGet Gallery. I think that it matches your requirements.

Basically he uses MsBuild to apply the version (with the MsBuild Community Extensions UpdateXml task) to the nuspec file and invoke the nuget.exe to package it up.

Letreece answered 25/2, 2011 at 15:4 Comment(0)
S
0

I recently published a solution for this that actually creates/updates the nuspec files during the build, so don't have to do so manually, then creates the nupkg files.

All you will have to add is a post-build event for copying the packages to their destination (or add it as an optional stage to my solution).

You can find an article with a walk-through guide here and the source code + binary here.

Sauerkraut answered 5/8, 2014 at 22:49 Comment(0)
N
0

With the latest nuget package format using "PackageReference" tags you can use the following simple postbuild event in your csproj to update nuspec file with latest dependencies.

  <Target Name="AfterBuild">
     <WriteLinesToFile File="dependencies.xml" Overwrite="true" Lines=""/>
     <WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="&lt;dependencies&gt;"/>
     <WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="&lt;dependency id=&quot;%(PackageReference.Identity)&quot; version=&quot;%(PackageReference.Version)&quot; /&gt;" />
     <WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="&lt;/dependencies &gt;"/>
     <Exec Command="powershell -NonInteractive -executionpolicy Unrestricted -command &quot;$xml = [xml] (Get-Content Project.nuspec); $xml.package.metadata.RemoveChild($xml.package.metadata.dependencies); $dependencies = [xml](Get-Content dependencies.xml); $xml.Package.Metadata.AppendChild($xml.ImportNode($dependencies.Dependencies, $true)); $xml.Save('Project.nuspec')&quot;"/>
     <Delete Files="dependencies.xml" />
  </Target>

Only premise for this is that you have a nuspec file with rest of the metadata mentioned in the project directory. Here is a sample nuspec file:

<?xml version="1.0"?>
<package>
   <metadata>
      <id>Package Id</id>
      <version>1.0.0</version>
      <authors>Author name</authors>
      <owners>Owner name</owners>
      <description>Description</description>
      <contentFiles>
         <files include="**/content.zip" buildAction="None" copyToOutput="true" flatten="false" />
      </contentFiles>
      <dependencies>
      </dependencies>
   </metadata>
   <files>
      <file src="bin\Release\Project.dll" target="lib\net462" />
      <file src="bin\Release\Project.pdb" target="lib\net462" />
      <file src="bin\Release\file.zip" target="Content" />
   </files>
</package>
Nevsa answered 26/1, 2019 at 17:54 Comment(0)
M
0

I solved it by using a command line Let's assume you have added the location of NuGet to your path environment or copies a stable version to a given directory (this is what I did)

I have my NuGet.exe as well as my certificate in a folder named D:\Build, you may need to update this to fit your path.

Then let's assume you have a codesign certificate file named: "CodeSignCertificate.pfx" with a password: pa$$w0rd

You can get a simple codesign certificate for 17 euro from Ascertia. they also have free trial certificates that are valid for 10 days. the link https://account.ascertia.com/onlineCA/default

then as a one liner I use :

for %f in (X:\Packages\*.nupkg) do D:\Build\nuget sign %f -CertificatePath D:\Build\CodeSignCertificate.pfx -Timestamper http://timestamp.digicert.com -CertificatePassword pa$$w0rd

This sign all my packages in my output directory

if you only want to sign the lastest the NuGet package as this might be the one you just compiled then you can use something like this.

set Path="X:\ASP-WAF\DLL"
for /f "tokens=*" %%a in ('dir /A:-D /B /O:-D /S %Path%') do set NEW=%%a&& goto:n 
:n
sign %NEW% -CertificatePath D:\Build\CodeSignCertificate.pfx -Timestamper http://timestamp.digicert.com -CertificatePassword pa$$w0rd

it's not a one-line but you can put it in a bat file and call that in your post build.

Mckenzie answered 5/9, 2020 at 11:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.