public void Build(out IRepository repo, out IIssueTracker issueTracker) { var commits = new List <Commit>(); var tags = new List <Tag>(); var closedIssues = new List <Issue>(); repo = Substitute.For <IRepository>(); issueTracker = Substitute.For <IIssueTracker>(); commits.Add(CreateCommit(_initialCommitTime)); var currentDate = _initialCommitTime.AddDays(1); foreach (var release in _releases) { // Create a commit, which *fixes* all the closed issues in the release commits.Add(CreateCommit(currentDate)); // Create closed issues foreach (var issue in release.Item2) { issue.DateClosed = currentDate; closedIssues.Add(issue); } // Create commit which completes the release, and tag that commit currentDate = currentDate.AddDays(1); var commit = CreateCommit(currentDate); commits.Add(commit); tags.Add(CreateTag(commit, release.Item1)); currentDate = currentDate.AddDays(1); } foreach (var additionalIssue in _additionalIssues) { closedIssues.Add(new Issue(GetNextId()) { DateCreated = currentDate, Title = additionalIssue, IssueType = IssueType.Issue }); var commit = CreateCommit(currentDate); commits.Add(commit); } SubstituteCommitLog(repo, commits, tags); var filter = new IssueTrackerFilter { IncludeClosed = true }; var issuesTask = issueTracker.GetIssuesAsync(filter); var issues = issuesTask.Result; issues.Returns(c => closedIssues.Where(i => c.Arg <DateTimeOffset?>() == null || i.DateClosed > c.Arg <DateTimeOffset?>())); }
public async Task ReturnsIssuesUsingRest() { var issueTracker = new JiraIssueTracker("https://catelproject.atlassian.net/", "CTL", null); var issueFilter = new IssueTrackerFilter { IncludeClosed = true, Since = new DateTimeOffset(DateTime.Today.AddMonths(-1)) }; var issues = await issueTracker.GetIssuesAsync(issueFilter); var issuesList = issues.ToList(); issuesList.ShouldNotBeEmpty(); }
public async Task <IEnumerable <Issue> > GetIssuesAsync(IssueTrackerFilter filter) { var repositoryIssueRequest = PrepareFilter(filter); var forRepository = await _gitHubClient.Issue.GetAllForRepository(Organisation, Repository, repositoryIssueRequest); var readOnlyList = forRepository.Where(i => i.ClosedAt > filter.Since); return(readOnlyList.Select(i => new Issue("#" + i.Number.ToString(CultureInfo.InvariantCulture)) { DateClosed = i.ClosedAt, Url = i.HtmlUrl.ToString(), Title = i.Title, IssueType = i.PullRequest == null ? IssueType.Issue : IssueType.PullRequest, Labels = i.Labels.Select(l => l.Name).ToArray(), Contributors = i.PullRequest == null ? new Contributor[0] : new[] { new Contributor(GetUserName(_gitHubClient, i.User), i.User.Login, i.User.HtmlUrl) } })); }
private string PrepareFilter(IssueTrackerFilter filter, IEnumerable <Jira.IssueStatus> openedStatuses, IEnumerable <Jira.IssueStatus> closedStatuses, IEnumerable <Jira.IssueResolution> acceptedResolutions) { var finalFilter = string.Empty; if (!string.IsNullOrWhiteSpace(filter.Filter)) { finalFilter = filter.Filter; } if (filter.IncludeOpen && filter.IncludeClosed) { // no need to filter anything } else if (!filter.IncludeOpen && !filter.IncludeClosed) { throw new Exception("Cannot exclude both open and closed issues, nothing will be returned"); } else if (filter.IncludeOpen) { finalFilter = finalFilter.AddJiraFilter(string.Format("status in ({0})", string.Join(", ", openedStatuses.Select(x => string.Format("\"{0}\"", x))))); } else if (filter.IncludeClosed) { finalFilter = finalFilter.AddJiraFilter(string.Format("status in ({0})", string.Join(", ", closedStatuses.Select(x => string.Format("\"{0}\"", x))))); } if (filter.Since.HasValue) { finalFilter = finalFilter.AddJiraFilter(string.Format("resolutiondate >= '{0}'", filter.Since.Value.ToString("yyyy-MM-dd"))); } if (acceptedResolutions.Any()) { finalFilter = finalFilter.AddJiraFilter(string.Format("resolution in ({0})", string.Join(", ", acceptedResolutions.Select(x => string.Format("\"{0}\"", x))))); } finalFilter = finalFilter.AddJiraFilter(string.Format("project = {0}", _project)); return(finalFilter); }
private Octokit.RepositoryIssueRequest PrepareFilter(IssueTrackerFilter filter) { var repositoryIssueRequest = new Octokit.RepositoryIssueRequest { Filter = Octokit.IssueFilter.All, Since = filter.Since, }; if (filter.IncludeOpen && filter.IncludeClosed) { repositoryIssueRequest.State = Octokit.ItemState.All; } else if (filter.IncludeOpen) { repositoryIssueRequest.State = Octokit.ItemState.Open; } else if (filter.IncludeClosed) { repositoryIssueRequest.State = Octokit.ItemState.Closed; } return(repositoryIssueRequest); }
public static async Task <SemanticReleaseNotes> GenerateReleaseNotesAsync(ReleaseNotesGenerationParameters generationParameters, IRepository gitRepo, IIssueTracker issueTracker, SemanticReleaseNotes previousReleaseNotes, Categories categories, TaggedCommit tagToStartFrom, ReleaseInfo currentReleaseInfo) { var releases = ReleaseFinder.FindReleases(gitRepo, tagToStartFrom, currentReleaseInfo); var findIssuesSince = IssueStartDateBasedOnPreviousReleaseNotes(gitRepo, previousReleaseNotes) ?? tagToStartFrom.Commit.Author.When; var filter = new IssueTrackerFilter { Since = findIssuesSince, IncludeOpen = false }; var closedIssues = (await issueTracker.GetIssuesAsync(filter)).ToArray(); // As discussed here: https://github.com/GitTools/GitReleaseNotes/issues/85 var semanticReleases = new Dictionary <string, SemanticRelease>(); foreach (var issue in closedIssues) { // 1) Include all issues from the issue tracker that are assigned to this release foreach (var fixVersion in issue.FixVersions) { if (!fixVersion.IsReleased) { continue; } if (!semanticReleases.ContainsKey(fixVersion.Name)) { semanticReleases.Add(fixVersion.Name, new SemanticRelease(fixVersion.Name, fixVersion.ReleaseDate)); } var semanticRelease = semanticReleases[fixVersion.Name]; var releaseNoteItem = new ReleaseNoteItem(issue.Title, issue.Id, issue.Url, issue.Labels, issue.DateClosed, new Contributor[] { /*TODO: implement*/ }); semanticRelease.ReleaseNoteLines.Add(releaseNoteItem); } // 2) Get closed issues from the issue tracker that have no fixversion but are closed between the last release and this release if (issue.FixVersions.Count == 0) { foreach (var release in releases) { if (issue.DateClosed.HasValue && issue.DateClosed.Value > release.PreviousReleaseDate && (release.When == null || issue.DateClosed <= release.When)) { if (!semanticReleases.ContainsKey(release.Name)) { var beginningSha = release.FirstCommit != null?release.FirstCommit.Substring(0, 10) : null; var endSha = release.LastCommit != null?release.LastCommit.Substring(0, 10) : null; semanticReleases.Add(release.Name, new SemanticRelease(release.Name, release.When, new ReleaseDiffInfo { BeginningSha = beginningSha, EndSha = endSha, // TODO DiffUrlFormat = context.Repository.DiffUrlFormat })); } var semanticRelease = semanticReleases[release.Name]; var releaseNoteItem = new ReleaseNoteItem(issue.Title, issue.Id, issue.Url, issue.Labels, issue.DateClosed, issue.Contributors); semanticRelease.ReleaseNoteLines.Add(releaseNoteItem); } } } } // 3) Remove any duplicates foreach (var semanticRelease in semanticReleases.Values) { var handledIssues = new HashSet <string>(); for (var i = 0; i < semanticRelease.ReleaseNoteLines.Count; i++) { var releaseNoteLine = semanticRelease.ReleaseNoteLines[i] as ReleaseNoteItem; if (releaseNoteLine == null) { continue; } if (handledIssues.Contains(releaseNoteLine.IssueNumber)) { semanticRelease.ReleaseNoteLines.RemoveAt(i--); continue; } handledIssues.Add(releaseNoteLine.IssueNumber); } } var semanticReleaseNotes = new SemanticReleaseNotes(semanticReleases.Values, categories); var mergedReleaseNotes = semanticReleaseNotes.Merge(previousReleaseNotes); return(mergedReleaseNotes); }
public async Task <IEnumerable <Issue> > GetIssuesAsync(IssueTrackerFilter filter) { Log.DebugFormat("Connecting to Jira server '{0}'", _server); var jira = Atlassian.Jira.Jira.CreateRestClient(_server, _authenticationInfo.Username, _authenticationInfo.Password, new Jira.JiraRestClientSettings()); var jiraRestClient = jira.RestClient; Log.Debug("Retrieving statuses"); var statuses = (await jiraRestClient.GetIssueStatusesAsync(CancellationToken.None)).ToList(); var resolutions = (await jiraRestClient.GetIssueResolutionsAsync(CancellationToken.None)).ToList(); var openedStatuses = GetOpenedStatuses(statuses); var closedStatuses = GetClosedStatuses(statuses); var acceptedResolutions = GetAcceptedResolutions(resolutions); var finalFilter = PrepareFilter(filter, openedStatuses, closedStatuses, acceptedResolutions); var issues = new List <Issue>(); Log.DebugFormat("Searching for issues using filter '{0}'", filter); const int MaxIssues = 200; // TODO: Once the Atlassian.Sdk issue type contains all info, remove custom JiraIssue var retrievedIssues = jiraRestClient.GetIssues(finalFilter, 0, MaxIssues); //var retrievedIssues = await jiraRestClient.GetIssuesFromJqlAsync(finalFilter, MaxIssues, 0, CancellationToken.None); int lastRetrievedIssuesCount = retrievedIssues.Count; while (lastRetrievedIssuesCount % MaxIssues == 0) { var newlyRetrievedIssues = jiraRestClient.GetIssues(finalFilter, lastRetrievedIssuesCount, MaxIssues); //var newlyRetrievedIssues = await jiraRestClient.GetIssuesFromJqlAsync(finalFilter, MaxIssues, lastRetrievedIssuesCount, CancellationToken.None); if (newlyRetrievedIssues.Count == 0) { break; } retrievedIssues.AddRange(newlyRetrievedIssues); lastRetrievedIssuesCount = retrievedIssues.Count; } foreach (var issue in retrievedIssues) { var gitIssue = new Issue(issue.key) { IssueType = IssueType.Issue, Title = issue.summary, Description = issue.description, DateCreated = issue.created, Labels = issue.labels.ToArray() }; if (closedStatuses.Any(x => string.Equals(x.Id, issue.status))) { gitIssue.DateClosed = issue.resolutionDate; } foreach (var fixVersion in issue.fixVersions) { gitIssue.FixVersions.Add(new Version { Name = fixVersion.name, ReleaseDate = fixVersion.releaseDate, IsReleased = fixVersion.released }); } var uri = new Uri(new Uri(_server), string.Format("/browse/{0}", issue.key)); gitIssue.Url = uri.ToString(); issues.Add(gitIssue); } Log.DebugFormat("Found '{0}' issues using filter '{1}'", issues.Count, filter); return(issues.AsEnumerable()); }
public async Task<IEnumerable<Issue>> GetIssuesAsync(IssueTrackerFilter filter) { Log.DebugFormat("Connecting to Jira server '{0}'", _server); var jira = Atlassian.Jira.Jira.CreateRestClient(_server, _authenticationInfo.Username, _authenticationInfo.Password, new Jira.JiraRestClientSettings()); var jiraRestClient = jira.RestClient; Log.Debug("Retrieving statuses"); var statuses = (await jiraRestClient.GetIssueStatusesAsync(CancellationToken.None)).ToList(); var resolutions = (await jiraRestClient.GetIssueResolutionsAsync(CancellationToken.None)).ToList(); var openedStatuses = GetOpenedStatuses(statuses); var closedStatuses = GetClosedStatuses(statuses); var acceptedResolutions = GetAcceptedResolutions(resolutions); var finalFilter = PrepareFilter(filter, openedStatuses, closedStatuses, acceptedResolutions); var issues = new List<Issue>(); Log.DebugFormat("Searching for issues using filter '{0}'", filter); const int MaxIssues = 200; // TODO: Once the Atlassian.Sdk issue type contains all info, remove custom JiraIssue var retrievedIssues = jiraRestClient.GetIssues(finalFilter, 0, MaxIssues); //var retrievedIssues = await jiraRestClient.GetIssuesFromJqlAsync(finalFilter, MaxIssues, 0, CancellationToken.None); int lastRetrievedIssuesCount = retrievedIssues.Count; while (lastRetrievedIssuesCount % MaxIssues == 0) { var newlyRetrievedIssues = jiraRestClient.GetIssues(finalFilter, lastRetrievedIssuesCount, MaxIssues); //var newlyRetrievedIssues = await jiraRestClient.GetIssuesFromJqlAsync(finalFilter, MaxIssues, lastRetrievedIssuesCount, CancellationToken.None); if (newlyRetrievedIssues.Count == 0) { break; } retrievedIssues.AddRange(newlyRetrievedIssues); lastRetrievedIssuesCount = retrievedIssues.Count; } foreach (var issue in retrievedIssues) { var gitIssue = new Issue(issue.key) { IssueType = IssueType.Issue, Title = issue.summary, Description = issue.description, DateCreated = issue.created, Labels = issue.labels.ToArray() }; if (closedStatuses.Any(x => string.Equals(x.Id, issue.status))) { gitIssue.DateClosed = issue.resolutionDate; } foreach (var fixVersion in issue.fixVersions) { gitIssue.FixVersions.Add(new Version { Name = fixVersion.name, ReleaseDate = fixVersion.releaseDate, IsReleased = fixVersion.released }); } var uri = new Uri(new Uri(_server), string.Format("/browse/{0}", issue.key)); gitIssue.Url = uri.ToString(); issues.Add(gitIssue); } Log.DebugFormat("Found '{0}' issues using filter '{1}'", issues.Count, filter); return issues.AsEnumerable(); }
private string PrepareFilter(IssueTrackerFilter filter, IEnumerable<Jira.IssueStatus> openedStatuses, IEnumerable<Jira.IssueStatus> closedStatuses, IEnumerable<Jira.IssueResolution> acceptedResolutions) { var finalFilter = string.Empty; if (!string.IsNullOrWhiteSpace(filter.Filter)) { finalFilter = filter.Filter; } if (filter.IncludeOpen && filter.IncludeClosed) { // no need to filter anything } else if (!filter.IncludeOpen && !filter.IncludeClosed) { throw new Exception("Cannot exclude both open and closed issues, nothing will be returned"); } else if (filter.IncludeOpen) { finalFilter = finalFilter.AddJiraFilter(string.Format("status in ({0})", string.Join(", ", openedStatuses.Select(x => string.Format("\"{0}\"", x))))); } else if (filter.IncludeClosed) { finalFilter = finalFilter.AddJiraFilter(string.Format("status in ({0})", string.Join(", ", closedStatuses.Select(x => string.Format("\"{0}\"", x))))); } if (filter.Since.HasValue) { finalFilter = finalFilter.AddJiraFilter(string.Format("resolutiondate >= '{0}'", filter.Since.Value.ToString("yyyy-MM-dd"))); } if (acceptedResolutions.Any()) { finalFilter = finalFilter.AddJiraFilter(string.Format("resolution in ({0})", string.Join(", ", acceptedResolutions.Select(x => string.Format("\"{0}\"", x))))); } finalFilter = finalFilter.AddJiraFilter(string.Format("project = {0}", _project)); return finalFilter; }