From c1faabb1d036689b2421342ccf1e747d96ab2cf5 Mon Sep 17 00:00:00 2001 From: David Federman Date: Fri, 15 Nov 2024 09:44:29 -0800 Subject: [PATCH] Add setting to opt-into ignoring the .NET SDK patch version (#105) --- Directory.Packages.props | 3 ++- README.md | 1 + src/Common.Tests/PluginSettingsTests.cs | 4 ++++ src/Common/Fingerprinting/FingerprintFactory.cs | 16 +++++++++++++++- src/Common/Microsoft.MSBuildCache.Common.csproj | 1 + src/Common/PluginSettings.cs | 2 ++ .../build/Microsoft.MSBuildCache.Common.targets | 2 ++ 7 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 25f974f..358ab76 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -29,13 +29,14 @@ + - + diff --git a/README.md b/README.md index 74286f2..4fe7e32 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,7 @@ These settings are available in addition to the [Common Settings](#common-settin | `$(MSBuildCacheBlobUri)` | `Uri` | | Specifies the uri of the Azure Storage Blob. | | `$(MSBuildCacheManagedIdentityClientId)` | `string` | | Specifies the managed identity client id when using the "ManagedIdentity" credential type | | `$(MSBuildCacheInteractiveAuthTokenDirectory)` | `string` | "%LOCALAPPDATA%\MSBuildCache\AuthTokenCache" | Specifies a token cache directory when using the "Interactive" credential type | +| `$(MSBuildCacheIgnoreDotNetSdkPatchVersion)` | `bool` | false | Whether to ignore the patch version when doing cache lookups. This trades off some correctness for the sake of getting cache hits when the SDK version isn't exactly the same. The default behavior is to consider the exact SDK version, eg. "8.0.404". With this setting set to true, it will instead use something like "8.0.4XX". Note that the major version, minor version, and feature bands are still considered. | When using the "ConnectionString" credential type, the connection string to the blob storage account must be provided in the `MSBCACHE_CONNECTIONSTRING` environment variable. This connection string needs both read and write access to the resource. diff --git a/src/Common.Tests/PluginSettingsTests.cs b/src/Common.Tests/PluginSettingsTests.cs index fb6d475..3606e7f 100644 --- a/src/Common.Tests/PluginSettingsTests.cs +++ b/src/Common.Tests/PluginSettingsTests.cs @@ -168,6 +168,10 @@ public void GetResultsForUnqueriedDependenciesSetting() public void TargetsToIgnoreSetting(StringListTestCase testCase) => TestStringListSetting(nameof(PluginSettings.TargetsToIgnore), testCase, pluginSettings => pluginSettings.TargetsToIgnore); + [TestMethod] + public void IgnoreDotNetSdkPatchVersionSetting() + => TestBoolSetting(nameof(PluginSettings.IgnoreDotNetSdkPatchVersion), pluginSettings => pluginSettings.IgnoreDotNetSdkPatchVersion); + private static void TestBoolSetting(string settingName, Func valueAccessor) => TestBasicSetting( settingName, diff --git a/src/Common/Fingerprinting/FingerprintFactory.cs b/src/Common/Fingerprinting/FingerprintFactory.cs index b489271..d37288b 100644 --- a/src/Common/Fingerprinting/FingerprintFactory.cs +++ b/src/Common/Fingerprinting/FingerprintFactory.cs @@ -12,6 +12,7 @@ using BuildXL.Cache.ContentStore.Interfaces.Extensions; using DotNet.Globbing; using Microsoft.MSBuildCache.Hashing; +using NuGet.Versioning; namespace Microsoft.MSBuildCache.Fingerprinting; @@ -111,7 +112,20 @@ void AddSettingToFingerprint(IReadOnlyCollection? patterns, string setting string dotnetSdkVersion = nodeContext.ProjectInstance.GetPropertyValue("NETCoreSdkVersion"); if (!string.IsNullOrEmpty(dotnetSdkVersion)) { - entries.Add(CreateFingerprintEntry($"DotnetSdkVersion: {dotnetSdkVersion}")); + if (_pluginSettings.IgnoreDotNetSdkPatchVersion + && NuGetVersion.TryParse(dotnetSdkVersion, out NuGetVersion? parsedDotnetSdkVersion)) + { + // The "feature band" indicates the feature set and is aligned with the Visual Studio version. It's "C00" in a version like A.B.CDD + // Extract it by removing the last two digits of the patch number, eg 123 -> 1. + int featureBand = parsedDotnetSdkVersion.Patch / 100; + + // Eg: "8.0.404" -> "8.0.4XX", or "9.0.100-rc.2.24474.11" -> "9.0.100" + entries.Add(CreateFingerprintEntry($"DotnetSdkVersion: {parsedDotnetSdkVersion.Major}.{parsedDotnetSdkVersion.Minor}.{featureBand}XX")); + } + else + { + entries.Add(CreateFingerprintEntry($"DotnetSdkVersion: {dotnetSdkVersion}")); + } } // Add predicted inputs diff --git a/src/Common/Microsoft.MSBuildCache.Common.csproj b/src/Common/Microsoft.MSBuildCache.Common.csproj index 3ba06ae..093bb43 100644 --- a/src/Common/Microsoft.MSBuildCache.Common.csproj +++ b/src/Common/Microsoft.MSBuildCache.Common.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Common/PluginSettings.cs b/src/Common/PluginSettings.cs index 766c6e7..2292444 100644 --- a/src/Common/PluginSettings.cs +++ b/src/Common/PluginSettings.cs @@ -105,6 +105,8 @@ public string LocalCacheRootPath public IReadOnlyList TargetsToIgnore { get; init; } = Array.Empty(); + public bool IgnoreDotNetSdkPatchVersion { get; init; } + public static T Create( IReadOnlyDictionary settings, PluginLoggerBase logger, diff --git a/src/Common/build/Microsoft.MSBuildCache.Common.targets b/src/Common/build/Microsoft.MSBuildCache.Common.targets index 8d67e4c..41ecc92 100644 --- a/src/Common/build/Microsoft.MSBuildCache.Common.targets +++ b/src/Common/build/Microsoft.MSBuildCache.Common.targets @@ -22,6 +22,7 @@ $(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheGlobalPropertiesToIgnore $(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheGetResultsForUnqueriedDependencies $(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheTargetsToIgnore + $(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheIgnoreDotNetSdkPatchVersion @@ -43,6 +44,7 @@ $(MSBuildCacheGlobalPropertiesToIgnore) $(MSBuildCacheGetResultsForUnqueriedDependencies) $(MSBuildCacheTargetsToIgnore) + $(MSBuildCacheIgnoreDotNetSdkPatchVersion)