Add support for ignore version ranges (#5611)

* Add ignore support

* Update tool

* Generate valid yaml

* Add space

* Update version

* Fix project file
This commit is contained in:
Rich Lander 2020-11-16 14:09:07 -08:00 committed by GitHub
parent 05d6baa1d4
commit dba4f9ec40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 184 additions and 25 deletions

View file

@ -1,6 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Console;
if (args is { Length: 0 } || args[0] is not string path)
@ -31,48 +37,89 @@ WriteLine(topMatter);
open-pull-requests-limit: 5
*/
string regex = @"PackageReference.*Version=""[0-9]";
// will change this location in a subsequent update
string packagesJsonUrl = "https://gist.githubusercontent.com/richlander/b6e9d0a2550396813c8899dc8b20748d/raw/2cc3b59314b39ac27442453ce7a1419fd4305b6a/packages.json";
Dictionary<string, string[]> packageIgnore = await GetPackagesInfo(packagesJsonUrl);
string validPackageReference = @"PackageReference.*Version=""[0-9]";
string packageReference = @"PackageReference Include=""";
string targetFrameworkStart = "<TargetFramework>";
string targetFrameworkEnd = "</TargetFramework>";
string dotnetDir = $"{Path.AltDirectorySeparatorChar}.dotnet";
foreach (string file in Directory.EnumerateFiles(path,"*.*",SearchOption.AllDirectories))
foreach (string directory in Directory.EnumerateDirectories(path,"*.*",SearchOption.AllDirectories))
{
if (!IsProject(file))
if (directory.EndsWith(dotnetDir))
{
continue;
}
string filename = Path.GetFileName(file);
string? parentDir = Path.GetDirectoryName(file);
string relativeDir = parentDir?.Substring(path.Length).Replace(Path.DirectorySeparatorChar,Path.AltDirectorySeparatorChar) ?? Path.AltDirectorySeparatorChar.ToString();
if (relativeDir.StartsWith(dotnetDir))
foreach (string file in Directory.EnumerateFiles(directory))
{
continue;
}
bool match = false;
foreach (string content in File.ReadLines(file))
{
if (Regex.IsMatch(content, regex))
if (!IsProject(file))
{
match = true;
break;
continue;
}
}
if (!match)
{
continue;
}
string filename = Path.GetFileName(file);
string? parentDir = Path.GetDirectoryName(file);
string relativeDir = parentDir?.Substring(path.Length).Replace(Path.DirectorySeparatorChar,Path.AltDirectorySeparatorChar) ?? Path.AltDirectorySeparatorChar.ToString();
string? targetFramework = null;
bool match = false;
List<PackageIgnoreMapping> mappings = new();
foreach (string content in File.ReadLines(file))
{
if (targetFramework is null && TryGetTargetFramework(content, out targetFramework))
{
}
WriteLine(
if (Regex.IsMatch(content, validPackageReference))
{
match = true;
if (TryGetPackageName(content, out string? packageName) &&
packageIgnore.TryGetValue($"{packageName}_{targetFramework}", out string[]? ignore))
{
mappings.Add(new(packageName,ignore));
}
break;
}
}
if (!match)
{
continue;
}
WriteLine(
$@" - package-ecosystem: ""nuget""
directory: ""{relativeDir}"" #{filename}
schedule:
interval: ""weekly""
day: ""wednesday""
open-pull-requests-limit: 5");
if (mappings.Count == 0)
{
continue;
}
/* Format:
ignore:
- dependency-name: "Microsoft.AspNetCore.Mvc.NewtonsoftJson"
versions: ["5.*"]
*/
WriteLine(" ignore:");
foreach(PackageIgnoreMapping mapping in mappings)
{
WriteLine(
$@" - dependency-name: ""{mapping.PackageName}""
versions: {PrintArrayAsYaml(mapping.Ignore)}");
}
}
}
bool IsProject(string filename) => Path.GetExtension(filename) switch
@ -80,3 +127,96 @@ bool IsProject(string filename) => Path.GetExtension(filename) switch
".csproj" or ".fsproj" or ".vbproj" => true,
_ => false
};
bool TryGetTargetFramework(string content, [NotNullWhen(true)] out string? targetFramework)
{
targetFramework = null;
int start = content.IndexOf(targetFrameworkStart);
if (start == -1)
{
return false;
}
int end = content.IndexOf(targetFrameworkEnd);
if (end == -1 ||
end < start)
{
return false;
}
int startOfTFM = start + targetFrameworkStart.Length;
targetFramework = content.Substring(startOfTFM, end - startOfTFM);
return targetFramework.StartsWith("net");
}
bool TryGetPackageName(string content, [NotNullWhen(true)] out string? packageName)
{
packageName = null;
int start = content.IndexOf(packageReference);
if (start < 0)
{
return false;
}
int startOfPackageName = start + packageReference.Length;
int endOfPackageName = content.AsSpan(startOfPackageName).IndexOf('"');
if (endOfPackageName == 0)
{
return false;
}
packageName = content.Substring(startOfPackageName, endOfPackageName);
return true;
}
async Task<Dictionary<string, string[]>> GetPackagesInfo(string url)
{
HttpClient client = new();
PackageInfoSet? packages = await client.GetFromJsonAsync<PackageInfoSet>(packagesJsonUrl);
if (packages is null)
{
throw new IOException("Could not download packages information");
}
Dictionary<string, string[]> packageIgnore = new();
foreach (PackageInfo package in packages.Packages)
{
foreach(PackageTargetFrameworkIgnoreMapping mapping in package.Mapping)
{
string key = $"{package.Name}_{mapping.TargetFramework}";
packageIgnore.Add(key, mapping.Ignore);
}
}
return packageIgnore;
}
string PrintArrayAsYaml(string[] array)
{
StringBuilder buffer = new();
buffer.Append("[");
for (int i = 0; i < array.Length; i++)
{
buffer.Append($@"""{array[i]}""");
if (i + 1 < array.Length)
{
buffer.Append(", ");
}
}
buffer.Append("]");
return buffer.ToString();
}
record PackageInfoSet(PackageInfo[] Packages);
record PackageInfo(string Name, PackageTargetFrameworkIgnoreMapping[] Mapping);
record PackageTargetFrameworkIgnoreMapping(string TargetFramework, string[] Ignore);
record PackageIgnoreMapping(string PackageName, string[] Ignore);

View file

@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<Description>A simple .NET Core tool for generating Dependabot config for .NET.</Description>
<VersionPrefix>1.0.2</VersionPrefix>
<VersionPrefix>1.0.3</VersionPrefix>
<Authors>Richard Lander</Authors>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageLicenseExpression>MIT</PackageLicenseExpression>

View file

@ -0,0 +1,19 @@
{
"packages" :
[
{
"name" : "Microsoft.AspNetCore.Mvc.NewtonsoftJson",
"mapping" :
[
{
"targetFramework" : "netcoreapp3.0",
"ignore" : ["3.1.*", "5.*"]
},
{
"targetFramework" : "netcoreapp3.1",
"ignore" : ["5.*"]
}
]
}
]
}