Exemplo n.º 1
0
 public BitBucketIssueTracker(IRepository gitRepository, BitBucketApi bitBucketApi, ILog log, GitReleaseNotesArguments arguments)
 {
     this.gitRepository = gitRepository;
     this.bitBucketApi  = bitBucketApi;
     this.log           = log;
     this.arguments     = arguments;
 }
Exemplo n.º 2
0
 public GitHubIssueTracker(IRepository gitRepository, Func <IGitHubClient> gitHubClientFactory, ILog log, GitReleaseNotesArguments arguments)
 {
     this.gitRepository       = gitRepository;
     this.log                 = log;
     this.arguments           = arguments;
     this.gitHubClientFactory = gitHubClientFactory;
 }
Exemplo n.º 3
0
        public Dictionary <ReleaseInfo, List <string> > GetIssueNumbers(GitReleaseNotesArguments arguments, Dictionary <ReleaseInfo, List <Commit> > releases, Regex issueRegex)
        {
            var result = new Dictionary <ReleaseInfo, List <string> >();

            foreach (var release in releases)
            {
                var issueNumbersToScan = new List <string>();
                foreach (var commit in release.Value)
                {
                    var matches = issueRegex.Matches(commit.Message).Cast <Match>();

                    foreach (var match in matches)
                    {
                        var issueNumber = match.Groups["issueNumber"].Value;
                        if (arguments.Verbose)
                        {
                            Log.WriteLine("Found issues {0} in commit {1}", issueNumber, commit.Sha);
                        }

                        issueNumbersToScan.Add(issueNumber);
                    }
                }

                result.Add(release.Key, issueNumbersToScan);
            }

            return(result);
        }
        public SemanticReleaseNotes ScanCommitMessagesForReleaseNotes(GitReleaseNotesArguments arguments, Commit[] commitsToScan)
        {
            var repoParts = arguments.Repo.Split('/');
            var organisation = repoParts[0];
            var repository = repoParts[1];

            var issueNumbersToScan = _issueNumberExtractor.GetIssueNumbers(arguments, commitsToScan, @"#(?<issueNumber>\d+)");

            var since = commitsToScan.Select(c=>c.Author.When).Min();
            var potentialIssues = _gitHubClient.Issue.GetForRepository(organisation, repository, new RepositoryIssueRequest
            {
                Filter = IssueFilter.All,
                Since = since,
                State = ItemState.Closed
            }).Result;

            var closedMentionedIssues = potentialIssues
                .Where(i => issueNumbersToScan.Contains(i.Number.ToString(CultureInfo.InvariantCulture)))
                .ToArray();

            return new SemanticReleaseNotes(closedMentionedIssues.Select(i=>
            {
                var labels = i.Labels == null ? new string[0] : i.Labels.Select(l=>l.Name).ToArray();
                return new ReleaseNoteItem(i.Title, string.Format("#{0}", i.Number), i.HtmlUrl, labels);
            }));
        }
 public GitHubIssueTracker(IRepository gitRepository, Func<IGitHubClient> gitHubClientFactory, ILog log, GitReleaseNotesArguments arguments)
 {
     this.gitRepository = gitRepository;
     this.log = log;
     this.arguments = arguments;
     this.gitHubClientFactory = gitHubClientFactory;
 }
        public Dictionary<ReleaseInfo, List<string>> GetIssueNumbers(GitReleaseNotesArguments arguments, Dictionary<ReleaseInfo, List<Commit>> releases, Regex issueRegex)
        {
            var result = new Dictionary<ReleaseInfo, List<string>>();

            foreach (var release in releases)
            {
                var issueNumbersToScan = new List<string>();
                foreach (var commit in release.Value)
                {
                    var matches = issueRegex.Matches(commit.Message).Cast<Match>();

                    foreach (var match in matches)
                    {
                        var issueNumber = match.Groups["issueNumber"].Value;
                        if (arguments.Verbose)
                            Console.WriteLine("Found issues {0} in commit {1}", issueNumber, commit.Sha);
                        issueNumbersToScan.Add(issueNumber);
                    }
                }

                result.Add(release.Key, issueNumbersToScan);
            }

            return result;
        }
