Skip to content

Commit

Permalink
Add LinkedTo method to IIssueClient Interface (#488)
Browse files Browse the repository at this point in the history
  • Loading branch information
LiorBanai authored Jul 25, 2023
1 parent f0503ab commit 5d4b6da
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 9 deletions.
29 changes: 21 additions & 8 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ csharp_style_var_for_built_in_types = true : suggestion
csharp_style_var_when_type_is_apparent = true : warning

# Expression-Bodied members
csharp_style_expression_bodied_accessors = true : suggestion
csharp_style_expression_bodied_indexers = true : suggestion
csharp_style_expression_bodied_operators = true : suggestion
csharp_style_expression_bodied_properties = true : suggestion
csharp_style_expression_bodied_accessors = true:suggestion
csharp_style_expression_bodied_indexers = true:suggestion
csharp_style_expression_bodied_operators = true:suggestion
csharp_style_expression_bodied_properties = true:suggestion
# Explicitly disabled due to difference in coding style between source and tests
#csharp_style_expression_bodied_constructors = true : warning
#csharp_style_expression_bodied_methods = true : warning
Expand All @@ -101,7 +101,7 @@ csharp_style_conditional_delegate_call = true : warning
csharp_style_throw_expression = true : warning

# Code block preferences
csharp_prefer_braces = when_multiline : suggestion
csharp_prefer_braces = when_multiline:suggestion

## Formatting conventions
# Dotnet formatting settings:
Expand Down Expand Up @@ -141,6 +141,16 @@ csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping options
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
dotnet_diagnostic.SA1507.severity = error

## Naming conventions
[*.{cs,vb}]
Expand All @@ -159,7 +169,7 @@ dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
# Constants are PascalCase
dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style
dotnet_naming_rule.constants_should_be_pascal_case.style = non_private_static_field_style

dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.required_modifiers = const
Expand Down Expand Up @@ -198,7 +208,7 @@ dotnet_naming_style.camel_case_style.capitalization = camel_case
# Local functions are PascalCase
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
dotnet_naming_rule.local_functions_should_be_pascal_case.style = non_private_static_field_style

dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_style.local_function_style.capitalization = pascal_case
Expand All @@ -216,7 +226,7 @@ dotnet_naming_symbols.type_parameter_symbol.applicable_accessibilities = *
# By default, name items with PascalCase
dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
dotnet_naming_rule.members_should_be_pascal_case.style = non_private_static_field_style

dotnet_naming_symbols.all_members.applicable_kinds = *

Expand Down Expand Up @@ -373,3 +383,6 @@ dotnet_diagnostic.SA1636.severity = none

# SA1649: File name should match first type name
dotnet_diagnostic.SA1649.severity = none
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
end_of_line = crlf
10 changes: 10 additions & 0 deletions NGitLab.Mock/Clients/IssueClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,16 @@ public Models.Issue Get(int projectId, int issueId)
return GetById(issueId);
}

public GitLabCollectionResponse<Models.Issue> LinkedToAsync(int projectId, int issueId)
{
throw new NotImplementedException();
}

public bool CreateLinkBetweenIssues(int sourceProjectId, int sourceIssueId, int targetProjectId, int targetIssueId)
{
throw new NotImplementedException();
}

public Models.Issue GetById(int issueId)
{
using (Context.BeginOperationScope())
Expand Down
18 changes: 18 additions & 0 deletions NGitLab.Tests/IssueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,23 @@ public async Task Test_get_new_and_updated_issue_with_duedate()

Assert.AreEqual(updatedDueDate, updatedIssue.DueDate);
}

