Cmdlets/src/XpandPosh.Cmdlets/CloseGitHubIssue/Close-GithubIssue.cs
using System;
using System.Linq; using System.Management.Automation; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; using System.Threading; using System.Threading.Tasks; using Octokit; using XpandPosh.CmdLets; namespace XpandPosh.Cmdlets.CloseGitHubIssue{ [CmdletBinding(SupportsShouldProcess = true)] [Cmdlet(VerbsCommon.Close, "GithubIssue",SupportsShouldProcess = true)] [OutputType(typeof(Issue))] public class CloseGithubIssue : GithubCmdlet{ [Parameter(Mandatory = true)] public string Repository1{ get; set; } [Parameter] public string Message{ get; set; } ="Closing issue for age. Feel free to reopen it at any time.\r\n\r\n.Thank you for your contribution."; [Parameter] public int DaysUntilClose{ get; set; } = 60; protected override Task ProcessRecordAsync(){ var appClient = CreateClient(); var repository = appClient.Repository.GetAllForOrg(Organization).ToObservable() .Select(list => list.First(_ => _.Name == Repository1)); var filter = new RepositoryIssueRequest{ SortDirection = SortDirection.Ascending, SortProperty = IssueSort.Updated, State = ItemStateFilter.Open }; var context = SynchronizationContext.Current; var issuesToClose = repository.SelectMany(_ => appClient.Issue.GetAllForRepository(_.Id, filter)) .SelectMany(list => list) .ObserveOn(context) .Where(issue => { var needsClosing = NeedsClosing(issue, DaysUntilClose); WriteVerbose($"Issue {issue.Number} needclose={needsClosing}"); return needsClosing; }) .CombineLatest(repository, (issue, repo) => (issue, repo)); return issuesToClose .ObserveOn(context) .Do(_ => WriteVerbose($"Closing issue #{_.issue.Number}")) .SelectMany(_ => { var issues = CloseIssue(appClient, _).Select(issue => CommentIssue( appClient, _)).Concat(); return ShouldProcess("Close Issue") ? issues : Observable.Return(_.issue); }) .DefaultIfEmpty() .ObserveOn(context) .Do(WriteObject) .ToTask(); } private IObservable<Issue> CommentIssue( GitHubClient appClient, (Issue issue, Repository repo) _){ return Observable.Defer(() => appClient.Issue.Comment.Create(_.repo.Id, _.issue.Number, Message) .ToObservable()).Select(comment => _.issue); } private static IObservable<Issue> CloseIssue(GitHubClient appClient, (Issue issue, Repository repo) _){ var issueUpdate = _.issue.ToUpdate(); issueUpdate.State = ItemState.Closed; return appClient.Issue.Update(_.repo.Id, _.issue.Number, issueUpdate).ToObservable().Select(issue => issue); } private static bool NeedsClosing(Issue issue, int daysUntilClose){ var totalDays = DateTimeOffset.UtcNow.Subtract(issue.CreatedAt.DateTime).TotalDays; if (issue.UpdatedAt.HasValue){ totalDays = DateTimeOffset.UtcNow.Subtract(issue.UpdatedAt.Value.DateTime).TotalDays; } return totalDays - daysUntilClose > 0; } } } |