Exemplo n.º 7
0
        public IEnumerable<OnlineIssue> GetClosedIssues(GitReleaseNotesArguments arguments, DateTimeOffset? since)
        {
            string jql;
            if (since.HasValue)
            {
                var sinceFormatted = since.Value.ToString("yyyy-MM-d HH:mm");
                jql = string.Format("{0} AND updated > '{1}'", arguments.Jql, sinceFormatted).Replace("\"", "\\\"");
            }
            else
            {
                jql = arguments.Jql;
            }

            var baseUrl = new Uri(arguments.JiraServer, UriKind.Absolute);
            var searchUri = new Uri(baseUrl, "/rest/api/latest/search");
            var httpRequest = WebRequest.CreateHttp(searchUri);
            var usernameAndPass = string.Format("{0}:{1}", arguments.Username, arguments.Password);
            var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(usernameAndPass));
            httpRequest.Headers.Add("Authorization", string.Format("Basic {0}", token));
            httpRequest.Method = "POST";
            httpRequest.ContentType = "application/json";

            using (var streamWriter = new StreamWriter(httpRequest.GetRequestStream()))
            {
                string json = "{\"jql\": \"" + jql + "\",\"startAt\": 0, \"maxResults\": 100, \"fields\": [\"summary\",\"issuetype\"]}";
                streamWriter.Write(json);
                streamWriter.Flush();
                streamWriter.Close();
            }

            var response = (HttpWebResponse)httpRequest.GetResponse();
            if ((int)response.StatusCode == 400)
            {
                throw new Exception("Jql query error, please review your Jql");
            }

            if (response.StatusCode != HttpStatusCode.OK)
                throw new Exception("Failed to query Jira: " + response.StatusDescription);

            using (var responseStream = response.GetResponseStream())
            using (var responseReader = new StreamReader(responseStream))
            {
                var responseObject = Json.Decode(responseReader.ReadToEnd());
                foreach (var issue in responseObject.issues)
                {
                    string summary = issue.fields.summary;
                    string id = issue.key;
                    string issueType = issue.fields.issuetype.name;

                    yield return new OnlineIssue
                    {
                        Id = id,
                        Title = summary,
                        IssueType = IssueType.Issue,
                        HtmlUrl = new Uri(baseUrl, string.Format("browse/{0}", id))
                    };
                }
            }
        }
Exemplo n.º 8
0
        private static void GenerateClassicalRequest(GitReleaseNotesArguments arguments, RestRequest request, string MethodLocation)
        {
            var usernameAndPass = string.Format("{0}:{1}", arguments.Username, arguments.Password);
            var token           = Convert.ToBase64String(Encoding.UTF8.GetBytes(usernameAndPass));

            request.Resource = string.Format(MethodLocation);
            request.AddHeader("Authorization", string.Format("Basic {0}", token));
        }
Exemplo n.º 9
0
 public IEnumerable<OnlineIssue> GetClosedIssues(GitReleaseNotesArguments arguments, DateTimeOffset? since)
 {
     var authenticationCookies = ConnectToYouTrack(arguments.Username, arguments.Password, arguments.YouTrackServer);
     return IssuesClosedSinceDate(
         authenticationCookies,
         arguments.YouTrackFilter,
         arguments.YouTrackServer,
         arguments.ProjectId,
         since);
 }
 public GitHubIssueTrackerTests()
 {
     _gitHubClient = Substitute.For<IGitHubClient>();
     _sut = new GitHubIssueTracker(new IssueNumberExtractor(), _gitHubClient);
     _gitReleaseNotesArguments = new GitReleaseNotesArguments
     {
         Repo = "Org/Repo",
         Token = "213"
     };
     _issuesClient = Substitute.For<IIssuesClient>();
 }
