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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 833b170b34a1cef53346970cdfc208b39f49899aaeeb1d2da285463eabf2aea3
|
4
|
+
data.tar.gz: aea74663e1ec787d2496c6d63f97c531d6ccd5415cdd810ce7d8518080b027cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 889ab157302c7dbb0be345ca4e5204fe5518d6aafbd61d7992008404fa84200240e6f88655027ddb4a77611964cb97e2ea7857ad6453d33e498e4d6416b79eb8
|
7
|
+
data.tar.gz: 17f3003ef471825cf980d00da41c528bb051dc64285d6ca808ca84bea09a89b91a197a388d8f62c4e089427a52e77ba24d13b452ec9bc7231b46d18c9c84d697
|
@@ -26,6 +26,7 @@
|
|
26
26
|
<PackageVersion Include="MSBuild.StructuredLogger" Version="2.2.386" />
|
27
27
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
28
28
|
<PackageVersion Include="NuGet.Core" Version="2.14.0" Aliases="CoreV2" />
|
29
|
+
<PackageVersion Include="Semver" Version="3.0.0" />
|
29
30
|
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
30
31
|
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.0" />
|
31
32
|
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
@@ -0,0 +1,197 @@
|
|
1
|
+
using System.Collections.Immutable;
|
2
|
+
using System.Text.Json;
|
3
|
+
using System.Text.RegularExpressions;
|
4
|
+
|
5
|
+
using Semver;
|
6
|
+
|
7
|
+
namespace DotNetPackageCorrelation;
|
8
|
+
|
9
|
+
public partial class Correlator
|
10
|
+
{
|
11
|
+
public static readonly JsonSerializerOptions SerializerOptions = new()
|
12
|
+
{
|
13
|
+
WriteIndented = true,
|
14
|
+
Converters = { new SemVersionConverter() },
|
15
|
+
};
|
16
|
+
|
17
|
+
private readonly DirectoryInfo _releaseNotesDirectory;
|
18
|
+
|
19
|
+
public Correlator(DirectoryInfo releaseNotesDirectory)
|
20
|
+
{
|
21
|
+
_releaseNotesDirectory = releaseNotesDirectory;
|
22
|
+
}
|
23
|
+
|
24
|
+
public async Task<(RuntimePackages RuntimePackages, IEnumerable<string> Warnings)> RunAsync()
|
25
|
+
{
|
26
|
+
var runtimeVersions = new List<Version>();
|
27
|
+
foreach (var directory in Directory.EnumerateDirectories(_releaseNotesDirectory.FullName))
|
28
|
+
{
|
29
|
+
var directoryName = Path.GetFileName(directory);
|
30
|
+
if (Version.TryParse(directoryName, out var version))
|
31
|
+
{
|
32
|
+
runtimeVersions.Add(version);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
var runtimePackages = new RuntimePackages();
|
37
|
+
var warnings = new List<string>();
|
38
|
+
foreach (var majorVersion in runtimeVersions)
|
39
|
+
{
|
40
|
+
var releasesJsonPath = Path.Combine(_releaseNotesDirectory.FullName, majorVersion.ToString(), "releases.json");
|
41
|
+
if (!File.Exists(releasesJsonPath))
|
42
|
+
{
|
43
|
+
warnings.Add($"Unable to find releases.json file for version {majorVersion}");
|
44
|
+
continue;
|
45
|
+
}
|
46
|
+
|
47
|
+
var releasesJson = await File.ReadAllTextAsync(releasesJsonPath);
|
48
|
+
var releasesFile = JsonSerializer.Deserialize<ReleasesFile>(releasesJson, SerializerOptions)!;
|
49
|
+
|
50
|
+
foreach (var release in releasesFile.Releases)
|
51
|
+
{
|
52
|
+
foreach (var sdk in release.GetSdks())
|
53
|
+
{
|
54
|
+
if (sdk.Version is null)
|
55
|
+
{
|
56
|
+
warnings.Add($"Skipping release with missing version information from {releasesJson}");
|
57
|
+
continue;
|
58
|
+
}
|
59
|
+
|
60
|
+
if (sdk.RuntimeVersion is null)
|
61
|
+
{
|
62
|
+
warnings.Add($"Skipping release with missing runtime version information from {releasesJson}");
|
63
|
+
continue;
|
64
|
+
}
|
65
|
+
|
66
|
+
if (runtimePackages.Runtimes.ContainsKey(sdk.RuntimeVersion))
|
67
|
+
{
|
68
|
+
// already processed this runtime
|
69
|
+
continue;
|
70
|
+
}
|
71
|
+
|
72
|
+
var packagesAndVersions = new PackageSet();
|
73
|
+
runtimePackages.Runtimes.Add(sdk.RuntimeVersion, packagesAndVersions);
|
74
|
+
var runtimeDirectory = new DirectoryInfo(Path.Combine(_releaseNotesDirectory.FullName, majorVersion.ToString(), sdk.RuntimeVersion.ToString()));
|
75
|
+
var runtimeMarkdownPath = Path.Combine(runtimeDirectory.FullName, $"{sdk.RuntimeVersion}.md");
|
76
|
+
if (!File.Exists(runtimeMarkdownPath))
|
77
|
+
{
|
78
|
+
warnings.Add($"Unable to find expected markdown file {runtimeMarkdownPath}");
|
79
|
+
continue;
|
80
|
+
}
|
81
|
+
|
82
|
+
var markdownContent = await File.ReadAllTextAsync(runtimeMarkdownPath);
|
83
|
+
var packages = GetPackagesFromMarkdown(runtimeMarkdownPath, markdownContent, warnings);
|
84
|
+
foreach (var (packageName, packageVersion) in packages)
|
85
|
+
{
|
86
|
+
packagesAndVersions.Packages[packageName] = packageVersion;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
return (runtimePackages, warnings);
|
93
|
+
}
|
94
|
+
|
95
|
+
public static ImmutableArray<(string Name, SemVersion Version)> GetPackagesFromMarkdown(string markdownPath, string markdownContent, List<string> warnings)
|
96
|
+
{
|
97
|
+
var lines = markdownContent.Split("\n").Select(l => l.Trim()).ToArray();
|
98
|
+
|
99
|
+
// the markdown file contains a table that looks like this:
|
100
|
+
// Package name | Version
|
101
|
+
// :----------- | :------------------
|
102
|
+
// Some.Package | 1.2.3
|
103
|
+
// ...
|
104
|
+
// however there are some formatting issues with some elements that prevent markdown parsers from
|
105
|
+
// discovering it, so we fall back to manual parsing
|
106
|
+
|
107
|
+
var tableStartLine = -1;
|
108
|
+
for (int i = 0; i < lines.Length; i++)
|
109
|
+
{
|
110
|
+
if (Regex.IsMatch(lines[i], "Package name.*Version"))
|
111
|
+
{
|
112
|
+
tableStartLine = i;
|
113
|
+
break;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
if (tableStartLine == -1)
|
118
|
+
{
|
119
|
+
warnings.Add($"Unable to find table start in file {markdownPath}");
|
120
|
+
return [];
|
121
|
+
}
|
122
|
+
|
123
|
+
// skip the column names and separator line
|
124
|
+
tableStartLine += 2;
|
125
|
+
|
126
|
+
var tableEndLine = lines.Length; // assume the end of the file unless we find a blank line
|
127
|
+
for (int i = tableStartLine; i < lines.Length; i++)
|
128
|
+
{
|
129
|
+
if (string.IsNullOrEmpty(lines[i]))
|
130
|
+
{
|
131
|
+
tableEndLine = i;
|
132
|
+
break;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
var packages = new List<(string Name, SemVersion Version)>();
|
137
|
+
for (int i = tableStartLine; i < tableEndLine; i++)
|
138
|
+
{
|
139
|
+
var line = lines[i].Trim();
|
140
|
+
var foundMatch = false;
|
141
|
+
foreach (var pattern in SpecialCasePatterns)
|
142
|
+
{
|
143
|
+
var match = pattern.Match(line);
|
144
|
+
if (match.Success)
|
145
|
+
{
|
146
|
+
var packageName = match.Groups["PackageName"].Value;
|
147
|
+
var packageVersionString = match.Groups["PackageVersion"].Value;
|
148
|
+
if (SemVersion.TryParse(packageVersionString, out var packageVersion))
|
149
|
+
{
|
150
|
+
packages.Add((packageName, packageVersion));
|
151
|
+
foundMatch = true;
|
152
|
+
break; ;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
if (!foundMatch)
|
158
|
+
{
|
159
|
+
warnings.Add($"Unable to parse package and version from string [{line}] in file [{markdownPath}]:{i}");
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
return packages.ToImmutableArray();
|
164
|
+
}
|
165
|
+
|
166
|
+
// The different patterns the lines in the markdown might take. Due to issues with regular expressions, this list
|
167
|
+
// is in a very specific order.
|
168
|
+
private static ImmutableArray<Regex> SpecialCasePatterns { get; } = [
|
169
|
+
StandardLineWithFileExtensions(),
|
170
|
+
StandardLine(),
|
171
|
+
PackageNameDotVersion(),
|
172
|
+
PackageFileNameWithOptionalTrailingPipe(),
|
173
|
+
MultiColumnWithOptionalFileSuffix(),
|
174
|
+
];
|
175
|
+
|
176
|
+
[GeneratedRegex(@"^(?<PackageName>[^|\s]+)\s*\|\s*(?<PackageVersion>[^|\s]+?)(\.symbols)?\.nupkg$", RegexOptions.Compiled)]
|
177
|
+
// Some.Package | 1.2.3.nupkg
|
178
|
+
// Some.Package | 1.2.3.symbols.nupkg
|
179
|
+
private static partial Regex StandardLineWithFileExtensions();
|
180
|
+
|
181
|
+
[GeneratedRegex(@"^(?<PackageName>[^|\s]+)\s*\|\s*(?<PackageVersion>[^|\s]+)$", RegexOptions.Compiled)]
|
182
|
+
// Some.Package | 1.2.3
|
183
|
+
private static partial Regex StandardLine();
|
184
|
+
|
185
|
+
[GeneratedRegex(@"^(?<PackageName>[^\d]+)\.(?<PackageVersion>[\d].+)$", RegexOptions.Compiled)]
|
186
|
+
// Some.Package.1.2.3
|
187
|
+
private static partial Regex PackageNameDotVersion();
|
188
|
+
|
189
|
+
[GeneratedRegex(@"^(?<PackageName>[^\d]+)\.(?<PackageVersion>\d.+?)\.nupkg(\s+\|)?$", RegexOptions.Compiled)]
|
190
|
+
// some.package.1.2.3.nupkg
|
191
|
+
// some.package.1.2.3.nupkg |
|
192
|
+
private static partial Regex PackageFileNameWithOptionalTrailingPipe();
|
193
|
+
|
194
|
+
[GeneratedRegex(@"^(?<PackageName>[^|\s]+)\s*\|[^|]*\|\s*(?<PackageVersion>.*?)(\.nupkg)?$", RegexOptions.Compiled)]
|
195
|
+
// Some.Package | 1.2 | 1.2.3.nupkg
|
196
|
+
private static partial Regex MultiColumnWithOptionalFileSuffix();
|
197
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
2
|
+
|
3
|
+
<PropertyGroup>
|
4
|
+
<TargetFramework>$(CommonTargetFramework)</TargetFramework>
|
5
|
+
</PropertyGroup>
|
6
|
+
|
7
|
+
<ItemGroup>
|
8
|
+
<PackageReference Include="Semver" />
|
9
|
+
<PackageReference Include="System.Text.Json" />
|
10
|
+
</ItemGroup>
|
11
|
+
|
12
|
+
</Project>
|
@@ -0,0 +1,68 @@
|
|
1
|
+
using Semver;
|
2
|
+
|
3
|
+
namespace DotNetPackageCorrelation;
|
4
|
+
|
5
|
+
public class PackageMapper
|
6
|
+
{
|
7
|
+
public RuntimePackages RuntimePackages { get; }
|
8
|
+
|
9
|
+
private PackageMapper(RuntimePackages runtimePackages)
|
10
|
+
{
|
11
|
+
RuntimePackages = runtimePackages;
|
12
|
+
}
|
13
|
+
|
14
|
+
/// <summary>
|
15
|
+
/// Find the version of <paramref name="candidatePackageName"/> that shipped at the same time as
|
16
|
+
/// "<paramref name="packageName"/>/<paramref name="packageVersion"/>".
|
17
|
+
/// </summary>
|
18
|
+
public SemVersion? GetPackageVersionThatShippedWithOtherPackage(string packageName, SemVersion packageVersion, string candidatePackageName)
|
19
|
+
{
|
20
|
+
var runtimeVersion = GetRuntimeVersionFromPackage(packageName, packageVersion);
|
21
|
+
if (runtimeVersion is null)
|
22
|
+
{
|
23
|
+
// no runtime found that contains the package
|
24
|
+
return null;
|
25
|
+
}
|
26
|
+
|
27
|
+
var candidateRuntimeVersions = RuntimePackages.Runtimes.Keys
|
28
|
+
.Where(v => v.Major == runtimeVersion.Major)
|
29
|
+
.Where(v => v.ComparePrecedenceTo(runtimeVersion) <= 0)
|
30
|
+
.OrderBy(v => v, SemVerComparer.Instance)
|
31
|
+
.Reverse()
|
32
|
+
.ToArray();
|
33
|
+
foreach (var candidateRuntimeVersion in candidateRuntimeVersions)
|
34
|
+
{
|
35
|
+
if (!RuntimePackages.Runtimes.TryGetValue(candidateRuntimeVersion, out var packageSet))
|
36
|
+
{
|
37
|
+
continue;
|
38
|
+
}
|
39
|
+
|
40
|
+
if (packageSet.Packages.TryGetValue(candidatePackageName, out var foundPackageVersion))
|
41
|
+
{
|
42
|
+
return foundPackageVersion;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
return null;
|
47
|
+
}
|
48
|
+
|
49
|
+
private SemVersion? GetRuntimeVersionFromPackage(string packageName, SemVersion packageVersion)
|
50
|
+
{
|
51
|
+
// TODO: linear search is slow
|
52
|
+
foreach (var runtime in RuntimePackages.Runtimes)
|
53
|
+
{
|
54
|
+
if (runtime.Value.Packages.TryGetValue(packageName, out var foundPackageVersion) &&
|
55
|
+
foundPackageVersion == packageVersion)
|
56
|
+
{
|
57
|
+
return runtime.Key;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
return null;
|
62
|
+
}
|
63
|
+
|
64
|
+
public static PackageMapper Load(RuntimePackages runtimePackages)
|
65
|
+
{
|
66
|
+
return new PackageMapper(runtimePackages);
|
67
|
+
}
|
68
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
using System.Text.Json.Serialization;
|
2
|
+
|
3
|
+
using Semver;
|
4
|
+
|
5
|
+
namespace DotNetPackageCorrelation;
|
6
|
+
|
7
|
+
public record PackageSet
|
8
|
+
{
|
9
|
+
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
|
10
|
+
public SortedDictionary<string, SemVersion> Packages { get; init; } = new(StringComparer.OrdinalIgnoreCase);
|
11
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
using System.Collections.Immutable;
|
2
|
+
using System.Text.Json.Serialization;
|
3
|
+
|
4
|
+
namespace DotNetPackageCorrelation;
|
5
|
+
|
6
|
+
public record Release
|
7
|
+
{
|
8
|
+
[JsonPropertyName("sdk")]
|
9
|
+
public required Sdk Sdk { get; init; }
|
10
|
+
|
11
|
+
[JsonPropertyName("sdks")]
|
12
|
+
public ImmutableArray<Sdk>? Sdks { get; init; } = [];
|
13
|
+
}
|
14
|
+
|
15
|
+
public static class ReleaseExtensions
|
16
|
+
{
|
17
|
+
public static IEnumerable<Sdk> GetSdks(this Release release)
|
18
|
+
{
|
19
|
+
yield return release.Sdk;
|
20
|
+
foreach (var sdk in release.Sdks ?? [])
|
21
|
+
{
|
22
|
+
yield return sdk;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
using System.Text.Json.Serialization;
|
2
|
+
|
3
|
+
using Semver;
|
4
|
+
|
5
|
+
namespace DotNetPackageCorrelation;
|
6
|
+
|
7
|
+
public record RuntimePackages
|
8
|
+
{
|
9
|
+
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
|
10
|
+
public SortedDictionary<SemVersion, PackageSet> Runtimes { get; init; } = new(SemVerComparer.Instance);
|
11
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
using System.Text.Json.Serialization;
|
2
|
+
|
3
|
+
using Semver;
|
4
|
+
|
5
|
+
namespace DotNetPackageCorrelation;
|
6
|
+
|
7
|
+
public record Sdk
|
8
|
+
{
|
9
|
+
[JsonPropertyName("version")]
|
10
|
+
public required SemVersion? Version { get; init; }
|
11
|
+
[JsonPropertyName("runtime-version")]
|
12
|
+
public SemVersion? RuntimeVersion { get; init; }
|
13
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
using Semver;
|
2
|
+
|
3
|
+
namespace DotNetPackageCorrelation;
|
4
|
+
|
5
|
+
public class SemVerComparer : IComparer<SemVersion>
|
6
|
+
{
|
7
|
+
public static SemVerComparer Instance = new();
|
8
|
+
|
9
|
+
public int Compare(SemVersion? x, SemVersion? y)
|
10
|
+
{
|
11
|
+
ArgumentNullException.ThrowIfNull(x);
|
12
|
+
ArgumentNullException.ThrowIfNull(y);
|
13
|
+
|
14
|
+
return x.ComparePrecedenceTo(y);
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
using System.Diagnostics.CodeAnalysis;
|
2
|
+
using System.Text.Json;
|
3
|
+
using System.Text.Json.Serialization;
|
4
|
+
|
5
|
+
using Semver;
|
6
|
+
|
7
|
+
namespace DotNetPackageCorrelation;
|
8
|
+
|
9
|
+
public class SemVersionConverter : JsonConverter<SemVersion?>
|
10
|
+
{
|
11
|
+
public override SemVersion? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
12
|
+
{
|
13
|
+
var value = reader.GetString();
|
14
|
+
if (SemVersion.TryParse(value, out var result))
|
15
|
+
{
|
16
|
+
return result;
|
17
|
+
}
|
18
|
+
|
19
|
+
return null;
|
20
|
+
}
|
21
|
+
|
22
|
+
public override SemVersion ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
23
|
+
{
|
24
|
+
var value = Read(ref reader, typeToConvert, options);
|
25
|
+
if (value is null)
|
26
|
+
{
|
27
|
+
throw new JsonException($"Unable to read {nameof(SemVersion)} as property name.");
|
28
|
+
}
|
29
|
+
|
30
|
+
return value;
|
31
|
+
}
|
32
|
+
|
33
|
+
public override void Write(Utf8JsonWriter writer, SemVersion? value, JsonSerializerOptions options)
|
34
|
+
{
|
35
|
+
writer.WriteStringValue(value?.ToString());
|
36
|
+
}
|
37
|
+
|
38
|
+
public override void WriteAsPropertyName(Utf8JsonWriter writer, [DisallowNull] SemVersion value, JsonSerializerOptions options)
|
39
|
+
{
|
40
|
+
writer.WritePropertyName(value.ToString());
|
41
|
+
}
|
42
|
+
}
|
data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/DotNetPackageCorrelation.Cli.csproj
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
2
|
+
|
3
|
+
<PropertyGroup>
|
4
|
+
<TargetFramework>$(CommonTargetFramework)</TargetFramework>
|
5
|
+
<OutputType>Exe</OutputType>
|
6
|
+
</PropertyGroup>
|
7
|
+
|
8
|
+
<ItemGroup>
|
9
|
+
<PackageReference Include="System.CommandLine" />
|
10
|
+
</ItemGroup>
|
11
|
+
|
12
|
+
<ItemGroup>
|
13
|
+
<ProjectReference Include="..\DotNetPackageCorrelation\DotNetPackageCorrelation.csproj" />
|
14
|
+
</ItemGroup>
|
15
|
+
|
16
|
+
</Project>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
using System.CommandLine;
|
2
|
+
using System.Text.Json;
|
3
|
+
|
4
|
+
using DotNetPackageCorrelation;
|
5
|
+
|
6
|
+
namespace DotNetPackageCorrelation.Cli;
|
7
|
+
|
8
|
+
public class Program
|
9
|
+
{
|
10
|
+
public static async Task<int> Main(string[] args)
|
11
|
+
{
|
12
|
+
var coreLocationOption = new Option<DirectoryInfo>("--core-location", "The location of the .NET Core source code.") { IsRequired = true };
|
13
|
+
var outputOption = new Option<FileInfo>("--output", "The location to write the result.") { IsRequired = true };
|
14
|
+
var command = new Command("build")
|
15
|
+
{
|
16
|
+
coreLocationOption,
|
17
|
+
outputOption,
|
18
|
+
};
|
19
|
+
command.TreatUnmatchedTokensAsErrors = true;
|
20
|
+
command.SetHandler(async (coreLocationDirectory, output) =>
|
21
|
+
{
|
22
|
+
// the tool is expected to be given the path to the .NET Core repository, but the correlator only needs a specific subdirectory
|
23
|
+
var releaseNotesDirectory = new DirectoryInfo(Path.Combine(coreLocationDirectory.FullName, "release-notes"));
|
24
|
+
var correlator = new Correlator(releaseNotesDirectory);
|
25
|
+
var (sdkPackages, _warnings) = await correlator.RunAsync();
|
26
|
+
var json = JsonSerializer.Serialize(sdkPackages, Correlator.SerializerOptions);
|
27
|
+
await File.WriteAllTextAsync(output.FullName, json);
|
28
|
+
}, coreLocationOption, outputOption);
|
29
|
+
var exitCode = await command.InvokeAsync(args);
|
30
|
+
return exitCode;
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,99 @@
|
|
1
|
+
using Semver;
|
2
|
+
|
3
|
+
using Xunit;
|
4
|
+
|
5
|
+
namespace DotNetPackageCorrelation.Tests;
|
6
|
+
|
7
|
+
public class CorrelatorTests
|
8
|
+
{
|
9
|
+
[Fact]
|
10
|
+
public async Task FileHandling_AllFilesShapedAppropriately()
|
11
|
+
{
|
12
|
+
// the JSON and markdown are shaped as expected
|
13
|
+
// we're able to determine from `Runtime.Package/8.0.0` that the corresponding version of `Some.Package` is `1.2.3`
|
14
|
+
var (packageMapper, warnings) = await PackageMapperFromFilesAsync(
|
15
|
+
("8.0/releases.json", """
|
16
|
+
{
|
17
|
+
"releases": [
|
18
|
+
{
|
19
|
+
"sdk": {
|
20
|
+
"version": "8.0.100",
|
21
|
+
"runtime-version": "8.0.0"
|
22
|
+
}
|
23
|
+
}
|
24
|
+
]
|
25
|
+
}
|
26
|
+
"""),
|
27
|
+
("8.0/8.0.0/8.0.0.md", """
|
28
|
+
Package name | Version
|
29
|
+
:-- | :--
|
30
|
+
Runtime.Package | 8.0.0
|
31
|
+
Some.Package | 1.2.3
|
32
|
+
""")
|
33
|
+
);
|
34
|
+
Assert.Empty(warnings);
|
35
|
+
AssertPackageVersion(packageMapper, "Runtime.Package", "8.0.0", "Some.Package", "1.2.3");
|
36
|
+
}
|
37
|
+
|
38
|
+
[Theory]
|
39
|
+
[InlineData("Some.Package | 1.2.3", "Some.Package", "1.2.3")] // happy path
|
40
|
+
[InlineData("Some.Package.1.2.3", "Some.Package", "1.2.3")] // looks like a restore directory
|
41
|
+
[InlineData("Some.Package | 1.2 | 1.2.3.nupkg", "Some.Package", "1.2.3")] // extra columns from a bad filename split
|
42
|
+
[InlineData("Some.Package | 1.2.3.nupkg", "Some.Package", "1.2.3")] // version contains package extension
|
43
|
+
[InlineData("Some.Package | 1.2.3.symbols.nupkg", "Some.Package", "1.2.3")] // version contains symbols package extension
|
44
|
+
[InlineData("some.package.1.2.3.nupkg", "some.package", "1.2.3")] // first column is a filename, second column is missing
|
45
|
+
[InlineData("some.package.1.2.3.nupkg |", "some.package", "1.2.3")] // first column is a filename, second column is empty
|
46
|
+
public void PackagesParsedFromMarkdown(string markdownLine, string expectedPackageName, string expectedPackageVersion)
|
47
|
+
{
|
48
|
+
var markdownContent = $"""
|
49
|
+
Package name | Version
|
50
|
+
:-- | :--
|
51
|
+
{markdownLine}
|
52
|
+
""";
|
53
|
+
var warnings = new List<string>();
|
54
|
+
var packages = Correlator.GetPackagesFromMarkdown("test.md", markdownContent, warnings);
|
55
|
+
Assert.Empty(warnings);
|
56
|
+
var actualpackage = Assert.Single(packages);
|
57
|
+
Assert.Equal(expectedPackageName, actualpackage.Name);
|
58
|
+
Assert.Equal(expectedPackageVersion, actualpackage.Version.ToString());
|
59
|
+
}
|
60
|
+
|
61
|
+
private static void AssertPackageVersion(PackageMapper packageMapper, string runtimePackageName, string runtimePackageVersion, string candidatePackageName, string? expectedPackageVersion)
|
62
|
+
{
|
63
|
+
var actualPackageVersion = packageMapper.GetPackageVersionThatShippedWithOtherPackage(runtimePackageName, SemVersion.Parse(runtimePackageVersion), candidatePackageName);
|
64
|
+
if (expectedPackageVersion is null)
|
65
|
+
{
|
66
|
+
Assert.Null(actualPackageVersion);
|
67
|
+
}
|
68
|
+
else
|
69
|
+
{
|
70
|
+
Assert.NotNull(actualPackageVersion);
|
71
|
+
Assert.Equal(expectedPackageVersion, actualPackageVersion.ToString());
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
private static async Task<(PackageMapper PackageMapper, IEnumerable<string> Warnings)> PackageMapperFromFilesAsync(params (string Path, string Content)[] files)
|
76
|
+
{
|
77
|
+
var testDirectory = Path.Combine(Path.GetDirectoryName(typeof(CorrelatorTests).Assembly.Location)!, "test-data", Guid.NewGuid().ToString("D"));
|
78
|
+
Directory.CreateDirectory(testDirectory);
|
79
|
+
|
80
|
+
try
|
81
|
+
{
|
82
|
+
foreach (var (path, content) in files)
|
83
|
+
{
|
84
|
+
var fullPath = Path.Combine(testDirectory, path);
|
85
|
+
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!);
|
86
|
+
await File.WriteAllTextAsync(fullPath, content);
|
87
|
+
}
|
88
|
+
|
89
|
+
var correlator = new Correlator(new DirectoryInfo(testDirectory));
|
90
|
+
var (runtimePackages, warnings) = await correlator.RunAsync();
|
91
|
+
var packageMapper = PackageMapper.Load(runtimePackages);
|
92
|
+
return (packageMapper, warnings);
|
93
|
+
}
|
94
|
+
finally
|
95
|
+
{
|
96
|
+
Directory.Delete(testDirectory, recursive: true);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/DotNetPackageCorrelation.Test.csproj
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
2
|
+
|
3
|
+
<PropertyGroup>
|
4
|
+
<TargetFramework>$(CommonTargetFramework)</TargetFramework>
|
5
|
+
<OutputType>Exe</OutputType>
|
6
|
+
</PropertyGroup>
|
7
|
+
|
8
|
+
<ItemGroup>
|
9
|
+
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
10
|
+
<PackageReference Include="xunit" />
|
11
|
+
<PackageReference Include="xunit.runner.visualstudio" />
|
12
|
+
</ItemGroup>
|
13
|
+
|
14
|
+
<ItemGroup>
|
15
|
+
<ProjectReference Include="..\DotNetPackageCorrelation\DotNetPackageCorrelation.csproj" />
|
16
|
+
</ItemGroup>
|
17
|
+
|
18
|
+
</Project>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
using System.Runtime.CompilerServices;
|
2
|
+
|
3
|
+
using Semver;
|
4
|
+
|
5
|
+
using Xunit;
|
6
|
+
|
7
|
+
namespace DotNetPackageCorrelation.Tests;
|
8
|
+
|
9
|
+
public class EndToEndTests
|
10
|
+
{
|
11
|
+
[Fact]
|
12
|
+
public async Task IntegrationTest()
|
13
|
+
{
|
14
|
+
// arrange
|
15
|
+
var thisFileDirectory = Path.GetDirectoryName(GetThisFilePath())!;
|
16
|
+
var dotnetCoreDirectory = Path.Combine(thisFileDirectory, "..", "..", "dotnet-core");
|
17
|
+
var correlator = new Correlator(new DirectoryInfo(Path.Combine(dotnetCoreDirectory, "release-notes")));
|
18
|
+
|
19
|
+
// act
|
20
|
+
var (runtimePackages, _warnings) = await correlator.RunAsync();
|
21
|
+
var packageMapper = PackageMapper.Load(runtimePackages);
|
22
|
+
|
23
|
+
// assert
|
24
|
+
// Microsoft.NETCore.App.Ref/8.0.8 didn't ship with System.Text.Json, but the previous version 8.0.7 shipped at the same time as System.Text.Json/8.0.4
|
25
|
+
var systemTextJsonVersion = packageMapper.GetPackageVersionThatShippedWithOtherPackage("Microsoft.NETCore.App.Ref", SemVersion.Parse("8.0.8"), "System.Text.Json");
|
26
|
+
Assert.Equal("8.0.4", systemTextJsonVersion?.ToString());
|
27
|
+
}
|
28
|
+
|
29
|
+
private static string GetThisFilePath([CallerFilePath] string? path = null) => path ?? throw new ArgumentNullException(nameof(path));
|
30
|
+
}
|