The existing build tasks for Azure DevOps have long had the option to update AssemblyInfo.cs before running a build task (which is really sweet BTW). Is there going to be support in the future for updating the version/package metadata properties in the new csproj format from the build task?
I've previously used a powershell script to take the output of the GitVersion variables to manually go into all the csproj files and update the properties before running dotnet build. It would be great if a future version of the build task could do this OOTB.
I'll try to find the powershell script I use which may better explain what I'm trying to achieve.
This is the powershell script I am using between running the GitVersion build task and the dotnet build task.
$buildVersion = $env:GitVersion_NuGetVersionV2
$sourcesDirectory = $env:BUILD_SOURCESDIRECTORY
Write-Host "Setting version $buildVersion. Searching for projects"
# Find all the csproj files
if ($buildVersion -eq $null) {
Write-Error ("GitVersion_NuGetVersionV2 environment variable is missing.")
exit 1
}
if ($sourcesDirectory -eq $null) {
Write-Error ("BUILD_SOURCESDIRECTORY environment variable is missing.")
exit 1
}
# This code snippet gets all the files in $Path that end in ".csproj" and any subdirectories.
Get-ChildItem -Path $sourcesDirectory -Filter "*.csproj" -Recurse -File |
ForEach-Object {
$projectPath = $_.FullName
$project = Select-Xml $projectPath -XPath "//Project"
$version = $project.Node.SelectSingleNode("PropertyGroup/Version")
if ($version -eq $null) {
Write-Host "Adding Version element to $projectPath"
$group = $project.Node.SelectSingleNode("PropertyGroup")
$version = $group.OwnerDocument.CreateElement("Version")
$group.AppendChild($version) | Out-Null
}
$version.InnerText = $env:GitVersion_NuGetVersionV2
$version.OwnerDocument.Save($projectPath)
Write-Host "Saved version $($env:GitVersion_NuGetVersionV2) to $projectPath"
}
You could also create/update the Directory.Build.props file with the properties you're interested in.
That would be a good addition to the Build Task, for example create Directory.Build.props for new sdk based projects and keep AssemblyInfo.cs for older project types.
You can have a look how we use it in GitVersion
https://github.com/GitTools/GitVersion/blob/master/src/Directory.Build.props
I haven't used props files before so I've been reading up on this file and I think I get how this might work. For example, this file could be created/updated to have something like the following (I'm totally guessing here).
<PropertyGroup>
<AssemblyVersion>$(GitVersion_AssemblySemVer)</AssemblyVersion>
<FileVersion>$(GitVersion_MajorMinorPatch)</FileVersion>
<InformationalVersion>$(GitVersion_InformationalVersion )</InformationalVersion>
</PropertyGroup>
In order to use Directory.Build.props for this purpose I can think of the following scenarios that would need to be handled:
If you can safely figure out how to handle existing Directory.Build.props files then this may work on Azure DevOps because creating/updating a Directory.Build.props file on the build agent repo wouldn't matter as the change would be cleared out after the build. This wouldn't work for the nuget package on a project because a create or update to a Directory.Build.props file would create a change on the file under source control on the developers machine.
Have I totally missed the mark here?
That's a good description of the the possible scenarios.
As far as I understand, the AssemblyInfo can still be used for setting the version number for the sdk style projects.
You can also pass them as build parameters similar to
dotnet build -p:Version=$(GitVersion_AssemblySemVer) (not tested) reference
Yep, you could push those three properties into the build task. That does require a manual configuration of the build step though. The thing I like about the AssemblyInfo option on the existing build task (at least for full framework msbuild builds) is that it is a zero config effort on the build workflow.
I've been thinking about this a bit more. The PowerShell script above is really just doing a similar action to what the AssemblyInfo logic does in the existing build task. It would be easier in the case of the new proj format though because it is xml rather than parsing the AssemblyInfo text file.
This process still wouldn't work for the GitVersionTask NuGet package because it would change what is under source control.
FYI, I've updated my script to include the other properties.
$nuGetVersion = $env:GitVersion_NuGetVersionV2
$sourcesDirectory = $env:BUILD_SOURCESDIRECTORY
Write-Host "Searching for projects under $($sourcesDirectory)"
# Find all the csproj files
if ($nuGetVersion -eq $null) {
Write-Error ("GitVersion_NuGetVersionV2 environment variable is missing.")
exit 1
}
if ($env:GitVersion_AssemblySemVer -eq $null) {
Write-Error ("GitVersion_AssemblySemVer environment variable is missing.")
exit 1
}
if ($env:GitVersion_MajorMinorPatch -eq $null) {
Write-Error ("GitVersion_MajorMinorPatch environment variable is missing.")
exit 1
}
if ($env:GitVersion_InformationalVersion -eq $null) {
Write-Error ("GitVersion_InformationalVersion environment variable is missing.")
exit 1
}
if ($sourcesDirectory -eq $null) {
Write-Error ("BUILD_SOURCESDIRECTORY environment variable is missing.")
exit 1
}
Function Set-NodeValue($rootNode, [string]$nodeName, [string]$value)
{
$nodePath = "PropertyGroup/$($nodeName)"
$node = $rootNode.Node.SelectSingleNode($nodePath)
if ($node -eq $null) {
Write-Host "Adding $($nodeName) element to existing PropertyGroup"
$group = $rootNode.Node.SelectSingleNode("PropertyGroup")
$node = $group.OwnerDocument.CreateElement($nodeName)
$group.AppendChild($node) | Out-Null
}
$node.InnerText = $value
Write-Host "Set $($nodeName) to $($value)"
}
# This code snippet gets all the files in $Path that end in ".csproj" and any subdirectories.
Get-ChildItem -Path $sourcesDirectory -Filter "*.csproj" -Recurse -File |
ForEach-Object {
Write-Host "Found project at $($_.FullName)"
$projectPath = $_.FullName
$project = Select-Xml $projectPath -XPath "//Project"
Set-NodeValue $project "Version" $nuGetVersion
Set-NodeValue $project "AssemblyVersion" $env:GitVersion_AssemblySemVer
Set-NodeValue $project "FileVersion" $env:GitVersion_MajorMinorPatch
Set-NodeValue $project "InformationalVersion" $env:GitVersion_InformationalVersion
$document = $project.Node.OwnerDocument
$document.PreserveWhitespace = $true
$document.Save($projectPath)
Write-Host ""
}
Write-Host "##vso[build.updatebuildnumber]$($nuGetVersion)"
This works fine as a custom DevOps build task but it would be nice if GitVersion did this OOTB :)
This issue has been automatically marked as stale because it has not had recent activity. After 30 days from now, it will be closed if no further activity occurs. Thank you for your contributions.
I still think this should be addressed
Having GitVersion update the .csproj files automatically would be sweet.
This issue has been automatically marked as stale because it has not had recent activity. After 30 days from now, it will be closed if no further activity occurs. Thank you for your contributions.
Presumably GitVersionCore could include a custom implementation to support this. Similar to how the AssemblyInfo logic works - https://github.com/GitTools/GitVersion/blob/master/src/GitVersionCore/Extensions/VersionAssemblyInfoResources/AssemblyInfoFileUpdater.cs
This issue has been automatically marked as stale because it has not had recent activity. After 30 days from now, it will be closed if no further activity occurs. Thank you for your contributions.
A pull request implementing this with tests will be accepted.
We started using GitVersion recently in our AzureDevOps setup. All of our project are either in .Net Core and .Net Standard and none of them have the AssemblyInfo.cs file. We are currently using the PowerShell script provided here as a workaround, but that would be great if GitVersion task on Azure DevOps can update the csproj file and add the version. Thank you.
Looking at taking care of this @asbjornu @arturcic as this is something I personally want for my AzDo pipelines.
Given that users want a minimalistic configuration, I can see a couple of approaches
/updateassemblyinfo, if we're in an SDK-style csproj and <GenerateAssemblyInfo> is either not present or true, edit the csproj properties directly. If we're not in an SDK csproj or <GenerateAssemblyInfo> is set to false, we will look for AssemblyInfo.cs as usual .csproj, edit it to set the properties.Alternatively, we could add a new switch /updateprojectinfo which will similarly set the assembly version information, but in the csproj files. The downside is that there will be additional work in AzDo to provide this UI experience for the checkbox/filename; the upside is that it is more explicit about what it's doing.
I'm comfortable with either approach. I'm going to use https://www.fuget.org/packages/Microsoft.Build/16.5.0 (I think this is the go-to package for reading/writing project metadata) to handle the project files.
@svengeance, I'm happy you're volunteering to look into this! Just a heads up of where we're heading with v6: We are hoping to introduce a new command-based CLI and also break GitVersion up in more independent parts, where dealing with specific build servers, output formats, serializations, etc., are compartementalized and made independent of each other. An introduction of an MSBuild dependency and more logic around it might therefore be wise to introduce after the groundworks for the new architecture is laid out. What do you think?
@asbjornu
I see, that sounds like a good move. I can see 3 ways forward
Personally I'd like to get a crack on this, so 1 or 2 are preferable to me, but I understand this is your timeline so let me know how you'd like to move forward
I can right off the bat say that 1 is nowhere close to true, so if you don't mind doing 2, then let's have a look at it in a PR. Just beware that it may be postponed and in need of a rewrite it if becomes too big and unwieldy.
Fair enough. I will try to implement it in such a way that it doesn't become a pain in the ass to move around. Hopefully I have something soon for you!
@roryprimrose if you apply the GitVersion NuGet package on your project to ensure that the assembly information gets updated, wouldn't this avoid the need to use your PowerShell script?
I've used the GitVersion NuGet package on my .NET Core project in order to get the correct assembly version and on Azure DevOps I have used the extension onlyo to ensure that the build number gets updated.
Most helpful comment
Having
GitVersionupdate the.csprojfiles automatically would be sweet.