Automatische Versionierung in neuem .csproj (.Net Standard)

Wer mit den neuen .Net Standard herumspielt stellt schnell fest, dass sich einiges bewegt und so auch die .csproj Files eine neue und deutlich verschlankte Struktur bekommen haben.

So müssen Files nicht mehr extra im .csproj angegeben werden und auch referenzierte NugetPackages und erstellen eines NuGet Packages sind darin verpackt worden.

Hier ein Beispiel:

https://github.com/lightwaver/Xamarin.Forms.HtmlLabel/blob/master/HtmlLabel.Std/HtmlLabel.Std.csproj

 

   

neueProjectSettings.PNG

Nun funktioniert das alles schon echt erstaunlich gut, aber wenn man auf seinem BuildServer - in meinem Fall via VSTS - automatische Builds machen möchte stellt man schnell fest dass die alten Varianten zum autmatischen Versionieren eines NuGet Packages einfach nicht mehr funktionieren und ein normales NuGet.exe kein Package davon mehr erzeugt.

So sieht der Fehler in einem normalen NuGet-Pack Schritt aus:

2017-11-07T20:12:33.4345846Z ##[section]Starting: NuGet pack 
2017-11-07T20:12:33.4345846Z ==============================================================================
2017-11-07T20:12:33.4345846Z Task         : NuGet
2017-11-07T20:12:33.4345846Z Description  : Restore, pack, or push NuGet packages, or run a NuGet command. Supports NuGet.org and authenticated feeds like Package Management and MyGet. Uses NuGet.exe and works with .NET Framework apps. For .NET Core and .NET Standard apps, use the .NET Core task.
2017-11-07T20:12:33.4345846Z Version      : 2.0.13
2017-11-07T20:12:33.4345846Z Author       : Microsoft Corporation
2017-11-07T20:12:33.4345846Z Help         : [More Information](https://go.microsoft.com/fwlink/?LinkID=613747)
2017-11-07T20:12:33.4345846Z ==============================================================================
2017-11-07T20:12:33.9658346Z [command]C:\WINDOWS\system32\chcp.com 65001
2017-11-07T20:12:33.9814554Z Active code page: 65001
2017-11-07T20:12:33.9970679Z Attempting to pack file: E:\VSOAgent2\_work\5\s\HtmlLabel.Std\HtmlLabel.Std.csproj
2017-11-07T20:12:33.9970679Z [command]E:\VSOAgent2\_work\_tool\NuGet\4.3.0\x64\nuget.exe pack E:\VSOAgent2\_work\5\s\HtmlLabel.Std\HtmlLabel.Std.csproj -NonInteractive -OutputDirectory E:\VSOAgent2\_work\5\a -Properties Configuration=Release -version 1.0.0.438 -Verbosity Detailed
2017-11-07T20:12:34.4814481Z NuGet Version: 4.3.0.4406
2017-11-07T20:12:34.4970512Z Attempting to build package from 'HtmlLabel.Std.csproj'.
2017-11-07T20:12:34.5751732Z MSBuild auto-detection: using msbuild version '15.4.8.50001' from 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin'. Use option -MSBuildVersion to force nuget to use a specific version of MSBuild.
2017-11-07T20:12:35.8563823Z Packing files from 'E:\VSOAgent2\_work\5\s\HtmlLabel.Std\bin\Release\netstandard1.0'.
2017-11-07T20:12:36.0439916Z Add file 'E:\VSOAgent2\_work\5\s\HtmlLabel.Std\bin\Release\netstandard1.0\MWX.XamForms.Controls.Std.dll' to package as 'lib\netstandard1.0\MWX.XamForms.Controls.Std.dll'
2017-11-07T20:12:36.0907910Z Unable to cast object of type 'System.String' to type 'NuGet.Frameworks.NuGet.Frameworks1051960.NuGetFramework'.
2017-11-07T20:12:36.1063912Z System.InvalidCastException: Unable to cast object of type 'System.String' to type 'NuGet.Frameworks.NuGet.Frameworks1051960.NuGetFramework'.
2017-11-07T20:12:36.1063912Z    at NuGet.ProjectManagement.NuGetProject.GetMetadata[T](String key)
2017-11-07T20:12:36.1063912Z    at NuGet.ProjectManagement.PackagesConfigNuGetProject..ctor(String folderPath, Dictionary`2 metadata)
2017-11-07T20:12:36.1063912Z    at CallSite.Target(Closure , CallSite , Type , Object , Dictionary`2 )
2017-11-07T20:12:36.1063912Z    at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
2017-11-07T20:12:36.1063912Z    at NuGet.CommandLine.ProjectFactory.AddDependencies(Dictionary`2 packagesAndDependencies)
2017-11-07T20:12:36.1063912Z    at NuGet.CommandLine.ProjectFactory.ProcessDependencies(PackageBuilder builder)
2017-11-07T20:12:36.1063912Z    at NuGet.CommandLine.ProjectFactory.CreateBuilder(String basePath, NuGetVersion version, String suffix, Boolean buildIfNeeded, PackageBuilder builder)
2017-11-07T20:12:36.1063912Z    at NuGet.Commands.PackCommandRunner.BuildFromProjectFile(String path)
2017-11-07T20:12:36.1063912Z    at NuGet.CommandLine.PackCommand.ExecuteCommand()
2017-11-07T20:12:36.1063912Z    at NuGet.CommandLine.Command.ExecuteCommandAsync()
2017-11-07T20:12:36.1063912Z    at NuGet.CommandLine.Command.Execute()
2017-11-07T20:12:36.1063912Z    at NuGet.CommandLine.Program.MainCore(String workingDirectory, String[] args)

Das liegt zum einen daran dass die Packages nun direkt mit msbuild erzeugt werden und andererseits, dass die VSTS Buildsteps einfach noch nicht soweit sind.

 

Aber es ist dennnoch relativ leicht möglich. denn einerseits kann man in den Projekt Optionen schnell anhaken dass immer ein NuGet Package erstellt werden soll und andererseits kann man schnell mit einem einfachen Powershell script die Versionnummer im csproj anpassen um die NuGet Version zu konfigurieren.

Ein einfaches Sample hab ich hier hinterlegt:

https://github.com/lightwaver/Xamarin.Forms.HtmlLabel/blob/master/HtmlLabel.Std/UpdateCSProjVersion.ps1

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$True)]
    [String]$version
)
#WriteInfomation(Get-ScriptDirectory)

$manifestPath = $(Get-Location).Path
$manifestPath = $manifestPath + "\HtmlLabel.Std.csproj"

$appConfig = New-Object XML

# make a backup
Copy-Item -Path $manifestPath -Destination $($manifestPath + ".bak") -Force

# load the config file as an xml object
$appConfig.Load($manifestPath)

    
Write-Host $("mapping VersionCode " + $appConfig.Project.PropertyGroup.Version + " to " + $version)

$appConfig.Project.PropertyGroup.Version = $version

$appConfig.Save($manifestPath)

Nun muss nur noch der VersionString als Parameter übergeben werden.

BuildIDZuVersionNummersetzen.PNG

Es geht natülich auf gleiche Art und Weise auch via Build-Variable.

Das wars schon - einfach das NuGet danach ins Artefakt Verzeichnis kopieren und pushen und fertig.