[Test]
[NGitLabRetry]
public async Task Test_get_linked_issue()
{
using var context = await GitLabTestContext.CreateAsync();
var project = context.CreateProject();
var issuesClient = context.Client.Issues;

var issue1 = await issuesClient.CreateAsync(new IssueCreate { ProjectId = project.Id, Title = "title1" });
var issue2 = await issuesClient.CreateAsync(new IssueCreate { ProjectId = project.Id, Title = "title2", Description = "related to #1" });
var linked = issuesClient.CreateLinkBetweenIssues(project.Id, issue1.IssueId, project.Id, issue2.IssueId);
Assert.IsTrue(linked, "Expected true for create Link between issues");
var issues = issuesClient.LinkedToAsync(project.Id, issue1.IssueId).ToList();

// for now, no API to link issues so not links exist but API should not throw
Assert.AreEqual(1, issues.Count, "Expected 1. Got {0}", issues.Count);
}
}
}
17 changes: 17 additions & 0 deletions NGitLab/IIssueClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,23 @@ public interface IIssueClient
/// <returns>The list of MR that are related this issue.</returns>
IEnumerable<MergeRequest> RelatedTo(int projectId, int issueIid);

/// <summary>
/// Get all Issues that are linked to a particular issue of particular project.
/// </summary>
/// <param name="projectId">The project id.</param>
/// <param name="issueId">The id of the issue in the project's scope.</param>
/// <returns>The list of Issues linked to this issue.</returns>
GitLabCollectionResponse<Issue> LinkedToAsync(int projectId, int issueId);

/// <summary>
/// Create links between Issues.
/// </summary>
/// <param name="sourceProjectId">The project id.</param>
/// <param name="sourceIssueId">The id of the issue in the project's scope.</param>
/// <param name="targetProjectId">The target project id.</param>
/// <param name="targetIssueId">The target id of the issue to link to.</param>
bool CreateLinkBetweenIssues(int sourceProjectId, int sourceIssueId, int targetProjectId, int targetIssueId);

GitLabCollectionResponse<MergeRequest> RelatedToAsync(int projectId, int issueIid);

/// <summary>
Expand Down
24 changes: 23 additions & 1 deletion NGitLab/Impl/IssueClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -10,6 +11,8 @@ public class IssueClient : IIssueClient
{
private const string IssuesUrl = "/issues";
private const string IssueByIdUrl = "/issues/{0}";
private const string LinkedIssuesByIdUrl = "/projects/{0}/issues/{1}/links";
private const string CreateLinkBetweenIssuesUrl = "/projects/{0}/issues/{1}/links?target_project_id={2}&target_issue_iid={3}";
private const string GroupIssuesUrl = "/groups/{0}/issues";
private const string ProjectIssuesUrl = "/projects/{0}/issues";
private const string SingleIssueUrl = "/projects/{0}/issues/{1}";
Expand Down Expand Up @@ -145,6 +148,25 @@ public IEnumerable<MergeRequest> RelatedTo(int projectId, int issueIid)
return _api.Get().GetAll<MergeRequest>(string.Format(CultureInfo.InvariantCulture, RelatedToUrl, projectId, issueIid));
}

public GitLabCollectionResponse<Issue> LinkedToAsync(int projectId, int issueId)
{
return _api.Get().GetAllAsync<Issue>(string.Format(CultureInfo.InvariantCulture, LinkedIssuesByIdUrl, projectId, issueId));
}

public bool CreateLinkBetweenIssues(int sourceProjectId, int sourceIssueId, int targetProjectId,
int targetIssueId)
{
try
{
_api.Post().Execute(string.Format(CultureInfo.InvariantCulture, CreateLinkBetweenIssuesUrl, sourceProjectId, sourceIssueId, targetProjectId, targetIssueId));
return true;
}
catch (Exception)
{
return false;
}
}

