Skip to content
This repository has been archived by the owner on Jul 12, 2022. It is now read-only.

Commit

Permalink
Possibility to name the branch NuKeeper makes for adding the updates …
Browse files Browse the repository at this point in the history
…(Feature #813) (#841)

* All is there except for BitBucketLocal, working on that.

* test fix

* BitBucketLocal update.

* Textual change and site update

* Fix Conflicts

* Fixes after merge and test

* test fix after merge

* typo

* Removed coda that potentially could destroy work

* Some fixes SonarQube pointed out and fixes for GitCmdDriver(test)

* usings fix

* added NukeeperLogger to last test

Co-authored-by: Stephan Tuinder <stuinder@sib.inlichtingenbureau.nl>
  • Loading branch information
StephanTuinder and Stephan Tuinder committed May 5, 2020
1 parent e9f7a7f commit bd22335
Show file tree
Hide file tree
Showing 63 changed files with 1,280 additions and 617 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using System;
using System.Globalization;
using System.IO;
using NSubstitute;
using NuKeeper.Abstractions.CollaborationPlatform;
using NuKeeper.Abstractions.Configuration;
using NuKeeper.Abstractions.Inspections.Files;
using NuKeeper.Abstractions.Logging;
using NuKeeper.Abstractions.Output;
using NUnit.Framework;
using System;
using System.Globalization;
using System.IO;

namespace NuKeeper.Abstractions.Tests.Configuration
{
Expand All @@ -30,7 +29,7 @@ public void TearDown()
Directory.Delete(_uniqueTemporaryFolder, true);
}
}



[Test]
Expand Down Expand Up @@ -58,7 +57,7 @@ public void MissingFileReturnsNoSettings()
Assert.That(data.OutputFileName, Is.Null);
Assert.That(data.LogDestination, Is.Null);
Assert.That(data.Platform, Is.Null);
Assert.That(data.BranchNamePrefix, Is.Null);
Assert.That(data.BranchNameTemplate, Is.Null);
Assert.That(data.DeleteBranchAfterMerge, Is.Null);
}

Expand Down Expand Up @@ -89,7 +88,7 @@ public void EmptyConfigReturnsNoSettings()
Assert.That(data.OutputFileName, Is.Null);
Assert.That(data.LogDestination, Is.Null);
Assert.That(data.Platform, Is.Null);
Assert.That(data.BranchNamePrefix, Is.Null);
Assert.That(data.BranchNameTemplate, Is.Null);
Assert.That(data.DeleteBranchAfterMerge, Is.Null);
}

Expand All @@ -102,7 +101,7 @@ public void EmptyConfigReturnsNoSettings()
""excludeRepos"":""repoOut"",
""label"": [ ""foo"", ""bar"" ],
""logFile"":""somefile.log"",
""branchNamePrefix"": ""nukeeper"",
""branchNameTemplate"": ""nukeeper/MyBranch"",
""maxPackageUpdates"": 42,
""maxRepo"": 12,
""verbosity"": ""Detailed"",
Expand Down Expand Up @@ -135,7 +134,7 @@ public void PopulatedConfigReturnsAllStringSettings()
Assert.That(data.ExcludeRepos, Is.EqualTo("repoOut"));
Assert.That(data.LogFile, Is.EqualTo("somefile.log"));
Assert.That(data.OutputFileName, Is.EqualTo("out_42.txt"));
Assert.That(data.BranchNamePrefix, Is.EqualTo("nukeeper"));
Assert.That(data.BranchNameTemplate, Is.EqualTo("nukeeper/MyBranch"));
Assert.That(data.DeleteBranchAfterMerge, Is.EqualTo(true));
}

Expand Down Expand Up @@ -188,7 +187,7 @@ public void PopulatedConfigReturnsEnumSettings()
}

[Test]
public void ConfigKeysAreCaseInsensitive()
public void ConfigKeysAreCaseInsensitive()
{
const string configData = @"{
""Age"":""3d"",
Expand All @@ -201,7 +200,7 @@ public void ConfigKeysAreCaseInsensitive()
""MAXrepo"":3,
""vErBoSiTy"": ""Q"",
""CHANGE"": ""PATCH"",
""bRanCHNamEPREfiX"": ""nukeeper"",
""bRanCHNamETempLATe"": ""nukeeper/MyBranch"",
""deLeTEBranCHafTERMerge"": ""true""
}";

