9

I would like to setup a CI/CD pipeline with build, test and deploy stages. I can build my project in build stage with

msbuild src\MyProject.csproj /t:Restore 
msbuild src\MyProject.csproj /p:Configuration=Release /p:OutputPath=../BuildOutput

Next I will build and run tests against ..\BuildOutput\MyProject.dll that has already been built.

msbuild tests\MyProject.Tests.csproj /t:Restore
msbuild tests\MyProject.Tests.csproj /p:Configuration=Release /p:OutputPath=../BuildOutput /p:BuildProjectReferences=false
vstest.console BuildOutput\MyProject.Tests.dll

Up to this point it seems to work.

Now I would like to generate nuget package. I can call:

msbuild src\MyProject.csproj /t:Pack /p:Configuration=Release /p:OutputPath=../BuildOutput /p:VersionPrefix=1.2.3

And that would create MyProject.1.2.3.nupkg in BuildOutput folder. However it re-builds that project.

I'm looking something similar to dotnet cli.

dotnet pack --no-build

But I cannot use dotnet because my project has a COM reference.

I also looked into Nuget.exe, but it seems to throw an error when I call nuget pack

Unable to cast object of type 'System.String' to type NuGet.Frameworks.NuGet.Frameworks1051960.NuGetFramework'.

Does msbuild have a property that can skip build?

1

1 Answer 1

6

It depends on whether this is acceptable in your workflow, but you could use the <GeneratePackageOnBuild> property in a <PropertyGroup> of your .csproj file to get the package whenever you build your project. In case your tests do not go through, you can then discard the .nupkg file, but at least there is no additional rebuild for getting the NuGet package.

There is a more complete example of how to use this setting at the end of the article Easily supporting multiple target frameworks (TFMs) with VS2017 and Nuget1, but an exemplary very simple snippet would look like this:

<PropertyGroup>
    <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
</PropertyGroup>

1: While the original link does not report a 404, it appears as blank in October 2021. The same article can, however, be found on another URL.

Sign up to request clarification or add additional context in comments.

5 Comments

That flow crossed my mind as well. So in build stage I build my project and create that package. If it is time to deploy then I just ship the package that was generated in build stage. Although it feels a bit redundant to always create package in build stage, I still prefer usable pipeline over none at all :).
Alternatively, if you want to define this exclusively at build-time (e.g., as part of your CI configuration), instead of hard-coding it into your project file, you can instead use the /t:build,pack switch. This differs from just using /t:pack in that it will ensure any projects that aren't intended for packaging still get built, as would happen if there were a separate /t:build task.
@O.R. Mapper Can you tell me in which props or targets file the GeneratePackageOnBuild is defined ?
The link to "this article" is broken
@pvoosten: Thank you for pointing this out - I think I have found a second source for the article and added it to the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.