From 04863acdf8b2574ea323762ae8a1bf23a702f306 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Tue, 21 Mar 2017 15:07:59 +0100 Subject: [PATCH 01/18] Update license to make the Sonar / Msft copyright more clear --- LICENSE | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LICENSE b/LICENSE index 47d9c10..0184941 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,8 @@ MIT License Copyright (c) 2017 BBT Software AG and contributors + +Parts of the code are inspired by code from https://github.com/SonarSource-VisualStudio/sonar-scanner-msbuild Copyright (c) 2015-2017 SonarSource SA and Microsoft Corporation Permission is hereby granted, free of charge, to any person obtaining a copy From 74e39eec29ed4672f88f9b29a4c7dd8ee1e6fa0e Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Tue, 21 Mar 2017 17:24:04 +0100 Subject: [PATCH 02/18] (GH-11) Add support for repository URLs using SSH scheme by converting them to HTTPS --- .../RepositoryDescriptionTests.cs | 70 ++++++++++++++++++- .../RepositoryDescription.cs | 35 +++++++++- .../TfsPullRequestSettings.cs | 10 ++- .../TfsPullRequestSystemAliases.cs | 8 ++- 4 files changed, 115 insertions(+), 8 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/RepositoryDescriptionTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/RepositoryDescriptionTests.cs index d3097fb..290057b 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/RepositoryDescriptionTests.cs +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/RepositoryDescriptionTests.cs @@ -48,6 +48,12 @@ public void Should_Throw_If_No_Valid_Url(string repoUrl, string expectedMessage) @"http://mytenant.visualstudio.com/defaultcollection", "myproject", "myrepository")] + [InlineData( + @"http://tfs.foo.com/foo/foo/_git/foo", + "foo", + @"http://tfs.foo.com/foo", + "foo", + "foo")] [InlineData( @"http://mytenant.visualstudio.com/defaultcollection/myproject/_git/myrepository/somethingelse", "defaultcollection", @@ -55,11 +61,71 @@ public void Should_Throw_If_No_Valid_Url(string repoUrl, string expectedMessage) "myproject", "myrepository")] [InlineData( - @"http://tfs.foo.com/foo/foo/_git/foo", + @"https://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository", + "defaultcollection", + @"https://myserver:8080/tfs/defaultcollection", + "myproject", + "myrepository")] + [InlineData( + @"https://tfs.myserver/defaultcollection/myproject/_git/myrepository", + "defaultcollection", + @"https://tfs.myserver/defaultcollection", + "myproject", + "myrepository")] + [InlineData( + @"https://mytenant.visualstudio.com/defaultcollection/myproject/_git/myrepository", + "defaultcollection", + @"https://mytenant.visualstudio.com/defaultcollection", + "myproject", + "myrepository")] + [InlineData( + @"https://mytenant.visualstudio.com/defaultcollection/myproject/_git/myrepository/somethingelse", + "defaultcollection", + @"https://mytenant.visualstudio.com/defaultcollection", + "myproject", + "myrepository")] + [InlineData( + @"https://tfs.foo.com/foo/foo/_git/foo", "foo", - @"http://tfs.foo.com/foo", + @"https://tfs.foo.com/foo", "foo", "foo")] + [InlineData( + @"ssh://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository", + "defaultcollection", + @"https://myserver:8080/tfs/defaultcollection", + "myproject", + "myrepository")] + [InlineData( + @"ssh://tfs.myserver/defaultcollection/myproject/_git/myrepository", + "defaultcollection", + @"https://tfs.myserver/defaultcollection", + "myproject", + "myrepository")] + [InlineData( + @"ssh://mytenant.visualstudio.com/defaultcollection/myproject/_git/myrepository", + "defaultcollection", + @"https://mytenant.visualstudio.com/defaultcollection", + "myproject", + "myrepository")] + [InlineData( + @"ssh://mytenant.visualstudio.com/defaultcollection/myproject/_git/myrepository/somethingelse", + "defaultcollection", + @"https://mytenant.visualstudio.com/defaultcollection", + "myproject", + "myrepository")] + [InlineData( + @"ssh://tfs.foo.com/foo/foo/_git/foo", + "foo", + @"https://tfs.foo.com/foo", + "foo", + "foo")] + [InlineData( + @"ssh://foo:bar@myserver:8080/tfs/defaultcollection/myproject/_git/myrepository", + "defaultcollection", + @"https://myserver:8080/tfs/defaultcollection", + "myproject", + "myrepository")] public void Should_Parse_Repo_Url(string repoUrl, string collectionName, string collectionurl, string projectName, string repositoryName) { // Given / When diff --git a/src/Cake.Prca.PullRequests.Tfs/RepositoryDescription.cs b/src/Cake.Prca.PullRequests.Tfs/RepositoryDescription.cs index 01da998..757c48c 100644 --- a/src/Cake.Prca.PullRequests.Tfs/RepositoryDescription.cs +++ b/src/Cake.Prca.PullRequests.Tfs/RepositoryDescription.cs @@ -11,12 +11,15 @@ internal class RepositoryDescription /// /// Initializes a new instance of the class. /// - /// Full URL of the repository, eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository + /// Full URL of the repository, + /// eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// Supported URL schemes are HTTP, HTTPS and SSH. + /// URLs using SSH scheme are converted to HTTPS. public RepositoryDescription(Uri repoUrl) { repoUrl.NotNull(nameof(repoUrl)); - var repoUrlString = repoUrl.ToString(); + var repoUrlString = ConvertToSupportedUriScheme(repoUrl).ToString(); var gitSeparator = new[] { "/_git/" }; var splitPath = repoUrl.AbsolutePath.Split(gitSeparator, StringSplitOptions.None); if (splitPath.Length < 2) @@ -61,5 +64,33 @@ public RepositoryDescription(Uri repoUrl) /// Gets the name of the Git repository. /// public string RepositoryName { get; private set; } + + /// + /// Converts the repository URL to a supported scheme if possible. + /// + /// Repository URL. + /// Repository URL with a supported scheme. + private static Uri ConvertToSupportedUriScheme(Uri repoUrl) + { + if (repoUrl.Scheme == Uri.UriSchemeHttp || repoUrl.Scheme == Uri.UriSchemeHttps) + { + return repoUrl; + } + + // Convert SSH url to HTTPS + if (repoUrl.Scheme == "ssh") + { + var uriBuilder = new UriBuilder(repoUrl) + { + Scheme = Uri.UriSchemeHttps, + UserName = string.Empty, + Password = string.Empty + }; + return uriBuilder.Uri; + } + + throw new UriFormatException( + $"Invalid scheme in URI {repoUrl}. Only HTTP, HTTPS and SSH are supported"); + } } } diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs index 76c74d3..b0766a0 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs @@ -10,7 +10,10 @@ public class TfsPullRequestSettings /// /// Initializes a new instance of the class. /// - /// Full URL of the Git repository, eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// Full URL of the Git repository, + /// eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// Supported URL schemes are HTTP, HTTPS and SSH. + /// URLs using SSH scheme are converted to HTTPS. /// Branch for which the pull request is made. public TfsPullRequestSettings(Uri repositoryUrl, string sourceBranch) { @@ -24,7 +27,10 @@ public TfsPullRequestSettings(Uri repositoryUrl, string sourceBranch) /// /// Initializes a new instance of the class. /// - /// Full URL of the Git repository, eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// Full URL of the Git repository, + /// eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// Supported URL schemes are HTTP, HTTPS and SSH. + /// URLs using SSH scheme are converted to HTTPS. /// ID of the pull request. public TfsPullRequestSettings(Uri repositoryUrl, int pullRequestId) { diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs index e8ef2b4..f8a68d6 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs @@ -18,7 +18,9 @@ public static class TfsPullRequestSystemAliases /// /// The context. /// Full URL of the Git repository, - /// eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// Supported URL schemes are HTTP, HTTPS and SSH. + /// URLs using SSH scheme are converted to HTTPS. /// Branch for which the pull request is made. /// Object for writing issues to Team Foundation Server or Visual Studio Team Services pull request. /// @@ -51,7 +53,9 @@ public static class TfsPullRequestSystemAliases /// /// The context. /// Full URL of the Git repository, - /// eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// eg. http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository. + /// Supported URL schemes are HTTP, HTTPS and SSH. + /// URLs using SSH scheme are converted to HTTPS. /// ID of the pull request. /// Object for writing issues to Team Foundation Server or Visual Studio Team Services pull request. /// From 2eff975b63ddd4830b2b340018bd621110775ec2 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Mon, 20 Mar 2017 18:14:01 +0100 Subject: [PATCH 03/18] Add StyleCop analyzer and ruleset for test assembly --- src/Cake.Prca.PullRequests.Tfs.Tests.ruleset | 8 ++++++++ .../Cake.Prca.PullRequests.Tfs.Tests.csproj | 7 +++++++ src/Cake.Prca.PullRequests.Tfs.Tests/packages.config | 1 + src/Cake.Prca.PullRequests.Tfs.ruleset | 2 +- 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/Cake.Prca.PullRequests.Tfs.Tests.ruleset diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests.ruleset b/src/Cake.Prca.PullRequests.Tfs.Tests.ruleset new file mode 100644 index 0000000..f12ba75 --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs.Tests.ruleset @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Cake.Prca.PullRequests.Tfs.Tests.csproj b/src/Cake.Prca.PullRequests.Tfs.Tests/Cake.Prca.PullRequests.Tfs.Tests.csproj index 82a8546..7447f53 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/Cake.Prca.PullRequests.Tfs.Tests.csproj +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Cake.Prca.PullRequests.Tfs.Tests.csproj @@ -23,6 +23,7 @@ DEBUG;TRACE prompt 4 + ..\Cake.Prca.PullRequests.Tfs.Tests.ruleset pdbonly @@ -31,6 +32,7 @@ TRACE prompt 4 + ..\Cake.Prca.PullRequests.Tfs.Tests.ruleset @@ -89,6 +91,11 @@ + + + + + diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/packages.config b/src/Cake.Prca.PullRequests.Tfs.Tests/packages.config index 44517ca..8943bfd 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/packages.config +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/packages.config @@ -3,6 +3,7 @@ + diff --git a/src/Cake.Prca.PullRequests.Tfs.ruleset b/src/Cake.Prca.PullRequests.Tfs.ruleset index f3a3433..358ddc3 100644 --- a/src/Cake.Prca.PullRequests.Tfs.ruleset +++ b/src/Cake.Prca.PullRequests.Tfs.ruleset @@ -1,5 +1,5 @@  - + From f78b33de5de284b60218d18e616ca5d6508f6bc5 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Mon, 20 Mar 2017 18:15:19 +0100 Subject: [PATCH 04/18] Fix analyzer issues --- .../Properties/AssemblyInfo.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Properties/AssemblyInfo.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/Properties/AssemblyInfo.cs index 06857e8..1a96fbe 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/Properties/AssemblyInfo.cs +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Properties/AssemblyInfo.cs @@ -1,7 +1,7 @@ using System.Reflection; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("TFS support for Cake Pull Request Code Analysis Testcases")] @@ -13,8 +13,8 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] @@ -24,11 +24,11 @@ // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -// You can specify all the values or you can default the Build and Revision Numbers +// You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] From f23e2dce98345bd14dbba91de42a5e6ef2ead424 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 15:39:28 +0100 Subject: [PATCH 05/18] (GH-16) Update alias examples to Cake.Prca.Issues.MsBuild 0.1.0 --- .../TfsPullRequestSystemAliases.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs index f8a68d6..0c1bb13 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs @@ -28,7 +28,10 @@ public static class TfsPullRequestSystemAliases /// /// /// @@ -63,7 +66,10 @@ public static class TfsPullRequestSystemAliases /// /// /// @@ -98,7 +104,10 @@ public static class TfsPullRequestSystemAliases /// "refs/heads/feature/myfeature"); /// /// ReportCodeAnalysisIssuesToPullRequest( - /// MsBuildCodeAnalysis(@"C:\build\msbuild.log", MsBuildXmlFileLoggerFormat), + /// MsBuildCodeAnalysis( + /// @"C:\build\msbuild.log", + /// MsBuildXmlFileLoggerFormat, + /// new DirectoryPath("c:\repo")), /// TfsPullRequests(pullRequestSettings)); /// ]]> /// From df5ffc8f9dfa085db4e57432cedcb5529258cc81 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 14:14:24 +0100 Subject: [PATCH 06/18] (GH-5) Add support for different authentication methods --- .../AuthenticationProviderTests.cs | 339 ++++++++++++++++++ .../Authentication/PrcaAadCredentialsTests.cs | 40 +++ .../PrcaBasicCredentialsTests.cs | 40 +++ .../PrcaNtlmCredentialsTests.cs | 22 ++ .../PrcaOAuthCredentialsTests.cs | 55 +++ .../Cake.Prca.PullRequests.Tfs.Tests.csproj | 5 + .../TfsPullRequestSettingsTests.cs | 10 +- .../Authentication/AuthenticationProvider.cs | 80 +++++ .../Authentication/PrcaAadCredentials.cs | 18 + .../Authentication/PrcaBasicCredentials.cs | 29 ++ .../Authentication/PrcaNtlmCredentials.cs | 9 + .../Authentication/PrcaOAuthCredentials.cs | 24 ++ .../Cake.Prca.PullRequests.Tfs.csproj | 7 + .../IPrcaCredentials.cs | 9 + .../PrcaCredentialsExtensions.cs | 44 +++ .../TfsPullRequestSettings.cs | 18 +- .../TfsPullRequestSystem.cs | 9 +- .../TfsPullRequestSystemAliases.cs | 128 ++++++- 18 files changed, 870 insertions(+), 16 deletions(-) create mode 100644 src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/AuthenticationProviderTests.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaAadCredentialsTests.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaBasicCredentialsTests.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaNtlmCredentialsTests.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaOAuthCredentialsTests.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs/Authentication/AuthenticationProvider.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaAadCredentials.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaBasicCredentials.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaNtlmCredentials.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaOAuthCredentials.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs/IPrcaCredentials.cs create mode 100644 src/Cake.Prca.PullRequests.Tfs/PrcaCredentialsExtensions.cs diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/AuthenticationProviderTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/AuthenticationProviderTests.cs new file mode 100644 index 0000000..26e4f7a --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/AuthenticationProviderTests.cs @@ -0,0 +1,339 @@ +namespace Cake.Prca.PullRequests.Tfs.Tests.Authentication +{ + using Tfs.Authentication; + using Shouldly; + using Xunit; + + public class AuthenticationProviderTests + { + public sealed class TheAuthenticationNtlmMethod + { + [Fact] + public void Should_Return_PrcaNtlmCredentials_Object() + { + // Given / When + var credentials = AuthenticationProvider.AuthenticationNtlm(); + + // Then + credentials.ShouldBeOfType(); + } + } + + public sealed class TheAuthenticationBasicMethod + { + [Fact] + public void Should_Throw_If_User_Name_Is_Null() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationBasic(null, "foo")); + + // Then + result.IsArgumentNullException("userName"); + } + + [Fact] + public void Should_Throw_If_User_Name_Is_Empty() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationBasic(string.Empty, "foo")); + + // Then + result.IsArgumentOutOfRangeException("userName"); + } + + [Fact] + public void Should_Throw_If_User_Name_Is_WhiteSpace() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationBasic(" ", "foo")); + + // Then + result.IsArgumentOutOfRangeException("userName"); + } + + [Fact] + public void Should_Throw_If_Password_Is_Null() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationBasic("foo", null)); + + // Then + result.IsArgumentNullException("password"); + } + + [Fact] + public void Should_Throw_If_Password_Is_Empty() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationBasic("foo", string.Empty)); + + // Then + result.IsArgumentOutOfRangeException("password"); + } + + [Fact] + public void Should_Throw_If_Password_Is_WhiteSpace() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationBasic("foo", " ")); + + // Then + result.IsArgumentOutOfRangeException("password"); + } + + [Fact] + public void Should_Return_PrcaBasicCredentials_Object() + { + // Given / When + var credentials = AuthenticationProvider.AuthenticationBasic("foo", "bar"); + + // Then + credentials.ShouldBeOfType(); + } + + [Fact] + public void Should_Set_User_Name() + { + // Given + const string userName = "foo"; + + // When + var credentials = AuthenticationProvider.AuthenticationBasic(userName, "bar"); + + // Then + credentials.ShouldBeOfType(); + ((PrcaBasicCredentials)credentials).UserName.ShouldBe(userName); + } + + [Fact] + public void Should_Set_Password() + { + // Given + const string password = "bar"; + + // When + var credentials = AuthenticationProvider.AuthenticationBasic("foo", password); + + // Then + credentials.ShouldBeOfType(); + ((PrcaBasicCredentials)credentials).Password.ShouldBe(password); + } + } + + public sealed class TheAuthenticationPersonalAccessTokenMethod + { + [Fact] + public void Should_Throw_If_Personal_Access_Token_Is_Null() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationPersonalAccessToken(null)); + + // Then + result.IsArgumentNullException("personalAccessToken"); + } + + [Fact] + public void Should_Throw_If_Personal_Access_Token_Is_Empty() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationPersonalAccessToken(string.Empty)); + + // Then + result.IsArgumentOutOfRangeException("personalAccessToken"); + } + + [Fact] + public void Should_Throw_If_Personal_Access_Token_Is_WhiteSpace() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationPersonalAccessToken(" ")); + + // Then + result.IsArgumentOutOfRangeException("personalAccessToken"); + } + + [Fact] + public void Should_Return_PrcaBasicCredentials_Object() + { + // Given / When + var credentials = AuthenticationProvider.AuthenticationPersonalAccessToken("foo"); + + // Then + credentials.ShouldBeOfType(); + } + + [Fact] + public void Should_Set_Personal_Access_Token() + { + // Given + const string personalAccessToken = "foo"; + + // When + var credentials = AuthenticationProvider.AuthenticationPersonalAccessToken(personalAccessToken); + + // Then + credentials.ShouldBeOfType(); + ((PrcaBasicCredentials)credentials).UserName.ShouldBe(string.Empty); + ((PrcaBasicCredentials)credentials).Password.ShouldBe(personalAccessToken); + } + } + + public sealed class TheAuthenticationOAuthMethod + { + [Fact] + public void Should_Throw_If_Access_Token_Is_Null() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationOAuth(null)); + + // Then + result.IsArgumentNullException("accessToken"); + } + + [Fact] + public void Should_Throw_If_Access_Token_Is_Empty() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationOAuth(string.Empty)); + + // Then + result.IsArgumentOutOfRangeException("accessToken"); + } + + [Fact] + public void Should_Throw_If_Access_Token_Is_WhiteSpace() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationOAuth(" ")); + + // Then + result.IsArgumentOutOfRangeException("accessToken"); + } + + [Fact] + public void Should_Return_PrcaOAuthCredentials_Object() + { + // Given / When + var credentials = AuthenticationProvider.AuthenticationOAuth("foo"); + + // Then + credentials.ShouldBeOfType(); + } + + [Fact] + public void Should_Set_Access_Token() + { + // Given + const string accessToken = "foo"; + + // When + var credentials = AuthenticationProvider.AuthenticationOAuth(accessToken); + + // Then + credentials.ShouldBeOfType(); + ((PrcaOAuthCredentials)credentials).AccessToken.ShouldBe(accessToken); + } + } + + public sealed class TheAuthenticationAzureActiveDirectoryMethod + { + [Fact] + public void Should_Throw_If_User_Name_Is_Null() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationAzureActiveDirectory(null, "foo")); + + // Then + result.IsArgumentNullException("userName"); + } + + [Fact] + public void Should_Throw_If_User_Name_Is_Empty() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationAzureActiveDirectory(string.Empty, "foo")); + + // Then + result.IsArgumentOutOfRangeException("userName"); + } + + [Fact] + public void Should_Throw_If_User_Name_Is_WhiteSpace() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationAzureActiveDirectory(" ", "foo")); + + // Then + result.IsArgumentOutOfRangeException("userName"); + } + + [Fact] + public void Should_Throw_If_Password_Is_Null() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationAzureActiveDirectory("foo", null)); + + // Then + result.IsArgumentNullException("password"); + } + + [Fact] + public void Should_Throw_If_Password_Is_Empty() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationAzureActiveDirectory("foo", string.Empty)); + + // Then + result.IsArgumentOutOfRangeException("password"); + } + + [Fact] + public void Should_Throw_If_Password_Is_WhiteSpace() + { + // Given / When + var result = Record.Exception(() => AuthenticationProvider.AuthenticationAzureActiveDirectory("foo", " ")); + + // Then + result.IsArgumentOutOfRangeException("password"); + } + + [Fact] + public void Should_Return_PrcaAadCredentials_Object() + { + // Given / When + var credentials = AuthenticationProvider.AuthenticationAzureActiveDirectory("foo", "bar"); + + // Then + credentials.ShouldBeOfType(); + } + + [Fact] + public void Should_Set_User_Name() + { + // Given + const string userName = "foo"; + + // When + var credentials = AuthenticationProvider.AuthenticationAzureActiveDirectory(userName, "bar"); + + // Then + credentials.ShouldBeOfType(); + ((PrcaAadCredentials)credentials).UserName.ShouldBe(userName); + } + + [Fact] + public void Should_Set_Password() + { + // Given + const string password = "bar"; + + // When + var credentials = AuthenticationProvider.AuthenticationAzureActiveDirectory("foo", password); + + // Then + credentials.ShouldBeOfType(); + ((PrcaAadCredentials)credentials).Password.ShouldBe(password); + } + } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaAadCredentialsTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaAadCredentialsTests.cs new file mode 100644 index 0000000..394852e --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaAadCredentialsTests.cs @@ -0,0 +1,40 @@ +namespace Cake.Prca.PullRequests.Tfs.Tests.Authentication +{ + using Shouldly; + using Tfs.Authentication; + using Xunit; + + public class PrcaAadCredentialsTests + { + public sealed class ThePrcaAadCredentialsCtor + { + [Theory] + [InlineData("foo")] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void Should_Set_User_Name(string userName) + { + // When + var credentials = new PrcaAadCredentials(userName, "bar"); + + // Then + credentials.UserName.ShouldBe(userName); + } + + [Theory] + [InlineData("bar")] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void Should_Set_Password_Name(string password) + { + // When + var credentials = new PrcaAadCredentials("foo", password); + + // Then + credentials.Password.ShouldBe(password); + } + } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaBasicCredentialsTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaBasicCredentialsTests.cs new file mode 100644 index 0000000..8e8ab91 --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaBasicCredentialsTests.cs @@ -0,0 +1,40 @@ +namespace Cake.Prca.PullRequests.Tfs.Tests.Authentication +{ + using Shouldly; + using Tfs.Authentication; + using Xunit; + + public class PrcaBasicCredentialsTests + { + public sealed class ThePrcaBasicCredentialsCtor + { + [Theory] + [InlineData("foo")] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void Should_Set_User_Name(string userName) + { + // When + var credentials = new PrcaBasicCredentials(userName, "bar"); + + // Then + credentials.UserName.ShouldBe(userName); + } + + [Theory] + [InlineData("bar")] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void Should_Set_Password_Name(string password) + { + // When + var credentials = new PrcaBasicCredentials("foo", password); + + // Then + credentials.Password.ShouldBe(password); + } + } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaNtlmCredentialsTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaNtlmCredentialsTests.cs new file mode 100644 index 0000000..32f217f --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaNtlmCredentialsTests.cs @@ -0,0 +1,22 @@ +namespace Cake.Prca.PullRequests.Tfs.Tests.Authentication +{ + using Shouldly; + using Tfs.Authentication; + using Xunit; + + public class PrcaNtlmCredentialsTests + { + public sealed class ThePrcaNtlmCredentialsCtor + { + [Fact] + public void Should_Not_Throw() + { + // Given / When + var credentials = new PrcaNtlmCredentials(); + + // Then + credentials.ShouldBeOfType(); + } + } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaOAuthCredentialsTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaOAuthCredentialsTests.cs new file mode 100644 index 0000000..e02afed --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/PrcaOAuthCredentialsTests.cs @@ -0,0 +1,55 @@ +namespace Cake.Prca.PullRequests.Tfs.Tests.Authentication +{ + using Shouldly; + using Tfs.Authentication; + using Xunit; + + public class PrcaOAuthCredentialsTests + { + public sealed class ThePrcaOAuthCredentialsCtor + { + [Fact] + public void Should_Throw_If_Access_Token_Is_Null() + { + // Given / When + var result = Record.Exception(() => new PrcaOAuthCredentials(null)); + + // Then + result.IsArgumentNullException("accessToken"); + } + + [Fact] + public void Should_Throw_If_Access_Token_Is_Empty() + { + // Given / When + var result = Record.Exception(() => new PrcaOAuthCredentials(string.Empty)); + + // Then + result.IsArgumentOutOfRangeException("accessToken"); + } + + [Fact] + public void Should_Throw_If_Access_Token_Is_WhiteSpace() + { + // Given / When + var result = Record.Exception(() => new PrcaOAuthCredentials(" ")); + + // Then + result.IsArgumentOutOfRangeException("accessToken"); + } + + [Fact] + public void Should_Set_Access_Token() + { + // Given + const string accessToken = "foo"; + + // When + var credentials = new PrcaOAuthCredentials(accessToken); + + // Then + credentials.AccessToken.ShouldBe(accessToken); + } + } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Cake.Prca.PullRequests.Tfs.Tests.csproj b/src/Cake.Prca.PullRequests.Tfs.Tests/Cake.Prca.PullRequests.Tfs.Tests.csproj index 7447f53..a638c6a 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/Cake.Prca.PullRequests.Tfs.Tests.csproj +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Cake.Prca.PullRequests.Tfs.Tests.csproj @@ -73,6 +73,11 @@ + + + + + diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/TfsPullRequestSettingsTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/TfsPullRequestSettingsTests.cs index a37c17c..bf0d6b3 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/TfsPullRequestSettingsTests.cs +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/TfsPullRequestSettingsTests.cs @@ -11,7 +11,7 @@ public sealed class TheTfsPullRequestSettings public void Should_Throw_If_RepositoryUrl_For_SourceBranch_Is_Null() { // Given / When - var result = Record.Exception(() => new TfsPullRequestSettings((Uri)null, "foo")); + var result = Record.Exception(() => new TfsPullRequestSettings((Uri)null, "foo", null)); // Then result.IsArgumentNullException("repositoryUrl"); @@ -21,7 +21,7 @@ public void Should_Throw_If_RepositoryUrl_For_SourceBranch_Is_Null() public void Should_Throw_If_SourceBranch_Is_Null() { // Given / When - var result = Record.Exception(() => new TfsPullRequestSettings(new Uri("http://example.com"), (string)null)); + var result = Record.Exception(() => new TfsPullRequestSettings(new Uri("http://example.com"), (string)null, null)); // Then result.IsArgumentNullException("sourceBranch"); @@ -31,7 +31,7 @@ public void Should_Throw_If_SourceBranch_Is_Null() public void Should_Throw_If_SourceBranch_Is_Empty() { // Given / When - var result = Record.Exception(() => new TfsPullRequestSettings(new Uri("http://example.com"), string.Empty)); + var result = Record.Exception(() => new TfsPullRequestSettings(new Uri("http://example.com"), string.Empty, null)); // Then result.IsArgumentOutOfRangeException("sourceBranch"); @@ -41,7 +41,7 @@ public void Should_Throw_If_SourceBranch_Is_Empty() public void Should_Throw_If_SourceBranch_Is_WhiteSpace() { // Given / When - var result = Record.Exception(() => new TfsPullRequestSettings(new Uri("http://example.com"), " ")); + var result = Record.Exception(() => new TfsPullRequestSettings(new Uri("http://example.com"), " ", null)); // Then result.IsArgumentOutOfRangeException("sourceBranch"); @@ -51,7 +51,7 @@ public void Should_Throw_If_SourceBranch_Is_WhiteSpace() public void Should_Throw_If_RepositoryUrl_For_PullRequestId_Is_Null() { // Given / When - var result = Record.Exception(() => new TfsPullRequestSettings((Uri)null, 0)); + var result = Record.Exception(() => new TfsPullRequestSettings((Uri)null, 0, null)); // Then result.IsArgumentNullException("repositoryUrl"); diff --git a/src/Cake.Prca.PullRequests.Tfs/Authentication/AuthenticationProvider.cs b/src/Cake.Prca.PullRequests.Tfs/Authentication/AuthenticationProvider.cs new file mode 100644 index 0000000..112e980 --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs/Authentication/AuthenticationProvider.cs @@ -0,0 +1,80 @@ +namespace Cake.Prca.PullRequests.Tfs.Authentication +{ + /// + /// Class providing credentials for different authentication schemas. + /// + internal static class AuthenticationProvider + { + /// + /// Returns credentials for integrated / NTLM authentication. + /// Can only be used for on-premise Team Foundation Server. + /// + /// Credentials for integrated / NTLM authentication. + public static IPrcaCredentials AuthenticationNtlm() + { + return new PrcaNtlmCredentials(); + } + + /// + /// Returns credentials for basic authentication. + /// Can only be used for on-premise Team Foundation Server configured for basic authentication. + /// See https://www.visualstudio.com/en-us/docs/integrate/get-started/auth/tfs-basic-auth. + /// + /// User name. + /// Password. + /// Credentials for basic authentication. + public static IPrcaCredentials AuthenticationBasic( + string userName, + string password) + { + userName.NotNullOrWhiteSpace(nameof(userName)); + password.NotNullOrWhiteSpace(nameof(password)); + + return new PrcaBasicCredentials(userName, password); + } + + /// + /// Returns credentials for authentication with a personal access token. + /// Can be used for Team Foundation Server and Visual Studio Team Services. + /// + /// Personal access token. + /// Credentials for authentication with a personal access token. + public static IPrcaCredentials AuthenticationPersonalAccessToken( + string personalAccessToken) + { + personalAccessToken.NotNullOrWhiteSpace(nameof(personalAccessToken)); + + return new PrcaBasicCredentials(string.Empty, personalAccessToken); + } + + /// + /// Returns credentials for OAuth authentication. + /// Can only be used with Visual Studio Team Services. + /// + /// OAuth access token. + /// Credentials for OAuth authentication. + public static IPrcaCredentials AuthenticationOAuth( + string accessToken) + { + accessToken.NotNullOrWhiteSpace(nameof(accessToken)); + + return new PrcaOAuthCredentials(accessToken); + } + + /// + /// Returns credentials for authentication with an Azure Active Directory. + /// + /// User name. + /// Password. + /// Credentials for authentication with an Azure Active Directory. + public static IPrcaCredentials AuthenticationAzureActiveDirectory( + string userName, + string password) + { + userName.NotNullOrWhiteSpace(nameof(userName)); + password.NotNullOrWhiteSpace(nameof(password)); + + return new PrcaAadCredentials(userName, password); + } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaAadCredentials.cs b/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaAadCredentials.cs new file mode 100644 index 0000000..a8e3179 --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaAadCredentials.cs @@ -0,0 +1,18 @@ +namespace Cake.Prca.PullRequests.Tfs.Authentication +{ + /// + /// Credentials for authentication with an Azure Active Directory. + /// + public class PrcaAadCredentials : PrcaBasicCredentials + { + /// + /// Initializes a new instance of the class. + /// + /// User name. + /// Password. + public PrcaAadCredentials(string userName, string password) + : base(userName, password) + { + } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaBasicCredentials.cs b/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaBasicCredentials.cs new file mode 100644 index 0000000..73ed0c6 --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaBasicCredentials.cs @@ -0,0 +1,29 @@ +namespace Cake.Prca.PullRequests.Tfs.Authentication +{ + /// + /// Credentials for basic authentication. + /// + public class PrcaBasicCredentials : IPrcaCredentials + { + /// + /// Initializes a new instance of the class. + /// + /// User name. + /// Password. + public PrcaBasicCredentials(string userName, string password) + { + this.UserName = userName; + this.Password = password; + } + + /// + /// Gets the user name. + /// + public string UserName { get; private set; } + + /// + /// Gets the password. + /// + public string Password { get; private set; } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaNtlmCredentials.cs b/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaNtlmCredentials.cs new file mode 100644 index 0000000..145eb07 --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaNtlmCredentials.cs @@ -0,0 +1,9 @@ +namespace Cake.Prca.PullRequests.Tfs.Authentication +{ + /// + /// Credentials for integrated / NTLM authentication. + /// + public class PrcaNtlmCredentials : IPrcaCredentials + { + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaOAuthCredentials.cs b/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaOAuthCredentials.cs new file mode 100644 index 0000000..485e534 --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs/Authentication/PrcaOAuthCredentials.cs @@ -0,0 +1,24 @@ +namespace Cake.Prca.PullRequests.Tfs.Authentication +{ + /// + /// Credentials for OAuth authentication. + /// + public class PrcaOAuthCredentials : IPrcaCredentials + { + /// + /// Initializes a new instance of the class. + /// + /// OAuth access token. + public PrcaOAuthCredentials(string accessToken) + { + accessToken.NotNullOrWhiteSpace(nameof(accessToken)); + + this.AccessToken = accessToken; + } + + /// + /// Gets the OAuth access token. + /// + public string AccessToken { get; private set; } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj b/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj index bc42d99..8708cde 100644 --- a/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj +++ b/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj @@ -149,9 +149,16 @@ + + + + + + + diff --git a/src/Cake.Prca.PullRequests.Tfs/IPrcaCredentials.cs b/src/Cake.Prca.PullRequests.Tfs/IPrcaCredentials.cs new file mode 100644 index 0000000..986b64c --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs/IPrcaCredentials.cs @@ -0,0 +1,9 @@ +namespace Cake.Prca.PullRequests.Tfs +{ + /// + /// Interface for different credential types. + /// + public interface IPrcaCredentials + { + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs/PrcaCredentialsExtensions.cs b/src/Cake.Prca.PullRequests.Tfs/PrcaCredentialsExtensions.cs new file mode 100644 index 0000000..0c2d7f3 --- /dev/null +++ b/src/Cake.Prca.PullRequests.Tfs/PrcaCredentialsExtensions.cs @@ -0,0 +1,44 @@ +namespace Cake.Prca.PullRequests.Tfs +{ + using Authentication; + using Microsoft.VisualStudio.Services.Client; + using Microsoft.VisualStudio.Services.Common; + using Microsoft.VisualStudio.Services.OAuth; + + /// + /// Extensions for the interface. + /// + internal static class PrcaCredentialsExtensions + { + /// + /// Returns the corresponding to a object. + /// + /// credential instance. + /// instance. + public static VssCredentials ToVssCredentials(this IPrcaCredentials credentials) + { + credentials.NotNull(nameof(credentials)); + + switch (credentials.GetType().Name) + { + case nameof(PrcaNtlmCredentials): + return new VssCredentials(); + + case nameof(PrcaBasicCredentials): + var basicCredentials = (PrcaBasicCredentials)credentials; + return new VssBasicCredential(basicCredentials.UserName, basicCredentials.Password); + + case nameof(PrcaOAuthCredentials): + var oAuthCredentials = (PrcaOAuthCredentials)credentials; + return new VssOAuthAccessTokenCredential(oAuthCredentials.AccessToken); + + case nameof(PrcaAadCredentials): + var aadCredentials = (PrcaAadCredentials)credentials; + return new VssAadCredential(aadCredentials.UserName, aadCredentials.Password); + + default: + throw new PrcaException("Unknown credential type."); + } + } + } +} diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs index b0766a0..f5743e9 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs @@ -15,13 +15,17 @@ public class TfsPullRequestSettings /// Supported URL schemes are HTTP, HTTPS and SSH. /// URLs using SSH scheme are converted to HTTPS. /// Branch for which the pull request is made. - public TfsPullRequestSettings(Uri repositoryUrl, string sourceBranch) + /// Credentials to use to authenticate against Team Foundation Server or + /// Visual Studio Team Services. + public TfsPullRequestSettings(Uri repositoryUrl, string sourceBranch, IPrcaCredentials credentials) { repositoryUrl.NotNull(nameof(repositoryUrl)); sourceBranch.NotNullOrWhiteSpace(nameof(sourceBranch)); + credentials.NotNull(nameof(credentials)); this.RepositoryUrl = repositoryUrl; this.SourceBranch = sourceBranch; + this.Credentials = credentials; } /// @@ -32,12 +36,16 @@ public TfsPullRequestSettings(Uri repositoryUrl, string sourceBranch) /// Supported URL schemes are HTTP, HTTPS and SSH. /// URLs using SSH scheme are converted to HTTPS. /// ID of the pull request. - public TfsPullRequestSettings(Uri repositoryUrl, int pullRequestId) + /// Credentials to use to authenticate against Team Foundation Server or + /// Visual Studio Team Services. + public TfsPullRequestSettings(Uri repositoryUrl, int pullRequestId, IPrcaCredentials credentials) { repositoryUrl.NotNull(nameof(repositoryUrl)); + credentials.NotNull(nameof(credentials)); this.RepositoryUrl = repositoryUrl; this.PullRequestId = pullRequestId; + this.Credentials = credentials; } /// @@ -54,5 +62,11 @@ public TfsPullRequestSettings(Uri repositoryUrl, int pullRequestId) /// Gets the ID of the pull request. /// public int? PullRequestId { get; private set; } + + /// + /// Gets the credetials used to authenticate against Team Foundation Server or + /// Visual Studio Team Services. + /// + public IPrcaCredentials Credentials { get; private set; } } } diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs index f77ca9d..7a20adc 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs @@ -9,7 +9,6 @@ using Core.IO; using Issues; using Microsoft.TeamFoundation.SourceControl.WebApi; - using Microsoft.VisualStudio.Services.Common; using Microsoft.VisualStudio.Services.WebApi; /// @@ -17,6 +16,7 @@ /// public sealed class TfsPullRequestSystem : PullRequestSystem { + private readonly TfsPullRequestSettings settings; private readonly RepositoryDescription repositoryDescription; private readonly GitPullRequest pullRequest; @@ -33,6 +33,8 @@ public TfsPullRequestSystem(ICakeLog log, TfsPullRequestSettings settings) { settings.NotNull(nameof(settings)); + this.settings = settings; + this.repositoryDescription = new RepositoryDescription(settings.RepositoryUrl); this.Log.Verbose( @@ -269,7 +271,10 @@ public override void PostDiscussionThreads(IEnumerable issue private GitHttpClient CreateGitClient() { - var connection = new VssConnection(this.repositoryDescription.CollectionUrl, new VssCredentials()); + var connection = + new VssConnection( + this.repositoryDescription.CollectionUrl, + this.settings.Credentials.ToVssCredentials()); var gitClient = connection.GetClient(); if (gitClient == null) diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs index 0c1bb13..7322338 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs @@ -1,6 +1,7 @@ namespace Cake.Prca.PullRequests.Tfs { using System; + using Authentication; using Core; using Core.Annotations; @@ -12,6 +13,104 @@ [CakeNamespaceImport("Cake.Prca.PullRequests.Tfs")] public static class TfsPullRequestSystemAliases { + /// + /// Returns credentials for integrated / NTLM authentication. + /// Can only be used for on-premise Team Foundation Server. + /// + /// The context. + /// Credentials for integrated / NTLM authentication + [CakeMethodAlias] + [CakeAliasCategory(CakeAliasConstants.PullRequestSystemCakeAliasCategory)] + public static IPrcaCredentials PrcaAuthenticationNtlm( + this ICakeContext context) + { + context.NotNull(nameof(context)); + + return AuthenticationProvider.AuthenticationNtlm(); + } + + /// + /// Returns credentials for basic authentication. + /// Can only be used for on-premise Team Foundation Server configured for basic authentication. + /// See https://www.visualstudio.com/en-us/docs/integrate/get-started/auth/tfs-basic-auth. + /// + /// The context. + /// User name. + /// Password. + /// Credentials for basic authentication. + [CakeMethodAlias] + [CakeAliasCategory(CakeAliasConstants.PullRequestSystemCakeAliasCategory)] + public static IPrcaCredentials PrcaAuthenticationBasic( + this ICakeContext context, + string userName, + string password) + { + context.NotNull(nameof(context)); + userName.NotNullOrWhiteSpace(nameof(userName)); + password.NotNullOrWhiteSpace(nameof(password)); + + return AuthenticationProvider.AuthenticationBasic(userName, password); + } + + /// + /// Returns credentials for authentication with a personal access token. + /// Can be used for Team Foundation Server and Visual Studio Team Services. + /// + /// The context. + /// Personal access token. + /// Credentials for authentication with a personal access token. + [CakeMethodAlias] + [CakeAliasCategory(CakeAliasConstants.PullRequestSystemCakeAliasCategory)] + public static IPrcaCredentials PrcaAuthenticationPersonalAccessToken( + this ICakeContext context, + string personalAccessToken) + { + context.NotNull(nameof(context)); + personalAccessToken.NotNullOrWhiteSpace(nameof(personalAccessToken)); + + return AuthenticationProvider.AuthenticationPersonalAccessToken(personalAccessToken); + } + + /// + /// Returns credentials for OAuth authentication. + /// Can only be used with Visual Studio Team Services. + /// + /// The context. + /// OAuth access token. + /// Credentials for OAuth authentication. + [CakeMethodAlias] + [CakeAliasCategory(CakeAliasConstants.PullRequestSystemCakeAliasCategory)] + public static IPrcaCredentials PrcaAuthenticationOAuth( + this ICakeContext context, + string accessToken) + { + context.NotNull(nameof(context)); + accessToken.NotNullOrWhiteSpace(nameof(accessToken)); + + return AuthenticationProvider.AuthenticationOAuth(accessToken); + } + + /// + /// Returns credentials for authentication with an Azure Active Directory. + /// + /// The context. + /// User name. + /// Password. + /// Credentials for authentication with an Azure Active Directory. + [CakeMethodAlias] + [CakeAliasCategory(CakeAliasConstants.PullRequestSystemCakeAliasCategory)] + public static IPrcaCredentials PrcaAuthenticationAzureActiveDirectory( + this ICakeContext context, + string userName, + string password) + { + context.NotNull(nameof(context)); + userName.NotNullOrWhiteSpace(nameof(userName)); + password.NotNullOrWhiteSpace(nameof(password)); + + return AuthenticationProvider.AuthenticationAzureActiveDirectory(userName, password); + } + /// /// Gets an object for writing issues to Team Foundation Server or Visual Studio Team Services pull request /// in a specific repository and for a specific source branch. @@ -22,6 +121,8 @@ public static class TfsPullRequestSystemAliases /// Supported URL schemes are HTTP, HTTPS and SSH. /// URLs using SSH scheme are converted to HTTPS. /// Branch for which the pull request is made. + /// Credentials to use to authenticate against Team Foundation Server or + /// Visual Studio Team Services. /// Object for writing issues to Team Foundation Server or Visual Studio Team Services pull request. /// /// Report code analysis issues reported as MsBuild warnings to a TFS pull request: @@ -32,7 +133,10 @@ public static class TfsPullRequestSystemAliases /// @"C:\build\msbuild.log", /// MsBuildXmlFileLoggerFormat, /// new DirectoryPath("c:\repo")), - /// TfsPullRequests(new Uri("http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository"), "refs/heads/feature/myfeature")); + /// TfsPullRequests( + /// new Uri("http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository"), + /// "refs/heads/feature/myfeature", + /// PrcaAuthenticationNtlm())); /// ]]> /// /// @@ -41,13 +145,15 @@ public static class TfsPullRequestSystemAliases public static IPullRequestSystem TfsPullRequests( this ICakeContext context, Uri repositoryUrl, - string sourceBranch) + string sourceBranch, + IPrcaCredentials credentials) { context.NotNull(nameof(context)); repositoryUrl.NotNull(nameof(repositoryUrl)); sourceBranch.NotNullOrWhiteSpace(nameof(sourceBranch)); + credentials.NotNull(nameof(credentials)); - return context.TfsPullRequests(new TfsPullRequestSettings(repositoryUrl, sourceBranch)); + return context.TfsPullRequests(new TfsPullRequestSettings(repositoryUrl, sourceBranch, credentials)); } /// @@ -60,6 +166,8 @@ public static class TfsPullRequestSystemAliases /// Supported URL schemes are HTTP, HTTPS and SSH. /// URLs using SSH scheme are converted to HTTPS. /// ID of the pull request. + /// Credentials to use to authenticate against Team Foundation Server or + /// Visual Studio Team Services. /// Object for writing issues to Team Foundation Server or Visual Studio Team Services pull request. /// /// Report code analysis issues reported as MsBuild warnings to a TFS pull request: @@ -70,7 +178,10 @@ public static class TfsPullRequestSystemAliases /// @"C:\build\msbuild.log", /// MsBuildXmlFileLoggerFormat, /// new DirectoryPath("c:\repo")), - /// TfsPullRequests(new Uri("http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository"), 5)); + /// TfsPullRequests( + /// new Uri("http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository"), + /// 5, + /// PrcaAuthenticationNtlm())); /// ]]> /// /// @@ -79,12 +190,14 @@ public static class TfsPullRequestSystemAliases public static IPullRequestSystem TfsPullRequests( this ICakeContext context, Uri repositoryUrl, - int pullRequestId) + int pullRequestId, + IPrcaCredentials credentials) { context.NotNull(nameof(context)); repositoryUrl.NotNull(nameof(repositoryUrl)); + credentials.NotNull(nameof(credentials)); - return context.TfsPullRequests(new TfsPullRequestSettings(repositoryUrl, pullRequestId)); + return context.TfsPullRequests(new TfsPullRequestSettings(repositoryUrl, pullRequestId, credentials)); } /// @@ -101,7 +214,8 @@ public static class TfsPullRequestSystemAliases /// var pullRequestSettings = /// new TfsPullRequestSettings( /// new Uri("http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository"), - /// "refs/heads/feature/myfeature"); + /// "refs/heads/feature/myfeature", + /// PrcaAuthenticationNtlm()); /// /// ReportCodeAnalysisIssuesToPullRequest( /// MsBuildCodeAnalysis( From 2c4fbea3af5d0e21a965a8cc855f7a2637eda443 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 16:06:29 +0100 Subject: [PATCH 07/18] (GH-5) Fix typo --- src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs index f5743e9..b2253ce 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSettings.cs @@ -64,7 +64,7 @@ public TfsPullRequestSettings(Uri repositoryUrl, int pullRequestId, IPrcaCredent public int? PullRequestId { get; private set; } /// - /// Gets the credetials used to authenticate against Team Foundation Server or + /// Gets the credentials used to authenticate against Team Foundation Server or /// Visual Studio Team Services. /// public IPrcaCredentials Credentials { get; private set; } From e4267fe3574eedf5143fdc937c961cd29b8085de Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 16:14:09 +0100 Subject: [PATCH 08/18] (GH-5) Fix code analysis issues --- .../Authentication/AuthenticationProviderTests.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/AuthenticationProviderTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/AuthenticationProviderTests.cs index 26e4f7a..87b3d86 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/AuthenticationProviderTests.cs +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/Authentication/AuthenticationProviderTests.cs @@ -1,7 +1,7 @@ namespace Cake.Prca.PullRequests.Tfs.Tests.Authentication { - using Tfs.Authentication; using Shouldly; + using Tfs.Authentication; using Xunit; public class AuthenticationProviderTests @@ -94,7 +94,7 @@ public void Should_Return_PrcaBasicCredentials_Object() [Fact] public void Should_Set_User_Name() { - // Given + // Given const string userName = "foo"; // When @@ -108,7 +108,7 @@ public void Should_Set_User_Name() [Fact] public void Should_Set_Password() { - // Given + // Given const string password = "bar"; // When @@ -165,7 +165,7 @@ public void Should_Return_PrcaBasicCredentials_Object() [Fact] public void Should_Set_Personal_Access_Token() { - // Given + // Given const string personalAccessToken = "foo"; // When @@ -223,7 +223,7 @@ public void Should_Return_PrcaOAuthCredentials_Object() [Fact] public void Should_Set_Access_Token() { - // Given + // Given const string accessToken = "foo"; // When @@ -310,7 +310,7 @@ public void Should_Return_PrcaAadCredentials_Object() [Fact] public void Should_Set_User_Name() { - // Given + // Given const string userName = "foo"; // When @@ -324,7 +324,7 @@ public void Should_Set_User_Name() [Fact] public void Should_Set_Password() { - // Given + // Given const string password = "bar"; // When From 4878798e130b70cba9dba3a306827fbaa33e218c Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Wed, 22 Mar 2017 08:39:33 +0100 Subject: [PATCH 09/18] (GH-15) Update MarkThreadAsFixed to 0.2 API --- .../TfsPullRequestSystem.cs | 59 ++++++------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs index 7a20adc..b87f75a 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs @@ -2,7 +2,6 @@ { using System; using System.Collections.Generic; - using System.Globalization; using System.Linq; using System.Threading; using Core.Diagnostics; @@ -20,8 +19,6 @@ public sealed class TfsPullRequestSystem : PullRequestSystem private readonly RepositoryDescription repositoryDescription; private readonly GitPullRequest pullRequest; - private readonly List cachedDiscussionThreads = new List(); - /// /// Initializes a new instance of the class. /// Connects to the TFS server using NTLM authentication. @@ -97,8 +94,6 @@ public TfsPullRequestSystem(ICakeLog log, TfsPullRequestSettings settings) /// public override IEnumerable FetchActiveDiscussionThreads(string commentSource) { - this.cachedDiscussionThreads.Clear(); - using (var gitClient = this.CreateGitClient()) { var request = @@ -117,7 +112,6 @@ public override IEnumerable FetchActiveDiscussionThreads( { if (thread.IsCommentSource(commentSource) && thread.Status == CommentThreadStatus.Active) { - this.cachedDiscussionThreads.Add(thread); threadList.Add(thread.ToPrcaDiscussionThread()); } } @@ -177,44 +171,29 @@ public override IEnumerable GetModifiedFilesInPullRequest() } /// - public override void MarkThreadAsFixed(IPrcaDiscussionThread thread) + public override void MarkThreadsAsFixed(IEnumerable threads) { - thread.NotNull(nameof(thread)); - - var threads = this.cachedDiscussionThreads.Where(x => x.Id == thread.Id).ToList(); - - if (!threads.Any()) - { - throw new PrcaException( - string.Format( - CultureInfo.InvariantCulture, - "Thread with ID {0} not found", - thread.Id)); - } - - if (threads.Count != 1) - { - throw new PrcaException( - string.Format( - CultureInfo.InvariantCulture, - "Found more than one thread with ID {0}", - thread.Id)); - } - - var newThread = new GitPullRequestCommentThread - { - Status = CommentThreadStatus.Fixed - }; + // ReSharper disable once PossibleMultipleEnumeration + threads.NotNull(nameof(threads)); using (var gitClient = this.CreateGitClient()) { - gitClient.UpdateThreadAsync( - newThread, - this.pullRequest.Repository.Id, - this.pullRequest.PullRequestId, - threads.Single().Id, - null, - CancellationToken.None).Wait(); + // ReSharper disable once PossibleMultipleEnumeration + foreach (var thread in threads) + { + var newThread = new GitPullRequestCommentThread + { + Status = CommentThreadStatus.Fixed + }; + + gitClient.UpdateThreadAsync( + newThread, + this.pullRequest.Repository.Id, + this.pullRequest.PullRequestId, + thread.Id, + null, + CancellationToken.None).Wait(); + } } } From 0c12909d16a82c59020021ccf04d250f9187ddb6 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 17:22:43 +0100 Subject: [PATCH 10/18] (GH-15) Ignore issues not related to a file --- src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs index b87f75a..f651e44 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs @@ -286,7 +286,9 @@ private GitHttpClient CreateGitClient() } // ReSharper disable once PossibleMultipleEnumeration - foreach (var issue in issues) + // We currenty don't support issues not related to a file. + // See https://github.com/cake-contrib/Cake.Prca.PullRequests.Tfs/issues/19 + foreach (var issue in issues.Where(x => x.AffectedFileRelativePath != null)) { this.Log.Information( "Creating a discussion comment for the issue at line {0} from {1}", From 4bb559494d466ad6b4ae6edaf3347bb6d977eb18 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 17:32:08 +0100 Subject: [PATCH 11/18] (GH-15) Update required Cake.Prca dependency --- nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec b/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec index 0db8c8b..69f824a 100644 --- a/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec +++ b/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec @@ -15,7 +15,7 @@ Copyright © 2017 BBT Software AG, Root/Zermatt, Switzerland Cake Script PullRequest CodeAnalysis Cake-Prca-PullRequestSystem TFS VSTS Linting - + From 69840fe8a70ddc0b07150bae71db240abe2bd00c Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 18:34:20 +0100 Subject: [PATCH 12/18] (GH-15) Update to Cake.Prca 0.2.0-beta0001 --- .../Cake.Prca.PullRequests.Tfs.csproj | 2 +- src/Cake.Prca.PullRequests.Tfs/packages.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj b/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj index 8708cde..45075e4 100644 --- a/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj +++ b/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj @@ -42,7 +42,7 @@ True - ..\packages\Cake.Prca.0.1.0-beta0001\lib\net45\Cake.Prca.dll + ..\packages\Cake.Prca.0.2.0-beta0001\lib\net45\Cake.Prca.dll True diff --git a/src/Cake.Prca.PullRequests.Tfs/packages.config b/src/Cake.Prca.PullRequests.Tfs/packages.config index 925d368..2b7e287 100644 --- a/src/Cake.Prca.PullRequests.Tfs/packages.config +++ b/src/Cake.Prca.PullRequests.Tfs/packages.config @@ -1,7 +1,7 @@  - + From 06391d54524fc7739fad74d9f82d9c3177a0cc92 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 18:36:55 +0100 Subject: [PATCH 13/18] (GH-15) Add link to release notes --- nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec | 1 + 1 file changed, 1 insertion(+) diff --git a/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec b/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec index 69f824a..38331ca 100644 --- a/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec +++ b/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec @@ -14,6 +14,7 @@ false Copyright © 2017 BBT Software AG, Root/Zermatt, Switzerland Cake Script PullRequest CodeAnalysis Cake-Prca-PullRequestSystem TFS VSTS Linting + https://github.com/cake-contrib/Cake.Prca.PullRequests.Tfs/releases/tag/0.2.0 From 0619c5d103462fc3a08ab9a46d1905fbb274cf35 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 23:11:24 +0100 Subject: [PATCH 14/18] (GH-15) Link to website and improve description --- nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec b/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec index 38331ca..f7584c6 100644 --- a/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec +++ b/nuspec/nuget/Cake.Prca.PullRequests.Tfs.nuspec @@ -7,9 +7,9 @@ BBT Software AG bbtsoftware, pascalberger, cake-contrib TFS support for the Pull Request Code Analysis Addin for Cake Build Automation System - The TFS / VSTS support for the Pull Request Code Analysis Addin for Cake allows you to write found issues to Team Foundation Server or Visual Studio Team Services pull requests. + The TFS / VSTS support for the Pull Request Code Analysis Addin for Cake allows you to write found issues as comments to Team Foundation Server or Visual Studio Team Services pull requests. https://github.com/cake-contrib/Cake.Prca.PullRequests.Tfs/blob/develop/LICENSE - https://github.com/cake-contrib/Cake.Prca.PullRequests.Tfs + http://cake-contrib.github.io/Cake.Prca.Website https://raw.githubusercontent.com/cake-build/graphics/aba74fb4cb5fe9454381af2cc70c870088229d5c/png/cake-medium.png false Copyright © 2017 BBT Software AG, Root/Zermatt, Switzerland From d0bf79583d3ef04f0d34c6d468fa3a57867955ae Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 23 Mar 2017 23:22:28 +0100 Subject: [PATCH 15/18] (GH-15) Update examples to latest version --- .../TfsPullRequestSystemAliases.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs index 7322338..ee4708a 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystemAliases.cs @@ -128,15 +128,17 @@ public static class TfsPullRequestSystemAliases /// Report code analysis issues reported as MsBuild warnings to a TFS pull request: /// /// /// /// @@ -173,15 +175,17 @@ public static class TfsPullRequestSystemAliases /// Report code analysis issues reported as MsBuild warnings to a TFS pull request: /// /// /// /// @@ -211,6 +215,7 @@ public static class TfsPullRequestSystemAliases /// Report code analysis issues reported as MsBuild warnings to a TFS pull request: /// /// /// /// From 8d65afe04cd24b877435a6b97bb73ec7d00dc973 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Fri, 24 Mar 2017 08:20:01 +0100 Subject: [PATCH 16/18] (GH-15) Code cleanup --- .../RepositoryDescriptionTests.cs | 3 +-- .../TfsPullRequestSettingsTests.cs | 6 +++--- src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/RepositoryDescriptionTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/RepositoryDescriptionTests.cs index 290057b..ed825d1 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/RepositoryDescriptionTests.cs +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/RepositoryDescriptionTests.cs @@ -22,8 +22,7 @@ public class RepositoryDescriptionTests public void Should_Throw_If_No_Valid_Url(string repoUrl, string expectedMessage) { // Given / When - RepositoryDescription foo; - var result = Record.Exception(() => foo = new RepositoryDescription(new Uri(repoUrl))); + var result = Record.Exception(() => new RepositoryDescription(new Uri(repoUrl))); // Then result.IsUriFormatExceptionException(expectedMessage); diff --git a/src/Cake.Prca.PullRequests.Tfs.Tests/TfsPullRequestSettingsTests.cs b/src/Cake.Prca.PullRequests.Tfs.Tests/TfsPullRequestSettingsTests.cs index bf0d6b3..7335c36 100644 --- a/src/Cake.Prca.PullRequests.Tfs.Tests/TfsPullRequestSettingsTests.cs +++ b/src/Cake.Prca.PullRequests.Tfs.Tests/TfsPullRequestSettingsTests.cs @@ -11,7 +11,7 @@ public sealed class TheTfsPullRequestSettings public void Should_Throw_If_RepositoryUrl_For_SourceBranch_Is_Null() { // Given / When - var result = Record.Exception(() => new TfsPullRequestSettings((Uri)null, "foo", null)); + var result = Record.Exception(() => new TfsPullRequestSettings(null, "foo", null)); // Then result.IsArgumentNullException("repositoryUrl"); @@ -21,7 +21,7 @@ public void Should_Throw_If_RepositoryUrl_For_SourceBranch_Is_Null() public void Should_Throw_If_SourceBranch_Is_Null() { // Given / When - var result = Record.Exception(() => new TfsPullRequestSettings(new Uri("http://example.com"), (string)null, null)); + var result = Record.Exception(() => new TfsPullRequestSettings(new Uri("http://example.com"), null, null)); // Then result.IsArgumentNullException("sourceBranch"); @@ -51,7 +51,7 @@ public void Should_Throw_If_SourceBranch_Is_WhiteSpace() public void Should_Throw_If_RepositoryUrl_For_PullRequestId_Is_Null() { // Given / When - var result = Record.Exception(() => new TfsPullRequestSettings((Uri)null, 0, null)); + var result = Record.Exception(() => new TfsPullRequestSettings(null, 0, null)); // Then result.IsArgumentNullException("repositoryUrl"); diff --git a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs index f651e44..f6619f6 100644 --- a/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs +++ b/src/Cake.Prca.PullRequests.Tfs/TfsPullRequestSystem.cs @@ -216,7 +216,6 @@ public override void PostDiscussionThreads(IEnumerable issue foreach (var thread in threads) { - // TODO Result handling? gitClient.CreateThreadAsync( thread, this.pullRequest.Repository.Id, @@ -312,7 +311,7 @@ private GitHttpClient CreateGitClient() continue; } - newThread.Comments = new List() { discussionComment }; + newThread.Comments = new List { discussionComment }; result.Add(newThread); } From b79fe8bad57bea2cf27d37c571854dee21f9c2fe Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Fri, 24 Mar 2017 09:56:45 +0100 Subject: [PATCH 17/18] (build) Corrected AppVeyor Configuration --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index afb3780..52e5097 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -22,5 +22,5 @@ branches: # Build Cache # #---------------------------------# cache: -- Source\packages -> Source\**\packages.config +- src\packages -> src\**\packages.config - tools -> setup.cake \ No newline at end of file From bc8c200e222956035dcfc1fd4d806a7dfca3691a Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Fri, 24 Mar 2017 10:00:52 +0100 Subject: [PATCH 18/18] Update to Cake.Prca 0.2.0 --- .../Cake.Prca.PullRequests.Tfs.csproj | 2 +- src/Cake.Prca.PullRequests.Tfs/packages.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj b/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj index 45075e4..34a69d1 100644 --- a/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj +++ b/src/Cake.Prca.PullRequests.Tfs/Cake.Prca.PullRequests.Tfs.csproj @@ -42,7 +42,7 @@ True - ..\packages\Cake.Prca.0.2.0-beta0001\lib\net45\Cake.Prca.dll + ..\packages\Cake.Prca.0.2.0\lib\net45\Cake.Prca.dll True diff --git a/src/Cake.Prca.PullRequests.Tfs/packages.config b/src/Cake.Prca.PullRequests.Tfs/packages.config index 2b7e287..29de75d 100644 --- a/src/Cake.Prca.PullRequests.Tfs/packages.config +++ b/src/Cake.Prca.PullRequests.Tfs/packages.config @@ -1,7 +1,7 @@  - +