Expand All @@ -223,7 +222,7 @@ public void ConfigKeysAreCaseInsensitive()
Assert.That(data.MaxRepo, Is.EqualTo(3));
Assert.That(data.Verbosity, Is.EqualTo(LogLevel.Quiet));
Assert.That(data.Change, Is.EqualTo(VersionChange.Patch));
Assert.That(data.BranchNamePrefix, Is.EqualTo("nukeeper"));
Assert.That(data.BranchNameTemplate, Is.EqualTo("nukeeper/MyBranch"));
Assert.That(data.DeleteBranchAfterMerge, Is.EqualTo(true));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using NuKeeper.Abstractions.CollaborationModels;
using NuKeeper.Abstractions.Configuration;
using System.Collections.Generic;
using System.Threading.Tasks;
using NuKeeper.Abstractions.CollaborationModels;

namespace NuKeeper.Abstractions.CollaborationPlatform
{
Expand All @@ -11,6 +11,8 @@ public interface ICollaborationPlatform

Task<User> GetCurrentUser();

Task<bool> PullRequestExists(ForkData target, string headBranch, string baseBranch);

Task OpenPullRequest(ForkData target, PullRequestRequest request, IEnumerable<string> labels);

Task<IReadOnlyList<Organization>> GetOrganizations();
Expand Down
2 changes: 1 addition & 1 deletion NuKeeper.Abstractions/Configuration/BranchSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace NuKeeper.Abstractions.Configuration
{
public class BranchSettings
{
public string BranchNamePrefix { get; set; }
public string BranchNameTemplate { get; set; }

public bool DeleteBranchAfterMerge { get; set; }
}
Expand Down
4 changes: 2 additions & 2 deletions NuKeeper.Abstractions/Configuration/FileSettings.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using NuKeeper.Abstractions.CollaborationPlatform;
using NuKeeper.Abstractions.Logging;
using NuKeeper.Abstractions.Output;
using System.Collections.Generic;

#pragma warning disable CA2227

Expand Down Expand Up @@ -39,7 +39,7 @@ public class FileSettings
public LogDestination? LogDestination { get; set; }
public Platform? Platform { get; set; }

public string BranchNamePrefix { get; set; }
public string BranchNameTemplate { get; set; }
public bool? DeleteBranchAfterMerge { get; set; }

public string GitCliPath { get; set; }
Expand Down
25 changes: 24 additions & 1 deletion NuKeeper.Abstractions/Git/IGitDriver.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NuKeeper.Abstractions.Inspections.Files;

Expand All @@ -14,15 +15,37 @@ public interface IGitDriver

Task AddRemote(string name, Uri endpoint);

/// <summary>
/// Checks out a local branch
/// </summary>
/// <param name="branchName"></param>
Task Checkout(string branchName);

Task CheckoutNewBranch(string branchName);
/// <summary>
/// does a checkout of a remote branch
/// </summary>
/// <param name="branchName"></param>
Task CheckoutRemoteToLocal(string branchName);

/// <summary>
/// Creates a new branch
/// </summary>
/// <param name="branchName"></param>
/// <returns></returns>
Task<bool> CheckoutNewBranch(string branchName);

Task Commit(string message);

Task Push(string remoteName, string branchName);

Task<string> GetCurrentHead();

/// <summary>
/// Gets the commit messages that are in branch <paramref name="headBranchName"/> but not in branch <paramref name="baseBranchName"/>
/// </summary>
/// <param name="baseBranchName"></param>
/// <param name="headBranchName"></param>
/// <returns></returns>
Task<IReadOnlyCollection<string>> GetNewCommitMessages(string baseBranchName, string headBranchName);
}
}
29 changes: 23 additions & 6 deletions NuKeeper.AzureDevOps/AzureDevOpsRestClient.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using Newtonsoft.Json;
using NuKeeper.Abstractions;
using NuKeeper.Abstractions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -7,9 +10,7 @@
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using NuKeeper.Abstractions;
using NuKeeper.Abstractions.Logging;
using System.Web;

