diff --git a/MinVer/build/MinVer.targets b/MinVer/build/MinVer.targets index b5ff278b..6929643c 100644 --- a/MinVer/build/MinVer.targets +++ b/MinVer/build/MinVer.targets @@ -62,8 +62,10 @@ $(MinVerVersion.Split(`+`, 2)[1]) $(MinVerMajor).0.0.0 $(MinVerMajor).$(MinVerMinor).$(MinVerPatch).0 - $(MinVerVersion) - $(MinVerVersion) + $(MinVerVersion) + $(MinVerMajor).$(MinVerMinor).$(MinVerPatch) + $(PackageVersion)-$(MinVerPreRelease) + $(PackageVersion) @@ -73,6 +75,7 @@ + diff --git a/MinVerTests.Infra/Package.cs b/MinVerTests.Infra/Package.cs index f47e063a..e2be7b4c 100644 --- a/MinVerTests.Infra/Package.cs +++ b/MinVerTests.Infra/Package.cs @@ -4,17 +4,18 @@ namespace MinVerTests.Infra { - public record Package(string Version, AssemblyVersion AssemblyVersion, FileVersion FileVersion) + public record Package(string Version, AssemblyVersion AssemblyVersion, FileVersion FileVersion, string InformationalVersion) { - public static Package WithVersion(int major, int minor, int patch, IEnumerable? preReleaseIdentifiers = null, int height = 0, string buildMetadata = "") + public static Package WithVersion(int major, int minor, int patch, IEnumerable? preReleaseIdentifiers = null, int height = 0, string buildMetadata = "", string? informationalVersionAdditionalBuildMetadata = "") { var preReleaseToken = preReleaseIdentifiers == null ? "" : GetPreReleaseToken(preReleaseIdentifiers.ToList()); var heightToken = height == 0 ? "" : $".{height}"; var buildMetadataToken = string.IsNullOrEmpty(buildMetadata) ? "" : $"+{buildMetadata}"; - var version = $"{major}.{minor}.{patch}{preReleaseToken}{heightToken}{buildMetadataToken}"; + var version = $"{major}.{minor}.{patch}{preReleaseToken}{heightToken}"; + var informationalVersion = $"{version}{buildMetadataToken}{informationalVersionAdditionalBuildMetadata}"; - return new Package(version, new AssemblyVersion(major, 0, 0, 0), new FileVersion(major, minor, patch, 0, version)); + return new Package(version, new AssemblyVersion(major, 0, 0, 0), new FileVersion(major, minor, patch, 0, informationalVersion), informationalVersion); } private static string GetPreReleaseToken(IReadOnlyList preReleaseIdentifiers) => preReleaseIdentifiers.Any() ? $"-{string.Join(".", preReleaseIdentifiers)}" : ""; diff --git a/MinVerTests.Infra/Sdk.cs b/MinVerTests.Infra/Sdk.cs index 8b8bfa7b..8250cb35 100644 --- a/MinVerTests.Infra/Sdk.cs +++ b/MinVerTests.Infra/Sdk.cs @@ -5,6 +5,7 @@ using System.IO; using System.IO.Compression; using System.Linq; +using System.Reflection; using System.Runtime.Loader; using System.Threading.Tasks; using Microsoft.Extensions.FileSystemGlobbing; @@ -171,23 +172,26 @@ private static async Task GetPackage(string fileName) var assemblyFileName = Directory.EnumerateFiles(extractedDirectoryName, "*.dll", new EnumerationOptions { RecurseSubdirectories = true, }).First(); - var systemAssemblyVersion = GetAssemblyVersion(assemblyFileName); + var (systemAssemblyVersion, informationalVersion) = GetAssemblyVersions(assemblyFileName); var assemblyVersion = new AssemblyVersion(systemAssemblyVersion.Major, systemAssemblyVersion.Minor, systemAssemblyVersion.Build, systemAssemblyVersion.Revision); var fileVersionInfo = FileVersionInfo.GetVersionInfo(assemblyFileName); var fileVersion = new FileVersion(fileVersionInfo.FileMajorPart, fileVersionInfo.FileMinorPart, fileVersionInfo.FileBuildPart, fileVersionInfo.FilePrivatePart, fileVersionInfo.ProductVersion ?? ""); - return new Package(nuspecVersion, assemblyVersion, fileVersion); + return new Package(nuspecVersion, assemblyVersion, fileVersion, informationalVersion); } - private static Version GetAssemblyVersion(string assemblyFileName) + private static (Version Version, string InformationalVersion) GetAssemblyVersions(string assemblyFileName) { var assemblyLoadContext = new AssemblyLoadContext(default, true); var assembly = assemblyLoadContext.LoadFromAssemblyPath(assemblyFileName); try { - return assembly.GetName().Version ?? throw new InvalidOperationException("The assembly version is null."); + return ( + assembly.GetName().Version ?? throw new InvalidOperationException("The assembly version is null."), + assembly.GetCustomAttributes().OfType().FirstOrDefault()?.InformationalVersion ?? + throw new InvalidOperationException("The assembly has no informational version.")); } finally { diff --git a/MinVerTests.Packages/AnnotatedTag.cs b/MinVerTests.Packages/AnnotatedTag.cs index 5231eb61..850d6929 100644 --- a/MinVerTests.Packages/AnnotatedTag.cs +++ b/MinVerTests.Packages/AnnotatedTag.cs @@ -26,6 +26,6 @@ public static async Task HasTagVersion() // assert Assert.Equal(expected, actual); - Assert.Equal(expected.Version, cliStandardOutput.Trim()); + Assert.Equal(expected.InformationalVersion, cliStandardOutput.Trim()); } } diff --git a/MinVerTests.Packages/BuildMetadata.cs b/MinVerTests.Packages/BuildMetadata.cs index 6768b02e..7a8bd115 100644 --- a/MinVerTests.Packages/BuildMetadata.cs +++ b/MinVerTests.Packages/BuildMetadata.cs @@ -22,6 +22,6 @@ public static async Task HasBuildMetadata() // assert Assert.Equal(expected, actual); - Assert.Equal(expected.Version, cliStandardOutput.Trim()); + Assert.Equal(expected.InformationalVersion, cliStandardOutput.Trim()); } } diff --git a/MinVerTests.Packages/OutputVariables.cs b/MinVerTests.Packages/OutputVariables.cs index 7121ad76..4e3adb37 100644 --- a/MinVerTests.Packages/OutputVariables.cs +++ b/MinVerTests.Packages/OutputVariables.cs @@ -28,7 +28,8 @@ public static async Task AreSet() Assert.Contains("MinVer: [output] MinVerBuildMetadata=build.6", standardOutput, StringComparison.Ordinal); Assert.Contains("MinVer: [output] AssemblyVersion=2.0.0.0", standardOutput, StringComparison.Ordinal); Assert.Contains("MinVer: [output] FileVersion=2.3.4.0", standardOutput, StringComparison.Ordinal); - Assert.Contains("MinVer: [output] PackageVersion=2.3.4-alpha-x.5+build.6", standardOutput, StringComparison.Ordinal); - Assert.Contains("MinVer: [output] Version=2.3.4-alpha-x.5+build.6", standardOutput, StringComparison.Ordinal); + Assert.Contains("MinVer: [output] InformationalVersion=2.3.4-alpha-x.5+build.6", standardOutput, StringComparison.Ordinal); + Assert.Contains("MinVer: [output] PackageVersion=2.3.4-alpha-x.5", standardOutput, StringComparison.Ordinal); + Assert.Contains("MinVer: [output] Version=2.3.4-alpha-x.5", standardOutput, StringComparison.Ordinal); } } diff --git a/MinVerTests.Packages/SourceLink.cs b/MinVerTests.Packages/SourceLink.cs new file mode 100644 index 00000000..15c3c0c9 --- /dev/null +++ b/MinVerTests.Packages/SourceLink.cs @@ -0,0 +1,38 @@ +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices.ComTypes; +using System.Threading.Tasks; +using MinVerTests.Infra; +using Xunit; + +namespace MinVerTests.Packages; + +public static class SourceLink +{ + [Fact] + public static async Task HasCommitSha() + { + // arrange + var path = MethodBase.GetCurrentMethod().GetTestDirectory(); + await Sdk.CreateProject(path); + + _ = await Sdk.DotNet($"add package Microsoft.SourceLink.GitHub --version 1.1.1 --package-directory packages", path); + _ = await Sdk.DotNet("restore --packages packages", path); + + await Git.Init(path); + await Git.Commit(path); + var sha = (await Git.GetCommitShas(path)).Single(); + + var buildMetadata = "build.123"; + var envVars = ("MinVerBuildMetadata", buildMetadata); + var expected = Package.WithVersion(0, 0, 0, new[] { "alpha", "0", }, 0, $"build.123", $".{sha}"); + + // act + var (actual, _, _) = await Sdk.BuildProject(path, envVars: envVars); + var (cliStandardOutput, _) = await MinVerCli.ReadAsync(path, envVars: envVars); + + // assert + Assert.Equal(expected, actual); + Assert.Equal($"{expected.Version}+{buildMetadata}", cliStandardOutput.Trim()); + } +} diff --git a/MinVerTests.Packages/TagWithBuildMetadata.cs b/MinVerTests.Packages/TagWithBuildMetadata.cs index e1a24b2a..43d3d4ec 100644 --- a/MinVerTests.Packages/TagWithBuildMetadata.cs +++ b/MinVerTests.Packages/TagWithBuildMetadata.cs @@ -26,6 +26,6 @@ public static async Task HasTagVersion() // assert Assert.Equal(expected, actual); - Assert.Equal(expected.Version, cliStandardOutput.Trim()); + Assert.Equal(expected.InformationalVersion, cliStandardOutput.Trim()); } } diff --git a/MinVerTests.Packages/VersionOverride.cs b/MinVerTests.Packages/VersionOverride.cs index e1f9e863..3d3e7436 100644 --- a/MinVerTests.Packages/VersionOverride.cs +++ b/MinVerTests.Packages/VersionOverride.cs @@ -28,6 +28,6 @@ public static async Task HasVersionOverride() // assert Assert.Equal(expected, actual); - Assert.Equal(expected.Version, cliStandardOutput.Trim()); + Assert.Equal(expected.InformationalVersion, cliStandardOutput.Trim()); } } diff --git a/README.md b/README.md index 37b7aa10..fc8e8710 100644 --- a/README.md +++ b/README.md @@ -89,12 +89,13 @@ MinVer sets the following custom properties: Those properties are used to set the following .NET SDK properties, satisfying the official [open-source library guidance for version numbers](https://docs.microsoft.com/en-ca/dotnet/standard/library-guidance/versioning#version-numbers): -| Property | Value | -| ----------------- | --------------------------------------------- | -| `AssemblyVersion` | `{MinVerMajor}.0.0.0` | -| `FileVersion` | `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}.0` | -| `PackageVersion` | `{MinVerVersion}` | -| `Version` | `{MinVerVersion}` | +| Property | Value | +|------------------------|-----------------------------------------------------------------------------------------------------------------| +| `AssemblyVersion` | `{MinVerMajor}.0.0.0` | +| `FileVersion` | `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}.0` | +| `InformationalVersion` | `{MinVerVersion}` | +| `PackageVersion` | `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}` (or `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}-{MinVerPreRelease}`) | +| `Version` | `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}` (or `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}-{MinVerPreRelease}`) | This behaviour can be [customised](#can-i-use-the-version-calculated-by-minver-for-other-purposes). @@ -249,6 +250,17 @@ environment: You can also specify build metadata in a version tag. If the tag is on the current commit, its build metadata will be used. If the tag is on an older commit, its build metadata will be ignored. Build metadata in `MinVerBuildMetadata` will be appended to build metadata in the tag. +Build metadata is only included in the [assembly informational version](https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/versioning#assembly-informational-version). You can include it elsewhere using a custom target. E.g.: + +```xml + + + $(PackageVersion)+$(MinVerBuildMetadata) + $(PackageVersion) + + +``` + ### Can I auto-increment the minor or major version after an RTM tag instead of the patch version? Yes! Specify which part of the version to auto-increment with `MinVerAutoIncrement`. By default, [MinVer will auto-increment the patch version](#how-it-works), but you can specify `minor` or `major` to increment the minor or major version instead. @@ -277,7 +289,6 @@ For example, for pull requests, you may want to inject the pull request number a $(MinVerMajor).$(MinVerMinor).$(MinVerPatch)-pr.$(APPVEYOR_PULL_REQUEST_NUMBER).build-id.$(APPVEYOR_BUILD_ID).$(MinVerPreRelease) - $(PackageVersion)+$(MinVerBuildMetadata) $(PackageVersion)