Search code examples
.net-corenuget-packagemsbuild-4.0

Change "Referencee" $(PackageVersion) During DNCore Pack


I am trying to use MSBuild to automatically update package versions based on the branch name. This works for the project itself, but referenced projects (that use the same MSBuild targets) use the default version - meaning that my targets are not running. For example, assume I have the following projects:

  • ConsoleApp1
    • ProjectReference: ClassLibrary1
  • ClassLibrary1

When building the above, I get the following nuspec/nugets:

  • ConsoleApp1 version 0.0.2-beta00001
    • dependency id="ClassLibrary1" version="1.0.0"
  • ClassLibrary version 0.0.2-beta00001

Note that the PackageVersion that is being pulled through is the default for the ProjectReference, while the project itself is building with the discovered package version.

I've tried changing GetTargetPathDependsOn as well as BeforeTargets="GetTargetPath;GetProjectsReferencingProjectJson" (after poking around in the Nuget Pack MSBuild), but they don't seem to be having an effect.

<PropertyGroup>
  <BuildDependsOn>
    OverridePackageVersion;
    $(BuildDependsOn);
  </BuildDependsOn>
  <GetTargetPathDependsOn>
    OverridePackageVersion;
    $(GetTargetPathDependsOn);
  </GetTargetPathDependsOn>
</PropertyGroup>

<Target Name="OverridePackageVersion"
        BeforeTargets="GetTargetPath;GetProjectsReferencingProjectJson"
        DependsOnTargets="GetDefaultVersion">

  <CreateProperty
    Value=""
    Condition="'$(AutoPackagePreName)'=='$(ReleaseBranchName)'">
    <Output TaskParameter="Value" PropertyName="AutoPackagePreName" />
  </CreateProperty>

  <CreateProperty
    Value="$([System.String]::Format( $(AutoPackagePreNumberFormat), $([MSBuild]::Add($(AutoPackagePreNumber), 0)) ))">
    <Output TaskParameter="Value" PropertyName="AutoPackagePreNumber" />
  </CreateProperty>

  <!-- Final Override -->

  <CreateProperty
    Value="$(AutoPackageVersion)"
    Condition="'$(AutoPackagePreName)'==''">
    <Output TaskParameter="Value" PropertyName="PackageVersion" />
  </CreateProperty>

  <CreateProperty
    Value="$(AutoPackageVersion)-$(AutoPackagePreName)$(AutoPackagePreNumber)"
    Condition="'$(AutoPackagePreName)'!=''">
    <Output TaskParameter="Value" PropertyName="PackageVersion" />
  </CreateProperty>

  <CreateProperty
    Value="$(PackageVersion)"
    Condition="'$(UpdateVersion)'=='true'">
    <Output TaskParameter="Value" PropertyName="Version" />
  </CreateProperty>

  <Message Importance="High" Text="Selected package version $(PackageVersion)." />

</Target>

Is this at all possible, or am I going to have to use Powershell in my CI?

The full source is available.


Solution

  • The targets you'd need to run before for the recent NuGet and .NET Core 2.* SDK versions are CollectPackageReferences;PrepareForBuild. To get it working in older versions, I used Restore;_GenerateRestoreProjectSpec in addition but these should no longer be necessary on recent tooling. See my Directory.Builds.targets i'm using to create a public NuGet package.

    At the moment, dependency package versions are locked down during restore time and read from the obj\project.assets.json file, this is why the restore-specific targets are used. Note that restore doesn't import props/targets files from NuGet packages so you currently cannot consume versioning logic via a NuGet package containing build assets that work for project-to-project references. See the GitHub issue for it - the plan seems to be to move from reading the assets file to re-evaluating the versions from referenced projects instead of locking them down during restore.