Exemplo n.º 11
0
        public IEnumerable <OnlineIssue> GetClosedIssues(GitReleaseNotesArguments arguments, DateTimeOffset?since)
        {
            var authenticationCookies = ConnectToYouTrack(arguments.Username, arguments.Password, arguments.YouTrackServer);

            return(IssuesClosedSinceDate(
                       authenticationCookies,
                       arguments.YouTrackFilter,
                       arguments.YouTrackServer,
                       arguments.ProjectId,
                       since));
        }
        public static Context ToContext(this GitReleaseNotesArguments arguments)
        {
            var context = new Context();

            context.WorkingDirectory = arguments.WorkingDirectory;
            context.Verbose          = arguments.Verbose;
            context.IssueTracker     = arguments.IssueTracker;
            context.OutputFile       = arguments.OutputFile;
            context.ProjectId        = arguments.ProjectId;
            context.Categories       = arguments.Categories;
            context.Version          = arguments.Version;
            context.AllTags          = arguments.AllTags;
            context.AllLabels        = arguments.AllLabels;

            var authentication = context.Authentication;

            authentication.Username = arguments.Username;
            authentication.Password = arguments.Password;

            var repository = context.Repository;

            repository.Url      = arguments.RepoUrl;
            repository.Branch   = arguments.RepoBranch;
            repository.Username = arguments.RepoUsername;
            repository.Password = arguments.RepoPassword;

            var gitHub = context.GitHub;

            gitHub.Repo  = arguments.Repo;
            gitHub.Token = arguments.Token;

            var jira = context.Jira;

            jira.JiraServer = arguments.JiraServer;
            jira.Jql        = arguments.Jql;

            var youTrack = context.YouTrack;

            youTrack.YouTrackServer = arguments.YouTrackServer;
            youTrack.YouTrackFilter = arguments.YouTrackFilter;

            var bitBucket = context.BitBucket;

            bitBucket.Repo              = arguments.Repo;
            bitBucket.ConsumerKey       = arguments.ConsumerKey;
            bitBucket.ConsumerSecretKey = arguments.ConsumerSecretKey;

            return(context);
        }
Exemplo n.º 13
0
        public static bool VerifyArguments(GitReleaseNotesArguments arguments)
        {
            if (string.IsNullOrEmpty(arguments.OutputFile))
            {
                Log.WriteLine("WARN: No Output file specified (*.md) [/OutputFile ...]");
            }

            if (!string.IsNullOrEmpty(arguments.OutputFile) && !arguments.OutputFile.EndsWith(".md"))
            {
                Log.WriteLine("WARN: Output file should have a .md extension [/OutputFile ...]");
                arguments.OutputFile = null;
            }

            return(true);
        }
Exemplo n.º 14
0
        public static bool VerifyArguments(GitReleaseNotesArguments arguments)
        {
            if (string.IsNullOrEmpty(arguments.OutputFile))
            {
                Log.WriteLine("WARN: No Output file specified (*.md) [/OutputFile ...]");
            }

            if (!string.IsNullOrEmpty(arguments.OutputFile) && !arguments.OutputFile.EndsWith(".md"))
            {
                Log.WriteLine("WARN: Output file should have a .md extension [/OutputFile ...]");
                arguments.OutputFile = null;
            }

            return true;
        }
        public void ApproveSimpleTests()
        {
            var arguments = new GitReleaseNotesArguments
            {
                OutputFile = "ReleaseFile.md"
            };
            var releaseNotes = new SemanticReleaseNotes(new[]
            {

                new ReleaseNoteItem("Issue 1", "#1", new Uri("http://github.com/org/repo/issues/1"), new string[0])
            });

            _sut.WriteReleaseNotes(arguments, releaseNotes);

            Approvals.Verify(GetContent());
        }
        public void AdditionalCategoriesCanBeSpecifiedOnCommandLine()
        {
            var arguments = new GitReleaseNotesArguments
            {
                Categories = "internal refactoring",
                OutputFile = "ReleaseFile.md"
            };
            var releaseNotes = new SemanticReleaseNotes(new[]
            {
                new ReleaseNoteItem("Issue 1", "#1", new Uri("http://github.com/org/repo/issues/1"), new[]{"internal refactoring"})
            });

            _sut.WriteReleaseNotes(arguments, releaseNotes);

            Approvals.Verify(GetContent());
        }
        public GitHubIssueTrackerTests()
        {
            _log = Substitute.For<ILog>();
            _gitHubClient = Substitute.For<IGitHubClient>();
            _issuesClient = Substitute.For<IIssuesClient>();
            _gitHubClient.Issue.Returns(_issuesClient);
            _arguments = new GitReleaseNotesArguments
            {
                Repo = "Org/Repo",
                Token = "213"
            };
            _repo = Substitute.For<IRepository>();
            _repo.Network.Returns(new NetworkEx());

            _sut = new GitHubIssueTracker(_repo, () => _gitHubClient, _log, _arguments);
        }
        public GitHubIssueTrackerTests()
        {
            log          = Substitute.For <ILog>();
            gitHubClient = Substitute.For <IGitHubClient>();
            issuesClient = Substitute.For <IIssuesClient>();
            gitHubClient.Issue.Returns(issuesClient);
            arguments = new GitReleaseNotesArguments
            {
                Repo  = "Org/Repo",
                Token = "213"
            };
            repo = Substitute.For <IRepository>();
            repo.Network.Returns(new NetworkEx());

            sut = new GitHubIssueTracker(repo, () => gitHubClient, log, arguments);
        }
        public void AbsolutePathIsWrittenToRepositoryRoot()
        {
            var arguments = new GitReleaseNotesArguments
            {
                Categories = "internal refactoring",
                OutputFile = "c:\\AnotherDir\\ReleaseFile.md"
            };
            var releaseNotes = new SemanticReleaseNotes(new[]
            {
                new ReleaseNoteItem("Issue 1", "#1", new Uri("http://github.com/org/repo/issues/1"), new string[0])
            });

            _sut.WriteReleaseNotes(arguments, releaseNotes);

            var fileName = _fileSystem.ReceivedCalls().Single(c => c.GetMethodInfo().Name == "WriteAllText").GetArguments()[0];
            Assert.Equal("c:\\AnotherDir\\ReleaseFile.md", fileName);
        }
