Преглед изворни кода

Widen dependency version range on Microsoft.AspNetCore.App to allow patch updates (#1186)

Originally, we thought using exact version ranges on the dependencies of Microsoft.AspNetCore.App
would help protect consumers from lifting binaries out of the shared framework. However,
this makes it difficult for consumers to use packages that share a dependency with .App.
When users tried to mix Microsoft.EntityFramework.SQLite 2.1.1 with Microsoft.AspNetCore.App 2.1.0,
NuGet errors and warnings made it difficult to reason about what was wrong, and how to resolve it.

This changes the dependency version range to allow uses to upgrade within the major.minor patch family
without needing to override NuGet warnings. This removes some of the protections against users
unintentionally lifting to a binary newer than the shared framework, however, after lots of discussion,
we believe this is a better user experience.
Nate McMaster пре 7 година
родитељ
комит
309e9e3077
2 измењених фајлова са 52 додато и 8 уклоњено
  1. 4 4
      build/SharedFx.targets
  2. 48 4
      build/tasks/AddMetapackageReferences.cs

+ 4 - 4
build/SharedFx.targets

@@ -70,7 +70,7 @@
     <RepoTasks.AddMetapackageReferences
       ReferencePackagePath="$(MetapackageWorkDirectory)$(MetapackageName).csproj"
       MetapackageReferenceType="$(MetapackageReferenceType)"
-      LockToExactVersions="$(LockToExactVersions)"
+      DependencyVersionRangeType="$(MetapackageDependencyVersionRangeType)"
       BuildArtifacts="@(ArtifactInfo)"
       PackageArtifacts="@(PackageArtifact)"
       ExternalDependencies="@(ExternalDependency)" />
@@ -87,7 +87,7 @@
         <AdditionalProperties>
           MetapackageName=Microsoft.AspNetCore.App;
           MetapackageReferenceType=AppMetapackage;
-          LockToExactVersions=true
+          MetapackageDependencyVersionRangeType=MajorMinor
         </AdditionalProperties>
       </_MetapackageBuilderProject>
 
@@ -95,7 +95,7 @@
         <AdditionalProperties>
           MetapackageName=Microsoft.AspNetCore.All;
           MetapackageReferenceType=AllMetapackage;
-          LockToExactVersions=false
+          MetapackageDependencyVersionRangeType=Minimum
         </AdditionalProperties>
       </_MetapackageBuilderProject>
 
@@ -103,7 +103,7 @@
         <AdditionalProperties>
           MetapackageName=Microsoft.AspNetCore.Analyzers;
           MetapackageReferenceType=Analyzer;
-          LockToExactVersions=true
+          MetapackageDependencyVersionRangeType=Minimum
         </AdditionalProperties>
       </_MetapackageBuilderProject>
     </ItemGroup>

+ 48 - 4
build/tasks/AddMetapackageReferences.cs

@@ -6,6 +6,7 @@ using System.Linq;
 using System.Xml;
 using Microsoft.Build.Framework;
 using Microsoft.Build.Utilities;
+using NuGet.Versioning;
 using RepoTasks.Utilities;
 
 namespace RepoTasks
@@ -19,7 +20,14 @@ namespace RepoTasks
         public string MetapackageReferenceType { get; set; }
 
         [Required]
-        public bool LockToExactVersions { get; set; }
+        public string DependencyVersionRangeType { get; set; }
+
+        // MSBuild doesn't allow binding to enums directly.
+        private enum VersionRangeType
+        {
+            Minimum, // [1.1.1, )
+            MajorMinor, // [1.1.1, 1.2.0)
+        }
 
         [Required]
         public ITaskItem[] BuildArtifacts { get; set; }
@@ -32,6 +40,12 @@ namespace RepoTasks
 
         public override bool Execute()
         {
+            if (!Enum.TryParse<VersionRangeType>(DependencyVersionRangeType, out var dependencyVersionType))
+            {
+                Log.LogError("Unexpected value {0} for DependencyVersionRangeType", DependencyVersionRangeType);
+                return false;
+            }
+
             // Parse input
             var metapackageArtifacts = PackageArtifacts.Where(p => p.GetMetadata(MetapackageReferenceType) == "true");
             var externalArtifacts = ExternalDependencies.Where(p => p.GetMetadata(MetapackageReferenceType) == "true");
@@ -65,8 +79,13 @@ namespace RepoTasks
                     throw;
                 }
 
-                var packageVersionValue = LockToExactVersions ? $"[{packageVersion}]" : packageVersion;
+                if (string.IsNullOrEmpty(packageVersion))
+                {
+                    Log.LogError("Missing version information for package {0}", packageName);
+                    continue;
+                }
 
+                var packageVersionValue = GetDependencyVersion(dependencyVersionType, packageName, packageVersion);
                 Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersionValue}");
 
                 var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
@@ -81,7 +100,14 @@ namespace RepoTasks
             {
                 var packageName = package.ItemSpec;
                 var packageVersion = package.GetMetadata("Version");
-                var packageVersionValue = LockToExactVersions ? $"[{packageVersion}]" : packageVersion;
+
+                if (string.IsNullOrEmpty(packageVersion))
+                {
+                    Log.LogError("Missing version information for package {0}", packageName);
+                    continue;
+                }
+
+                var packageVersionValue = GetDependencyVersion(dependencyVersionType, packageName, packageVersion);
 
                 Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersionValue}");
 
@@ -99,7 +125,25 @@ namespace RepoTasks
             xmlDoc.AppendChild(projectElement);
             xmlDoc.Save(ReferencePackagePath);
 
-            return true;
+            return !Log.HasLoggedErrors;
+        }
+
+        private string GetDependencyVersion(VersionRangeType dependencyVersionType, string packageName, string packageVersion)
+        {
+            switch (dependencyVersionType)
+            {
+                case VersionRangeType.MajorMinor:
+                    if (!NuGetVersion.TryParse(packageVersion, out var nugetVersion))
+                    {
+                        Log.LogError("Invalid NuGet version '{0}' for package {1}", packageVersion, packageName);
+                        return null;
+                    }
+                    return $"[{packageVersion}, {nugetVersion.Major}.{nugetVersion.Minor + 1}.0)";
+                case VersionRangeType.Minimum:
+                    return packageVersion;
+                default:
+                    throw new NotImplementedException();
+            }
         }
     }
 }