dependabot-nuget 0.322.0 → 0.322.1
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/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +10 -23
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +9 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +15 -232
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +1 -154
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/AzurePackageDetailFinder.cs +30 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/DetailedPullRequestBodyGenerator.cs +237 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/GitHubPackageDetailFinder.cs +101 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/GitLabPackageDetailFinder.cs +107 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/HttpFetcher.cs +32 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/IHttpFetcher.cs +30 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/IPackageDetailFinder.cs +47 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/IPullRequestBodyGenerator.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/SimplePullRequestBodyGenerator.cs +15 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestTextGenerator.cs +7 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +3 -525
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/CreateSecurityUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/GroupUpdateAllVersionsHandler.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshGroupUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshSecurityUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshVersionUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/FileWriterWorker.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/XmlFileWriter.cs +10 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +1 -856
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -200
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +6 -556
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +9 -73
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Clone/CloneWorkerTests.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/DependencySolver/MSBuildDependencySolverTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +1 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +3 -62
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +13 -563
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +20 -267
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/EndToEndTests.cs +131 -131
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +0 -203
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestBodyGenerator/DetailedPullRequestBodyGeneratorTests.cs +871 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestBodyGenerator/IPackageDetailFinderTests.cs +28 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestBodyGenerator/TestHttpFetcher.cs +23 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestTextTests.cs +3 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +6 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/CreateSecurityUpdatePullRequestHandlerTests.cs +6 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/GroupUpdateAllVersionsHandlerTests.cs +18 -18
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshGroupUpdatePullRequestHandlerTests.cs +15 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshSecurityUpdatePullRequestHandlerTests.cs +21 -21
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshVersionUpdatePullRequestHandlerTests.cs +15 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/UpdateHandlersTestsBase.cs +1 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/FileWriterWorkerTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/XmlFileWriterTests.cs +85 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackageReferenceUpdaterTests.cs +1 -159
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +10 -660
- metadata +16 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunResult.cs +0 -13
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestMessageTests.cs +0 -296
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +0 -3592
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatePermittedAndMessageTests.cs +0 -457
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +0 -378
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterHelperTests.cs +0 -175
@@ -0,0 +1,30 @@
|
|
1
|
+
using NuGet.Versioning;
|
2
|
+
|
3
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
4
|
+
|
5
|
+
internal class AzurePackageDetailFinder : IPackageDetailFinder
|
6
|
+
{
|
7
|
+
public string GetCompareUrlPath(string? oldTag, string? newTag)
|
8
|
+
{
|
9
|
+
// azure devops doesn't support direct tag listing so both parameters are likely to be null, but just in case, this is the correct url format
|
10
|
+
if (oldTag is not null && newTag is not null)
|
11
|
+
{
|
12
|
+
return $"branchCompare?baseVersion=GT{oldTag}&targetVersion=GT{newTag}";
|
13
|
+
}
|
14
|
+
|
15
|
+
if (newTag is not null)
|
16
|
+
{
|
17
|
+
return $"commits?itemVersion=GT{newTag}";
|
18
|
+
}
|
19
|
+
|
20
|
+
return "commits";
|
21
|
+
}
|
22
|
+
|
23
|
+
public Task<Dictionary<NuGetVersion, (string TagName, string? Details)>> GetReleaseDataForVersionsAsync(string repoName, NuGetVersion oldVersion, NuGetVersion newVersion)
|
24
|
+
{
|
25
|
+
// azure devops doesn't support direct tag listing
|
26
|
+
return Task.FromResult(new Dictionary<NuGetVersion, (string TagName, string? Details)>());
|
27
|
+
}
|
28
|
+
|
29
|
+
public string GetReleasesUrlPath() => "tags";
|
30
|
+
}
|
@@ -0,0 +1,237 @@
|
|
1
|
+
using System.Collections.Immutable;
|
2
|
+
using System.Text;
|
3
|
+
using System.Text.RegularExpressions;
|
4
|
+
|
5
|
+
using NuGet.Versioning;
|
6
|
+
|
7
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
8
|
+
using NuGetUpdater.Core.Updater;
|
9
|
+
|
10
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
11
|
+
|
12
|
+
internal class DetailedPullRequestBodyGenerator : IPullRequestBodyGenerator, IDisposable
|
13
|
+
{
|
14
|
+
private readonly IHttpFetcher _httpFetcher;
|
15
|
+
|
16
|
+
public const string TruncatedMessage = "...\n\n_Description has been truncated_";
|
17
|
+
|
18
|
+
public DetailedPullRequestBodyGenerator(IHttpFetcher httpFetcher)
|
19
|
+
{
|
20
|
+
_httpFetcher = httpFetcher;
|
21
|
+
}
|
22
|
+
|
23
|
+
public void Dispose()
|
24
|
+
{
|
25
|
+
_httpFetcher.Dispose();
|
26
|
+
}
|
27
|
+
|
28
|
+
public async Task<string> GeneratePullRequestBodyTextAsync(Job job, ImmutableArray<UpdateOperationBase> updateOperationsPerformed, ImmutableArray<ReportedDependency> updatedDependencies)
|
29
|
+
{
|
30
|
+
var sb = new StringBuilder();
|
31
|
+
var dedupedUpdateOperations = updateOperationsPerformed
|
32
|
+
.DistinctBy(u => $"{u.DependencyName}/{u.OldVersion}/{u.NewVersion}", StringComparer.OrdinalIgnoreCase)
|
33
|
+
.OrderBy(u => u.DependencyName, StringComparer.OrdinalIgnoreCase)
|
34
|
+
.ThenBy(u => u.OldVersion, NullableNuGetVersionComparer.Instance)
|
35
|
+
.ThenBy(u => u.NewVersion)
|
36
|
+
.ToImmutableArray();
|
37
|
+
foreach (var updateOperation in dedupedUpdateOperations)
|
38
|
+
{
|
39
|
+
if (sb.Length > 0)
|
40
|
+
{
|
41
|
+
// ensure a blank line between entries
|
42
|
+
sb.AppendLine();
|
43
|
+
}
|
44
|
+
|
45
|
+
var reportText = $"{updateOperation.GetReport(includeFileNames: false)}.";
|
46
|
+
var updatedDependency = updatedDependencies
|
47
|
+
.Where(d => d.Name.Equals(updateOperation.DependencyName, StringComparison.OrdinalIgnoreCase))
|
48
|
+
.Where(d => NuGetVersion.TryParse(d.Version, out var version) && version == updateOperation.NewVersion)
|
49
|
+
.FirstOrDefault();
|
50
|
+
var sourceUrl = (updatedDependency?.Requirements ?? [])
|
51
|
+
.Select(r => r.Source?.SourceUrl)
|
52
|
+
.FirstOrDefault(u => u is not null);
|
53
|
+
if (sourceUrl is null)
|
54
|
+
{
|
55
|
+
// no source url, just append the report text
|
56
|
+
sb.AppendLine(reportText);
|
57
|
+
}
|
58
|
+
else
|
59
|
+
{
|
60
|
+
// build detailed report
|
61
|
+
var packageNameIndex = reportText.IndexOf(updateOperation.DependencyName, StringComparison.OrdinalIgnoreCase);
|
62
|
+
if (packageNameIndex >= 0)
|
63
|
+
{
|
64
|
+
// link the package name
|
65
|
+
sb.AppendLine($"{reportText[..packageNameIndex]}[{updateOperation.DependencyName}]({sourceUrl}){reportText[(packageNameIndex + updateOperation.DependencyName.Length)..]}");
|
66
|
+
}
|
67
|
+
else
|
68
|
+
{
|
69
|
+
sb.AppendLine(reportText);
|
70
|
+
}
|
71
|
+
|
72
|
+
// more details
|
73
|
+
if (Uri.TryCreate(sourceUrl, UriKind.Absolute, out var uri))
|
74
|
+
{
|
75
|
+
IPackageDetailFinder? packageDetailFinder = uri.Host.ToLowerInvariant() switch
|
76
|
+
{
|
77
|
+
"dev.azure.com" => new AzurePackageDetailFinder(),
|
78
|
+
"github.com" => new GitHubPackageDetailFinder(_httpFetcher),
|
79
|
+
"gitlab.com" => new GitLabPackageDetailFinder(_httpFetcher),
|
80
|
+
var host when host.EndsWith(".visualstudio.com") => new AzurePackageDetailFinder(),
|
81
|
+
_ => null,
|
82
|
+
};
|
83
|
+
|
84
|
+
if (packageDetailFinder is not null &&
|
85
|
+
updateOperation.OldVersion is not null)
|
86
|
+
{
|
87
|
+
var repoName = uri.LocalPath.TrimStart('/');
|
88
|
+
var versionsAndDetails = await packageDetailFinder.GetReleaseDataForVersionsAsync(repoName, updateOperation.OldVersion, updateOperation.NewVersion);
|
89
|
+
var ordered = versionsAndDetails
|
90
|
+
.Where(kv => kv.Key != updateOperation.OldVersion)
|
91
|
+
.OrderByDescending(kv => kv.Key)
|
92
|
+
.ToList();
|
93
|
+
|
94
|
+
sb.AppendLine();
|
95
|
+
var detailsLineTemplate = IsHtmlSupported(job.Source.Provider)
|
96
|
+
? "<details>\n<summary>{0}</summary>"
|
97
|
+
: "# {0}";
|
98
|
+
sb.AppendLine(string.Format(detailsLineTemplate, "Release notes"));
|
99
|
+
|
100
|
+
var releasesUrlPath = packageDetailFinder.GetReleasesUrlPath();
|
101
|
+
if (releasesUrlPath is not null)
|
102
|
+
{
|
103
|
+
sb.AppendLine();
|
104
|
+
sb.AppendLine($"_Sourced from [{updateOperation.DependencyName}'s releases]({sourceUrl}/{releasesUrlPath})._");
|
105
|
+
}
|
106
|
+
|
107
|
+
foreach (var (version, (tagName, body)) in ordered)
|
108
|
+
{
|
109
|
+
sb.AppendLine();
|
110
|
+
sb.AppendLine($"## {version}");
|
111
|
+
if (body is not null)
|
112
|
+
{
|
113
|
+
var truncatedBody = TruncateLineCount(body);
|
114
|
+
sb.AppendLine();
|
115
|
+
sb.AppendLine(truncatedBody);
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
if (ordered.Count == 0)
|
120
|
+
{
|
121
|
+
sb.AppendLine();
|
122
|
+
sb.AppendLine("No release notes found for this version range.");
|
123
|
+
}
|
124
|
+
|
125
|
+
string? oldTag = null;
|
126
|
+
if (versionsAndDetails.TryGetValue(updateOperation.OldVersion, out var oldVersionDetails))
|
127
|
+
{
|
128
|
+
oldTag = oldVersionDetails.TagName;
|
129
|
+
}
|
130
|
+
|
131
|
+
string? newTag = null;
|
132
|
+
if (versionsAndDetails.TryGetValue(updateOperation.NewVersion, out var newVersionDetails))
|
133
|
+
{
|
134
|
+
newTag = newVersionDetails.TagName;
|
135
|
+
}
|
136
|
+
|
137
|
+
var compareUrlPath = packageDetailFinder.GetCompareUrlPath(oldTag, newTag);
|
138
|
+
sb.AppendLine();
|
139
|
+
sb.AppendLine($"Commits viewable in [compare view]({sourceUrl}/{compareUrlPath}).");
|
140
|
+
if (IsHtmlSupported(job.Source.Provider))
|
141
|
+
{
|
142
|
+
sb.AppendLine("</details>");
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
var prBody = sb.ToString().Replace("\r", "").TrimEnd();
|
150
|
+
var scrubbedBody = ScrubLinksAndMentions(prBody);
|
151
|
+
var truncatedPrBody = TruncateCharacterCount(scrubbedBody, GetMaxPrLength(job.Source.Provider));
|
152
|
+
return truncatedPrBody;
|
153
|
+
}
|
154
|
+
|
155
|
+
private static bool IsHtmlSupported(string sourceProvider)
|
156
|
+
{
|
157
|
+
return sourceProvider switch
|
158
|
+
{
|
159
|
+
"azure" or
|
160
|
+
"bitbucket" or
|
161
|
+
"codecommit" => false,
|
162
|
+
_ => true,
|
163
|
+
};
|
164
|
+
}
|
165
|
+
|
166
|
+
private static string TruncateLineCount(string text, int maxLines = 50)
|
167
|
+
{
|
168
|
+
var lines = text.Replace("\r", "").Split('\n');
|
169
|
+
if (lines.Length <= maxLines)
|
170
|
+
{
|
171
|
+
return text;
|
172
|
+
}
|
173
|
+
|
174
|
+
var truncatedText = string.Join("\n", lines.Take(maxLines)) + "\n ... (truncated)";
|
175
|
+
return truncatedText;
|
176
|
+
}
|
177
|
+
|
178
|
+
internal static int? GetMaxPrLength(string sourceProvider)
|
179
|
+
{
|
180
|
+
// values from, e.g., https://github.com/dependabot/dependabot-core/blob/5109e3e63925469ca0d6e7fa9449470d22c1847b/common/lib/dependabot/pull_request_creator/github.rb#L20
|
181
|
+
return sourceProvider switch
|
182
|
+
{
|
183
|
+
"azure" => 3999,
|
184
|
+
"bitbucket" => 262143,
|
185
|
+
"codecommit" => 10239,
|
186
|
+
"github" => 65535,
|
187
|
+
_ => null, // default case, no specific limit
|
188
|
+
};
|
189
|
+
}
|
190
|
+
|
191
|
+
private static string TruncateCharacterCount(string text, int? maxLength)
|
192
|
+
{
|
193
|
+
if (maxLength is null || text.Length <= maxLength)
|
194
|
+
{
|
195
|
+
return text;
|
196
|
+
}
|
197
|
+
|
198
|
+
var adjustedMaxLength = maxLength.Value - TruncatedMessage.Length;
|
199
|
+
var truncatedText = text[..adjustedMaxLength] + TruncatedMessage;
|
200
|
+
return truncatedText;
|
201
|
+
}
|
202
|
+
|
203
|
+
private static string ScrubLinksAndMentions(string text)
|
204
|
+
{
|
205
|
+
var mentionPattern = new Regex(@"(?<AtSymbol>@)(?<Name>[a-z0-9]+(-[a-z0-9]+)*)", RegexOptions.IgnoreCase);
|
206
|
+
var scrubbedOfMentions = mentionPattern.Replace(text, match => $"@\u200B{match.Groups["Name"].Value}");
|
207
|
+
|
208
|
+
var issuePattern = new Regex(@"(?<NumberSign>#)(?<Number>\d+)", RegexOptions.IgnoreCase);
|
209
|
+
var scrubbedOfIssues = issuePattern.Replace(scrubbedOfMentions, match => $"#\u200B{match.Groups["Number"].Value}");
|
210
|
+
return scrubbedOfIssues;
|
211
|
+
}
|
212
|
+
|
213
|
+
private class NullableNuGetVersionComparer : IComparer<NuGetVersion?>
|
214
|
+
{
|
215
|
+
public static readonly NullableNuGetVersionComparer Instance = new();
|
216
|
+
|
217
|
+
public int Compare(NuGetVersion? x, NuGetVersion? y)
|
218
|
+
{
|
219
|
+
if (x is null && y is null)
|
220
|
+
{
|
221
|
+
return 0;
|
222
|
+
}
|
223
|
+
|
224
|
+
if (x is null)
|
225
|
+
{
|
226
|
+
return -1;
|
227
|
+
}
|
228
|
+
|
229
|
+
if (y is null)
|
230
|
+
{
|
231
|
+
return 1;
|
232
|
+
}
|
233
|
+
|
234
|
+
return x.CompareTo(y);
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
@@ -0,0 +1,101 @@
|
|
1
|
+
using System.Text.Json;
|
2
|
+
|
3
|
+
using NuGet.Versioning;
|
4
|
+
|
5
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
6
|
+
|
7
|
+
internal class GitHubPackageDetailFinder : IPackageDetailFinder
|
8
|
+
{
|
9
|
+
private readonly IHttpFetcher _httpFetcher;
|
10
|
+
|
11
|
+
public GitHubPackageDetailFinder(IHttpFetcher httpFetcher)
|
12
|
+
{
|
13
|
+
_httpFetcher = httpFetcher;
|
14
|
+
}
|
15
|
+
|
16
|
+
public string GetCompareUrlPath(string? oldTag, string? newTag)
|
17
|
+
{
|
18
|
+
if (oldTag is not null && newTag is not null)
|
19
|
+
{
|
20
|
+
return $"compare/{oldTag}...{newTag}";
|
21
|
+
}
|
22
|
+
|
23
|
+
if (newTag is not null)
|
24
|
+
{
|
25
|
+
return $"commits/{newTag}";
|
26
|
+
}
|
27
|
+
|
28
|
+
return "commits";
|
29
|
+
}
|
30
|
+
|
31
|
+
public async Task<Dictionary<NuGetVersion, (string TagName, string? Details)>> GetReleaseDataForVersionsAsync(string repoName, NuGetVersion oldVersion, NuGetVersion newVersion)
|
32
|
+
{
|
33
|
+
var result = new Dictionary<NuGetVersion, (string TagName, string? Details)>();
|
34
|
+
var url = $"https://api.github.com/repos/{repoName}/releases?per_page=100";
|
35
|
+
var jsonOption = await _httpFetcher.GetJsonElementAsync(url);
|
36
|
+
if (jsonOption is null)
|
37
|
+
{
|
38
|
+
return result;
|
39
|
+
}
|
40
|
+
|
41
|
+
var json = jsonOption.Value;
|
42
|
+
if (json.ValueKind != JsonValueKind.Array)
|
43
|
+
{
|
44
|
+
return result;
|
45
|
+
}
|
46
|
+
|
47
|
+
if (json.GetArrayLength() == 0)
|
48
|
+
{
|
49
|
+
return result;
|
50
|
+
}
|
51
|
+
|
52
|
+
foreach (var releaseObject in json.EnumerateArray())
|
53
|
+
{
|
54
|
+
if (releaseObject.ValueKind != JsonValueKind.Object)
|
55
|
+
{
|
56
|
+
continue;
|
57
|
+
}
|
58
|
+
|
59
|
+
// get release name
|
60
|
+
if (!releaseObject.TryGetProperty("name", out var releasenameElement) ||
|
61
|
+
releasenameElement.ValueKind != JsonValueKind.String)
|
62
|
+
{
|
63
|
+
continue;
|
64
|
+
}
|
65
|
+
|
66
|
+
var releaseName = releasenameElement.GetString()!;
|
67
|
+
|
68
|
+
// get tag name
|
69
|
+
if (!releaseObject.TryGetProperty("tag_name", out var tagNameElement) ||
|
70
|
+
tagNameElement.ValueKind != JsonValueKind.String)
|
71
|
+
{
|
72
|
+
continue;
|
73
|
+
}
|
74
|
+
|
75
|
+
var tagName = tagNameElement.GetString()!;
|
76
|
+
|
77
|
+
// find matching version
|
78
|
+
var correspondingVersion = IPackageDetailFinder.GetVersionFromNames(releaseName, tagName);
|
79
|
+
if (correspondingVersion is null)
|
80
|
+
{
|
81
|
+
continue;
|
82
|
+
}
|
83
|
+
|
84
|
+
if (correspondingVersion >= oldVersion && correspondingVersion <= newVersion)
|
85
|
+
{
|
86
|
+
if (!releaseObject.TryGetProperty("body", out var bodyElement) ||
|
87
|
+
bodyElement.ValueKind != JsonValueKind.String)
|
88
|
+
{
|
89
|
+
continue;
|
90
|
+
}
|
91
|
+
|
92
|
+
var body = bodyElement.GetString()!;
|
93
|
+
result[correspondingVersion] = (tagName, body);
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
return result;
|
98
|
+
}
|
99
|
+
|
100
|
+
public string GetReleasesUrlPath() => "releases";
|
101
|
+
}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
using System.Text.Json;
|
2
|
+
|
3
|
+
using NuGet.Versioning;
|
4
|
+
|
5
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
6
|
+
|
7
|
+
internal class GitLabPackageDetailFinder : IPackageDetailFinder
|
8
|
+
{
|
9
|
+
private readonly IHttpFetcher _httpFetcher;
|
10
|
+
|
11
|
+
public GitLabPackageDetailFinder(IHttpFetcher httpFetcher)
|
12
|
+
{
|
13
|
+
_httpFetcher = httpFetcher;
|
14
|
+
}
|
15
|
+
|
16
|
+
public string GetCompareUrlPath(string? oldTag, string? newTag)
|
17
|
+
{
|
18
|
+
if (oldTag is not null && newTag is not null)
|
19
|
+
{
|
20
|
+
return $"-/compare/{oldTag}...{newTag}";
|
21
|
+
}
|
22
|
+
|
23
|
+
if (newTag is not null)
|
24
|
+
{
|
25
|
+
return $"-/commits/{newTag}";
|
26
|
+
}
|
27
|
+
|
28
|
+
return "-/commits";
|
29
|
+
}
|
30
|
+
|
31
|
+
public async Task<Dictionary<NuGetVersion, (string TagName, string? Details)>> GetReleaseDataForVersionsAsync(string repoName, NuGetVersion oldVersion, NuGetVersion newVersion)
|
32
|
+
{
|
33
|
+
var result = new Dictionary<NuGetVersion, (string TagName, string? Details)>();
|
34
|
+
var url = $"https://gitlab.com/api/v4/projects/{Uri.EscapeDataString(repoName)}/repository/tags";
|
35
|
+
var jsonOption = await _httpFetcher.GetJsonElementAsync(url);
|
36
|
+
if (jsonOption is null)
|
37
|
+
{
|
38
|
+
return result;
|
39
|
+
}
|
40
|
+
|
41
|
+
var json = jsonOption.Value;
|
42
|
+
if (json.ValueKind != JsonValueKind.Array)
|
43
|
+
{
|
44
|
+
return result;
|
45
|
+
}
|
46
|
+
|
47
|
+
if (json.GetArrayLength() == 0)
|
48
|
+
{
|
49
|
+
return result;
|
50
|
+
}
|
51
|
+
|
52
|
+
foreach (var responseObject in json.EnumerateArray())
|
53
|
+
{
|
54
|
+
if (responseObject.ValueKind != JsonValueKind.Object)
|
55
|
+
{
|
56
|
+
continue;
|
57
|
+
}
|
58
|
+
|
59
|
+
// get release name
|
60
|
+
if (!responseObject.TryGetProperty("name", out var releaseNameElement) ||
|
61
|
+
releaseNameElement.ValueKind != JsonValueKind.String)
|
62
|
+
{
|
63
|
+
continue;
|
64
|
+
}
|
65
|
+
|
66
|
+
var releaseName = releaseNameElement.GetString()!;
|
67
|
+
|
68
|
+
// get release info
|
69
|
+
string? tagName = null;
|
70
|
+
string? description = null;
|
71
|
+
if (responseObject.TryGetProperty("release", out var releaseObject) &&
|
72
|
+
releaseObject.ValueKind == JsonValueKind.Object)
|
73
|
+
{
|
74
|
+
if (releaseObject.TryGetProperty("tag_name", out var tagNameElement) &&
|
75
|
+
tagNameElement.ValueKind == JsonValueKind.String)
|
76
|
+
{
|
77
|
+
tagName = tagNameElement.GetString()!;
|
78
|
+
}
|
79
|
+
|
80
|
+
if (releaseObject.TryGetProperty("description", out var descriptionElement) &&
|
81
|
+
descriptionElement.ValueKind == JsonValueKind.String)
|
82
|
+
{
|
83
|
+
description = descriptionElement.GetString();
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
// find matching version
|
88
|
+
var correspondingVersion = IPackageDetailFinder.GetVersionFromNames(releaseName, tagName);
|
89
|
+
if (correspondingVersion is null)
|
90
|
+
{
|
91
|
+
continue;
|
92
|
+
}
|
93
|
+
|
94
|
+
var resultTag = tagName ?? releaseName;
|
95
|
+
if (resultTag is not null &&
|
96
|
+
correspondingVersion >= oldVersion &&
|
97
|
+
correspondingVersion <= newVersion)
|
98
|
+
{
|
99
|
+
result[correspondingVersion] = (resultTag, description);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
return result;
|
104
|
+
}
|
105
|
+
|
106
|
+
public string GetReleasesUrlPath() => "-/releases";
|
107
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
using System.Net.Http.Headers;
|
2
|
+
|
3
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
4
|
+
|
5
|
+
internal class HttpFetcher : IHttpFetcher
|
6
|
+
{
|
7
|
+
private readonly HttpClient _httpClient;
|
8
|
+
|
9
|
+
public HttpFetcher()
|
10
|
+
{
|
11
|
+
_httpClient = new HttpClient();
|
12
|
+
}
|
13
|
+
|
14
|
+
public void Dispose()
|
15
|
+
{
|
16
|
+
_httpClient.Dispose();
|
17
|
+
}
|
18
|
+
|
19
|
+
public async Task<string?> GetStringAsync(string url)
|
20
|
+
{
|
21
|
+
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
22
|
+
request.Headers.UserAgent.Add(new ProductInfoHeaderValue("dependabot-core", null));
|
23
|
+
var response = await _httpClient.SendAsync(request);
|
24
|
+
if (!response.IsSuccessStatusCode)
|
25
|
+
{
|
26
|
+
return null;
|
27
|
+
}
|
28
|
+
|
29
|
+
var result = await response.Content.ReadAsStringAsync();
|
30
|
+
return result;
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
using System.Text.Json;
|
2
|
+
|
3
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
4
|
+
|
5
|
+
internal interface IHttpFetcher : IDisposable
|
6
|
+
{
|
7
|
+
Task<string?> GetStringAsync(string url);
|
8
|
+
}
|
9
|
+
|
10
|
+
internal static class IHttpFetcherExtensions
|
11
|
+
{
|
12
|
+
public static async Task<JsonElement?> GetJsonElementAsync(this IHttpFetcher fetcher, string url)
|
13
|
+
{
|
14
|
+
var jsonString = await fetcher.GetStringAsync(url);
|
15
|
+
if (jsonString is null)
|
16
|
+
{
|
17
|
+
return null;
|
18
|
+
}
|
19
|
+
|
20
|
+
try
|
21
|
+
{
|
22
|
+
var json = JsonSerializer.Deserialize<JsonElement>(jsonString);
|
23
|
+
return json;
|
24
|
+
}
|
25
|
+
catch (JsonException)
|
26
|
+
{
|
27
|
+
return null;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/IPackageDetailFinder.cs
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
using NuGet.Versioning;
|
2
|
+
|
3
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
4
|
+
|
5
|
+
internal interface IPackageDetailFinder
|
6
|
+
{
|
7
|
+
string GetReleasesUrlPath();
|
8
|
+
string GetCompareUrlPath(string? oldTag, string? newTag);
|
9
|
+
Task<Dictionary<NuGetVersion, (string TagName, string? Details)>> GetReleaseDataForVersionsAsync(string repoName, NuGetVersion oldVersion, NuGetVersion newVersion);
|
10
|
+
|
11
|
+
internal static NuGetVersion? GetVersionFromNames(string? releaseName, string? tagName)
|
12
|
+
{
|
13
|
+
var prefixesToTrim = new[]
|
14
|
+
{
|
15
|
+
"version-",
|
16
|
+
"version.",
|
17
|
+
"version ",
|
18
|
+
"version",
|
19
|
+
"v-",
|
20
|
+
"v.",
|
21
|
+
"v ",
|
22
|
+
"v",
|
23
|
+
};
|
24
|
+
foreach (var candidateName in new[] { releaseName, tagName }.Where(n => n is not null).Cast<string>())
|
25
|
+
{
|
26
|
+
foreach (var prefix in prefixesToTrim)
|
27
|
+
{
|
28
|
+
if (candidateName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
29
|
+
{
|
30
|
+
var trimmedCandidateName = candidateName[prefix.Length..];
|
31
|
+
if (NuGetVersion.TryParse(trimmedCandidateName, out var versionFromTrimmed))
|
32
|
+
{
|
33
|
+
return versionFromTrimmed;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
// no prefix match, try the whole string
|
39
|
+
if (NuGetVersion.TryParse(candidateName, out var versionFromWhole))
|
40
|
+
{
|
41
|
+
return versionFromWhole;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
return null;
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
using System.Collections.Immutable;
|
2
|
+
|
3
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
4
|
+
using NuGetUpdater.Core.Updater;
|
5
|
+
|
6
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
7
|
+
|
8
|
+
public interface IPullRequestBodyGenerator
|
9
|
+
{
|
10
|
+
public Task<string> GeneratePullRequestBodyTextAsync(Job job, ImmutableArray<UpdateOperationBase> updateOperationsPerformed, ImmutableArray<ReportedDependency> updatedDependencies);
|
11
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
using System.Collections.Immutable;
|
2
|
+
|
3
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
4
|
+
using NuGetUpdater.Core.Updater;
|
5
|
+
|
6
|
+
namespace NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
7
|
+
|
8
|
+
internal class SimplePullRequestBodyGenerator : IPullRequestBodyGenerator
|
9
|
+
{
|
10
|
+
public Task<string> GeneratePullRequestBodyTextAsync(Job job, ImmutableArray<UpdateOperationBase> updateOperationsPerformed, ImmutableArray<ReportedDependency> updatedDependencies)
|
11
|
+
{
|
12
|
+
var prBody = UpdateOperationBase.GenerateUpdateOperationReport(updateOperationsPerformed, includeFileNames: false);
|
13
|
+
return Task.FromResult(prBody);
|
14
|
+
}
|
15
|
+
}
|
@@ -3,6 +3,7 @@ using System.Text;
|
|
3
3
|
using System.Text.RegularExpressions;
|
4
4
|
|
5
5
|
using NuGetUpdater.Core.Run.ApiModel;
|
6
|
+
using NuGetUpdater.Core.Run.PullRequestBodyGenerator;
|
6
7
|
using NuGetUpdater.Core.Updater;
|
7
8
|
|
8
9
|
using DependencySet = (string Name, (NuGet.Versioning.NuGetVersion? OldVersion, NuGet.Versioning.NuGetVersion NewVersion)[] Versions);
|
@@ -124,9 +125,12 @@ public class PullRequestTextGenerator
|
|
124
125
|
return dependencySets;
|
125
126
|
}
|
126
127
|
|
127
|
-
public static string
|
128
|
+
public static async Task<string> GetPullRequestBodyAsync(Job job, ImmutableArray<UpdateOperationBase> updateOperationsPerformed, ImmutableArray<ReportedDependency> updatedDependencies, ExperimentsManager experimentsManager)
|
128
129
|
{
|
129
|
-
var
|
130
|
-
|
130
|
+
var bodyGenerator = experimentsManager.GenerateSimplePrBody
|
131
|
+
? (IPullRequestBodyGenerator)new SimplePullRequestBodyGenerator()
|
132
|
+
: new DetailedPullRequestBodyGenerator(new HttpFetcher());
|
133
|
+
var prBody = await bodyGenerator.GeneratePullRequestBodyTextAsync(job, updateOperationsPerformed, updatedDependencies);
|
134
|
+
return prBody;
|
131
135
|
}
|
132
136
|
}
|