Exemplo n.º 20
0
        public IEnumerable <OnlineIssue> GetClosedIssues(GitReleaseNotesArguments arguments, DateTimeOffset?since, string accountName, string repoSlug, bool oauth)
        {
            var baseUrl    = new Uri(ApiUrl, UriKind.Absolute);
            var restClient = new RestClient(baseUrl.AbsoluteUri);
            var issuesUrl  = string.Format("repositories/{0}/{1}/issues/", accountName, repoSlug);
            var request    = new RestRequest(issuesUrl);

            if (oauth)
            {
                GenerateOauthRequest(arguments, baseUrl, issuesUrl, request);
            }
            else
            {
                GenerateClassicalRequest(arguments, request, issuesUrl);
            }
            var response = restClient.Execute(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("Failed to query BitBucket: " + response.StatusDescription);
            }
            dynamic responseObject = SimpleJson.DeserializeObject(response.Content);
            var     issues         = new List <OnlineIssue>();

            foreach (var issue in responseObject.issues)
            {
                DateTimeOffset lastChange = DateTimeOffset.Parse(issue.utc_last_updated);
                if (issue.status != IssueClosed || lastChange <= since)
                {
                    continue;
                }
                string summary = issue.content;
                string id      = issue.local_id.ToString();
                string title   = issue.title;
                issues.Add(new OnlineIssue
                {
                    Id         = id,
                    Title      = summary,
                    IssueType  = IssueType.Issue,
                    HtmlUrl    = new Uri(baseUrl, string.Format("/repositories/{0}/{1}/issue/{2}/{3}", accountName, repoSlug, id, title)),
                    DateClosed = lastChange
                });
            }
            return(issues);
        }
        public GitHubIssueTrackerTests()
        {
            gitHubClient = Substitute.For<IGitHubClient>();
            issuesClient = Substitute.For<IIssuesClient>();
            gitHubClient.Issue.Returns(issuesClient);
            arguments = new GitReleaseNotesArguments
            {
                Repo = "Org/Repo",
                Token = "213"
            };

            var context = arguments.ToContext();

            repo = Substitute.For<IRepository>();
            repo.Network.Returns(new NetworkEx());

            sut = new GitHubIssueTracker(repo, () => gitHubClient, context);
        }
        /// <param name="issueNumberRegexPattern">Must have a named group called 'issueNumber'</param>
        public List<string> GetIssueNumbers(GitReleaseNotesArguments arguments, Commit[] commitsToScan, string issueNumberRegexPattern)
        {
            var issueNumbersToScan = new List<string>();
            var issueRegex = new Regex(issueNumberRegexPattern, RegexOptions.Compiled);

            foreach (var commit in commitsToScan)
            {
                var matches = issueRegex.Matches(commit.Message).Cast<Match>();

                foreach (var match in matches)
                {
                    var issueNumber = match.Groups["issueNumber"].Value;
                    if (arguments.Verbose)
                        Console.WriteLine("Found issues {0} in commit {1}", issueNumber, commit.Sha);
                    issueNumbersToScan.Add(issueNumber);
                }
            }
            return issueNumbersToScan;
        }
