diff --git a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs index dd5c78bc85..3d5167d8df 100644 --- a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs @@ -650,5 +650,21 @@ public interface IObservableRepositoriesClient /// All topics now associated with the repository. IObservable ReplaceAllTopics(string owner, string name, RepositoryTopics topics); + /// + /// Gets the list of errors in the codeowners file + /// + /// The owner of the repository + /// The name of the repository + /// Returns the list of errors in the codeowners files + [ManualRoute("GET", "/repos/{owner}/{repo}/codeowners/errors")] + IObservable GetAllCodeOwnersErrors(string owner, string name); + + /// + /// Gets the list of errors in the codeowners file + /// + /// The Id of the repository + /// Returns the list of errors in the codeowners files + [ManualRoute("GET", "/repositories/{id}/codeowners/errors")] + IObservable GetAllCodeOwnersErrors(long repositoryId); } } diff --git a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs index 80f68d1009..4e23db5923 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs @@ -753,6 +753,32 @@ public IObservable GetLicenseContents(long repositoryI return _client.GetLicenseContents(repositoryId).ToObservable(); } + /// + /// Gets the list of errors in the codeowners file + /// + /// The owner of the repository + /// The name of the repository + /// Returns the list of errors in the codeowners files + [ManualRoute("GET", "/repos/{owner}/{repo}/codeowners/errors")] + public IObservable GetAllCodeOwnersErrors(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return _client.GetAllCodeOwnersErrors(owner, name).ToObservable(); + } + + /// + /// Gets the list of errors in the codeowners file + /// + /// The Id of the repository + /// Returns the list of errors in the codeowners files + [ManualRoute("GET", "/repositories/{id}/codeowners/errors")] + public IObservable GetAllCodeOwnersErrors(long repositoryId) + { + return _client.GetAllCodeOwnersErrors(repositoryId).ToObservable(); + } + /// /// Updates the specified repository with the values given in /// diff --git a/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs index ce2a9fa34d..6aeb8fc263 100644 --- a/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Octokit; using Octokit.Tests.Integration; @@ -2102,6 +2103,7 @@ public async Task GetsPagesOfBranchesWithRepositoryId() public class TheGetLicenseContentsMethod { [IntegrationTest] + [PotentiallyFlakyTest] public async Task ReturnsLicenseContent() { var github = Helper.GetAuthenticatedClient(); @@ -2114,6 +2116,7 @@ public async Task ReturnsLicenseContent() } [IntegrationTest] + [PotentiallyFlakyTest] public async Task ReturnsLicenseContentWithRepositoryId() { var github = Helper.GetAuthenticatedClient(); @@ -2126,6 +2129,39 @@ public async Task ReturnsLicenseContentWithRepositoryId() } } + public class TheGetCodeOwnersErrorsMethod : GitHubClientTestBase + { + [IntegrationTest] + public async Task ReturnsCodeOwnersErrors() + { + using (var repoContext = await _github.CreateUserRepositoryContext()) + { + await _github.Repository.Content.CreateFile(repoContext.RepositoryOwner, repoContext.RepositoryName, ".github/codeowners", new CreateFileRequest("Create codeowners", @"* snyrting6@hotmail.com")); + + // Sometimes it takes a second to create the file + Thread.Sleep(TimeSpan.FromSeconds(2)); + + var license = await _github.Repository.GetAllCodeOwnersErrors(repoContext.RepositoryOwner, repoContext.RepositoryName); + Assert.NotEmpty(license.Errors); + } + } + + [IntegrationTest] + public async Task ReturnsCodeOwnersErrorsWithRepositoryId() + { + using (var repoContext = await _github.CreateUserRepositoryContext()) + { + await _github.Repository.Content.CreateFile(repoContext.RepositoryId, ".github/codeowners", new CreateFileRequest("Create codeowners", @"* snyrting6@hotmail.com")); + + // Sometimes it takes a second to create the file + Thread.Sleep(TimeSpan.FromSeconds(2)); + + var license = await _github.Repository.GetAllCodeOwnersErrors(repoContext.RepositoryId); + Assert.NotEmpty(license.Errors); + } + } + } + public class TheTransferMethod { [IntegrationTest] diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index 9d95cd1cee..7a7a88879b 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -1070,6 +1070,42 @@ public async Task EnsuresNonNullArguments() } } + public class TheGetCodeOwnersErrorsMethod + { + [Fact] + public async Task RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new RepositoriesClient(connection); + + await client.GetAllCodeOwnersErrors("owner", "name"); + + connection.Received() + .Get(Arg.Is(u => u.ToString() == "repos/owner/name/codeowners/errors")); + } + + [Fact] + public async Task RequestsTheCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new RepositoriesClient(connection); + + await client.GetAllCodeOwnersErrors(1); + + connection.Received() + .Get(Arg.Is(u => u.ToString() == "repositories/1/codeowners/errors")); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new RepositoriesClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.GetAllCodeOwnersErrors(null, "repo")); + await Assert.ThrowsAsync(() => client.GetAllCodeOwnersErrors("owner", null)); + } + } + public class TheGetAllTagsMethod { [Fact] diff --git a/Octokit/Clients/IRepositoriesClient.cs b/Octokit/Clients/IRepositoriesClient.cs index 773b76353c..e4dc59a28e 100644 --- a/Octokit/Clients/IRepositoriesClient.cs +++ b/Octokit/Clients/IRepositoriesClient.cs @@ -714,5 +714,21 @@ public interface IRepositoriesClient /// All topics now associated with the repository. Task ReplaceAllTopics(string owner, string name, RepositoryTopics topics); + /// + /// Gets the list of errors in the codeowners file + /// + /// The owner of the repository + /// The name of the repository + /// Returns the list of errors in the codeowners files + [ManualRoute("GET", "/repos/{owner}/{repo}/codeowners/errors")] + Task GetAllCodeOwnersErrors(string owner, string name); + + /// + /// Gets the list of errors in the codeowners file + /// + /// The Id of the repository + /// Returns the list of errors in the codeowners files + [ManualRoute("GET", "/repositories/{id}/codeowners/errors")] + Task GetAllCodeOwnersErrors(long repositoryId); } } diff --git a/Octokit/Clients/RepositoriesClient.cs b/Octokit/Clients/RepositoriesClient.cs index 4d4bfe3bad..df7d3f4fe6 100644 --- a/Octokit/Clients/RepositoriesClient.cs +++ b/Octokit/Clients/RepositoriesClient.cs @@ -11,7 +11,7 @@ namespace Octokit /// A client for GitHub's Repositories API. /// /// - /// See the Repositories API documentation for more details. + /// See the Repositories API documentation for more details. /// public class RepositoriesClient : ApiClient, IRepositoriesClient { @@ -1114,6 +1114,32 @@ public Task GetLicenseContents(long repositoryId) return ApiConnection.Get(ApiUrls.RepositoryLicense(repositoryId)); } + /// + /// Gets the list of errors in the codeowners file + /// + /// The owner of the repository + /// The name of the repository + /// Returns the list of errors in the codeowners files + [ManualRoute("GET", "/repos/{owner}/{repo}/codeowners/errors")] + public Task GetAllCodeOwnersErrors(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return ApiConnection.Get(ApiUrls.RepositoryCodeOwnersErrors(owner, name)); + } + + /// + /// Gets the list of errors in the codeowners file + /// + /// The Id of the repository + /// Returns the list of errors in the codeowners files + [ManualRoute("GET", "/repositories/{id}/codeowners/errors")] + public Task GetAllCodeOwnersErrors(long repositoryId) + { + return ApiConnection.Get(ApiUrls.RepositoryCodeOwnersErrors(repositoryId)); + } + /// /// A client for GitHub's Repository Pages API. /// diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index df99a617c0..098de9c8ef 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -1995,6 +1995,27 @@ public static Uri SearchLabels() return "search/labels".FormatUri(); } + /// + /// Returns the for repository codeowners errors. + /// + /// The owner of the repository + /// The name of the repository + /// the for repository topics. + public static Uri RepositoryCodeOwnersErrors(string owner, string name) + { + return "repos/{0}/{1}/codeowners/errors".FormatUri(owner, name); + } + + /// + /// Returns the for repository codeowners errors. + /// + /// The ID of the repository + /// the for repository topics. + public static Uri RepositoryCodeOwnersErrors(long repositoryId) + { + return "repositories/{0}/codeowners/errors".FormatUri(repositoryId); + } + /// /// Returns the for repository contributors. /// diff --git a/Octokit/Models/Response/RepositoryCodeOwnersErrors.cs b/Octokit/Models/Response/RepositoryCodeOwnersErrors.cs new file mode 100644 index 0000000000..0248f0c190 --- /dev/null +++ b/Octokit/Models/Response/RepositoryCodeOwnersErrors.cs @@ -0,0 +1,58 @@ +using Octokit.Internal; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class RepositoryCodeOwnersErrors + { + public RepositoryCodeOwnersErrors() + { + } + + public RepositoryCodeOwnersErrors(List errors) + { + Errors = errors; + } + + public IReadOnlyList Errors { get; private set; } + + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class RepositoryCodeOwnersError + { + public RepositoryCodeOwnersError() + { + } + + public RepositoryCodeOwnersError(int line, int column, string kind, string source, string suggestion, string message, string path) + { + Line = line; + Column = column; + Kind = kind; + Source = source; + Suggestion = suggestion; + Message = message; + Path = path; + } + + public int Line { get; private set; } + + public int Column { get; private set; } + + public string Kind { get; private set; } + + public string Source { get; private set; } + + public string Suggestion { get; private set; } + + public string Message { get; private set; } + + public string Path { get; private set; } + + internal string DebuggerDisplay => new SimpleJsonSerializer().Serialize(this); + } + + internal string DebuggerDisplay => new SimpleJsonSerializer().Serialize(this); + } +} diff --git a/Octokit/Models/Response/RepositoryTag.cs b/Octokit/Models/Response/RepositoryTag.cs index 37ce9baf20..74c0769246 100644 --- a/Octokit/Models/Response/RepositoryTag.cs +++ b/Octokit/Models/Response/RepositoryTag.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization;