dependabot-nuget 0.292.0 → 0.293.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/.gitignore +1 -0
- data/helpers/lib/NuGetUpdater/Directory.Packages.props +1 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Correlator.cs +197 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/DotNetPackageCorrelation.csproj +12 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageMapper.cs +68 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageSet.cs +11 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/Release.cs +25 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/ReleasesFile.cs +9 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/RuntimePackages.cs +11 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/Sdk.cs +13 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/SemVerComparer.cs +16 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/SemVersionConverter.cs +42 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/DotNetPackageCorrelation.Cli.csproj +16 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/Program.cs +32 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/CorrelatorTests.cs +99 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/DotNetPackageCorrelation.Test.csproj +18 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/EndToEndTests.cs +30 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/RuntimePackagesTests.cs +206 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +6 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +8 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +17 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +7 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +46 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +8 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Extensions.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/CloneWorker.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +7 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +3 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +99 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EnsureDotNetPackageCorrelation.targets +25 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +9 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +5 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/MissingFileException.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +3 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +3 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotFound.cs +7 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotParseable.cs +15 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +24 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +6 -21
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/UnparseableFileException.cs +12 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +21 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +6 -30
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DotNetPackageCorrelationManager.cs +46 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +51 -27
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +15 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +15 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +20 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +108 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +16 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +15 -28
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +5 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +9 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestBase.cs +24 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/ExpectedUpdateOperationResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +11 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +14 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +148 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +12 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.sln +18 -1
- data/lib/dependabot/nuget/native_helpers.rb +41 -16
- metadata +25 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +0 -12
@@ -70,11 +70,12 @@ public class CloneWorker
|
|
70
70
|
catch (HttpRequestException ex)
|
71
71
|
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
72
72
|
{
|
73
|
+
// this is a _very_ specific case we want to handle before the common error handling kicks in
|
73
74
|
error = new JobRepoNotFound(ex.Message);
|
74
75
|
}
|
75
76
|
catch (Exception ex)
|
76
77
|
{
|
77
|
-
error =
|
78
|
+
error = JobErrorBase.ErrorFromException(ex, _jobId, repoContentsPath);
|
78
79
|
}
|
79
80
|
|
80
81
|
if (error is not null)
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<Project>
|
2
2
|
<Import Project="DependencyDiscovery.props" />
|
3
3
|
|
4
|
-
<Target Name="_DiscoverDependencies" DependsOnTargets="GenerateBuildDependencyFile;ResolvePackageAssets">
|
4
|
+
<Target Name="_DiscoverDependencies" DependsOnTargets="ResolveAssemblyReferences;GenerateBuildDependencyFile;ResolvePackageAssets">
|
5
5
|
<!--
|
6
|
-
The
|
6
|
+
The targets ResolveAssemblyReferences and GenerateBuildDependencyFile are sufficient for projects targeting .NET Standard or .NET Core.
|
7
7
|
The target ResolvePackageAssets is necessary for projects targeting .NET Framework.
|
8
8
|
-->
|
9
9
|
</Target>
|
@@ -1,5 +1,4 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
|
-
using System.Net;
|
3
2
|
using System.Text.Json;
|
4
3
|
using System.Text.Json.Serialization;
|
5
4
|
|
@@ -10,7 +9,7 @@ using Microsoft.Build.Exceptions;
|
|
10
9
|
|
11
10
|
using NuGet.Frameworks;
|
12
11
|
|
13
|
-
using NuGetUpdater.Core.
|
12
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
14
13
|
using NuGetUpdater.Core.Utilities;
|
15
14
|
|
16
15
|
namespace NuGetUpdater.Core.Discover;
|
@@ -19,6 +18,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
19
18
|
{
|
20
19
|
public const string DiscoveryResultFileName = "./.dependabot/discovery.json";
|
21
20
|
|
21
|
+
private readonly string _jobId;
|
22
22
|
private readonly ExperimentsManager _experimentsManager;
|
23
23
|
private readonly ILogger _logger;
|
24
24
|
private readonly HashSet<string> _processedProjectPaths = new(StringComparer.Ordinal); private readonly HashSet<string> _restoredMSBuildSdks = new(StringComparer.OrdinalIgnoreCase);
|
@@ -29,8 +29,9 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
29
29
|
Converters = { new JsonStringEnumConverter() },
|
30
30
|
};
|
31
31
|
|
32
|
-
public DiscoveryWorker(ExperimentsManager experimentsManager, ILogger logger)
|
32
|
+
public DiscoveryWorker(string jobId, ExperimentsManager experimentsManager, ILogger logger)
|
33
33
|
{
|
34
|
+
_jobId = jobId;
|
34
35
|
_experimentsManager = experimentsManager;
|
35
36
|
_logger = logger;
|
36
37
|
}
|
@@ -48,23 +49,11 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
48
49
|
{
|
49
50
|
result = await RunAsync(repoRootPath, workspacePath);
|
50
51
|
}
|
51
|
-
catch (HttpRequestException ex)
|
52
|
-
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
53
|
-
{
|
54
|
-
result = new WorkspaceDiscoveryResult
|
55
|
-
{
|
56
|
-
ErrorType = ErrorType.AuthenticationFailure,
|
57
|
-
ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(PathHelper.JoinPath(repoRootPath, workspacePath))) + ")",
|
58
|
-
Path = workspacePath,
|
59
|
-
Projects = [],
|
60
|
-
};
|
61
|
-
}
|
62
52
|
catch (Exception ex)
|
63
53
|
{
|
64
54
|
result = new WorkspaceDiscoveryResult
|
65
55
|
{
|
66
|
-
|
67
|
-
ErrorDetails = ex.ToString(),
|
56
|
+
Error = JobErrorBase.ErrorFromException(ex, _jobId, PathHelper.JoinPath(repoRootPath, workspacePath)),
|
68
57
|
Path = workspacePath,
|
69
58
|
Projects = [],
|
70
59
|
};
|
@@ -123,8 +112,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
123
112
|
DotNetToolsJson = null,
|
124
113
|
GlobalJson = null,
|
125
114
|
Projects = projectResults.Where(p => p.IsSuccess).OrderBy(p => p.FilePath).ToImmutableArray(),
|
126
|
-
|
127
|
-
ErrorDetails = failedProjectResult.FilePath,
|
115
|
+
Error = failedProjectResult.Error,
|
128
116
|
IsSuccess = false,
|
129
117
|
};
|
130
118
|
|
@@ -192,8 +180,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
192
180
|
ImportedFiles = ImmutableArray<string>.Empty,
|
193
181
|
AdditionalFiles = ImmutableArray<string>.Empty,
|
194
182
|
IsSuccess = false,
|
195
|
-
|
196
|
-
ErrorDetails = "Failed to parse project file found at " + invalidProjectFile,
|
183
|
+
Error = new DependencyFileNotParseable(invalidProjectFile),
|
197
184
|
}];
|
198
185
|
}
|
199
186
|
if (projects.IsEmpty)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
|
-
|
2
|
+
|
3
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
3
4
|
|
4
5
|
namespace NuGetUpdater.Core.Discover;
|
5
6
|
|
@@ -8,8 +9,7 @@ public record ProjectDiscoveryResult : IDiscoveryResultWithDependencies
|
|
8
9
|
public required string FilePath { get; init; }
|
9
10
|
public required ImmutableArray<Dependency> Dependencies { get; init; }
|
10
11
|
public bool IsSuccess { get; init; } = true;
|
11
|
-
public
|
12
|
-
public ErrorType? ErrorType { get; init; }
|
12
|
+
public JobErrorBase? Error { get; init; } = null;
|
13
13
|
public ImmutableArray<Property> Properties { get; init; } = [];
|
14
14
|
public ImmutableArray<string> TargetFrameworks { get; init; } = [];
|
15
15
|
public ImmutableArray<string> ReferencedProjectPaths { get; init; } = [];
|
@@ -9,6 +9,8 @@ using NuGet.Versioning;
|
|
9
9
|
|
10
10
|
using NuGetUpdater.Core.Utilities;
|
11
11
|
|
12
|
+
using Semver;
|
13
|
+
|
12
14
|
using LoggerProperty = Microsoft.Build.Logging.StructuredLogger.Property;
|
13
15
|
|
14
16
|
namespace NuGetUpdater.Core.Discover;
|
@@ -72,6 +74,9 @@ internal static class SdkProjectDiscovery
|
|
72
74
|
Dictionary<string, HashSet<string>> topLevelPackagesPerProject = new(PathComparer.Instance);
|
73
75
|
// projectPath, packageNames
|
74
76
|
|
77
|
+
Dictionary<string, Dictionary<string, Dictionary<string, string>>> packagesReplacedBySdkPerProject = new(PathComparer.Instance);
|
78
|
+
// projectPath tfm packageName, packageVersion
|
79
|
+
|
75
80
|
Dictionary<string, Dictionary<string, string>> resolvedProperties = new(PathComparer.Instance);
|
76
81
|
// projectPath propertyName, propertyValue
|
77
82
|
|
@@ -164,7 +169,7 @@ internal static class SdkProjectDiscovery
|
|
164
169
|
}
|
165
170
|
break;
|
166
171
|
case NamedNode namedNode when namedNode is AddItem or RemoveItem:
|
167
|
-
ProcessResolvedPackageReference(namedNode, packagesPerProject, topLevelPackagesPerProject);
|
172
|
+
ProcessResolvedPackageReference(namedNode, packagesPerProject, topLevelPackagesPerProject, experimentsManager);
|
168
173
|
|
169
174
|
if (namedNode is AddItem addItem)
|
170
175
|
{
|
@@ -203,6 +208,70 @@ internal static class SdkProjectDiscovery
|
|
203
208
|
}
|
204
209
|
}
|
205
210
|
break;
|
211
|
+
case Target target when target.Name == "_HandlePackageFileConflicts":
|
212
|
+
// this only works if we've installed the exact SDK required
|
213
|
+
if (experimentsManager.InstallDotnetSdks)
|
214
|
+
{
|
215
|
+
var projectEvaluation = GetNearestProjectEvaluation(target);
|
216
|
+
if (projectEvaluation is null)
|
217
|
+
{
|
218
|
+
break;
|
219
|
+
}
|
220
|
+
|
221
|
+
var removedReferences = target.Children.OfType<RemoveItem>().FirstOrDefault(r => r.Name == "Reference");
|
222
|
+
var addedReferences = target.Children.OfType<AddItem>().FirstOrDefault(r => r.Name == "Reference");
|
223
|
+
if (removedReferences is null || addedReferences is null)
|
224
|
+
{
|
225
|
+
break;
|
226
|
+
}
|
227
|
+
|
228
|
+
foreach (var removedAssembly in removedReferences.Children.OfType<Item>())
|
229
|
+
{
|
230
|
+
var removedPackageName = GetChildMetadataValue(removedAssembly, "NuGetPackageId");
|
231
|
+
var removedFileName = Path.GetFileName(removedAssembly.Name);
|
232
|
+
if (removedPackageName is null || removedFileName is null)
|
233
|
+
{
|
234
|
+
continue;
|
235
|
+
}
|
236
|
+
|
237
|
+
var existingProjectPackagesByTfm = packagesPerProject.GetOrAdd(projectEvaluation.ProjectFile, () => new(PathComparer.Instance));
|
238
|
+
var existingProjectPackages = existingProjectPackagesByTfm.GetOrAdd(tfm, () => new(StringComparer.OrdinalIgnoreCase));
|
239
|
+
if (!existingProjectPackages.ContainsKey(removedPackageName))
|
240
|
+
{
|
241
|
+
continue;
|
242
|
+
}
|
243
|
+
|
244
|
+
var correspondingAddedFile = addedReferences.Children.OfType<Item>()
|
245
|
+
.FirstOrDefault(i => removedFileName.Equals(Path.GetFileName(i.Name), StringComparison.OrdinalIgnoreCase));
|
246
|
+
if (correspondingAddedFile is null)
|
247
|
+
{
|
248
|
+
continue;
|
249
|
+
}
|
250
|
+
|
251
|
+
var runtimePackageName = GetChildMetadataValue(correspondingAddedFile, "NuGetPackageId");
|
252
|
+
var runtimePackageVersion = GetChildMetadataValue(correspondingAddedFile, "NuGetPackageVersion");
|
253
|
+
if (runtimePackageName is null ||
|
254
|
+
runtimePackageVersion is null ||
|
255
|
+
!SemVersion.TryParse(runtimePackageVersion, out var parsedRuntimePackageVersion))
|
256
|
+
{
|
257
|
+
continue;
|
258
|
+
}
|
259
|
+
|
260
|
+
var packageMapper = DotNetPackageCorrelationManager.GetPackageMapper();
|
261
|
+
var replacementPackageVersion = packageMapper.GetPackageVersionThatShippedWithOtherPackage(runtimePackageName, parsedRuntimePackageVersion, removedPackageName);
|
262
|
+
if (replacementPackageVersion is null)
|
263
|
+
{
|
264
|
+
continue;
|
265
|
+
}
|
266
|
+
|
267
|
+
var packagesPerThisProject = packagesReplacedBySdkPerProject.GetOrAdd(projectEvaluation.ProjectFile, () => new(PathComparer.Instance));
|
268
|
+
var packagesPerTfm = packagesPerThisProject.GetOrAdd(tfm, () => new(StringComparer.OrdinalIgnoreCase));
|
269
|
+
packagesPerTfm[removedPackageName] = replacementPackageVersion.ToString();
|
270
|
+
var relativeProjectPath = Path.GetRelativePath(repoRootPath, projectEvaluation.ProjectFile).NormalizePathToUnix();
|
271
|
+
logger.Info($"Re-added SDK managed package [{removedPackageName}/{replacementPackageVersion}] to project [{relativeProjectPath}]");
|
272
|
+
}
|
273
|
+
}
|
274
|
+
break;
|
206
275
|
}
|
207
276
|
}, takeChildrenSnapshot: true);
|
208
277
|
}
|
@@ -228,6 +297,33 @@ internal static class SdkProjectDiscovery
|
|
228
297
|
{
|
229
298
|
// gather some project-level information
|
230
299
|
var packagesByTfm = packagesPerProject[projectPath];
|
300
|
+
if (packagesReplacedBySdkPerProject.TryGetValue(projectPath, out var packagesReplacedBySdk))
|
301
|
+
{
|
302
|
+
var consolidatedPackagesByTfm = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
|
303
|
+
|
304
|
+
// copy the first dictionary
|
305
|
+
foreach (var kvp in packagesByTfm)
|
306
|
+
{
|
307
|
+
var tfm = kvp.Key;
|
308
|
+
var packages = kvp.Value;
|
309
|
+
consolidatedPackagesByTfm[tfm] = packages;
|
310
|
+
}
|
311
|
+
|
312
|
+
// merge in the second
|
313
|
+
foreach (var kvp in packagesReplacedBySdk)
|
314
|
+
{
|
315
|
+
var tfm = kvp.Key;
|
316
|
+
var packages = kvp.Value;
|
317
|
+
var replacedPackages = consolidatedPackagesByTfm.GetOrAdd(tfm, () => new(StringComparer.OrdinalIgnoreCase));
|
318
|
+
foreach (var packagePair in packages)
|
319
|
+
{
|
320
|
+
replacedPackages[packagePair.Key] = packagePair.Value;
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
packagesByTfm = consolidatedPackagesByTfm;
|
325
|
+
}
|
326
|
+
|
231
327
|
var projectFullDirectory = Path.GetDirectoryName(projectPath)!;
|
232
328
|
var doc = XDocument.Load(projectPath);
|
233
329
|
var localPropertyDefinitionElements = doc.Root!.XPathSelectElements("/Project/PropertyGroup/*");
|
@@ -288,7 +384,8 @@ internal static class SdkProjectDiscovery
|
|
288
384
|
private static void ProcessResolvedPackageReference(
|
289
385
|
NamedNode node,
|
290
386
|
Dictionary<string, Dictionary<string, Dictionary<string, string>>> packagesPerProject, // projectPath -> tfm -> (packageName, packageVersion)
|
291
|
-
Dictionary<string, HashSet<string>> topLevelPackagesPerProject
|
387
|
+
Dictionary<string, HashSet<string>> topLevelPackagesPerProject,
|
388
|
+
ExperimentsManager experimentsManager
|
292
389
|
)
|
293
390
|
{
|
294
391
|
var doRemoveOperation = node is RemoveItem;
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<Project>
|
2
|
+
|
3
|
+
<PropertyGroup>
|
4
|
+
<PackageCorrelationCliDirectory>$(MSBuildThisFileDirectory)..\DotNetPackageCorrelation.Cli</PackageCorrelationCliDirectory>
|
5
|
+
<DotNetCoreDirectory>$(MSBuildThisFileDirectory)..\..\dotnet-core</DotNetCoreDirectory>
|
6
|
+
<PackageCorrelationFile>$(MSBuildThisFileDirectory)dotnet-package-correlation.json</PackageCorrelationFile>
|
7
|
+
</PropertyGroup>
|
8
|
+
|
9
|
+
<ItemGroup>
|
10
|
+
<None Include="$(PackageCorrelationFile)" CopyToOutputDirectory="PreserveNewest" />
|
11
|
+
<_DotNetCoreFiles Include="$(DotNetCoreDirectory)\**\*" />
|
12
|
+
</ItemGroup>
|
13
|
+
|
14
|
+
<Target Name="BuildDotNetPackageCorrelationFile" Inputs="@(_DotNetCoreFiles)" Outputs="$(PackageCorrelationFile)" BeforeTargets="GetCopyToOutputDirectoryItems">
|
15
|
+
<Exec Command="dotnet run --core-location "$(DotNetCoreDirectory)" --output "$(PackageCorrelationFile)"" WorkingDirectory="$(PackageCorrelationCliDirectory)" />
|
16
|
+
</Target>
|
17
|
+
|
18
|
+
<Target Name="CleanDotNetPackageCorrelationFile" BeforeTargets="Clean">
|
19
|
+
<Delete Files="$(PackageCorrelationFile)" Condition="Exists('$(PackageCorrelationFile)')" />
|
20
|
+
</Target>
|
21
|
+
|
22
|
+
<Target Name="RebuildDotNetPackageCorrelationFile" BeforeTargets="Rebuild" DependsOnTargets="CleanDotNetPackageCorrelationFile">
|
23
|
+
</Target>
|
24
|
+
|
25
|
+
</Project>
|
@@ -1,6 +1,7 @@
|
|
1
1
|
using System.Text.Json;
|
2
2
|
|
3
3
|
using NuGetUpdater.Core.Run;
|
4
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
4
5
|
|
5
6
|
namespace NuGetUpdater.Core;
|
6
7
|
|
@@ -30,42 +31,28 @@ public record ExperimentsManager
|
|
30
31
|
};
|
31
32
|
}
|
32
33
|
|
33
|
-
public static async Task<(ExperimentsManager ExperimentsManager,
|
34
|
+
public static async Task<(ExperimentsManager ExperimentsManager, JobErrorBase? Error)> FromJobFileAsync(string jobId, string jobFilePath)
|
34
35
|
{
|
35
36
|
var experimentsManager = new ExperimentsManager();
|
36
|
-
|
37
|
+
JobErrorBase? error = null;
|
38
|
+
var jobFileContent = string.Empty;
|
37
39
|
try
|
38
40
|
{
|
39
|
-
|
41
|
+
jobFileContent = await File.ReadAllTextAsync(jobFilePath);
|
40
42
|
var jobWrapper = RunWorker.Deserialize(jobFileContent);
|
41
43
|
experimentsManager = GetExperimentsManager(jobWrapper.Job.Experiments);
|
42
44
|
}
|
43
|
-
catch (BadRequirementException ex)
|
44
|
-
{
|
45
|
-
errorResult = new NativeResult
|
46
|
-
{
|
47
|
-
ErrorType = ErrorType.BadRequirement,
|
48
|
-
ErrorDetails = ex.Message,
|
49
|
-
};
|
50
|
-
}
|
51
45
|
catch (JsonException ex)
|
52
46
|
{
|
53
|
-
|
54
|
-
{
|
55
|
-
ErrorType = ErrorType.Unknown,
|
56
|
-
ErrorDetails = $"Error deserializing job file: {ex}: {File.ReadAllText(jobFilePath)}",
|
57
|
-
};
|
47
|
+
// this is a very specific case where we want to log the JSON contents for easier debugging
|
48
|
+
error = JobErrorBase.ErrorFromException(new NotSupportedException($"Error deserializing job file contents: {jobFileContent}", ex), jobId, Environment.CurrentDirectory); // TODO
|
58
49
|
}
|
59
50
|
catch (Exception ex)
|
60
51
|
{
|
61
|
-
|
62
|
-
{
|
63
|
-
ErrorType = ErrorType.Unknown,
|
64
|
-
ErrorDetails = ex.ToString(),
|
65
|
-
};
|
52
|
+
error = JobErrorBase.ErrorFromException(ex, jobId, Environment.CurrentDirectory); // TODO
|
66
53
|
}
|
67
54
|
|
68
|
-
return (experimentsManager,
|
55
|
+
return (experimentsManager, error);
|
69
56
|
}
|
70
57
|
|
71
58
|
private static bool IsEnabled(Dictionary<string, object>? experiments, string experimentName)
|
@@ -13,12 +13,16 @@ internal sealed class PackagesConfigBuildFile : XmlBuildFile
|
|
13
13
|
public PackagesConfigBuildFile(string basePath, string path, XmlDocumentSyntax contents)
|
14
14
|
: base(basePath, path, contents)
|
15
15
|
{
|
16
|
+
var invalidPackageElements = Packages.Where(p => p.GetAttribute("id") is null || p.GetAttribute("version") is null).ToList();
|
17
|
+
if (invalidPackageElements.Any())
|
18
|
+
{
|
19
|
+
throw new UnparseableFileException("`package` element missing `id` or `version` attributes", path);
|
20
|
+
}
|
16
21
|
}
|
17
22
|
|
18
23
|
public IEnumerable<IXmlElementSyntax> Packages => Contents.RootSyntax.GetElements("package", StringComparison.OrdinalIgnoreCase);
|
19
24
|
|
20
25
|
public IEnumerable<Dependency> GetDependencies() => Packages
|
21
|
-
.Where(p => p.GetAttribute("id") is not null && p.GetAttribute("version") is not null)
|
22
26
|
.Select(p => new Dependency(
|
23
27
|
p.GetAttributeValue("id", StringComparison.OrdinalIgnoreCase),
|
24
28
|
p.GetAttributeValue("version", StringComparison.OrdinalIgnoreCase),
|
@@ -1,8 +1,8 @@
|
|
1
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
2
|
+
|
1
3
|
namespace NuGetUpdater.Core;
|
2
4
|
|
3
5
|
public record NativeResult
|
4
6
|
{
|
5
|
-
|
6
|
-
public ErrorType? ErrorType { get; init; }
|
7
|
-
public object? ErrorDetails { get; init; }
|
7
|
+
public JobErrorBase? Error { get; init; } = null;
|
8
8
|
}
|
@@ -14,6 +14,7 @@
|
|
14
14
|
</ItemGroup>
|
15
15
|
|
16
16
|
<ItemGroup>
|
17
|
+
<ProjectReference Include="..\DotNetPackageCorrelation\DotNetPackageCorrelation.csproj" />
|
17
18
|
<ProjectReference Include="..\NuGetProjects\NuGet.CommandLine\NuGet.CommandLine.csproj" />
|
18
19
|
</ItemGroup>
|
19
20
|
|
@@ -31,4 +32,6 @@
|
|
31
32
|
<InternalsVisibleTo Include="NuGetUpdater.Core.Test" />
|
32
33
|
</ItemGroup>
|
33
34
|
|
35
|
+
<Import Project="EnsureDotNetPackageCorrelation.targets" />
|
36
|
+
|
34
37
|
</Project>
|
@@ -2,10 +2,14 @@ namespace NuGetUpdater.Core.Run.ApiModel;
|
|
2
2
|
|
3
3
|
public record DependencyFileNotFound : JobErrorBase
|
4
4
|
{
|
5
|
-
public DependencyFileNotFound(string
|
5
|
+
public DependencyFileNotFound(string filePath, string? message = null)
|
6
6
|
: base("dependency_file_not_found")
|
7
7
|
{
|
8
|
-
|
9
|
-
|
8
|
+
if (message is not null)
|
9
|
+
{
|
10
|
+
Details["message"] = message;
|
11
|
+
}
|
12
|
+
|
13
|
+
Details["file-path"] = filePath.NormalizePathToUnix();
|
10
14
|
}
|
11
15
|
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
namespace NuGetUpdater.Core.Run.ApiModel;
|
2
|
+
|
3
|
+
public record DependencyFileNotParseable : JobErrorBase
|
4
|
+
{
|
5
|
+
public DependencyFileNotParseable(string filePath, string? message = null)
|
6
|
+
: base("dependency_file_not_parseable")
|
7
|
+
{
|
8
|
+
if (message is not null)
|
9
|
+
{
|
10
|
+
Details["message"] = message;
|
11
|
+
}
|
12
|
+
|
13
|
+
Details["file-path"] = filePath.NormalizePathToUnix();
|
14
|
+
}
|
15
|
+
}
|
@@ -1,5 +1,10 @@
|
|
1
|
+
using System.Net;
|
1
2
|
using System.Text.Json.Serialization;
|
2
3
|
|
4
|
+
using Microsoft.Build.Exceptions;
|
5
|
+
|
6
|
+
using NuGetUpdater.Core.Analyze;
|
7
|
+
|
3
8
|
namespace NuGetUpdater.Core.Run.ApiModel;
|
4
9
|
|
5
10
|
public abstract record JobErrorBase
|
@@ -14,4 +19,23 @@ public abstract record JobErrorBase
|
|
14
19
|
|
15
20
|
[JsonPropertyName("error-details")]
|
16
21
|
public Dictionary<string, object> Details { get; init; } = new();
|
22
|
+
|
23
|
+
public static JobErrorBase ErrorFromException(Exception ex, string jobId, string currentDirectory)
|
24
|
+
{
|
25
|
+
return ex switch
|
26
|
+
{
|
27
|
+
BadRequirementException badRequirement => new BadRequirement(badRequirement.Message),
|
28
|
+
HttpRequestException httpRequest => httpRequest.StatusCode switch
|
29
|
+
{
|
30
|
+
HttpStatusCode.Unauthorized or
|
31
|
+
HttpStatusCode.Forbidden => new PrivateSourceAuthenticationFailure(NuGetContext.GetPackageSourceUrls(currentDirectory)),
|
32
|
+
_ => new UnknownError(ex, jobId),
|
33
|
+
},
|
34
|
+
InvalidProjectFileException invalidProjectFile => new DependencyFileNotParseable(invalidProjectFile.ProjectFile),
|
35
|
+
MissingFileException missingFile => new DependencyFileNotFound(missingFile.FilePath, missingFile.Message),
|
36
|
+
UnparseableFileException unparseableFile => new DependencyFileNotParseable(unparseableFile.FilePath, unparseableFile.Message),
|
37
|
+
UpdateNotPossibleException updateNotPossible => new UpdateNotPossible(updateNotPossible.Dependencies),
|
38
|
+
_ => new UnknownError(ex, jobId),
|
39
|
+
};
|
40
|
+
}
|
17
41
|
}
|
@@ -53,7 +53,7 @@ public class RunWorker
|
|
53
53
|
private async Task<RunResult> RunWithErrorHandlingAsync(Job job, DirectoryInfo repoContentsPath, string baseCommitSha)
|
54
54
|
{
|
55
55
|
JobErrorBase? error = null;
|
56
|
-
|
56
|
+
var currentDirectory = repoContentsPath.FullName; // used for error reporting below
|
57
57
|
var runResult = new RunResult()
|
58
58
|
{
|
59
59
|
Base64DependencyFiles = [],
|
@@ -69,7 +69,7 @@ public class RunWorker
|
|
69
69
|
foreach (var directory in job.GetAllDirectories())
|
70
70
|
{
|
71
71
|
var localPath = PathHelper.JoinPath(repoContentsPath.FullName, directory);
|
72
|
-
|
72
|
+
currentDirectory = localPath;
|
73
73
|
var result = await RunForDirectory(job, repoContentsPath, directory, baseCommitSha, experimentsManager);
|
74
74
|
foreach (var dependencyFile in result.Base64DependencyFiles)
|
75
75
|
{
|
@@ -84,26 +84,9 @@ public class RunWorker
|
|
84
84
|
BaseCommitSha = baseCommitSha,
|
85
85
|
};
|
86
86
|
}
|
87
|
-
catch (HttpRequestException ex)
|
88
|
-
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
89
|
-
{
|
90
|
-
error = new PrivateSourceAuthenticationFailure(lastUsedPackageSourceUrls);
|
91
|
-
}
|
92
|
-
catch (BadRequirementException ex)
|
93
|
-
{
|
94
|
-
error = new BadRequirement(ex.Message);
|
95
|
-
}
|
96
|
-
catch (MissingFileException ex)
|
97
|
-
{
|
98
|
-
error = new DependencyFileNotFound("file not found", ex.FilePath);
|
99
|
-
}
|
100
|
-
catch (UpdateNotPossibleException ex)
|
101
|
-
{
|
102
|
-
error = new UpdateNotPossible(ex.Dependencies);
|
103
|
-
}
|
104
87
|
catch (Exception ex)
|
105
88
|
{
|
106
|
-
error =
|
89
|
+
error = JobErrorBase.ErrorFromException(ex, _jobId, currentDirectory);
|
107
90
|
}
|
108
91
|
|
109
92
|
if (error is not null)
|
@@ -123,6 +106,8 @@ public class RunWorker
|
|
123
106
|
_logger.Info("Discovery JSON content:");
|
124
107
|
_logger.Info(JsonSerializer.Serialize(discoveryResult, DiscoveryWorker.SerializerOptions));
|
125
108
|
|
109
|
+
// TODO: report errors
|
110
|
+
|
126
111
|
// report dependencies
|
127
112
|
var discoveredUpdatedDependencies = GetUpdatedDependencyListFromDiscovery(discoveryResult, repoContentsPath.FullName);
|
128
113
|
await _apiHandler.UpdateDependencyList(discoveredUpdatedDependencies);
|
@@ -221,7 +206,7 @@ public class RunWorker
|
|
221
206
|
var dependencyFilePath = Path.Join(discoveryResult.Path, project.FilePath).FullyNormalizedRootedPath();
|
222
207
|
var updateResult = await _updaterWorker.RunAsync(repoContentsPath.FullName, dependencyFilePath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, isTransitive: false);
|
223
208
|
// TODO: need to report if anything was actually updated
|
224
|
-
if (updateResult.
|
209
|
+
if (updateResult.Error is null)
|
225
210
|
{
|
226
211
|
if (dependencyLocation != dependencyFilePath)
|
227
212
|
{
|
@@ -4,6 +4,8 @@ using Microsoft.Language.Xml;
|
|
4
4
|
|
5
5
|
using NuGet.Versioning;
|
6
6
|
|
7
|
+
using NuGetUpdater.Core.Utilities;
|
8
|
+
|
7
9
|
namespace NuGetUpdater.Core;
|
8
10
|
|
9
11
|
/// <summary>
|
@@ -36,6 +38,25 @@ internal static class PackageReferenceUpdater
|
|
36
38
|
|
37
39
|
// Get the set of all top-level dependencies in the current project
|
38
40
|
var topLevelDependencies = MSBuildHelper.GetTopLevelPackageDependencyInfos(buildFiles).ToArray();
|
41
|
+
var isDependencyTopLevel = topLevelDependencies.Any(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase));
|
42
|
+
if (isDependencyTopLevel)
|
43
|
+
{
|
44
|
+
var packageMapper = DotNetPackageCorrelationManager.GetPackageMapper();
|
45
|
+
// TODO: this is slow
|
46
|
+
var isSdkReplacementPackage = packageMapper.RuntimePackages.Runtimes.Any(r =>
|
47
|
+
{
|
48
|
+
return r.Value.Packages.Any(p => dependencyName.Equals(p.Key, StringComparison.Ordinal));
|
49
|
+
});
|
50
|
+
if (isSdkReplacementPackage)
|
51
|
+
{
|
52
|
+
// If we're updating a top level SDK replacement package, the version listed in the project file won't
|
53
|
+
// necessarily match the resolved version that caused the update because the SDK might have replaced
|
54
|
+
// the package. To handle this scenario, we pretend the version we're searching for is the actual
|
55
|
+
// version in the file, not the resolved version. This allows us to keep a strict equality check when
|
56
|
+
// finding the file to update.
|
57
|
+
previousDependencyVersion = topLevelDependencies.First(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase)).Version!;
|
58
|
+
}
|
59
|
+
}
|
39
60
|
|
40
61
|
if (!await DoesDependencyRequireUpdateAsync(repoRootPath, projectPath, tfms, topLevelDependencies, dependencyName, newDependencyVersion, experimentsManager, logger))
|
41
62
|
{
|