Exemplo n.º 23
0
        public GitHubIssueTrackerTests()
        {
            gitHubClient = Substitute.For <IGitHubClient>();
            issuesClient = Substitute.For <IIssuesClient>();
            gitHubClient.Issue.Returns(issuesClient);
            arguments = new GitReleaseNotesArguments
            {
                IssueTracker          = IssueTracker.GitHub,
                IssueTrackerProjectId = "Org/Repo",
                IssueTrackerToken     = "213"
            };

            var context = arguments.ToContext();

            repo = Substitute.For <IRepository>();
            repo.Network.Returns(new NetworkEx());

            sut = new GitHubIssueTracker(repo, () => gitHubClient, context);
        }
Exemplo n.º 24
0
        private static void GenerateOauthRequest(GitReleaseNotesArguments arguments, Uri baseUrl, string MethodLocation, RestRequest request)
        {
            var    consumerKey    = arguments.Username;
            var    consumerSecret = arguments.Password;
            var    oAuth          = new OAuthBase();
            var    nonce          = oAuth.GenerateNonce();
            var    timeStamp      = oAuth.GenerateTimeStamp();
            string normalizedUrl;
            string normalizedRequestParameters;
            var    sig = oAuth.GenerateSignature(new Uri(baseUrl + MethodLocation), consumerKey, consumerSecret, null, null, "GET", timeStamp, nonce, out normalizedUrl, out normalizedRequestParameters);

            request.Resource = string.Format(MethodLocation);
            request.Method   = Method.GET;
            request.AddParameter("oauth_consumer_key", consumerKey);
            request.AddParameter("oauth_nonce", nonce);
            request.AddParameter("oauth_timestamp", timeStamp);
            request.AddParameter("oauth_signature_method", "HMAC-SHA1");
            request.AddParameter("oauth_version", "1.0");
            request.AddParameter("oauth_signature", sig);
        }
Exemplo n.º 25
0
        public bool VerifyArgumentsAndWriteErrorsToConsole(GitReleaseNotesArguments arguments)
        {
            if (arguments.Repo == null)
            {
                Console.WriteLine("GitHub repository cannot be null");
                return false;
            }
            var repoParts = arguments.Repo.Split('/');

            if (repoParts.Length != 2)
            {
                Console.WriteLine("GitHub repository name should be in format Organisation/RepoName");
                return false;
            }

            if (string.IsNullOrEmpty(arguments.Token))
            {
                Console.WriteLine("You must specify a GitHub Authentication token with the /Token argument");
                return false;
            }

            return true;
        }
Exemplo n.º 26
0
        private void GetRepository(GitReleaseNotesArguments arguments, out string organisation, out string repository)
        {
            if (RemotePresentWhichMatches)
            {
                if (TryRemote(out organisation, out repository, "upstream"))
                {
                    return;
                }
                if (TryRemote(out organisation, out repository, "origin"))
                {
                    return;
                }
                var remoteName = gitRepository.Network.Remotes.First(r => r.Url.ToLower().Contains("github.com")).Name;
                if (TryRemote(out organisation, out repository, remoteName))
                {
                    return;
                }
            }

            var repoParts = arguments.Repo.Split('/');

            organisation = repoParts[0];
            repository   = repoParts[1];
        }
 public JiraIssueTracker(IJiraApi jiraApi, GitReleaseNotesArguments arguments)
 {
     this.jiraApi = jiraApi;
     this.arguments = arguments;
 }
 public YouTrackIssueTracker(IYouTrackApi youTrackApi, ILog log, GitReleaseNotesArguments arguments)
 {
     this.youTrackApi = youTrackApi;
     this.log         = log;
     this.arguments   = arguments;
 }
        public void ItemIsCategorised()
        {
            var arguments = new GitReleaseNotesArguments
            {
                OutputFile = "ReleaseFile.md"
            };
            var releaseNotes = new SemanticReleaseNotes(new[]
            {
                new ReleaseNoteItem("Issue 1", "#1", new Uri("http://github.com/org/repo/issues/1"), new[]{"feature"})
            });

            _sut.WriteReleaseNotes(arguments, releaseNotes);

            Approvals.Verify(GetContent());
        }