public GitLabCollectionResponse<MergeRequest> RelatedToAsync(int projectId, int issueIid)
{
return _api.Get().GetAllAsync<MergeRequest>(string.Format(CultureInfo.InvariantCulture, RelatedToUrl, projectId, issueIid));
Expand Down
4 changes: 4 additions & 0 deletions NGitLab/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ NGitLab.IIssueClient.ClosedBy(int projectId, int issueIid) -> System.Collections
NGitLab.IIssueClient.ClosedByAsync(int projectId, int issueIid) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.MergeRequest>
NGitLab.IIssueClient.Create(NGitLab.Models.IssueCreate issueCreate) -> NGitLab.Models.Issue
NGitLab.IIssueClient.CreateAsync(NGitLab.Models.IssueCreate issueCreate, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<NGitLab.Models.Issue>
NGitLab.IIssueClient.CreateLinkBetweenIssues(int sourceProjectId, int sourceIssueId, int targetProjectId, int targetIssueId) -> bool
NGitLab.IIssueClient.Edit(NGitLab.Models.IssueEdit issueEdit) -> NGitLab.Models.Issue
NGitLab.IIssueClient.EditAsync(NGitLab.Models.IssueEdit issueEdit, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<NGitLab.Models.Issue>
NGitLab.IIssueClient.ForGroupsAsync(int groupId) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.Issue>
Expand All @@ -263,6 +264,7 @@ NGitLab.IIssueClient.GetAsync(int projectId, NGitLab.Models.IssueQuery query) ->
NGitLab.IIssueClient.GetAsync(NGitLab.Models.IssueQuery query) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.Issue>
NGitLab.IIssueClient.GetById(int issueId) -> NGitLab.Models.Issue
NGitLab.IIssueClient.GetByIdAsync(int issueId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<NGitLab.Models.Issue>
NGitLab.IIssueClient.LinkedToAsync(int projectId, int issueId) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.Issue>
NGitLab.IIssueClient.Owned.get -> System.Collections.Generic.IEnumerable<NGitLab.Models.Issue>
NGitLab.IIssueClient.RelatedTo(int projectId, int issueIid) -> System.Collections.Generic.IEnumerable<NGitLab.Models.MergeRequest>
NGitLab.IIssueClient.RelatedToAsync(int projectId, int issueIid) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.MergeRequest>
Expand Down Expand Up @@ -498,6 +500,7 @@ NGitLab.Impl.IssueClient.ClosedBy(int projectId, int issueIid) -> System.Collect
NGitLab.Impl.IssueClient.ClosedByAsync(int projectId, int issueIid) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.MergeRequest>
NGitLab.Impl.IssueClient.Create(NGitLab.Models.IssueCreate issueCreate) -> NGitLab.Models.Issue
NGitLab.Impl.IssueClient.CreateAsync(NGitLab.Models.IssueCreate issueCreate, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<NGitLab.Models.Issue>
NGitLab.Impl.IssueClient.CreateLinkBetweenIssues(int sourceProjectId, int sourceIssueId, int targetProjectId, int targetIssueId) -> bool
NGitLab.Impl.IssueClient.Edit(NGitLab.Models.IssueEdit issueEdit) -> NGitLab.Models.Issue
NGitLab.Impl.IssueClient.EditAsync(NGitLab.Models.IssueEdit issueEdit, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<NGitLab.Models.Issue>
NGitLab.Impl.IssueClient.ForGroupsAsync(int groupId) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.Issue>
Expand All @@ -513,6 +516,7 @@ NGitLab.Impl.IssueClient.GetAsync(NGitLab.Models.IssueQuery query) -> NGitLab.Gi
NGitLab.Impl.IssueClient.GetById(int issueId) -> NGitLab.Models.Issue
NGitLab.Impl.IssueClient.GetByIdAsync(int issueId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<NGitLab.Models.Issue>
NGitLab.Impl.IssueClient.IssueClient(NGitLab.Impl.API api) -> void
NGitLab.Impl.IssueClient.LinkedToAsync(int projectId, int issueId) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.Issue>
NGitLab.Impl.IssueClient.Owned.get -> System.Collections.Generic.IEnumerable<NGitLab.Models.Issue>
NGitLab.Impl.IssueClient.RelatedTo(int projectId, int issueIid) -> System.Collections.Generic.IEnumerable<NGitLab.Models.MergeRequest>
NGitLab.Impl.IssueClient.RelatedToAsync(int projectId, int issueIid) -> NGitLab.GitLabCollectionResponse<NGitLab.Models.MergeRequest>
Expand Down

0 comments on commit 5d4b6da

Please sign in to comment.