Cmdlets/src/XpandPosh.Cmdlets/CheckpointGithubIssue/Checkpoint-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 SmartFormat; using XpandPosh.CmdLets; namespace XpandPosh.Cmdlets.CheckpointGithubIssue{ [CmdletBinding(SupportsShouldProcess = true)] [Cmdlet(VerbsData.Checkpoint, "GitHubIssue",SupportsShouldProcess = true)] public class CheckpointGitHubIssue : GitHubCmdlet{ [Parameter(Mandatory = true)] public string Repository1{ get; set; } [Parameter(Mandatory = true)] public string Repository2{ get; set; } [Parameter(Mandatory = true)] public string Message{ get; set; } [Parameter] public string Branch{ get; set; } protected override Task ProcessRecordAsync(){ return LinkCommits() .HandleErrors(this,Repository1) .WriteObject(this) .ToTask(); } private IObservable<PSObject> LinkCommits( ){ var appClient = NewGitHubClient(); var synchronizationContext = SynchronizationContext.Current; var issueToNotify = appClient .LastMileStone(Organization, Repository1) .WriteVerboseObject(this,milestone => milestone.Title) .SelectMany(milestone => appClient .CommitIssues(Organization, Repository1, Repository2, milestone.Title,Branch) .SelectMany(tuple => { var issues = tuple.commitIssues .SelectMany(_ => _.issues.Select(issue => (_.commit, issue))).ToObservable() .WriteVerboseObject(this,_ => $"Commit ({_.commit.Sha}){_.commit.Commit.Message} links to {_.issue.Number}",synchronizationContext) .SelectMany(_ => appClient.Issue.Comment .GetAllForIssue(tuple.repoTuple.repo1.Id, _.issue.Number) .ToObservable() .ObserveOn(synchronizationContext) .Where(list => { WriteVerbose($"Searching {list.Count} comments in Issue {_.issue.Number} for {_.commit.Sha}"); var checkpoint = list.Any(comment => comment.Body.Contains(_.commit.Sha)); WriteVerbose($"Checkpoint {(!checkpoint ? " not " : null)}exists"); return !checkpoint; }) .Select(list => (repo1: tuple.repoTuple.repo1.Id, repo2: tuple.repoTuple.repo2.Id,_.commit, _.issue))); return issues; })) .Replay().RefCount() .WriteVerboseObject(this); return issueToNotify .GroupBy(_ => (_.issue, _.repo1)) .SelectMany(_ => { return _.TakeUntil(_.LastAsync()).ToArray() .Select(tuples => tuples.Select(valueTuple => valueTuple.commit).ToArray()) .Select(hubCommits => (key: _.Key, commits: hubCommits)); }) .ObserveOn(synchronizationContext) .SelectMany(_ => { var comment = GenerateComment(_); var issue = _.key.issue; var psObject = Observable.Return(new PSObject(new { IssueNumber = issue.Number, Milestone = issue.Milestone?.Title,issue.Title, Commits = string.Join(",", _.commits.Select(commit => commit.Commit.Message)), Comment = comment })); var text = $"Create comment for issue {_.key.issue.Number}"; WriteVerbose(text); if (ShouldProcess(text)){ return appClient.Issue.Comment.Create(_.key.repo1, _.key.issue.Number, comment) .ToObservable().Select(issueComment => psObject).Concat(); } return psObject; }) .DefaultIfEmpty(); } private string GenerateComment(((Issue issue, long repoId) key, GitHubCommit[] commits) _){ var objects = new object[] { new{ Options = this, Commits = string.Join(",", _.commits.Select(commit => $@"[{commit.Commit.Message}](https://github.com/{Organization}/{Repository2}/commit/{commit.Sha})")) } }; var comment = Smart.Format(Message, objects); return comment; } } } |