Exemplo n.º 30
0
 public JiraIssueTracker(IJiraApi jiraApi, ILog log, GitReleaseNotesArguments arguments)
 {
     this.jiraApi   = jiraApi;
     this.log       = log;
     this.arguments = arguments;
 }
 public YouTrackIssueTracker(IYouTrackApi youTrackApi, GitReleaseNotesArguments arguments)
 {
     this.youTrackApi = youTrackApi;
     this.arguments = arguments;
 }
        private void GetRepository(GitReleaseNotesArguments arguments, out string organisation, out string repository)
        {
            if (RemotePresentWhichMatches)
            {
                if (TryRemote(out organisation, out repository, "upstream"))
                    return;
                if (TryRemote(out organisation, out repository, "origin"))
                    return;
                var remoteName = gitRepository.Network.Remotes.First(r => r.Url.ToLower().Contains("github.com")).Name;
                if (TryRemote(out organisation, out repository, remoteName))
                    return;
            }

            var repoParts = arguments.Repo.Split('/');
            organisation = repoParts[0];
            repository = repoParts[1];
        }
Exemplo n.º 33
0
        public IEnumerable <OnlineIssue> GetClosedIssues(GitReleaseNotesArguments arguments, DateTimeOffset?since)
        {
            string jql;

            if (since.HasValue)
            {
                var sinceFormatted = since.Value.ToString("yyyy-MM-d HH:mm");
                jql = string.Format("{0} AND updated > '{1}'", arguments.Jql, sinceFormatted).Replace("\"", "\\\"");
            }
            else
            {
                jql = arguments.Jql;
            }

            var baseUrl         = new Uri(arguments.JiraServer, UriKind.Absolute);
            var searchUri       = new Uri(baseUrl, "/rest/api/latest/search");
            var httpRequest     = WebRequest.CreateHttp(searchUri);
            var usernameAndPass = string.Format("{0}:{1}", arguments.Username, arguments.Password);
            var token           = Convert.ToBase64String(Encoding.UTF8.GetBytes(usernameAndPass));

            httpRequest.Headers.Add("Authorization", string.Format("Basic {0}", token));
            httpRequest.Method      = "POST";
            httpRequest.ContentType = "application/json";

            using (var streamWriter = new StreamWriter(httpRequest.GetRequestStream()))
            {
                string json = "{\"jql\": \"" + jql + "\",\"startAt\": 0, \"maxResults\": 100, \"fields\": [\"summary\",\"issuetype\"]}";
                streamWriter.Write(json);
                streamWriter.Flush();
                streamWriter.Close();
            }

            var response = (HttpWebResponse)httpRequest.GetResponse();

            if ((int)response.StatusCode == 400)
            {
                throw new Exception("Jql query error, please review your Jql");
            }

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("Failed to query Jira: " + response.StatusDescription);
            }

            using (var responseStream = response.GetResponseStream())
                using (var responseReader = new StreamReader(responseStream))
                {
                    var responseObject = Json.Decode(responseReader.ReadToEnd());
                    foreach (var issue in responseObject.issues)
                    {
                        string summary   = issue.fields.summary;
                        string id        = issue.key;
                        string issueType = issue.fields.issuetype.name;

                        yield return(new OnlineIssue
                        {
                            Id = id,
                            Title = summary,
                            IssueType = IssueType.Issue,
                            HtmlUrl = new Uri(baseUrl, string.Format("browse/{0}", id))
                        });
                    }
                }
        }