diff --git a/.azure-build.yml b/.azure-build.yml index 5aa5420eb..ed24437e4 100644 --- a/.azure-build.yml +++ b/.azure-build.yml @@ -1,7 +1,7 @@ strategy: matrix: Linux: - imageName: 'ubuntu-16.04' + imageName: 'ubuntu-latest' Windows: imageName: 'windows-2019' Mac: diff --git a/Docker/SDK2.1/Dockerfile b/Docker/SDK5.0/Dockerfile similarity index 78% rename from Docker/SDK2.1/Dockerfile rename to Docker/SDK5.0/Dockerfile index fef7b4d54..b9839ce84 100644 --- a/Docker/SDK2.1/Dockerfile +++ b/Docker/SDK5.0/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/core/sdk:2.1 +FROM mcr.microsoft.com/dotnet/sdk:5.0-focal ARG NUKEEPER_VERSION=0.34.0 RUN dotnet tool install --global NuKeeper --version $NUKEEPER_VERSION ENV PATH="${PATH}:/root/.dotnet/tools" diff --git a/NuKeeper.Abstractions.Tests/NuKeeper.Abstractions.Tests.csproj b/NuKeeper.Abstractions.Tests/NuKeeper.Abstractions.Tests.csproj index c0915806e..dd63432c0 100644 --- a/NuKeeper.Abstractions.Tests/NuKeeper.Abstractions.Tests.csproj +++ b/NuKeeper.Abstractions.Tests/NuKeeper.Abstractions.Tests.csproj @@ -10,14 +10,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NuKeeper.Abstractions/Configuration/AuthSettings.cs b/NuKeeper.Abstractions/Configuration/AuthSettings.cs index 3b5b94eed..10fb541a6 100644 --- a/NuKeeper.Abstractions/Configuration/AuthSettings.cs +++ b/NuKeeper.Abstractions/Configuration/AuthSettings.cs @@ -4,6 +4,13 @@ namespace NuKeeper.Abstractions.Configuration { public class AuthSettings { + /// + /// Provide the credentials required to authenticate against a different repository providers. + /// + /// Repository URLs e.g. https://dev.azure.com/ or https://api.github.com/ or https://developer.atlassian.com/bitbucket/api/2/reference/ + /// Personal Access Tokens or Client Secret. The GitHub client with use anonymous authentication it the token is blank. I.e. public repositories + /// + /// See for a similar model. public AuthSettings(Uri apiBase, string token, string username = null) { ApiBase = apiBase; diff --git a/NuKeeper.Abstractions/NuKeeper.Abstractions.csproj b/NuKeeper.Abstractions/NuKeeper.Abstractions.csproj index cb0504778..ebeda497a 100644 --- a/NuKeeper.Abstractions/NuKeeper.Abstractions.csproj +++ b/NuKeeper.Abstractions/NuKeeper.Abstractions.csproj @@ -9,9 +9,9 @@ - + - + diff --git a/NuKeeper.AzureDevOps/AzureDevOpsSettingsReader.cs b/NuKeeper.AzureDevOps/AzureDevOpsSettingsReader.cs index e02146b68..c55988abf 100644 --- a/NuKeeper.AzureDevOps/AzureDevOpsSettingsReader.cs +++ b/NuKeeper.AzureDevOps/AzureDevOpsSettingsReader.cs @@ -47,7 +47,7 @@ public override async Task RepositorySettings(Uri repository var settings = repositoryUri.IsFile ? await CreateSettingsFromLocal(repositoryUri, targetBranch) - : CreateSettingsFromRemote(repositoryUri); + : CreateSettingsFromRemote(repositoryUri, targetBranch); if (settings == null) { @@ -59,7 +59,7 @@ public override async Task RepositorySettings(Uri repository return settings; } - private static RepositorySettings CreateSettingsFromRemote(Uri repositoryUri) + private static RepositorySettings CreateSettingsFromRemote(Uri repositoryUri, string targetBranch) { // URL pattern is // https://dev.azure.com/{org}/{project}/_git/{repo}/ @@ -80,8 +80,8 @@ private static RepositorySettings CreateSettingsFromRemote(Uri repositoryUri) pathParts[0], //org repositoryUri, //uri Uri.UnescapeDataString(pathParts[1]), // project - Uri.UnescapeDataString(pathParts[3]) // reponame - ); + Uri.UnescapeDataString(pathParts[3]), // reponame + new RemoteInfo { BranchName = targetBranch }); } else if (indexOfGit == 1 && pathParts.Length == 3) { @@ -89,15 +89,18 @@ private static RepositorySettings CreateSettingsFromRemote(Uri repositoryUri) null, //org repositoryUri, //uri Uri.UnescapeDataString(pathParts[0]), // project - Uri.UnescapeDataString(pathParts[2]) // reponame - ); + Uri.UnescapeDataString(pathParts[2]), // reponame + new RemoteInfo { BranchName = targetBranch }); } return null; } private async Task CreateSettingsFromLocal(Uri repositoryUri, string targetBranch) { - var remoteInfo = new RemoteInfo(); + var remoteInfo = new RemoteInfo() + { + BranchName = targetBranch, + }; var localCopy = repositoryUri; if (await _gitDriver.IsGitRepo(repositoryUri)) @@ -138,7 +141,8 @@ private async Task CreateSettingsFromLocal(Uri repositoryUri pathParts[0], //org repositoryUri, //uri Uri.UnescapeDataString(pathParts[1]), // project - Uri.UnescapeDataString(pathParts[3]) // reponame + Uri.UnescapeDataString(pathParts[3]), // reponame + remoteInfo ); } else if (indexOfGit == 1 && pathParts.Length == 3) @@ -147,7 +151,8 @@ private async Task CreateSettingsFromLocal(Uri repositoryUri null, //org repositoryUri, //uri Uri.UnescapeDataString(pathParts[0]), // project - Uri.UnescapeDataString(pathParts[2]) // reponame + Uri.UnescapeDataString(pathParts[2]), // reponame + remoteInfo ); } return null; diff --git a/NuKeeper.Git.Tests/NuKeeper.Git.Tests.csproj b/NuKeeper.Git.Tests/NuKeeper.Git.Tests.csproj index d8e8178f4..037a652d8 100644 --- a/NuKeeper.Git.Tests/NuKeeper.Git.Tests.csproj +++ b/NuKeeper.Git.Tests/NuKeeper.Git.Tests.csproj @@ -15,14 +15,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NuKeeper.GitHub.Tests/NuKeeper.GitHub.Tests.csproj b/NuKeeper.GitHub.Tests/NuKeeper.GitHub.Tests.csproj index 0ebd22a53..d155d4613 100644 --- a/NuKeeper.GitHub.Tests/NuKeeper.GitHub.Tests.csproj +++ b/NuKeeper.GitHub.Tests/NuKeeper.GitHub.Tests.csproj @@ -9,14 +9,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NuKeeper.GitHub/NuKeeper.GitHub.csproj b/NuKeeper.GitHub/NuKeeper.GitHub.csproj index b236720fd..55346b3a0 100644 --- a/NuKeeper.GitHub/NuKeeper.GitHub.csproj +++ b/NuKeeper.GitHub/NuKeeper.GitHub.csproj @@ -9,7 +9,7 @@ - + diff --git a/NuKeeper.GitHub/OctokitClient.cs b/NuKeeper.GitHub/OctokitClient.cs index f59f67c3d..688678687 100644 --- a/NuKeeper.GitHub/OctokitClient.cs +++ b/NuKeeper.GitHub/OctokitClient.cs @@ -40,12 +40,20 @@ public void Initialise(AuthSettings settings) } _apiBase = settings.ApiBase; + Credentials creds; + if (string.IsNullOrWhiteSpace(settings.Token)) + { + creds = Credentials.Anonymous; + } + else + { + creds = new Credentials(settings.Token, AuthenticationType.Oauth); + } _client = new GitHubClient(new ProductHeaderValue("NuKeeper"), _apiBase) { - Credentials = new Credentials(settings.Token) + Credentials = creds }; - _initialised = true; } @@ -206,7 +214,6 @@ public async Task Search(SearchCodeRequest search) { repos.Add(repo.Owner, repo.Name); } - var result = await _client.Search.SearchCode( new Octokit.SearchCodeRequest() { diff --git a/NuKeeper.Gitea.Tests/NuKeeper.Gitea.Tests.csproj b/NuKeeper.Gitea.Tests/NuKeeper.Gitea.Tests.csproj index 166b4ca3f..eeb77c74b 100644 --- a/NuKeeper.Gitea.Tests/NuKeeper.Gitea.Tests.csproj +++ b/NuKeeper.Gitea.Tests/NuKeeper.Gitea.Tests.csproj @@ -9,14 +9,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NuKeeper.Gitlab.Tests/NuKeeper.Gitlab.Tests.csproj b/NuKeeper.Gitlab.Tests/NuKeeper.Gitlab.Tests.csproj index edd513046..6135116d9 100644 --- a/NuKeeper.Gitlab.Tests/NuKeeper.Gitlab.Tests.csproj +++ b/NuKeeper.Gitlab.Tests/NuKeeper.Gitlab.Tests.csproj @@ -10,14 +10,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NuKeeper.Inspection.Tests/NuKeeper.Inspection.Tests.csproj b/NuKeeper.Inspection.Tests/NuKeeper.Inspection.Tests.csproj index 814c93984..0175155be 100644 --- a/NuKeeper.Inspection.Tests/NuKeeper.Inspection.Tests.csproj +++ b/NuKeeper.Inspection.Tests/NuKeeper.Inspection.Tests.csproj @@ -7,14 +7,14 @@ ..\CodeAnalysisRulesForTests.ruleset - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NuKeeper.Integration.Tests/Engine/RepositoryFilterTests.cs b/NuKeeper.Integration.Tests/Engine/RepositoryFilterTests.cs index 7314eb6d5..7a3f12583 100644 --- a/NuKeeper.Integration.Tests/Engine/RepositoryFilterTests.cs +++ b/NuKeeper.Integration.Tests/Engine/RepositoryFilterTests.cs @@ -37,12 +37,10 @@ public async Task ShouldNotFilterOutADotnetRepository() } private RepositoryFilter MakeRepositoryFilter() - { - const string testKeyWithOnlyPublicAccess = "c13d2ce7774d39ae99ddaad46bd69c3d459b9992"; - + { var collaborationFactory = Substitute.For(); var gitHubClient = new OctokitClient(NukeeperLogger); - gitHubClient.Initialise(new AuthSettings(new Uri("https://api.github.com"), testKeyWithOnlyPublicAccess)); + gitHubClient.Initialise(new AuthSettings(new Uri("https://api.github.com"), "")); collaborationFactory.CollaborationPlatform.Returns(gitHubClient); return new RepositoryFilter(collaborationFactory, NukeeperLogger); diff --git a/NuKeeper.Integration.Tests/NuGet/Process/DotNetUpdatePackageCommandTests.cs b/NuKeeper.Integration.Tests/NuGet/Process/DotNetUpdatePackageCommandTests.cs index f90b747e5..cd578c1d3 100644 --- a/NuKeeper.Integration.Tests/NuGet/Process/DotNetUpdatePackageCommandTests.cs +++ b/NuKeeper.Integration.Tests/NuGet/Process/DotNetUpdatePackageCommandTests.cs @@ -109,6 +109,13 @@ public async Task ShouldUpdateDotnetClassicWithPackageReference() await ExecuteValidUpdateTest(_testDotNetClassicProject, PackageReferenceType.ProjectFileOldStyle); } + [Test] + public async Task ShouldUpdateProjectFilenameWithSpaces() + { + await ExecuteValidUpdateTest(_testDotNetClassicProject, PackageReferenceType.ProjectFileOldStyle, "Project With Spaces.csproj"); + } + + private async Task ExecuteValidUpdateTest( string testProjectContents, PackageReferenceType packageReferenceType, diff --git a/NuKeeper.Integration.Tests/NuKeeper.Integration.Tests.csproj b/NuKeeper.Integration.Tests/NuKeeper.Integration.Tests.csproj index ae7aa9b4f..79c9a4568 100644 --- a/NuKeeper.Integration.Tests/NuKeeper.Integration.Tests.csproj +++ b/NuKeeper.Integration.Tests/NuKeeper.Integration.Tests.csproj @@ -4,18 +4,18 @@ ..\CodeAnalysisRulesForTests.ruleset - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/NuKeeper.Tests/Engine/NugetRestoreTests.cs b/NuKeeper.Tests/Engine/NugetRestoreTests.cs new file mode 100644 index 000000000..c57c2963e --- /dev/null +++ b/NuKeeper.Tests/Engine/NugetRestoreTests.cs @@ -0,0 +1,51 @@ +using NSubstitute; +using NuKeeper.Abstractions.Logging; +using NuKeeper.Abstractions.NuGet; +using NuKeeper.Update.Process; +using NuKeeper.Update.ProcessRunner; +using NUnit.Framework; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace NuKeeper.Tests.Engine +{ + [TestFixture] + public class NugetRestoreTests + { + [Test] + public async Task WhenNugetRestoreIsCalledThenArgsIncludePackageDirectory() + { + var logger = Substitute.For(); + var nuGetPath = Substitute.For(); + var monoExecuter = Substitute.For(); + var externalProcess = Substitute.For(); + var file = new FileInfo("packages.config"); + nuGetPath.Executable.Returns(@"c:\DoesNotExist\nuget.exe"); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + externalProcess.Run(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()).Returns(new ProcessOutput("", "", 0)); + } + else + { + monoExecuter.CanRun().Returns(true); + monoExecuter.Run(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()).Returns(new ProcessOutput("", "", 0)); + } + var cmd = new NuGetFileRestoreCommand(logger, nuGetPath, monoExecuter, externalProcess); + + await cmd.Invoke(file, NuGetSources.GlobalFeed); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + await externalProcess.Received(1).Run(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()); + await externalProcess.ReceivedWithAnyArgs().Run(Arg.Any(), Arg.Any(), $"restore {file.Name} - Source ${NuGetSources.GlobalFeed} -NonInteractive -PackagesDirectory ..\\packages", Arg.Any()); + } + else + { + logger.DidNotReceiveWithAnyArgs().Error(Arg.Any(), Arg.Any()); + await monoExecuter.Received(1).Run(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()); + await monoExecuter.ReceivedWithAnyArgs().Run(Arg.Any(), Arg.Any(), $"restore {file.Name} - Source ${NuGetSources.GlobalFeed} -NonInteractive -PackagesDirectory ..\\packages", Arg.Any()); + } + } + } +} diff --git a/NuKeeper.Tests/NuKeeper.Tests.csproj b/NuKeeper.Tests/NuKeeper.Tests.csproj index 8ad48c5a1..103fa27ea 100644 --- a/NuKeeper.Tests/NuKeeper.Tests.csproj +++ b/NuKeeper.Tests/NuKeeper.Tests.csproj @@ -4,18 +4,18 @@ ..\CodeAnalysisRulesForTests.ruleset - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/NuKeeper.Update.Tests/NuKeeper.Update.Tests.csproj b/NuKeeper.Update.Tests/NuKeeper.Update.Tests.csproj index 513ca4b10..9510a5e31 100644 --- a/NuKeeper.Update.Tests/NuKeeper.Update.Tests.csproj +++ b/NuKeeper.Update.Tests/NuKeeper.Update.Tests.csproj @@ -7,14 +7,14 @@ ..\CodeAnalysisRulesForTests.ruleset - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NuKeeper.Update/Process/DotNetUpdatePackageCommand.cs b/NuKeeper.Update/Process/DotNetUpdatePackageCommand.cs index c8d65bf98..c0c67d2af 100644 --- a/NuKeeper.Update/Process/DotNetUpdatePackageCommand.cs +++ b/NuKeeper.Update/Process/DotNetUpdatePackageCommand.cs @@ -37,20 +37,20 @@ public DotNetUpdatePackageCommand(IExternalProcess externalProcess) } var projectPath = currentPackage.Path.Info.DirectoryName; - var projectFileName = currentPackage.Path.Info.Name; + var projectFileNameCommandLine = ArgumentEscaper.EscapeAndConcatenate(new string[] { currentPackage.Path.Info.Name }); var sourceUrl = UriEscapedForArgument(packageSource.SourceUri); var sources = allSources.CommandLine("-s"); - var restoreCommand = $"restore {projectFileName} {sources}"; + var restoreCommand = $"restore {projectFileNameCommandLine} {sources}"; await _externalProcess.Run(projectPath, "dotnet", restoreCommand, true); if (currentPackage.Path.PackageReferenceType == PackageReferenceType.ProjectFileOldStyle) { - var removeCommand = $"remove {projectFileName} package {currentPackage.Id}"; + var removeCommand = $"remove {projectFileNameCommandLine} package {currentPackage.Id}"; await _externalProcess.Run(projectPath, "dotnet", removeCommand, true); } - var addCommand = $"add {projectFileName} package {currentPackage.Id} -v {newVersion} -s {sourceUrl}"; + var addCommand = $"add {projectFileNameCommandLine} package {currentPackage.Id} -v {newVersion} -s {sourceUrl}"; await _externalProcess.Run(projectPath, "dotnet", addCommand, true); } diff --git a/NuKeeper.Update/Process/NuGetFileRestoreCommand.cs b/NuKeeper.Update/Process/NuGetFileRestoreCommand.cs index 3413cba46..9294d7be0 100644 --- a/NuKeeper.Update/Process/NuGetFileRestoreCommand.cs +++ b/NuKeeper.Update/Process/NuGetFileRestoreCommand.cs @@ -55,8 +55,13 @@ public async Task Invoke(FileInfo file, NuGetSources sources) var fileNameCommandLine = ArgumentEscaper.EscapeAndConcatenate(new[] { file.Name }); var sourcesCommandLine = sources.CommandLine("-Source"); + string restoreCommand = $"restore {fileNameCommandLine} {sourcesCommandLine} -NonInteractive"; - var restoreCommand = $"restore {fileNameCommandLine} {sourcesCommandLine} -NonInteractive"; + // see: https://docs.microsoft.com/en-us/nuget/reference/cli-reference/cli-ref-restore + if (string.Equals(file.Name, "packages.config", StringComparison.OrdinalIgnoreCase)) + { + restoreCommand = $"{restoreCommand} -PackagesDirectory ..\\packages"; + } ProcessOutput processOutput; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) diff --git a/NuKeeper/NuKeeper.csproj b/NuKeeper/NuKeeper.csproj index 74ed5cf79..e95d4a1b9 100644 --- a/NuKeeper/NuKeeper.csproj +++ b/NuKeeper/NuKeeper.csproj @@ -1,6 +1,6 @@ - netcoreapp2.1;netcoreapp3.1;net5.0 + netcoreapp3.1;net5.0 Exe true nukeeper @@ -12,15 +12,15 @@ ..\CodeAnalysisRules.ruleset - - + + runtime; build; native; contentfiles; analyzers all - - - + + + @@ -41,7 +41,7 @@ - + true tools\$(TargetFramework)\any\NuGet.exe diff --git a/Nukeeper.AzureDevOps.Tests/AzureDevOpsSettingsReaderTests.cs b/Nukeeper.AzureDevOps.Tests/AzureDevOpsSettingsReaderTests.cs index dfa67cc79..c0f8b5508 100644 --- a/Nukeeper.AzureDevOps.Tests/AzureDevOpsSettingsReaderTests.cs +++ b/Nukeeper.AzureDevOps.Tests/AzureDevOpsSettingsReaderTests.cs @@ -82,7 +82,7 @@ public async Task InvalidUrlReturnsNull(string value) [Test] public async Task RepositorySettings_GetsCorrectSettingsOrganisation() { - var settings = await _azureSettingsReader.RepositorySettings(new Uri("https://dev.azure.com/org/project/_git/reponame"), true); + var settings = await _azureSettingsReader.RepositorySettings(new Uri("https://dev.azure.com/org/project/_git/reponame"), true, "develop"); Assert.IsNotNull(settings); Assert.AreEqual(settings.ApiUri, "https://dev.azure.com/org/"); @@ -90,12 +90,13 @@ public async Task RepositorySettings_GetsCorrectSettingsOrganisation() Assert.AreEqual(settings.RepositoryName, "reponame"); Assert.AreEqual(settings.RepositoryOwner, "project"); Assert.AreEqual(settings.SetAutoMerge, true); + Assert.AreEqual(settings.RemoteInfo.BranchName, "develop"); } [Test] public async Task RepositorySettings_GetsCorrectSettingsPrivate() { - var settings = await _azureSettingsReader.RepositorySettings(new Uri("https://dev.azure.com/owner/_git/reponame"), true); + var settings = await _azureSettingsReader.RepositorySettings(new Uri("https://dev.azure.com/owner/_git/reponame"), true, "main"); Assert.IsNotNull(settings); Assert.AreEqual(settings.ApiUri, "https://dev.azure.com/"); @@ -103,6 +104,7 @@ public async Task RepositorySettings_GetsCorrectSettingsPrivate() Assert.AreEqual(settings.RepositoryName, "reponame"); Assert.AreEqual(settings.RepositoryOwner, "owner"); Assert.AreEqual(settings.SetAutoMerge, true); + Assert.AreEqual(settings.RemoteInfo.BranchName, "main"); } [Test] @@ -129,6 +131,5 @@ public async Task RepositorySettings_HandlesSpacesInRepo() Assert.AreEqual("repo name", settings.RepositoryName); Assert.AreEqual("project name", settings.RepositoryOwner); } - } } diff --git a/Nukeeper.AzureDevOps.Tests/Nukeeper.AzureDevOps.Tests.csproj b/Nukeeper.AzureDevOps.Tests/Nukeeper.AzureDevOps.Tests.csproj index 144c0552d..563930782 100644 --- a/Nukeeper.AzureDevOps.Tests/Nukeeper.AzureDevOps.Tests.csproj +++ b/Nukeeper.AzureDevOps.Tests/Nukeeper.AzureDevOps.Tests.csproj @@ -10,14 +10,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Nukeeper.BitBucketLocal/BitBucketLocalPlatform.cs b/Nukeeper.BitBucketLocal/BitBucketLocalPlatform.cs index 84c179981..04ef06f99 100644 --- a/Nukeeper.BitBucketLocal/BitBucketLocalPlatform.cs +++ b/Nukeeper.BitBucketLocal/BitBucketLocalPlatform.cs @@ -66,7 +66,7 @@ public async Task OpenPullRequest(ForkData target, PullRequestRequest request, I var repositories = await _client.GetGitRepositories(target.Owner); var targetRepository = repositories.FirstOrDefault(x => x.Name.Equals(target.Name, StringComparison.InvariantCultureIgnoreCase)); - var reviewers = await _client.GetBitBucketReviewers(target.Owner, targetRepository.Name); + var reviewers = await _client.GetBitBucketReviewers(target.Owner, targetRepository.Name, targetRepository.Id, request.Head, request.BaseRef); var pullReq = new PullRequest { diff --git a/Nukeeper.BitBucketLocal/BitBucketLocalSettingsReader.cs b/Nukeeper.BitBucketLocal/BitBucketLocalSettingsReader.cs index d66ceec2e..0f241e3df 100644 --- a/Nukeeper.BitBucketLocal/BitBucketLocalSettingsReader.cs +++ b/Nukeeper.BitBucketLocal/BitBucketLocalSettingsReader.cs @@ -55,7 +55,8 @@ public Task RepositorySettings(Uri repositoryUri, bool setAu ApiUri = new Uri($"{repositoryUri.Scheme}://{repositoryUri.Authority}"), RepositoryUri = repositoryUri, RepositoryName = repoName, - RepositoryOwner = project + RepositoryOwner = project, + RemoteInfo = targetBranch != null ? new RemoteInfo { BranchName = targetBranch } : null }); } diff --git a/Nukeeper.BitBucketLocal/BitbucketLocalRestClient.cs b/Nukeeper.BitBucketLocal/BitbucketLocalRestClient.cs index 98d3faeaa..9a248762f 100644 --- a/Nukeeper.BitBucketLocal/BitbucketLocalRestClient.cs +++ b/Nukeeper.BitBucketLocal/BitbucketLocalRestClient.cs @@ -138,10 +138,11 @@ public async Task CreatePullRequest(PullRequest pullReq, string pro return await HandleResponse(response, caller); } - public async Task> GetBitBucketReviewers(string projectName, string repositoryName, [CallerMemberName] string caller = null) + public async Task> GetBitBucketReviewers(string projectName, string repositoryName, int repositoryId, string head, string baseRef, [CallerMemberName] string caller = null) { - var response = await GetResourceOrEmpty>($@"{ApiReviewersPath}/projects/{projectName}/repos/{repositoryName}/conditions", caller); - return response.SelectMany(c => c.Reviewers).Select(usr => new PullRequestReviewer() { User = usr }); + var response = await GetResourceOrEmpty>($@"{ApiReviewersPath}/projects/{projectName}/repos/{repositoryName}/reviewers?sourceRepoId={repositoryId}&targetRepoId={repositoryId}&sourceRefId={head}&targetRefId={baseRef}", caller); + + return response.Where(r => r.Active).Select(user => new PullRequestReviewer { User = user }); } } } diff --git a/Nukeeper.BitBucketLocal/Models/Reviewer.cs b/Nukeeper.BitBucketLocal/Models/Reviewer.cs index db851e555..761cd2100 100644 --- a/Nukeeper.BitBucketLocal/Models/Reviewer.cs +++ b/Nukeeper.BitBucketLocal/Models/Reviewer.cs @@ -6,5 +6,8 @@ public class Reviewer { [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("active")] + public bool Active { get; set; } } -} \ No newline at end of file +} diff --git a/site/content/platform/azure-devops.md b/site/content/platform/azure-devops.md index 3248af361..e30fa545c 100644 --- a/site/content/platform/azure-devops.md +++ b/site/content/platform/azure-devops.md @@ -18,35 +18,35 @@ Azure Devops gives us the option to do it either in editor mode, or in yaml. #### Yaml 1. Add a new build pipeline and select yaml. 1. Add the following **yaml** file and adjust where necessary: - ```yml - trigger: none # don't run as CI build - - schedules: - - cron: "0 0 * * *" # run daily at UTC midnight - displayName: Check for updated dependencies - branches: - include: - - master - always: true # regardless of changes - - resources: - - repo: self # point to its own repo, change it if you don't want that - - pool: - name: Hosted VS2017 # can be anything you want - - steps: - - task: nukeeper.nukeeper.nukeeper.NuKeeper@0 - displayName: NuKeeper - ``` -1. Optionally add extra arguments, The extension just calls the **repo** command, so any arguments extra for your repo command can be added here. - ```yml - steps: - - task: nukeeper.nukeeper.nukeeper.NuKeeper@0 +```yml +trigger: none # don't run as CI build + +schedules: +- cron: "0 0 * * *" # run daily at UTC midnight + displayName: Check for updated dependencies + branches: + include: + - master + always: true # regardless of changes + +resources: + - repo: self # point to its own repo, change it if you don't want that + +pool: + name: Hosted VS2017 # can be anything you want + +steps: + - task: nukeeper.nukeeper.nukeeper.NuKeeper@0 displayName: NuKeeper - inputs: - arguments: '-m 3 -v d' - ``` +``` +1. Optionally add extra arguments, The extension just calls the **repo** command, so any arguments extra for your repo command can be added here. +```yml +steps: +- task: nukeeper.nukeeper.nukeeper.NuKeeper@0 +displayName: NuKeeper +inputs: + arguments: '-m 3 -v d' +``` 1. Finally give the **build service user** the required *[Permissions](#permissions)* and take it for a spin by qeueing a new build! #### Editor mode