namespace NuKeeper.AzureDevOps
{
Expand Down Expand Up @@ -86,11 +87,12 @@ private async Task<T> HandleResponse<T>(HttpResponseMessage response, [CallerMem
}
}

private static Uri BuildAzureDevOpsUri(string relativePath, bool previewApi = false)
public static Uri BuildAzureDevOpsUri(string relativePath, bool previewApi = false)
{
var separator = relativePath.Contains("?") ? "&" : "?";
return previewApi
? new Uri($"{relativePath}?api-version=4.1-preview.1", UriKind.Relative)
: new Uri($"{relativePath}?api-version=4.1", UriKind.Relative);
? new Uri($"{relativePath}{separator}api-version=4.1-preview.1", UriKind.Relative)
: new Uri($"{relativePath}{separator}api-version=4.1", UriKind.Relative);
}

public async Task<IEnumerable<Project>> GetProjects()
Expand All @@ -111,6 +113,21 @@ public async Task<IEnumerable<GitRefs>> GetRepositoryRefs(string projectName, st
return response?.value.AsEnumerable();
}

//https://docs.microsoft.com/en-us/rest/api/azure/devops/git/pull%20requests/get%20pull%20requests?view=azure-devops-rest-5.0
public async Task<IEnumerable<PullRequest>> GetPullRequests(
string projectName,
string azureRepositoryId,
string headBranch,
string baseBranch)
{
var encodedBaseBranch = HttpUtility.UrlEncode(baseBranch);
var encodedHeadBranch = HttpUtility.UrlEncode(headBranch);

var response = await GetResource<PullRequestResource>($"{projectName}/_apis/git/repositories/{azureRepositoryId}/pullrequests?searchCriteria.sourceRefName={encodedHeadBranch}&searchCriteria.targetRefName={encodedBaseBranch}");

return response?.value.AsEnumerable();
}

public async Task<PullRequest> CreatePullRequest(PRRequest request, string projectName, string azureRepositoryId)
{
var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
Expand Down
74 changes: 52 additions & 22 deletions NuKeeper.AzureDevOps/AzureDevOpsSettingsReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public override async Task<bool> CanRead(Uri repositoryUri)
return repositoryUri?.Host.Contains(PlatformHost, StringComparison.OrdinalIgnoreCase) == true;
}

public override async Task<RepositorySettings> RepositorySettings(Uri repositoryUri, string targetBranch)
public override async Task<RepositorySettings> RepositorySettings(Uri repositoryUri, string targetBranch = null)
{
if (repositoryUri == null)
{
Expand All @@ -59,23 +59,38 @@ public override async Task<RepositorySettings> RepositorySettings(Uri repository

private RepositorySettings CreateSettingsFromRemote(Uri repositoryUri)
{
// URL pattern is
// URL pattern is
// https://dev.azure.com/{org}/{project}/_git/{repo}/
// for a organisation or
// https://dev.azure.com/{owner}/_git/{repo}
// for a private repository
var path = repositoryUri.AbsolutePath;

var pathParts = path.Split('/')
.Where(s => !string.IsNullOrWhiteSpace(s))
.ToList();
.ToArray();

var indexOfGit = Array.FindIndex(pathParts, t => t.Equals("_git", StringComparison.InvariantCultureIgnoreCase));

if (pathParts.Count != 4)
if (indexOfGit == 2 && pathParts.Length == 4)
{
return null;
return CreateRepositorySettings(
pathParts[0], //org
repositoryUri, //uri
Uri.UnescapeDataString(pathParts[1]), // project
Uri.UnescapeDataString(pathParts[3]) // reponame
);
}

var org = pathParts[0];
var project = Uri.UnescapeDataString(pathParts[1]);
var repoName = Uri.UnescapeDataString(pathParts[3]);

return CreateRepositorySettings(org, repositoryUri, project, repoName);
else if (indexOfGit == 1 && pathParts.Length == 3)
{
return CreateRepositorySettings(
null, //org
repositoryUri, //uri
Uri.UnescapeDataString(pathParts[0]), // project
Uri.UnescapeDataString(pathParts[2]) // reponame
);
}
return null;
}

private async Task<RepositorySettings> CreateSettingsFromLocal(Uri repositoryUri, string targetBranch)
Expand All @@ -102,28 +117,43 @@ private async Task<RepositorySettings> CreateSettingsFromLocal(Uri repositoryUri
throw new NuKeeperException("No git repository found");
}

// URL pattern is
// URL pattern is
// https://dev.azure.com/{org}/{project}/_git/{repo}/
// for a organisation or
// https://dev.azure.com/{owner}/_git/{repo}
// for a private repository
var path = repositoryUri.AbsolutePath;

var pathParts = path.Split('/')
.Where(s => !string.IsNullOrWhiteSpace(s))
.ToList();
.ToArray();

var indexOfGit = Array.FindIndex(pathParts, t => t.Equals("_git", StringComparison.InvariantCultureIgnoreCase));

if (pathParts.Count != 4)
if (indexOfGit == 2 && pathParts.Length == 4)
{
return null;
return CreateRepositorySettings(
pathParts[0], //org
repositoryUri, //uri
Uri.UnescapeDataString(pathParts[1]), // project
Uri.UnescapeDataString(pathParts[3]) // reponame
);
}

var org = pathParts[0];
var project = Uri.UnescapeDataString(pathParts[1]);
var repoName = Uri.UnescapeDataString(pathParts[3]);

return CreateRepositorySettings(org, repositoryUri, project, repoName, remoteInfo);
else if (indexOfGit == 1 && pathParts.Length == 3)
{
return CreateRepositorySettings(
null, //org
repositoryUri, //uri
Uri.UnescapeDataString(pathParts[0]), // project
Uri.UnescapeDataString(pathParts[2]) // reponame
);
}
return null;
}

private static RepositorySettings CreateRepositorySettings(string org, Uri repositoryUri, string project, string repoName, RemoteInfo remoteInfo = null) => new RepositorySettings
{
ApiUri = new Uri($"https://dev.azure.com/{org}/"),
ApiUri = string.IsNullOrWhiteSpace(org) ? new Uri($"https://dev.azure.com/") : new Uri($"https://dev.azure.com/{org}/"),
RepositoryUri = repositoryUri,
RepositoryName = repoName,
RepositoryOwner = project,
Expand Down
16 changes: 15 additions & 1 deletion NuKeeper.AzureDevOps/AzureDevopsPlatform.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using NuKeeper.Abstractions.CollaborationModels;
using NuKeeper.Abstractions.CollaborationPlatform;
using NuKeeper.Abstractions.Configuration;
using NuKeeper.Abstractions.Logging;
Expand All @@ -6,7 +7,6 @@
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using NuKeeper.Abstractions.CollaborationModels;

namespace NuKeeper.AzureDevOps
{
Expand Down Expand Up @@ -34,6 +34,20 @@ public Task<User> GetCurrentUser()
return Task.FromResult(new User("user@email.com", "", ""));
}

public async Task<bool> PullRequestExists(ForkData target, string headBranch, string baseBranch)
{
var repos = await _client.GetGitRepositories(target.Owner);
var repo = repos.Single(x => x.name == target.Name);

var result = await _client.GetPullRequests(
target.Owner,
repo.id,
$"refs/heads/{headBranch}",
$"refs/heads/{baseBranch}");

return result.Any();
}

public async Task OpenPullRequest(ForkData target, PullRequestRequest request, IEnumerable<string> labels)
{
var repos = await _client.GetGitRepositories(target.Owner);
Expand Down
7 changes: 7 additions & 0 deletions NuKeeper.AzureDevOps/AzureDevopsRestTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ public class PullRequestErrorResource
public int errorCode { get; set; }
public int eventId { get; set; }
}

public class PullRequestResource
{
public int Count { get; set; }
public IEnumerable<PullRequest> value { get; set; }
}

public class PullRequest
{
public AzureRepository AzureRepository { get; set; }
Expand Down
Loading

0 comments on commit bd22335

Please sign in to comment.