diff --git a/.github/renovate.json b/.github/renovate.json index 1ede6e0..f538101 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,4 +1,4 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ "github>nils-a/renovate-config" ] - } \ No newline at end of file + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ "github>nils-org/renovate-config" ] +} diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7c84dc4..2ded347 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -40,12 +40,12 @@ jobs: #WYAM_DEPLOY_REMOTE: ${{ github.event.repository.html_url }} steps: - - name: Checkout the repository - uses: actions/checkout@v3.1.0 + - name: Checkout the repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Fetch all tags and branches run: git fetch --prune --unshallow - name: Setup .NET - uses: actions/setup-dotnet@v3.0.3 + uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 with: dotnet-version: | 2.1.818 @@ -54,18 +54,18 @@ jobs: 6.0.x 7.0.x - name: Cache Tools - uses: actions/cache@v3.0.11 + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 with: path: tools key: ${{ runner.os }}-tools-${{ hashFiles('recipe.cake') }} - name: Build project - uses: cake-build/cake-action@v1.4.1 + uses: cake-build/cake-action@a6eb054329257c9e70a6c6bf01747ad6e1d9d52b # v1.4.1 with: script-path: recipe.cake target: CI - cake-version: 1.3.0 + cake-version: tool-manifest - name: Upload Issues - uses: actions/upload-artifact@v3.1.1 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: if-no-files-found: warn name: ${{ matrix.os }} Issues @@ -73,7 +73,7 @@ jobs: BuildArtifacts/report.html BuildArtifacts/**/coverlet/*.xml - name: Upload Packages - uses: actions/upload-artifact@v3.1.1 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 if: runner.os == 'Windows' with: if-no-files-found: warn diff --git a/global.json b/global.json index cb5eb57..2b5fcb7 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.100", + "version": "7.0.403", "rollForward": "latestFeature" } } diff --git a/recipe.cake b/recipe.cake index c36779a..48cdb63 100644 --- a/recipe.cake +++ b/recipe.cake @@ -1,4 +1,4 @@ -#load nuget:?package=Cake.Recipe&version=3.0.1 +#load nuget:?package=Cake.Recipe&version=3.1.1 var standardNotificationMessage = "Version {0} of {1} has just been released, it will be available here https://www.nuget.org/packages/{1}, once package indexing is complete."; diff --git a/src/GitHubMilestoneCleaner/Commands/AutoCleanupCommand.cs b/src/GitHubMilestoneCleaner/Commands/AutoCleanupCommand.cs index 8db9b4c..3df8b4f 100644 --- a/src/GitHubMilestoneCleaner/Commands/AutoCleanupCommand.cs +++ b/src/GitHubMilestoneCleaner/Commands/AutoCleanupCommand.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -113,16 +114,41 @@ public override async Task ExecuteAsync(CommandContext context, Settings se return 0; } - foreach (var issue in toRemove) + async Task DoRemove(Action? callback = null) { - var group = grouped.First(g => g.MainIssue.Id == issue.Id || g.SubIssues.Any(i => i.Id == issue.Id)); - var comment = issue == group.MainIssue ? settings.TopIssueComment : settings.SubIssueComment; - if (!string.IsNullOrEmpty(comment)) + foreach (var issue in toRemove) { - comment = string.Format(comment, group.MainIssue.HtmlUrl); + var group = grouped.First(g => g.MainIssue.Id == issue.Id || g.SubIssues.Any(i => i.Id == issue.Id)); + var comment = issue == group.MainIssue ? settings.TopIssueComment : settings.SubIssueComment; + if (!string.IsNullOrEmpty(comment)) + { + comment = string.Format(comment, group.MainIssue.HtmlUrl); + } + + await adapter.RemoveMilestone(repo, issue, comment); + callback?.Invoke(); } + } + + if (settings.NonInteractive) + { + await DoRemove(); + } + else + { + await AnsiConsole.Progress() + .StartAsync(async ctx => + { + var inc = 100d / toRemove.Count; + var task = ctx.AddTask($"Cleaning {toRemove.Count} issues"); + await DoRemove(() => + { + task.Increment(inc); + }); - await adapter.RemoveMilestone(repo, issue, comment); + var rest = 100 - task.Percentage; + task.Increment(rest); + }); } return 0; diff --git a/src/GitHubMilestoneCleaner/Engines/IssueGroupEngine.cs b/src/GitHubMilestoneCleaner/Engines/IssueGroupEngine.cs index 810460d..b27bbb9 100644 --- a/src/GitHubMilestoneCleaner/Engines/IssueGroupEngine.cs +++ b/src/GitHubMilestoneCleaner/Engines/IssueGroupEngine.cs @@ -8,17 +8,27 @@ namespace GitHubMilestoneCleaner.Engines; public class IssueGroupEngine { private readonly Regex _versionMatcher = - new Regex( - @"(0|[1-9]\d*)(\.(0|[1-9]\d*))+(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?"); + new( + @"\s*(from|to) v?(0|[1-9]\d*)(\.(0|[1-9]\d*))+(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?"); + private readonly Regex _digestMatcher = new(@"\s*digest to [0-9a-fA-F]+$"); + public IEnumerable GroupIssues(IEnumerable issues) { - + var matchers = new[] + { + _versionMatcher, + _digestMatcher + }; + return issues .Select(x => new { Issue = x, - VersionAgnosticName = _versionMatcher.Replace(x.Title, string.Empty) + VersionAgnosticName = (matchers + .FirstOrDefault(m => m.IsMatch(x.Title))? + .Replace(x.Title, string.Empty) ?? x.Title) + .TrimEnd(), }) .GroupBy(x => x.VersionAgnosticName) .Select(x => diff --git a/src/GitHubMilestoneCleaner/Extension/GitHubClientExtensions.cs b/src/GitHubMilestoneCleaner/Extension/GitHubClientExtensions.cs index 4d72623..9622b93 100644 --- a/src/GitHubMilestoneCleaner/Extension/GitHubClientExtensions.cs +++ b/src/GitHubMilestoneCleaner/Extension/GitHubClientExtensions.cs @@ -31,7 +31,7 @@ public static class GitHubClientExtensions return TimeSpan.FromSeconds(secondsToWait); }, - async (ex, _, _, ctx) => + (ex, _, _, ctx) => { var cancellationTokenSource = (CancellationTokenSource)ctx[CancellationTokenSourceKey]; if (ex is Octokit.NotFoundException) @@ -39,6 +39,8 @@ public static class GitHubClientExtensions AnsiConsole.MarkupLine($"[red]{ex.GetType().Name}: {ex.Message}[/]"); cancellationTokenSource.Cancel(); } + + return Task.CompletedTask; }); public static async Task WithRetry( diff --git a/src/GitHubMilestoneCleaner/GitHubMilestoneCleaner.csproj b/src/GitHubMilestoneCleaner/GitHubMilestoneCleaner.csproj index a827ac7..fc34009 100644 --- a/src/GitHubMilestoneCleaner/GitHubMilestoneCleaner.csproj +++ b/src/GitHubMilestoneCleaner/GitHubMilestoneCleaner.csproj @@ -38,10 +38,10 @@ - - - - - + + + + +