From 043e64b89f5c51106d6862efcbecf962147af81f Mon Sep 17 00:00:00 2001 From: Ryan Gribble Date: Wed, 11 Jul 2018 20:38:54 +1000 Subject: [PATCH 1/2] Implement new Project Card archiving (#1842) * add Archived to ProjectCard response add Archived to ProjectCardUpdate update integration tests * Add ProjectCardRequest model and update GetAll calls to use it Update unit tests Update integration tests * skip_branch_with_pr still ends up building the branch on the initial push, so let's only build master instead --- .../Clients/IObservableProjectCardsClient.cs | 21 ++++ .../Clients/ObservableProjectCardsClient.cs | 35 +++++- .../Clients/ProjectCardsClientTests.cs | 105 +++++++++++++++++- .../ObservableProjectCardsClientTests.cs | 100 ++++++++++++++++- .../Clients/ProjectCardsClientTests.cs | 24 +++- .../Models/ProjectCardRequestTests.cs | 28 +++++ .../ObservableProjectCardsClientTests.cs | 23 +++- Octokit/Clients/IProjectCardsClient.cs | 21 ++++ Octokit/Clients/ProjectCardsClient.cs | 34 +++++- Octokit/Models/Request/ProjectCardRequest.cs | 64 +++++++++++ Octokit/Models/Request/ProjectCardUpdate.cs | 17 ++- Octokit/Models/Response/ProjectCard.cs | 8 +- appveyor.yml | 4 +- 13 files changed, 467 insertions(+), 17 deletions(-) create mode 100644 Octokit.Tests/Models/ProjectCardRequestTests.cs create mode 100644 Octokit/Models/Request/ProjectCardRequest.cs diff --git a/Octokit.Reactive/Clients/IObservableProjectCardsClient.cs b/Octokit.Reactive/Clients/IObservableProjectCardsClient.cs index d9e8496f00..ff6209b0aa 100644 --- a/Octokit.Reactive/Clients/IObservableProjectCardsClient.cs +++ b/Octokit.Reactive/Clients/IObservableProjectCardsClient.cs @@ -30,6 +30,27 @@ public interface IObservableProjectCardsClient /// Options for changing the API response IObservable GetAll(int columnId, ApiOptions options); + /// + /// Gets all cards. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the column + /// Used to filter the list of project cards returned + IObservable GetAll(int columnId, ProjectCardRequest request); + + /// + /// Gets all cards. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the column + /// Used to filter the list of project cards returned + /// Options for changing the API response + IObservable GetAll(int columnId, ProjectCardRequest request, ApiOptions options); + /// /// Gets a single card. /// diff --git a/Octokit.Reactive/Clients/ObservableProjectCardsClient.cs b/Octokit.Reactive/Clients/ObservableProjectCardsClient.cs index fc77652fa6..424f1c7cc3 100644 --- a/Octokit.Reactive/Clients/ObservableProjectCardsClient.cs +++ b/Octokit.Reactive/Clients/ObservableProjectCardsClient.cs @@ -1,7 +1,6 @@ using Octokit.Reactive.Internal; using System; using System.Reactive.Threading.Tasks; -using System.Collections.Generic; namespace Octokit.Reactive { @@ -48,9 +47,41 @@ public IObservable GetAll(int columnId, ApiOptions options) { Ensure.ArgumentNotNull(options, nameof(options)); + return GetAll(columnId, new ProjectCardRequest(), options); + } + + /// + /// Gets all cards. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the column + /// Used to filter the list of project cards returned + public IObservable GetAll(int columnId, ProjectCardRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAll(columnId, request, ApiOptions.None); + } + + /// + /// Gets all cards. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the column + /// Used to filter the list of project cards returned + /// Options for changing the API response + public IObservable GetAll(int columnId, ProjectCardRequest request, ApiOptions options) + { + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + var url = ApiUrls.ProjectCards(columnId); - return _connection.GetAndFlattenAllPages(url, new Dictionary(), AcceptHeaders.ProjectsApiPreview, options); + return _connection.GetAndFlattenAllPages(url, request.ToParametersDictionary(), AcceptHeaders.ProjectsApiPreview, options); } /// diff --git a/Octokit.Tests.Integration/Clients/ProjectCardsClientTests.cs b/Octokit.Tests.Integration/Clients/ProjectCardsClientTests.cs index 538872765b..3c127e0b9d 100644 --- a/Octokit.Tests.Integration/Clients/ProjectCardsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/ProjectCardsClientTests.cs @@ -2,8 +2,6 @@ using Octokit.Tests.Integration; using Octokit.Tests.Integration.Helpers; using System; -using System.Linq; -using System.Net; using System.Threading.Tasks; using Xunit; @@ -33,8 +31,57 @@ public async Task GetsAllCards() var result = await _github.Repository.Project.Card.GetAll(column.Id); Assert.Equal(2, result.Count); - Assert.True(result.FirstOrDefault(x => x.Id == card1.Id).Id == card1.Id); - Assert.True(result.FirstOrDefault(x => x.Id == card2.Id).Id == card2.Id); + Assert.Contains(result, x => x.Id == card1.Id); + Assert.Contains(result, x => x.Id == card2.Id); + } + + [IntegrationTest] + public async Task GetsAllArchivedCards() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card1 = await CreateCardHelper(_github, column.Id); + var card2 = await CreateArchivedCardHelper(_github, column.Id); + + var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.Archived); + + var result = await _github.Repository.Project.Card.GetAll(column.Id, request); + + Assert.Equal(1, result.Count); + Assert.Contains(result, x => x.Id == card2.Id); + } + + [IntegrationTest] + public async Task GetsAllNotArchivedCards() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card1 = await CreateCardHelper(_github, column.Id); + var card2 = await CreateArchivedCardHelper(_github, column.Id); + + var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.NotArchived); + + var result = await _github.Repository.Project.Card.GetAll(column.Id, request); + + Assert.Equal(1, result.Count); + Assert.Contains(result, x => x.Id == card1.Id); + } + + [IntegrationTest] + public async Task GetsAllArchivedAndNotArchivedCards() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card1 = await CreateCardHelper(_github, column.Id); + var card2 = await CreateArchivedCardHelper(_github, column.Id); + + var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.All); + + var result = await _github.Repository.Project.Card.GetAll(column.Id, request); + + Assert.Equal(2, result.Count); + Assert.Contains(result, x => x.Id == card1.Id); + Assert.Contains(result, x => x.Id == card2.Id); } [IntegrationTest] @@ -207,7 +254,10 @@ public async Task UpdatesCard() var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); var column = await CreateColumnHelper(_github, project.Id); var card = await CreateCardHelper(_github, column.Id); - var cardUpdate = new ProjectCardUpdate("newNameOfNote"); + var cardUpdate = new ProjectCardUpdate + { + Note = "newNameOfNote" + }; var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate); @@ -215,6 +265,42 @@ public async Task UpdatesCard() Assert.Equal(card.Id, result.Id); } + [IntegrationTest] + public async Task ArchivesCard() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card = await CreateCardHelper(_github, column.Id); + var cardUpdate = new ProjectCardUpdate + { + Archived = true + }; + + var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate); + + Assert.Equal(card.Id, result.Id); + Assert.False(card.Archived); + Assert.True(result.Archived); + } + + [IntegrationTest] + public async Task UnarchivesCard() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card = await CreateArchivedCardHelper(_github, column.Id); + var cardUpdate = new ProjectCardUpdate + { + Archived = false + }; + + var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate); + + Assert.Equal(card.Id, result.Id); + Assert.True(card.Archived); + Assert.False(result.Archived); + } + public void Dispose() { if (_context != null) @@ -343,6 +429,15 @@ private static async Task CreateCardHelper(IGitHubClient githubClie return result; } + private static async Task CreateArchivedCardHelper(IGitHubClient githubClient, int columnId) + { + var newCard = new NewProjectCard(Helper.MakeNameWithTimestamp("new-card")); + var card = await githubClient.Repository.Project.Card.Create(columnId, newCard); + var result = await githubClient.Repository.Project.Card.Update(card.Id, new ProjectCardUpdate { Archived = true }); + + return result; + } + private static async Task CreateIssueCardHelper(IGitHubClient githubClient, int issueId, int columnId) { var newCard = new NewProjectCard(issueId, ProjectCardContentType.Issue); diff --git a/Octokit.Tests.Integration/Reactive/ObservableProjectCardsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableProjectCardsClientTests.cs index d1181610c6..d3f29dbaea 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableProjectCardsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableProjectCardsClientTests.cs @@ -4,7 +4,6 @@ using Octokit.Tests.Integration.Helpers; using System; using System.Linq; -using System.Net; using System.Threading.Tasks; using Xunit; using System.Reactive.Linq; @@ -39,6 +38,55 @@ public async Task GetsAllCards() Assert.True(result.FirstOrDefault(x => x.Id == card2.Id).Id == card2.Id); } + [IntegrationTest] + public async Task GetsAllArchivedCards() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card1 = await CreateCardHelper(_github, column.Id); + var card2 = await CreateArchivedCardHelper(_github, column.Id); + + var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.Archived); + + var result = await _github.Repository.Project.Card.GetAll(column.Id, request).ToList(); + + Assert.Equal(1, result.Count); + Assert.Contains(result, x => x.Id == card2.Id); + } + + [IntegrationTest] + public async Task GetsAllNotArchivedCards() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card1 = await CreateCardHelper(_github, column.Id); + var card2 = await CreateArchivedCardHelper(_github, column.Id); + + var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.NotArchived); + + var result = await _github.Repository.Project.Card.GetAll(column.Id, request).ToList(); + + Assert.Equal(1, result.Count); + Assert.Contains(result, x => x.Id == card1.Id); + } + + [IntegrationTest] + public async Task GetsAllArchivedAndNotArchivedCards() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card1 = await CreateCardHelper(_github, column.Id); + var card2 = await CreateArchivedCardHelper(_github, column.Id); + + var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.All); + + var result = await _github.Repository.Project.Card.GetAll(column.Id, request).ToList(); + + Assert.Equal(2, result.Count); + Assert.Contains(result, x => x.Id == card1.Id); + Assert.Contains(result, x => x.Id == card2.Id); + } + [IntegrationTest] public async Task ReturnsCorrectCountOfCardWithoutStart() { @@ -209,7 +257,10 @@ public async Task UpdatesCard() var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); var column = await CreateColumnHelper(_github, project.Id); var card = await CreateCardHelper(_github, column.Id); - var cardUpdate = new ProjectCardUpdate("newNameOfNote"); + var cardUpdate = new ProjectCardUpdate + { + Note = "newNameOfNote" + }; var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate); @@ -217,6 +268,42 @@ public async Task UpdatesCard() Assert.Equal(card.Id, result.Id); } + [IntegrationTest] + public async Task ArchivesCard() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card = await CreateCardHelper(_github, column.Id); + var cardUpdate = new ProjectCardUpdate + { + Archived = true + }; + + var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate); + + Assert.Equal(card.Id, result.Id); + Assert.False(card.Archived); + Assert.True(result.Archived); + } + + [IntegrationTest] + public async Task UnarchivesCard() + { + var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId); + var column = await CreateColumnHelper(_github, project.Id); + var card = await CreateArchivedCardHelper(_github, column.Id); + var cardUpdate = new ProjectCardUpdate + { + Archived = false + }; + + var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate); + + Assert.Equal(card.Id, result.Id); + Assert.True(card.Archived); + Assert.False(result.Archived); + } + public void Dispose() { if (_context != null) @@ -345,6 +432,15 @@ private static async Task CreateCardHelper(IObservableGitHubClient return result; } + private static async Task CreateArchivedCardHelper(IObservableGitHubClient githubClient, int columnId) + { + var newCard = new NewProjectCard(Helper.MakeNameWithTimestamp("new-card")); + var card = await githubClient.Repository.Project.Card.Create(columnId, newCard); + var result = await githubClient.Repository.Project.Card.Update(card.Id, new ProjectCardUpdate { Archived = true }); + + return result; + } + private static async Task CreateIssueCardHelper(IObservableGitHubClient githubClient, int issueId, int columnId) { var newCard = new NewProjectCard(issueId, ProjectCardContentType.Issue); diff --git a/Octokit.Tests/Clients/ProjectCardsClientTests.cs b/Octokit.Tests/Clients/ProjectCardsClientTests.cs index e2edc82cad..7021c2e77d 100644 --- a/Octokit.Tests/Clients/ProjectCardsClientTests.cs +++ b/Octokit.Tests/Clients/ProjectCardsClientTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using NSubstitute; using Xunit; @@ -33,12 +34,33 @@ public async Task RequestCorrectURL() Args.ApiOptions); } + [Fact] + public async Task SendsAppropriateParameters() + { + var connection = Substitute.For(); + var client = new ProjectCardsClient(connection); + + await client.GetAll(1, new ProjectCardRequest(ProjectCardArchivedStateFilter.NotArchived)); + + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "projects/columns/1/cards"), + Arg.Is>(x => + x.Count == 1 + && x["archived_state"] == "not_archived"), + "application/vnd.github.inertia-preview+json", + Args.ApiOptions); + } + [Fact] public async Task EnsuresNonNullArguments() { var client = new ProjectCardsClient(Substitute.For()); + var request = new ProjectCardRequest(); - await Assert.ThrowsAsync(() => client.GetAll(1, null)); + await Assert.ThrowsAsync(() => client.GetAll(1, (ProjectCardRequest)null)); + await Assert.ThrowsAsync(() => client.GetAll(1, (ApiOptions)null)); + await Assert.ThrowsAsync(() => client.GetAll(1, null, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAll(1, request, null)); } } diff --git a/Octokit.Tests/Models/ProjectCardRequestTests.cs b/Octokit.Tests/Models/ProjectCardRequestTests.cs new file mode 100644 index 0000000000..60efbf9a29 --- /dev/null +++ b/Octokit.Tests/Models/ProjectCardRequestTests.cs @@ -0,0 +1,28 @@ +using Octokit; +using Xunit; + +public class ProjectCardRequestTests +{ + public class TheToParametersDictionaryMethod + { + [Fact] + public void ContainsSetValues() + { + var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.All); + + var parameters = request.ToParametersDictionary(); + + Assert.Equal("all", parameters["archived_state"]); + } + + [Fact] + public void ReturnsDefaultValuesForDefaultRequest() + { + var request = new ProjectCardRequest(); + + var parameters = request.ToParametersDictionary(); + + Assert.Empty(parameters); + } + } +} diff --git a/Octokit.Tests/Reactive/ObservableProjectCardsClientTests.cs b/Octokit.Tests/Reactive/ObservableProjectCardsClientTests.cs index 8be07b0e4c..3fa491ffdf 100644 --- a/Octokit.Tests/Reactive/ObservableProjectCardsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableProjectCardsClientTests.cs @@ -37,13 +37,34 @@ public void RequestCorrectURL() "application/vnd.github.inertia-preview+json"); } + [Fact] + public async Task SendsAppropriateParameters() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableProjectCardsClient(gitHubClient); + + client.GetAll(1, new ProjectCardRequest(ProjectCardArchivedStateFilter.NotArchived)); + + connection.Received().Get>( + Arg.Is(u => u.ToString() == "projects/columns/1/cards"), + Arg.Is>(x => + x.Count == 1 + && x["archived_state"] == "not_archived"), + "application/vnd.github.inertia-preview+json"); + } + [Fact] public async Task EnsuresNonNullArguments() { var gitHubClient = Substitute.For(); var client = new ObservableProjectCardsClient(gitHubClient); + var request = new ProjectCardRequest(); - await Assert.ThrowsAsync(() => client.GetAll(1, null).ToTask()); + await Assert.ThrowsAsync(() => client.GetAll(1, (ProjectCardRequest)null).ToTask()); + await Assert.ThrowsAsync(() => client.GetAll(1, (ApiOptions)null).ToTask()); + await Assert.ThrowsAsync(() => client.GetAll(1, null, ApiOptions.None).ToTask()); + await Assert.ThrowsAsync(() => client.GetAll(1, request, null).ToTask()); } } diff --git a/Octokit/Clients/IProjectCardsClient.cs b/Octokit/Clients/IProjectCardsClient.cs index c33831c34c..f119de634d 100644 --- a/Octokit/Clients/IProjectCardsClient.cs +++ b/Octokit/Clients/IProjectCardsClient.cs @@ -31,6 +31,27 @@ public interface IProjectCardsClient /// Options for changing the API response Task> GetAll(int columnId, ApiOptions options); + /// + /// Gets all cards. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the column + /// Used to filter the list of project cards returned + Task> GetAll(int columnId, ProjectCardRequest request); + + /// + /// Gets all cards. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the column + /// Used to filter the list of project cards returned + /// Options for changing the API response + Task> GetAll(int columnId, ProjectCardRequest request, ApiOptions options); + /// /// Gets a single card. /// diff --git a/Octokit/Clients/ProjectCardsClient.cs b/Octokit/Clients/ProjectCardsClient.cs index a16cd58086..bc952bd7cd 100644 --- a/Octokit/Clients/ProjectCardsClient.cs +++ b/Octokit/Clients/ProjectCardsClient.cs @@ -41,7 +41,39 @@ public Task> GetAll(int columnId, ApiOptions options) { Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.ProjectCards(columnId), new Dictionary(), AcceptHeaders.ProjectsApiPreview, options); + return GetAll(columnId, new ProjectCardRequest(), options); + } + + /// + /// Gets all cards. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the column + /// Used to filter the list of project cards returned + public Task> GetAll(int columnId, ProjectCardRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAll(columnId, request, ApiOptions.None); + } + + /// + /// Gets all cards. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the column + /// Used to filter the list of project cards returned + /// Options for changing the API response + public Task> GetAll(int columnId, ProjectCardRequest request, ApiOptions options) + { + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.ProjectCards(columnId), request.ToParametersDictionary(), AcceptHeaders.ProjectsApiPreview, options); } /// diff --git a/Octokit/Models/Request/ProjectCardRequest.cs b/Octokit/Models/Request/ProjectCardRequest.cs new file mode 100644 index 0000000000..1c316d9ba1 --- /dev/null +++ b/Octokit/Models/Request/ProjectCardRequest.cs @@ -0,0 +1,64 @@ +using System.Diagnostics; +using System.Globalization; +using Octokit.Internal; + +namespace Octokit +{ + /// + /// Used to filter requests for lists of projects + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class ProjectCardRequest : RequestParameters + { + /// + /// Used to filter requests for lists of projects + /// + public ProjectCardRequest() + { + } + + /// + /// Used to filter requests for lists of projects + /// + /// Which project cards to include. + public ProjectCardRequest(ProjectCardArchivedStateFilter archived) + { + ArchivedState = archived; + } + + /// + /// Which project cards to include./>. + /// + [Parameter(Key = "archived_state")] + public ProjectCardArchivedStateFilter? ArchivedState { get; private set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "ArchivedState: {0} ", ArchivedState?.ToString() ?? "null"); + } + } + } + + public enum ProjectCardArchivedStateFilter + { + /// + /// Items that are open. + /// + [Parameter(Value = "not_archived")] + NotArchived, + + /// + /// Items that are closed. + /// + [Parameter(Value = "archived")] + Archived, + + /// + /// All the items. + /// + [Parameter(Value = "all")] + All + } +} diff --git a/Octokit/Models/Request/ProjectCardUpdate.cs b/Octokit/Models/Request/ProjectCardUpdate.cs index e0fe7c1c59..1e7f47d627 100644 --- a/Octokit/Models/Request/ProjectCardUpdate.cs +++ b/Octokit/Models/Request/ProjectCardUpdate.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using System.Globalization; namespace Octokit @@ -6,6 +7,11 @@ namespace Octokit [DebuggerDisplay("{DebuggerDisplay,nq}")] public class ProjectCardUpdate { + public ProjectCardUpdate() + { + } + + [Obsolete("This constructor will be removed in a future release, due to the 'Note' parameter not being mandatory. Use object initializer syntax instead.")] public ProjectCardUpdate(string note) { Note = note; @@ -14,13 +20,18 @@ public ProjectCardUpdate(string note) /// /// The new note of the card. /// - public string Note { get; private set; } + public string Note { get; set; } + + /// + /// Archive/Unarchive the card. + /// + public bool? Archived { get; set; } internal string DebuggerDisplay { get { - return string.Format(CultureInfo.InvariantCulture, "Note: {0}", Note); + return string.Format(CultureInfo.InvariantCulture, "Note: {0}, Archived: {1}", Note, Archived?.ToString() ?? "null"); } } } diff --git a/Octokit/Models/Response/ProjectCard.cs b/Octokit/Models/Response/ProjectCard.cs index ff8f139832..c8128e1436 100644 --- a/Octokit/Models/Response/ProjectCard.cs +++ b/Octokit/Models/Response/ProjectCard.cs @@ -9,7 +9,7 @@ public class ProjectCard { public ProjectCard() { } - public ProjectCard(string columnUrl, string contentUrl, int id, string nodeId, string note, User creator, DateTimeOffset createdAt, DateTimeOffset updatedAt) + public ProjectCard(string columnUrl, string contentUrl, int id, string nodeId, string note, User creator, DateTimeOffset createdAt, DateTimeOffset updatedAt, bool archived) { ColumnUrl = columnUrl; ContentUrl = contentUrl; @@ -19,6 +19,7 @@ public ProjectCard(string columnUrl, string contentUrl, int id, string nodeId, s Creator = creator; CreatedAt = createdAt; UpdatedAt = updatedAt; + Archived = archived; } /// @@ -61,6 +62,11 @@ public ProjectCard(string columnUrl, string contentUrl, int id, string nodeId, s /// public DateTimeOffset UpdatedAt { get; protected set; } + /// + /// Whether this card is archived. + /// + public bool Archived { get; protected set; } + internal string DebuggerDisplay { get diff --git a/appveyor.yml b/appveyor.yml index e2e754cd50..6d09d6be6b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,8 @@ image: Visual Studio 2017 -skip_branch_with_pr: true +branches: + only: + - master init: - git config --global core.autocrlf input From 4df21a61deeb59dc511c9e7cb3718151d7313be3 Mon Sep 17 00:00:00 2001 From: Ryan Gribble Date: Sat, 14 Jul 2018 20:01:41 +1000 Subject: [PATCH 2/2] Implement Check Suites API (#1846) * Check run request models * Check Run response models * Check run clients * Check run ApiUrls and AcceptHeaders * Pack it all together for now * Add missing accept headers to connection calls * Standardize class definitions * Standardize function names * Merge ICheckRunAnnotationsClient into ICheckRunsClient * Properly organize clients * Cleanup CheckRun response model * Fix slug check run urls * Add checks installation permission * Use StringEnums where appropriate * Cleanup check run output models * Flesh out CheckSuite model * Delete CheckRunsList * Remove a sealed, fix some line endings * Adding check suite models * Skeleton check suite client implementation * Add check suite ApiUrls * Flesh out check suites client * Add parameterless CheckRun constructor * Add DebuggerDisplay to checks models * Add observable checks interfaces * Add return values to POST and PATCH check clients * Fix some check suite client return values * Skeleton reactive checks implementation * Implement observable checks clients * Remove rogue tabs * Add CheckSuiteEventPayload * Add CheckRunEventPayload * Add DebuggerDisplay attributes to checks API payloads * Properly nullables check suite/run conclusion * Add CheckSuiteEventTests * Fix checks client accessor naming issues * Add missing Text field to CheckRunOutput * Marks CheckRunUpdate's conclusion as nullable * Fix reactive checks client naming * Today I learned DateTimeOffset is a struct Makes CheckRunUpdate's DateTimeOffsets nullable * Modify check clients to put slug version before repo id version * Add nullable to CheckRun.CompletedAt * Implement parameterless ICheckRunsClient.GetAllForReference and GetAllForCheckSuite * Add missing RequestParameters base to CheckSuiteRequest * Implement checks API GetAll methods * Bring parity to Reactive checks clients * fix project settings to get GitHubApp helper working again * remove un-needed InstallationId setting - provide helper method to find installation based on owner * fix up request object ctors based on required/optional parameters * fix up request object ctors based on required/optional parameters * add some initial integration tests for CheckSuites and CheckRuns including some helper methods * Add test for Request CheckSuite Fix Request CheckSuite to use correct Uri Fix Request CheckSuite return type as it doesnt return an object Fix CheckSuiteTriggerRequest ctor to make required fields mandatory * simplify Get CheckSuite test to not require as much data setup * Add test for CheckSuite GetAllForReference * Add test for CheckSuite UpdatePreferences * rename response models * rename CheckSuitesList to CheckSuitesResponse and use as response to the GetAll calls * Fix tests * Fix observable * fix model convention tests * remove CheckRuns so we can focus only on CheckSuites for now * naming things is hard * oh so many unit tests for CheckSuites methods * make client mockable * Fix issue with .Max() when no results returned * fix request parameter names * add Xml doc comments * Add XmlDoc comments to request/common model objects * rename class to match usage * tidy ups * xmldoc for observable clients * fix method order * add observable unit tests and get them passing * Add Observable unit tests and get them passing * add observable integration tests * tidy up ApiUrl method name * whitespace/using tidy ups * Ensure CheckSuiteEventPayload class is handled in deserializer and add to activity test * add response model XmlDoc comments * missed one xmldoc * add xmldoc to NewCheckSuite request and remove HeadBranch property as it doesnt exist anymore * add some extra check suites integration tests --- .../Clients/IObservableCheckSuitesClient.cs | 166 ++++++++ .../Clients/IObservableChecksClient.cs | 19 + .../Clients/ObservableCheckSuitesClient.cs | 271 ++++++++++++ .../Clients/ObservableChecksClient.cs | 26 ++ Octokit.Reactive/IObservableGitHubClient.cs | 1 + Octokit.Reactive/ObservableGitHubClient.cs | 2 + .../Clients/CheckSuitesClientTests.cs | 256 +++++++++++ .../Clients/GitHubAppsClientTests.cs | 11 +- Octokit.Tests.Integration/Helper.cs | 66 ++- .../Octokit.Tests.Integration.csproj | 4 +- .../ObservableCheckSuitesClientTests.cs | 258 ++++++++++++ .../Clients/CheckSuitesClientTests.cs | 397 ++++++++++++++++++ Octokit.Tests/Clients/ChecksClientTests.cs | 17 + Octokit.Tests/Clients/EventsClientTests.cs | 1 + Octokit.Tests/Helpers/MockedIApiConnection.cs | 21 + Octokit.Tests/Models/CheckSuiteEventTests.cs | 23 + .../ObservableCheckSuitesClientTests.cs | 373 ++++++++++++++++ .../Reactive/ObservableChecksClientTests.cs | 18 + Octokit/Clients/CheckSuitesClient.cs | 285 +++++++++++++ Octokit/Clients/ChecksClient.cs | 28 ++ Octokit/Clients/ICheckSuitesClient.cs | 166 ++++++++ Octokit/Clients/IChecksClient.cs | 19 + Octokit/GitHubClient.cs | 9 + Octokit/Helpers/AcceptHeaders.cs | 2 + Octokit/Helpers/ApiUrls.cs | 109 +++++ Octokit/Http/SimpleJsonSerializer.cs | 2 + Octokit/IGitHubClient.cs | 8 + Octokit/Models/Common/CheckStatus.cs | 37 ++ .../Common/CheckSuitePreferenceAutoTrigger.cs | 39 ++ .../Models/Common/CheckSuitePreferences.cs | 34 ++ Octokit/Models/Request/CheckSuiteRequest.cs | 27 ++ .../Request/CheckSuiteTriggerRequest.cs | 28 ++ Octokit/Models/Request/NewCheckSuite.cs | 25 ++ .../CheckSuiteEventPayload.cs | 11 + Octokit/Models/Response/CheckSuite.cs | 86 ++++ .../Response/CheckSuitePreferencesResponse.cs | 31 ++ .../Models/Response/CheckSuitesResponse.cs | 32 ++ .../Response/InstallationPermissions.cs | 9 +- script/configure-integration-tests.ps1 | 1 - 39 files changed, 2905 insertions(+), 13 deletions(-) create mode 100644 Octokit.Reactive/Clients/IObservableCheckSuitesClient.cs create mode 100644 Octokit.Reactive/Clients/IObservableChecksClient.cs create mode 100644 Octokit.Reactive/Clients/ObservableCheckSuitesClient.cs create mode 100644 Octokit.Reactive/Clients/ObservableChecksClient.cs create mode 100644 Octokit.Tests.Integration/Clients/CheckSuitesClientTests.cs create mode 100644 Octokit.Tests.Integration/Reactive/ObservableCheckSuitesClientTests.cs create mode 100644 Octokit.Tests/Clients/CheckSuitesClientTests.cs create mode 100644 Octokit.Tests/Clients/ChecksClientTests.cs create mode 100644 Octokit.Tests/Helpers/MockedIApiConnection.cs create mode 100644 Octokit.Tests/Models/CheckSuiteEventTests.cs create mode 100644 Octokit.Tests/Reactive/ObservableCheckSuitesClientTests.cs create mode 100644 Octokit.Tests/Reactive/ObservableChecksClientTests.cs create mode 100644 Octokit/Clients/CheckSuitesClient.cs create mode 100644 Octokit/Clients/ChecksClient.cs create mode 100644 Octokit/Clients/ICheckSuitesClient.cs create mode 100644 Octokit/Clients/IChecksClient.cs create mode 100644 Octokit/Models/Common/CheckStatus.cs create mode 100644 Octokit/Models/Common/CheckSuitePreferenceAutoTrigger.cs create mode 100644 Octokit/Models/Common/CheckSuitePreferences.cs create mode 100644 Octokit/Models/Request/CheckSuiteRequest.cs create mode 100644 Octokit/Models/Request/CheckSuiteTriggerRequest.cs create mode 100644 Octokit/Models/Request/NewCheckSuite.cs create mode 100644 Octokit/Models/Response/ActivityPayloads/CheckSuiteEventPayload.cs create mode 100644 Octokit/Models/Response/CheckSuite.cs create mode 100644 Octokit/Models/Response/CheckSuitePreferencesResponse.cs create mode 100644 Octokit/Models/Response/CheckSuitesResponse.cs diff --git a/Octokit.Reactive/Clients/IObservableCheckSuitesClient.cs b/Octokit.Reactive/Clients/IObservableCheckSuitesClient.cs new file mode 100644 index 0000000000..07e0a5937b --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableCheckSuitesClient.cs @@ -0,0 +1,166 @@ +using System; + +namespace Octokit.Reactive +{ + /// + /// A client for GitHub's Check Suites API. + /// + /// + /// See the Check Suites API documentation for more information. + /// + public interface IObservableCheckSuitesClient + { + /// + /// Gets a single Check Suite by Id + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The Id of the check suite + IObservable Get(string owner, string name, long checkSuiteId); + + /// + /// Gets a single Check Suite by Id + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The Id of the check suite + IObservable Get(long repositoryId, long checkSuiteId); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + IObservable GetAllForReference(string owner, string name, string reference); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + IObservable GetAllForReference(long repositoryId, string reference); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + IObservable GetAllForReference(string owner, string name, string reference, CheckSuiteRequest request); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + IObservable GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + /// Options to change the API response + IObservable GetAllForReference(string owner, string name, string reference, CheckSuiteRequest request, ApiOptions options); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + /// Options to change the API response + IObservable GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request, ApiOptions options); + + /// + /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The check suite preferences + IObservable UpdatePreferences(string owner, string name, CheckSuitePreferences preferences); + + /// + /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The check suite preferences + IObservable UpdatePreferences(long repositoryId, CheckSuitePreferences preferences); + + /// + /// Creates a new Check Suite + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Details of the Check Suite to create + IObservable Create(string owner, string name, NewCheckSuite newCheckSuite); + + /// + /// Creates a new Check Suite + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// Details of the Check Suite to create + IObservable Create(long repositoryId, NewCheckSuite newCheckSuite); + + /// + /// Triggers GitHub to create a new check suite, without pushing new code to a repository + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Details of the Check Suite request + IObservable Request(string owner, string name, CheckSuiteTriggerRequest request); + + /// + /// Triggers GitHub to create a new check suite, without pushing new code to a repository + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// Details of the Check Suite request + IObservable Request(long repositoryId, CheckSuiteTriggerRequest request); + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Clients/IObservableChecksClient.cs b/Octokit.Reactive/Clients/IObservableChecksClient.cs new file mode 100644 index 0000000000..a5127ae78f --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableChecksClient.cs @@ -0,0 +1,19 @@ +namespace Octokit.Reactive +{ + /// + /// A client for GitHub's Checks API. + /// + /// + /// See the Checks API documentation for more information. + /// + public interface IObservableChecksClient + { + /// + /// A client for GitHub's Check Suites API. + /// + /// + /// See the Check Suites API documentation for more information. + /// + IObservableCheckSuitesClient Suite { get; } + } +} diff --git a/Octokit.Reactive/Clients/ObservableCheckSuitesClient.cs b/Octokit.Reactive/Clients/ObservableCheckSuitesClient.cs new file mode 100644 index 0000000000..78c67d2096 --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableCheckSuitesClient.cs @@ -0,0 +1,271 @@ +using System; +using System.Reactive.Threading.Tasks; +using Octokit.Reactive.Internal; + +namespace Octokit.Reactive +{ + /// + /// A client for GitHub's Check Suites API. + /// + /// + /// See the Check Suites API documentation for more information. + /// + public class ObservableCheckSuitesClient : IObservableCheckSuitesClient + { + readonly ICheckSuitesClient _client; + readonly IConnection _connection; + + /// + /// Initializes a new GitHub Check Suites API client. + /// + /// An used to make the requests + public ObservableCheckSuitesClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, nameof(client)); + + _client = client.Check.Suite; + _connection = client.Connection; + } + + /// + /// Gets a single Check Suite by Id + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The Id of the check suite + public IObservable Get(string owner, string name, long checkSuiteId) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return _client.Get(owner, name, checkSuiteId).ToObservable(); + } + + /// + /// Gets a single Check Suite by Id + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The Id of the check suite + public IObservable Get(long repositoryId, long checkSuiteId) + { + return _client.Get(repositoryId, checkSuiteId).ToObservable(); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + public IObservable GetAllForReference(string owner, string name, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + + return GetAllForReference(owner, name, reference, new CheckSuiteRequest(), ApiOptions.None); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + public IObservable GetAllForReference(long repositoryId, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + + return GetAllForReference(repositoryId, reference, new CheckSuiteRequest(), ApiOptions.None); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + public IObservable GetAllForReference(string owner, string name, string reference, CheckSuiteRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAllForReference(owner, name, reference, request, ApiOptions.None); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + public IObservable GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAllForReference(repositoryId, reference, request, ApiOptions.None); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + /// Options to change the API response + public IObservable GetAllForReference(string owner, string name, string reference, CheckSuiteRequest request, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.CheckSuitesForReference(owner, name, reference), request.ToParametersDictionary(), AcceptHeaders.ChecksApiPreview, options); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + /// Options to change the API response + public IObservable GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.CheckSuitesForReference(repositoryId, reference), request.ToParametersDictionary(), AcceptHeaders.ChecksApiPreview, options); + } + + /// + /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The check suite preferences + public IObservable UpdatePreferences(string owner, string name, CheckSuitePreferences preferences) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(preferences, nameof(preferences)); + + return _client.UpdatePreferences(owner, name, preferences).ToObservable(); + } + + /// + /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The check suite preferences + public IObservable UpdatePreferences(long repositoryId, CheckSuitePreferences preferences) + { + Ensure.ArgumentNotNull(preferences, nameof(preferences)); + + return _client.UpdatePreferences(repositoryId, preferences).ToObservable(); + } + + /// + /// Creates a new Check Suite + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Details of the Check Suite to create + public IObservable Create(string owner, string name, NewCheckSuite newCheckSuite) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(newCheckSuite, nameof(newCheckSuite)); + + return _client.Create(owner, name, newCheckSuite).ToObservable(); + } + + /// + /// Creates a new Check Suite + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// Details of the Check Suite to create + public IObservable Create(long repositoryId, NewCheckSuite newCheckSuite) + { + Ensure.ArgumentNotNull(newCheckSuite, nameof(newCheckSuite)); + + return _client.Create(repositoryId, newCheckSuite).ToObservable(); + } + + /// + /// Triggers GitHub to create a new check suite, without pushing new code to a repository + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Details of the Check Suite request + public IObservable Request(string owner, string name, CheckSuiteTriggerRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return _client.Request(owner, name, request).ToObservable(); + } + + /// + /// Triggers GitHub to create a new check suite, without pushing new code to a repository + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// Details of the Check Suite request + + public IObservable Request(long repositoryId, CheckSuiteTriggerRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return _client.Request(repositoryId, request).ToObservable(); + } + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Clients/ObservableChecksClient.cs b/Octokit.Reactive/Clients/ObservableChecksClient.cs new file mode 100644 index 0000000000..90c4b72dcd --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableChecksClient.cs @@ -0,0 +1,26 @@ +namespace Octokit.Reactive +{ + /// + /// A client for GitHub's Checks API. + /// + /// + /// See the Checks API documentation for more information. + /// + public class ObservableChecksClient : IObservableChecksClient + { + public ObservableChecksClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, nameof(client)); + + Suite = new ObservableCheckSuitesClient(client); + } + + /// + /// A client for GitHub's Check Suites API. + /// + /// + /// See the Check Suites API documentation for more information. + /// + public IObservableCheckSuitesClient Suite { get; private set; } + } +} \ No newline at end of file diff --git a/Octokit.Reactive/IObservableGitHubClient.cs b/Octokit.Reactive/IObservableGitHubClient.cs index 2de5664e3e..bacdc13d72 100644 --- a/Octokit.Reactive/IObservableGitHubClient.cs +++ b/Octokit.Reactive/IObservableGitHubClient.cs @@ -32,5 +32,6 @@ public interface IObservableGitHubClient : IApiInfoProvider IObservableEnterpriseClient Enterprise { get; } IObservableMigrationClient Migration { get; } IObservableReactionsClient Reaction { get; } + IObservableChecksClient Check { get; } } } \ No newline at end of file diff --git a/Octokit.Reactive/ObservableGitHubClient.cs b/Octokit.Reactive/ObservableGitHubClient.cs index a7fd8ce636..f891ec847d 100644 --- a/Octokit.Reactive/ObservableGitHubClient.cs +++ b/Octokit.Reactive/ObservableGitHubClient.cs @@ -48,6 +48,7 @@ public ObservableGitHubClient(IGitHubClient gitHubClient) Enterprise = new ObservableEnterpriseClient(gitHubClient); Migration = new ObservableMigrationClient(gitHubClient); Reaction = new ObservableReactionsClient(gitHubClient); + Check = new ObservableChecksClient(gitHubClient); } public IConnection Connection @@ -85,6 +86,7 @@ public void SetRequestTimeout(TimeSpan timeout) public IObservableEnterpriseClient Enterprise { get; private set; } public IObservableMigrationClient Migration { get; private set; } public IObservableReactionsClient Reaction { get; private set; } + public IObservableChecksClient Check { get; private set; } /// /// Gets the latest API Info - this will be null if no API calls have been made diff --git a/Octokit.Tests.Integration/Clients/CheckSuitesClientTests.cs b/Octokit.Tests.Integration/Clients/CheckSuitesClientTests.cs new file mode 100644 index 0000000000..f2f4901db0 --- /dev/null +++ b/Octokit.Tests.Integration/Clients/CheckSuitesClientTests.cs @@ -0,0 +1,256 @@ +using System.Linq; +using System.Threading.Tasks; +using Octokit.Tests.Integration.Helpers; +using Xunit; + +namespace Octokit.Tests.Integration.Clients +{ + public class CheckSuitesClientTests + { + public class TheGetMethod + { + IGitHubClient _github; + IGitHubClient _githubAppInstallation; + + public TheGetMethod() + { + _github = Helper.GetAuthenticatedClient(); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName); + } + + [GitHubAppsTest] + public async Task GetsCheckSuite() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + // Need to get a CheckSuiteId so we can test the Get method + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, "master"); + var checkSuite = (await _githubAppInstallation.Check.Suite.GetAllForReference(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha)).CheckSuites.First(); + + // Get Check Suite by Id + var result = await _github.Check.Suite.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, checkSuite.Id); + + // Check result + Assert.Equal(checkSuite.Id, result.Id); + Assert.Equal(headCommit.Sha, result.HeadSha); + } + } + + [GitHubAppsTest] + public async Task GetsCheckSuiteWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + // Need to get a CheckSuiteId so we can test the Get method + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); + var checkSuite = (await _githubAppInstallation.Check.Suite.GetAllForReference(repoContext.RepositoryId, headCommit.Sha)).CheckSuites.First(); + + // Get Check Suite by Id + var result = await _github.Check.Suite.Get(repoContext.RepositoryId, checkSuite.Id); + + // Check result + Assert.Equal(checkSuite.Id, result.Id); + Assert.Equal(headCommit.Sha, result.HeadSha); + } + } + } + + public class TheGetAllForReferenceMethod + { + IGitHubClient _github; + IGitHubClient _githubAppInstallation; + + public TheGetAllForReferenceMethod() + { + _github = Helper.GetAuthenticatedClient(); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName); + } + + [GitHubAppsTest] + public async Task GetsAllCheckSuites() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, "master"); + + var checkSuites = await _githubAppInstallation.Check.Suite.GetAllForReference(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha); + + Assert.NotEmpty(checkSuites.CheckSuites); + foreach (var checkSuite in checkSuites.CheckSuites) + { + Assert.Equal(headCommit.Sha, checkSuite.HeadSha); + } + } + } + + [GitHubAppsTest] + public async Task GetsAllCheckSuitesWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); + + var checkSuites = await _githubAppInstallation.Check.Suite.GetAllForReference(repoContext.RepositoryId, headCommit.Sha); + + Assert.NotEmpty(checkSuites.CheckSuites); + foreach (var checkSuite in checkSuites.CheckSuites) + { + Assert.Equal(headCommit.Sha, checkSuite.HeadSha); + } + } + } + } + + public class TheUpdatePreferencesMethod + { + IGitHubClient _github; + IGitHubClient _githubAppInstallation; + + public TheUpdatePreferencesMethod() + { + _github = Helper.GetAuthenticatedClient(); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName); + } + + [GitHubAppsTest] + public async Task UpdatesPreferences() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var preference = new CheckSuitePreferences(new[] + { + new CheckSuitePreferenceAutoTrigger(Helper.GitHubAppId, false) + }); + var result = await _githubAppInstallation.Check.Suite.UpdatePreferences(repoContext.RepositoryOwner, repoContext.RepositoryName, preference); + + Assert.Equal(repoContext.RepositoryId, result.Repository.Id); + Assert.Equal(Helper.GitHubAppId, result.Preferences.AutoTriggerChecks[0].AppId); + Assert.Equal(false, result.Preferences.AutoTriggerChecks[0].Setting); + } + } + + [GitHubAppsTest] + public async Task UpdatesPreferencesWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var preference = new CheckSuitePreferences(new[] + { + new CheckSuitePreferenceAutoTrigger(Helper.GitHubAppId, false) + }); + var result = await _githubAppInstallation.Check.Suite.UpdatePreferences(repoContext.RepositoryId, preference); + + Assert.Equal(repoContext.RepositoryId, result.Repository.Id); + Assert.Equal(Helper.GitHubAppId, result.Preferences.AutoTriggerChecks[0].AppId); + Assert.Equal(false, result.Preferences.AutoTriggerChecks[0].Setting); + } + } + } + + public class TheCreateMethod + { + IGitHubClient _github; + IGitHubClient _githubAppInstallation; + + public TheCreateMethod() + { + _github = Helper.GetAuthenticatedClient(); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName); + } + + [GitHubAppsTest] + public async Task CreatesCheckSuite() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + // Turn off auto creation of check suite for this repo + var preference = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(Helper.GitHubAppId, false) }); + await _githubAppInstallation.Check.Suite.UpdatePreferences(repoContext.RepositoryOwner, repoContext.RepositoryName, preference); + + // Create a new feature branch + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, "master"); + var featureBranch = await Helper.CreateFeatureBranch(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha, "my-feature"); + + // Create a check suite for the feature branch + var newCheckSuite = new NewCheckSuite(featureBranch.Object.Sha); + var result = await _githubAppInstallation.Check.Suite.Create(repoContext.RepositoryOwner, repoContext.RepositoryName, newCheckSuite); + + // Check result + Assert.NotNull(result); + Assert.Equal(featureBranch.Object.Sha, result.HeadSha); + } + } + + [GitHubAppsTest] + public async Task CreatesCheckSuiteWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + // Turn off auto creation of check suite for this repo + var preference = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(Helper.GitHubAppId, false) }); + await _githubAppInstallation.Check.Suite.UpdatePreferences(repoContext.RepositoryId, preference); + + // Create a new feature branch + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); + var featureBranch = await Helper.CreateFeatureBranch(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha, "my-feature"); + + // Create a check suite for the feature branch + var newCheckSuite = new NewCheckSuite(featureBranch.Object.Sha); + var result = await _githubAppInstallation.Check.Suite.Create(repoContext.RepositoryId, newCheckSuite); + + // Check result + Assert.NotNull(result); + Assert.Equal(featureBranch.Object.Sha, result.HeadSha); + } + } + } + + public class TheRequestMethod + { + IGitHubClient _github; + IGitHubClient _githubAppInstallation; + + public TheRequestMethod() + { + _github = Helper.GetAuthenticatedClient(); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName); + } + + [GitHubAppsTest] + public async Task RequestsCheckSuite() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, "master"); + + var result = await _githubAppInstallation.Check.Suite.Request(repoContext.RepositoryOwner, repoContext.RepositoryName, new CheckSuiteTriggerRequest(headCommit.Sha)); + + Assert.True(result); + } + } + + [GitHubAppsTest] + public async Task RequestsCheckSuiteWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); + + var result = await _githubAppInstallation.Check.Suite.Request(repoContext.RepositoryId, new CheckSuiteTriggerRequest(headCommit.Sha)); + + Assert.True(result); + } + } + } + } +} diff --git a/Octokit.Tests.Integration/Clients/GitHubAppsClientTests.cs b/Octokit.Tests.Integration/Clients/GitHubAppsClientTests.cs index c62e654718..84c416ea27 100644 --- a/Octokit.Tests.Integration/Clients/GitHubAppsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/GitHubAppsClientTests.cs @@ -65,7 +65,6 @@ public async Task GetsAllInstallations() { var result = await _github.GitHubApps.GetAllInstallationsForCurrent(); - Assert.True(result.Any(x => x.Id == Helper.GitHubAppInstallationId)); foreach (var installation in result) { Assert.Equal(Helper.GitHubAppId, installation.AppId); @@ -91,8 +90,10 @@ public TheGetInstallationMethod() [GitHubAppsTest] public async Task GetsInstallation() { - var installationId = Helper.GitHubAppInstallationId; + // Get the installation Id + var installationId = Helper.GetGitHubAppInstallationForOwner(Helper.UserName).Id; + // Get the installation by Id var result = await _github.GitHubApps.GetInstallation(installationId); Assert.True(result.AppId == Helper.GitHubAppId); @@ -116,10 +117,12 @@ public TheCreateInstallationTokenMethod() } [GitHubAppsTest] - public async Task GetsInstallation() + public async Task CreatesInstallationToken() { - var installationId = Helper.GitHubAppInstallationId; + // Get the installation Id + var installationId = Helper.GetGitHubAppInstallationForOwner(Helper.UserName).Id; + // Create installation token var result = await _github.GitHubApps.CreateInstallationToken(installationId); Assert.NotNull(result.Token); diff --git a/Octokit.Tests.Integration/Helper.cs b/Octokit.Tests.Integration/Helper.cs index 32b67b4180..f005e0ffb9 100644 --- a/Octokit.Tests.Integration/Helper.cs +++ b/Octokit.Tests.Integration/Helper.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Reflection; +using System.Threading.Tasks; namespace Octokit.Tests.Integration { @@ -171,11 +173,6 @@ public static string GitHubAppSlug get { return Environment.GetEnvironmentVariable("OCTOKIT_GITHUBAPP_SLUG"); } } - public static long GitHubAppInstallationId - { - get { return Convert.ToInt64(Environment.GetEnvironmentVariable("OCTOKIT_GITHUBAPP_INSTALLATIONID")); } - } - public static void DeleteRepo(IConnection connection, Repository repository) { if (repository != null) @@ -304,6 +301,28 @@ public static GitHubClient GetAuthenticatedGitHubAppsClient() }; } + public static Installation GetGitHubAppInstallationForOwner(string owner) + { + var client = GetAuthenticatedGitHubAppsClient(); + var installations = client.GitHubApps.GetAllInstallationsForCurrent().Result; + var installation = installations.First(x => x.Account.Login == owner); + + return installation; + } + + public static GitHubClient GetAuthenticatedGitHubAppInstallationForOwner(string owner) + { + var client = GetAuthenticatedGitHubAppsClient(); + var installation = GetGitHubAppInstallationForOwner(owner); + + var token = client.GitHubApps.CreateInstallationToken(installation.Id).Result.Token; + + return new GitHubClient(new ProductHeaderValue("OctokitTests"), TargetUrl) + { + Credentials = new Credentials(token) + }; + } + public static void DeleteInvitations(IConnection connection, List invitees, int teamId) { try @@ -327,5 +346,42 @@ public static string InviteMemberToTeam(IConnection connection, int teamId, stri return login; } + + public async static Task CreateFeatureBranch(string owner, string repo, string parentSha, string branchName) + { + var github = Helper.GetAuthenticatedClient(); + + // Create content blob + var baselineBlob = new NewBlob + { + Content = "I am overwriting this blob with something new", + Encoding = EncodingType.Utf8 + }; + var baselineBlobResult = await github.Git.Blob.Create(owner, repo, baselineBlob); + + // Create tree item + var treeItem = new NewTreeItem + { + Type = TreeType.Blob, + Mode = FileMode.File, + Path = "README.md", + Sha = baselineBlobResult.Sha + }; + + // Create tree + var newTree = new NewTree(); + newTree.Tree.Add(treeItem); + var tree = await github.Git.Tree.Create(owner, repo, newTree); + + // Create commit + var newCommit = new NewCommit("this is the new commit", tree.Sha, parentSha); + var commit = await github.Git.Commit.Create(owner, repo, newCommit); + + // Create branch + var branch = await github.Git.Reference.Create(owner, repo, new NewReference($"refs/heads/{branchName}", commit.Sha)); + + // Return commit + return branch; + } } } diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 9ed8fc2720..c38f326981 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -19,7 +19,7 @@ false - + $(DefineConstants);GITHUBJWT_HELPER_AVAILABLE @@ -45,7 +45,7 @@ - + 0.0.2 diff --git a/Octokit.Tests.Integration/Reactive/ObservableCheckSuitesClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableCheckSuitesClientTests.cs new file mode 100644 index 0000000000..61983e0b2c --- /dev/null +++ b/Octokit.Tests.Integration/Reactive/ObservableCheckSuitesClientTests.cs @@ -0,0 +1,258 @@ +using System.Linq; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Octokit.Reactive; +using Octokit.Tests.Integration.Helpers; +using Xunit; + +namespace Octokit.Tests.Integration.Reactive +{ + public class ObservableCheckSuitesClientTests + { + public class TheGetMethod + { + IObservableGitHubClient _github; + IObservableGitHubClient _githubAppInstallation; + + public TheGetMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = new ObservableGitHubClient(Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName)); + } + + [GitHubAppsTest] + public async Task GetsCheckSuite() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + // Need to get a CheckSuiteId so we can test the Get method + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, "master"); + var checkSuite = (await _githubAppInstallation.Check.Suite.GetAllForReference(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha)).CheckSuites.First(); + + // Get Check Suite by Id + var result = await _github.Check.Suite.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, checkSuite.Id); + + // Check result + Assert.Equal(checkSuite.Id, result.Id); + Assert.Equal(headCommit.Sha, result.HeadSha); + } + } + + [GitHubAppsTest] + public async Task GetsCheckSuiteWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + // Need to get a CheckSuiteId so we can test the Get method + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); + var checkSuite = (await _githubAppInstallation.Check.Suite.GetAllForReference(repoContext.RepositoryId, headCommit.Sha)).CheckSuites.First(); + + // Get Check Suite by Id + var result = await _github.Check.Suite.Get(repoContext.RepositoryId, checkSuite.Id); + + // Check result + Assert.Equal(checkSuite.Id, result.Id); + Assert.Equal(headCommit.Sha, result.HeadSha); + } + } + } + + public class TheGetAllForReferenceMethod + { + IObservableGitHubClient _github; + IObservableGitHubClient _githubAppInstallation; + + public TheGetAllForReferenceMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = new ObservableGitHubClient(Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName)); + } + + [GitHubAppsTest] + public async Task GetsAllCheckSuites() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, "master"); + + var checkSuites = await _githubAppInstallation.Check.Suite.GetAllForReference(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha); + + Assert.NotEmpty(checkSuites.CheckSuites); + foreach (var checkSuite in checkSuites.CheckSuites) + { + Assert.Equal(headCommit.Sha, checkSuite.HeadSha); + } + } + } + + [GitHubAppsTest] + public async Task GetsAllCheckSuitesWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); + + var checkSuites = await _githubAppInstallation.Check.Suite.GetAllForReference(repoContext.RepositoryId, headCommit.Sha); + + Assert.NotEmpty(checkSuites.CheckSuites); + foreach (var checkSuite in checkSuites.CheckSuites) + { + Assert.Equal(headCommit.Sha, checkSuite.HeadSha); + } + } + } + } + + public class TheUpdatePreferencesMethod + { + IObservableGitHubClient _github; + IObservableGitHubClient _githubAppInstallation; + + public TheUpdatePreferencesMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = new ObservableGitHubClient(Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName)); + } + + [GitHubAppsTest] + public async Task UpdatesPreferences() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var preference = new CheckSuitePreferences(new[] + { + new CheckSuitePreferenceAutoTrigger(Helper.GitHubAppId, false) + }); + var result = await _githubAppInstallation.Check.Suite.UpdatePreferences(repoContext.RepositoryOwner, repoContext.RepositoryName, preference); + + Assert.Equal(repoContext.RepositoryId, result.Repository.Id); + Assert.Equal(Helper.GitHubAppId, result.Preferences.AutoTriggerChecks[0].AppId); + Assert.Equal(false, result.Preferences.AutoTriggerChecks[0].Setting); + } + } + + [GitHubAppsTest] + public async Task UpdatesPreferencesWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var preference = new CheckSuitePreferences(new[] + { + new CheckSuitePreferenceAutoTrigger(Helper.GitHubAppId, false) + }); + var result = await _githubAppInstallation.Check.Suite.UpdatePreferences(repoContext.RepositoryId, preference); + + Assert.Equal(repoContext.RepositoryId, result.Repository.Id); + Assert.Equal(Helper.GitHubAppId, result.Preferences.AutoTriggerChecks[0].AppId); + Assert.Equal(false, result.Preferences.AutoTriggerChecks[0].Setting); + } + } + } + + public class TheCreateMethod + { + IObservableGitHubClient _github; + IObservableGitHubClient _githubAppInstallation; + + public TheCreateMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = new ObservableGitHubClient(Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName)); + } + + [GitHubAppsTest] + public async Task CreatesCheckSuite() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + // Turn off auto creation of check suite for this repo + var preference = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(Helper.GitHubAppId, false) }); + await _githubAppInstallation.Check.Suite.UpdatePreferences(repoContext.RepositoryOwner, repoContext.RepositoryName, preference); + + // Create a new feature branch + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, "master"); + var featureBranch = await Helper.CreateFeatureBranch(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha, "my-feature"); + + // Create a check suite for the feature branch + var newCheckSuite = new NewCheckSuite(featureBranch.Object.Sha); + var result = await _githubAppInstallation.Check.Suite.Create(repoContext.RepositoryOwner, repoContext.RepositoryName, newCheckSuite); + + // Check result + Assert.NotNull(result); + Assert.Equal(featureBranch.Object.Sha, result.HeadSha); + } + } + + [GitHubAppsTest] + public async Task CreatesCheckSuiteWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + // Turn off auto creation of check suite for this repo + var preference = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(Helper.GitHubAppId, false) }); + await _githubAppInstallation.Check.Suite.UpdatePreferences(repoContext.RepositoryId, preference); + + // Create a new feature branch + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); + var featureBranch = await Helper.CreateFeatureBranch(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha, "my-feature"); + + // Create a check suite for the feature branch + var newCheckSuite = new NewCheckSuite(featureBranch.Object.Sha); + var result = await _githubAppInstallation.Check.Suite.Create(repoContext.RepositoryId, newCheckSuite); + + // Check result + Assert.NotNull(result); + Assert.Equal(featureBranch.Object.Sha, result.HeadSha); + } + } + } + + public class TheRequestMethod + { + IObservableGitHubClient _github; + IObservableGitHubClient _githubAppInstallation; + + public TheRequestMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + + // Authenticate as a GitHubApp Installation + _githubAppInstallation = new ObservableGitHubClient(Helper.GetAuthenticatedGitHubAppInstallationForOwner(Helper.UserName)); + } + + [GitHubAppsTest] + public async Task RequestsCheckSuite() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryOwner, repoContext.RepositoryName, "master"); + + var result = await _githubAppInstallation.Check.Suite.Request(repoContext.RepositoryOwner, repoContext.RepositoryName, new CheckSuiteTriggerRequest(headCommit.Sha)); + + Assert.True(result); + } + } + + [GitHubAppsTest] + public async Task RequestsCheckSuiteWithRepositoryId() + { + using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) + { + var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); + + var result = await _githubAppInstallation.Check.Suite.Request(repoContext.RepositoryId, new CheckSuiteTriggerRequest(headCommit.Sha)); + + Assert.True(result); + } + } + } + } +} diff --git a/Octokit.Tests/Clients/CheckSuitesClientTests.cs b/Octokit.Tests/Clients/CheckSuitesClientTests.cs new file mode 100644 index 0000000000..5223dd0a59 --- /dev/null +++ b/Octokit.Tests/Clients/CheckSuitesClientTests.cs @@ -0,0 +1,397 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; +using NSubstitute; +using Octokit.Tests.Helpers; +using Xunit; + +namespace Octokit.Tests.Clients +{ + public class CheckSuitesClientTests + { + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new CheckSuitesClient(null)); + } + } + + public class TheGetMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + await client.Get("fake", "repo", 1); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "repos/fake/repo/check-suites/1"), + Arg.Any>(), + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + await client.Get(1, 1); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "repositories/1/check-suites/1"), + Arg.Any>(), + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + await Assert.ThrowsAsync(() => client.Get(null, "repo", 1)); + await Assert.ThrowsAsync(() => client.Get("fake", null, 1)); + await Assert.ThrowsAsync(() => client.Get(null, "repo", 1)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + await Assert.ThrowsAsync(() => client.Get("", "repo", 1)); + await Assert.ThrowsAsync(() => client.Get("fake", "", 1)); + } + } + + public class TheGetAllForReferenceMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + await client.GetAllForReference("fake", "repo", "ref"); + + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repos/fake/repo/commits/ref/check-suites"), + Args.EmptyDictionary, + "application/vnd.github.antiope-preview+json", + Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + await client.GetAllForReference(1, "ref"); + + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repositories/1/commits/ref/check-suites"), + Args.EmptyDictionary, + "application/vnd.github.antiope-preview+json", + Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithRequest() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var request = new CheckSuiteRequest + { + AppId = 123, + CheckName = "build" + }; + + await client.GetAllForReference("fake", "repo", "ref", request); + + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repos/fake/repo/commits/ref/check-suites"), + Arg.Is>(x => + x["app_id"] == "123" + && x["check_name"] == "build"), + "application/vnd.github.antiope-preview+json", + Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithRequestWithRepositoryId() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var request = new CheckSuiteRequest + { + AppId = 123, + CheckName = "build" + }; + + await client.GetAllForReference(1, "ref", request); + + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repositories/1/commits/ref/check-suites"), + Arg.Is>(x => + x["app_id"] == "123" + && x["check_name"] == "build"), + "application/vnd.github.antiope-preview+json", + Args.ApiOptions); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var request = new CheckSuiteRequest(); + + await Assert.ThrowsAsync(() => client.GetAllForReference(null, "repo", "ref")); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", null, "ref")); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", null)); + + await Assert.ThrowsAsync(() => client.GetAllForReference(null, "repo", "ref", request)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", null, "ref", request)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", null, request)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", "ref", null)); + + await Assert.ThrowsAsync(() => client.GetAllForReference(null, "repo", "ref", request, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", null, "ref", request, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", null, request, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", "ref", null, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", "ref", request, null)); + + await Assert.ThrowsAsync(() => client.GetAllForReference(1, null)); + + await Assert.ThrowsAsync(() => client.GetAllForReference(1, null, request)); + await Assert.ThrowsAsync(() => client.GetAllForReference(1, "ref", null)); + + await Assert.ThrowsAsync(() => client.GetAllForReference(1, null, request, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForReference(1, "ref", null, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForReference(1, "ref", request, null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var request = new CheckSuiteRequest(); + + await Assert.ThrowsAsync(() => client.GetAllForReference("", "repo", "ref")); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "", "ref")); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", "")); + + await Assert.ThrowsAsync(() => client.GetAllForReference("", "repo", "ref", request)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "", "ref", request)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", "", request)); + + await Assert.ThrowsAsync(() => client.GetAllForReference("", "repo", "ref", request, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "", "ref", request, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForReference("fake", "repo", "", request, ApiOptions.None)); + + await Assert.ThrowsAsync(() => client.GetAllForReference(1, "")); + + await Assert.ThrowsAsync(() => client.GetAllForReference(1, "", request)); + + await Assert.ThrowsAsync(() => client.GetAllForReference(1, "", request, ApiOptions.None)); + } + } + + public class TheUpdatePreferencesMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var preferences = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(123, true) }); + + await client.UpdatePreferences("fake", "repo", preferences); + + connection.Received().Patch( + Arg.Is(u => u.ToString() == "repos/fake/repo/check-suites/preferences"), + preferences, + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var preferences = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(123, true) }); + + await client.UpdatePreferences(1, preferences); + + connection.Received().Patch( + Arg.Is(u => u.ToString() == "repositories/1/check-suites/preferences"), + preferences, + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var preferences = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(123, true) }); + + await Assert.ThrowsAsync(() => client.UpdatePreferences(null, "repo", preferences)); + await Assert.ThrowsAsync(() => client.UpdatePreferences("fake", null, preferences)); + await Assert.ThrowsAsync(() => client.UpdatePreferences("fake", "repo", null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var preferences = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(123, true) }); + + await Assert.ThrowsAsync(() => client.UpdatePreferences("", "repo", preferences)); + await Assert.ThrowsAsync(() => client.UpdatePreferences("fake", "", preferences)); + } + } + + public class TheCreateMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var newCheckSuite = new NewCheckSuite("123abc"); + + await client.Create("fake", "repo", newCheckSuite); + + connection.Received().Post( + Arg.Is(u => u.ToString() == "repos/fake/repo/check-suites"), + newCheckSuite, + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var newCheckSuite = new NewCheckSuite("123abc"); + + await client.Create(1, newCheckSuite); + + connection.Received().Post( + Arg.Is(u => u.ToString() == "repositories/1/check-suites"), + newCheckSuite, + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var newCheckSuite = new NewCheckSuite("123abc"); + + await Assert.ThrowsAsync(() => client.Create(null, "repo", newCheckSuite)); + await Assert.ThrowsAsync(() => client.Create("fake", null, newCheckSuite)); + await Assert.ThrowsAsync(() => client.Create("fake", "repo", null)); + + await Assert.ThrowsAsync(() => client.Create(1, null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var newCheckSuite = new NewCheckSuite("123abc"); + + await Assert.ThrowsAsync(() => client.Create("", "repo", newCheckSuite)); + await Assert.ThrowsAsync(() => client.Create("fake", "", newCheckSuite)); + } + } + + public class TheRequestMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = MockedIApiConnection.PostReturnsHttpStatus(HttpStatusCode.Created); + var client = new CheckSuitesClient(connection); + + var request = new CheckSuiteTriggerRequest("123abc"); + + await client.Request("fake", "repo", request); + + connection.Connection.Received().Post( + Arg.Is(u => u.ToString() == "repos/fake/repo/check-suite-requests"), + request, + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = MockedIApiConnection.PostReturnsHttpStatus(HttpStatusCode.Created); + var client = new CheckSuitesClient(connection); + + var request = new CheckSuiteTriggerRequest("123abc"); + + await client.Request(1, request); + + connection.Connection.Received().Post( + Arg.Is(u => u.ToString() == "repositories/1/check-suite-requests"), + request, + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var request = new CheckSuiteTriggerRequest("123abc"); + + await Assert.ThrowsAsync(() => client.Request(null, "repo", request)); + await Assert.ThrowsAsync(() => client.Request("fake", null, request)); + await Assert.ThrowsAsync(() => client.Request("fake", "repo", null)); + + await Assert.ThrowsAsync(() => client.Request(1, null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var connection = Substitute.For(); + var client = new CheckSuitesClient(connection); + + var request = new CheckSuiteTriggerRequest("123abc"); + + await Assert.ThrowsAsync(() => client.Request("", "repo", request)); + await Assert.ThrowsAsync(() => client.Request("fake", "", request)); + } + } + } +} \ No newline at end of file diff --git a/Octokit.Tests/Clients/ChecksClientTests.cs b/Octokit.Tests/Clients/ChecksClientTests.cs new file mode 100644 index 0000000000..dfed4391d5 --- /dev/null +++ b/Octokit.Tests/Clients/ChecksClientTests.cs @@ -0,0 +1,17 @@ +using System; +using Xunit; + +namespace Octokit.Tests.Clients +{ + public class ChecksClientTests + { + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new ChecksClient(null)); + } + } + } +} diff --git a/Octokit.Tests/Clients/EventsClientTests.cs b/Octokit.Tests/Clients/EventsClientTests.cs index 803f6fb487..3c9a79d2ac 100644 --- a/Octokit.Tests/Clients/EventsClientTests.cs +++ b/Octokit.Tests/Clients/EventsClientTests.cs @@ -553,6 +553,7 @@ public async Task EnsuresNonNullArguments() private readonly Dictionary _activityTypes = new Dictionary { + {"CheckSuiteEvent", typeof(CheckSuiteEventPayload)}, {"CommitCommentEvent", typeof(CommitCommentPayload)}, {"ForkEvent", typeof(ForkEventPayload)}, {"IssueCommentEvent", typeof(IssueCommentPayload)}, diff --git a/Octokit.Tests/Helpers/MockedIApiConnection.cs b/Octokit.Tests/Helpers/MockedIApiConnection.cs new file mode 100644 index 0000000000..8d40a37f5d --- /dev/null +++ b/Octokit.Tests/Helpers/MockedIApiConnection.cs @@ -0,0 +1,21 @@ +using System; +using System.Net; +using NSubstitute; + +namespace Octokit.Tests.Helpers +{ + public static class MockedIApiConnection + { + public static IApiConnection PostReturnsHttpStatus(HttpStatusCode status) + { + var connection = Substitute.For(); + connection.Post(Arg.Any(), Arg.Any(), Arg.Any()) + .Returns(status); + + var apiConnection = Substitute.For(); + apiConnection.Connection.Returns(connection); + + return apiConnection; + } + } +} diff --git a/Octokit.Tests/Models/CheckSuiteEventTests.cs b/Octokit.Tests/Models/CheckSuiteEventTests.cs new file mode 100644 index 0000000000..cccfa91454 --- /dev/null +++ b/Octokit.Tests/Models/CheckSuiteEventTests.cs @@ -0,0 +1,23 @@ +using Octokit.Internal; +using Xunit; + +namespace Octokit.Tests.Models +{ + public class CheckSuiteEventTests + { + [Fact] + public void CanBeDeserialized() + { + const string json = "{\r\n \"action\": \"rerequested\",\r\n \"check_suite\": {\r\n \"id\": 276096,\r\n \"head_branch\": null,\r\n \"head_sha\": \"73955d02043135d48809add98052c2170522158f\",\r\n \"status\": \"queued\",\r\n \"conclusion\": null,\r\n \"url\": \"https://api.github.com/repos/tgstation/tgstation/check-suites/276096\",\r\n \"before\": null,\r\n \"after\": null,\r\n \"pull_requests\": [\r\n\r\n ],\r\n \"app\": {\r\n \"id\": 9880,\r\n \"owner\": {\r\n \"login\": \"Cyberboss\",\r\n \"id\": 8171642,\r\n \"avatar_url\": \"https://avatars3.githubusercontent.com/u/8171642?v=4\",\r\n \"gravatar_id\": \"\",\r\n \"url\": \"https://api.github.com/users/Cyberboss\",\r\n \"html_url\": \"https://github.com/Cyberboss\",\r\n \"followers_url\": \"https://api.github.com/users/Cyberboss/followers\",\r\n \"following_url\": \"https://api.github.com/users/Cyberboss/following{/other_user}\",\r\n \"gists_url\": \"https://api.github.com/users/Cyberboss/gists{/gist_id}\",\r\n \"starred_url\": \"https://api.github.com/users/Cyberboss/starred{/owner}{/repo}\",\r\n \"subscriptions_url\": \"https://api.github.com/users/Cyberboss/subscriptions\",\r\n \"organizations_url\": \"https://api.github.com/users/Cyberboss/orgs\",\r\n \"repos_url\": \"https://api.github.com/users/Cyberboss/repos\",\r\n \"events_url\": \"https://api.github.com/users/Cyberboss/events{/privacy}\",\r\n \"received_events_url\": \"https://api.github.com/users/Cyberboss/received_events\",\r\n \"type\": \"User\",\r\n \"site_admin\": false\r\n },\r\n \"name\": \"MapDiffBot\",\r\n \"description\": \"Creates diff images of BYOND .dmm maps\",\r\n \"external_url\": \"https://github.com/MapDiffBot/MapDiffBot\",\r\n \"html_url\": \"https://github.com/apps/mapdiffbot\",\r\n \"created_at\": 1520618356,\r\n \"updated_at\": 1521225691\r\n },\r\n \"created_at\": \"2018-05-11T05:42:21Z\",\r\n \"updated_at\": \"2018-05-11T13:45:34Z\",\r\n \"unique_check_runs_count\": 1,\r\n \"check_runs_url\": \"https://api.github.com/repos/tgstation/tgstation/check-suites/276096/check-runs\",\r\n \"head_commit\": {\r\n \"id\": \"73955d02043135d48809add98052c2170522158f\",\r\n \"tree_id\": \"ef367b2a31c69d095c45e1b357afb9c78c4b6631\",\r\n \"message\": \"Remove a duplicate pipe in MetaStation maint\",\r\n \"timestamp\": \"2018-05-07T22:36:13-07:00\",\r\n \"author\": {\r\n \"name\": \"Tad Hardesty\",\r\n \"email\": \"tad@platymuus.com\"\r\n },\r\n \"committer\": {\r\n \"name\": \"Tad Hardesty\",\r\n \"email\": \"tad@platymuus.com\"\r\n }\r\n }\r\n },\r\n \"repository\": {\r\n \"id\": 3234987,\r\n \"name\": \"tgstation\",\r\n \"full_name\": \"tgstation/tgstation\",\r\n \"owner\": {\r\n \"login\": \"tgstation\",\r\n \"id\": 1363778,\r\n \"avatar_url\": \"https://avatars2.githubusercontent.com/u/1363778?v=4\",\r\n \"gravatar_id\": \"\",\r\n \"url\": \"https://api.github.com/users/tgstation\",\r\n \"html_url\": \"https://github.com/tgstation\",\r\n \"followers_url\": \"https://api.github.com/users/tgstation/followers\",\r\n \"following_url\": \"https://api.github.com/users/tgstation/following{/other_user}\",\r\n \"gists_url\": \"https://api.github.com/users/tgstation/gists{/gist_id}\",\r\n \"starred_url\": \"https://api.github.com/users/tgstation/starred{/owner}{/repo}\",\r\n \"subscriptions_url\": \"https://api.github.com/users/tgstation/subscriptions\",\r\n \"organizations_url\": \"https://api.github.com/users/tgstation/orgs\",\r\n \"repos_url\": \"https://api.github.com/users/tgstation/repos\",\r\n \"events_url\": \"https://api.github.com/users/tgstation/events{/privacy}\",\r\n \"received_events_url\": \"https://api.github.com/users/tgstation/received_events\",\r\n \"type\": \"Organization\",\r\n \"site_admin\": false\r\n },\r\n \"private\": false,\r\n \"html_url\": \"https://github.com/tgstation/tgstation\",\r\n \"description\": \"the /tg/station branch of SS13\",\r\n \"fork\": false,\r\n \"url\": \"https://api.github.com/repos/tgstation/tgstation\",\r\n \"forks_url\": \"https://api.github.com/repos/tgstation/tgstation/forks\",\r\n \"keys_url\": \"https://api.github.com/repos/tgstation/tgstation/keys{/key_id}\",\r\n \"collaborators_url\": \"https://api.github.com/repos/tgstation/tgstation/collaborators{/collaborator}\",\r\n \"teams_url\": \"https://api.github.com/repos/tgstation/tgstation/teams\",\r\n \"hooks_url\": \"https://api.github.com/repos/tgstation/tgstation/hooks\",\r\n \"issue_events_url\": \"https://api.github.com/repos/tgstation/tgstation/issues/events{/number}\",\r\n \"events_url\": \"https://api.github.com/repos/tgstation/tgstation/events\",\r\n \"assignees_url\": \"https://api.github.com/repos/tgstation/tgstation/assignees{/user}\",\r\n \"branches_url\": \"https://api.github.com/repos/tgstation/tgstation/branches{/branch}\",\r\n \"tags_url\": \"https://api.github.com/repos/tgstation/tgstation/tags\",\r\n \"blobs_url\": \"https://api.github.com/repos/tgstation/tgstation/git/blobs{/sha}\",\r\n \"git_tags_url\": \"https://api.github.com/repos/tgstation/tgstation/git/tags{/sha}\",\r\n \"git_refs_url\": \"https://api.github.com/repos/tgstation/tgstation/git/refs{/sha}\",\r\n \"trees_url\": \"https://api.github.com/repos/tgstation/tgstation/git/trees{/sha}\",\r\n \"statuses_url\": \"https://api.github.com/repos/tgstation/tgstation/statuses/{sha}\",\r\n \"languages_url\": \"https://api.github.com/repos/tgstation/tgstation/languages\",\r\n \"stargazers_url\": \"https://api.github.com/repos/tgstation/tgstation/stargazers\",\r\n \"contributors_url\": \"https://api.github.com/repos/tgstation/tgstation/contributors\",\r\n \"subscribers_url\": \"https://api.github.com/repos/tgstation/tgstation/subscribers\",\r\n \"subscription_url\": \"https://api.github.com/repos/tgstation/tgstation/subscription\",\r\n \"commits_url\": \"https://api.github.com/repos/tgstation/tgstation/commits{/sha}\",\r\n \"git_commits_url\": \"https://api.github.com/repos/tgstation/tgstation/git/commits{/sha}\",\r\n \"comments_url\": \"https://api.github.com/repos/tgstation/tgstation/comments{/number}\",\r\n \"issue_comment_url\": \"https://api.github.com/repos/tgstation/tgstation/issues/comments{/number}\",\r\n \"contents_url\": \"https://api.github.com/repos/tgstation/tgstation/contents/{+path}\",\r\n \"compare_url\": \"https://api.github.com/repos/tgstation/tgstation/compare/{base}...{head}\",\r\n \"merges_url\": \"https://api.github.com/repos/tgstation/tgstation/merges\",\r\n \"archive_url\": \"https://api.github.com/repos/tgstation/tgstation/{archive_format}{/ref}\",\r\n \"downloads_url\": \"https://api.github.com/repos/tgstation/tgstation/downloads\",\r\n \"issues_url\": \"https://api.github.com/repos/tgstation/tgstation/issues{/number}\",\r\n \"pulls_url\": \"https://api.github.com/repos/tgstation/tgstation/pulls{/number}\",\r\n \"milestones_url\": \"https://api.github.com/repos/tgstation/tgstation/milestones{/number}\",\r\n \"notifications_url\": \"https://api.github.com/repos/tgstation/tgstation/notifications{?since,all,participating}\",\r\n \"labels_url\": \"https://api.github.com/repos/tgstation/tgstation/labels{/name}\",\r\n \"releases_url\": \"https://api.github.com/repos/tgstation/tgstation/releases{/id}\",\r\n \"deployments_url\": \"https://api.github.com/repos/tgstation/tgstation/deployments\",\r\n \"created_at\": \"2012-01-21T17:32:47Z\",\r\n \"updated_at\": \"2018-05-11T06:24:11Z\",\r\n \"pushed_at\": \"2018-05-11T12:11:58Z\",\r\n \"git_url\": \"git://github.com/tgstation/tgstation.git\",\r\n \"ssh_url\": \"git@github.com:tgstation/tgstation.git\",\r\n \"clone_url\": \"https://github.com/tgstation/tgstation.git\",\r\n \"svn_url\": \"https://github.com/tgstation/tgstation\",\r\n \"homepage\": \"https://www.tgstation13.org/\",\r\n \"size\": 1126165,\r\n \"stargazers_count\": 515,\r\n \"watchers_count\": 515,\r\n \"language\": \"DM\",\r\n \"has_issues\": true,\r\n \"has_projects\": true,\r\n \"has_downloads\": true,\r\n \"has_wiki\": true,\r\n \"has_pages\": false,\r\n \"forks_count\": 1783,\r\n \"mirror_url\": null,\r\n \"archived\": false,\r\n \"open_issues_count\": 1211,\r\n \"license\": {\r\n \"key\": \"agpl-3.0\",\r\n \"name\": \"GNU Affero General Public License v3.0\",\r\n \"spdx_id\": \"AGPL-3.0\",\r\n \"url\": \"https://api.github.com/licenses/agpl-3.0\"\r\n },\r\n \"forks\": 1783,\r\n \"open_issues\": 1211,\r\n \"watchers\": 515,\r\n \"default_branch\": \"master\"\r\n },\r\n \"organization\": {\r\n \"login\": \"tgstation\",\r\n \"id\": 1363778,\r\n \"url\": \"https://api.github.com/orgs/tgstation\",\r\n \"repos_url\": \"https://api.github.com/orgs/tgstation/repos\",\r\n \"events_url\": \"https://api.github.com/orgs/tgstation/events\",\r\n \"hooks_url\": \"https://api.github.com/orgs/tgstation/hooks\",\r\n \"issues_url\": \"https://api.github.com/orgs/tgstation/issues\",\r\n \"members_url\": \"https://api.github.com/orgs/tgstation/members{/member}\",\r\n \"public_members_url\": \"https://api.github.com/orgs/tgstation/public_members{/member}\",\r\n \"avatar_url\": \"https://avatars2.githubusercontent.com/u/1363778?v=4\",\r\n \"description\": \"\"\r\n },\r\n \"sender\": {\r\n \"login\": \"Cyberboss\",\r\n \"id\": 8171642,\r\n \"avatar_url\": \"https://avatars3.githubusercontent.com/u/8171642?v=4\",\r\n \"gravatar_id\": \"\",\r\n \"url\": \"https://api.github.com/users/Cyberboss\",\r\n \"html_url\": \"https://github.com/Cyberboss\",\r\n \"followers_url\": \"https://api.github.com/users/Cyberboss/followers\",\r\n \"following_url\": \"https://api.github.com/users/Cyberboss/following{/other_user}\",\r\n \"gists_url\": \"https://api.github.com/users/Cyberboss/gists{/gist_id}\",\r\n \"starred_url\": \"https://api.github.com/users/Cyberboss/starred{/owner}{/repo}\",\r\n \"subscriptions_url\": \"https://api.github.com/users/Cyberboss/subscriptions\",\r\n \"organizations_url\": \"https://api.github.com/users/Cyberboss/orgs\",\r\n \"repos_url\": \"https://api.github.com/users/Cyberboss/repos\",\r\n \"events_url\": \"https://api.github.com/users/Cyberboss/events{/privacy}\",\r\n \"received_events_url\": \"https://api.github.com/users/Cyberboss/received_events\",\r\n \"type\": \"User\",\r\n \"site_admin\": false\r\n },\r\n \"installation\": {\r\n \"id\": 103621\r\n }\r\n}"; + + + var serializer = new SimpleJsonSerializer(); + + var payload = serializer.Deserialize(json); + + Assert.Equal("rerequested", payload.Action); + Assert.Equal("73955d02043135d48809add98052c2170522158f", payload.CheckSuite.HeadSha); + Assert.Equal(CheckStatus.Queued, payload.CheckSuite.Status.Value); + } + } +} diff --git a/Octokit.Tests/Reactive/ObservableCheckSuitesClientTests.cs b/Octokit.Tests/Reactive/ObservableCheckSuitesClientTests.cs new file mode 100644 index 0000000000..fd76da6edf --- /dev/null +++ b/Octokit.Tests/Reactive/ObservableCheckSuitesClientTests.cs @@ -0,0 +1,373 @@ +using System; +using System.Collections.Generic; +using System.Reactive.Threading.Tasks; +using System.Threading.Tasks; +using NSubstitute; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Clients +{ + public class ObservableObservableCheckSuitesClientTests + { + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new ObservableCheckSuitesClient(null)); + } + } + + public class TheGetMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + client.Get("fake", "repo", 1); + + gitHubClient.Check.Suite.Received().Get("fake", "repo", 1); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + client.Get(1, 1); + + gitHubClient.Check.Suite.Received().Get(1, 1); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + Assert.Throws(() => client.Get(null, "repo", 1)); + Assert.Throws(() => client.Get("fake", null, 1)); + Assert.Throws(() => client.Get(null, "repo", 1)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + Assert.Throws(() => client.Get("", "repo", 1)); + Assert.Throws(() => client.Get("fake", "", 1)); + } + } + + public class TheGetAllForReferenceMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableCheckSuitesClient(gitHubClient); + + client.GetAllForReference("fake", "repo", "ref"); + + connection.Received().Get>( + Arg.Is(u => u.ToString() == "repos/fake/repo/commits/ref/check-suites"), + Args.EmptyDictionary, + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableCheckSuitesClient(gitHubClient); + + client.GetAllForReference(1, "ref"); + + connection.Received().Get>( + Arg.Is(u => u.ToString() == "repositories/1/commits/ref/check-suites"), + Args.EmptyDictionary, + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task RequestsCorrectUrlWithRequest() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var request = new CheckSuiteRequest + { + AppId = 123, + CheckName = "build" + }; + + client.GetAllForReference("fake", "repo", "ref", request); + + connection.Received().Get>( + Arg.Is(u => u.ToString() == "repos/fake/repo/commits/ref/check-suites"), + Arg.Is>(x => + x["app_id"] == "123" + && x["check_name"] == "build"), + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task RequestsCorrectUrlWithRequestWithRepositoryId() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var request = new CheckSuiteRequest + { + AppId = 123, + CheckName = "build" + }; + + client.GetAllForReference(1, "ref", request); + + connection.Received().Get>( + Arg.Is(u => u.ToString() == "repositories/1/commits/ref/check-suites"), + Arg.Is>(x => + x["app_id"] == "123" + && x["check_name"] == "build"), + "application/vnd.github.antiope-preview+json"); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var request = new CheckSuiteRequest(); + + Assert.Throws(() => client.GetAllForReference(null, "repo", "ref")); + Assert.Throws(() => client.GetAllForReference("fake", null, "ref")); + Assert.Throws(() => client.GetAllForReference("fake", "repo", null)); + + Assert.Throws(() => client.GetAllForReference(null, "repo", "ref", request)); + Assert.Throws(() => client.GetAllForReference("fake", null, "ref", request)); + Assert.Throws(() => client.GetAllForReference("fake", "repo", null, request)); + Assert.Throws(() => client.GetAllForReference("fake", "repo", "ref", null)); + + Assert.Throws(() => client.GetAllForReference(null, "repo", "ref", request, ApiOptions.None)); + Assert.Throws(() => client.GetAllForReference("fake", null, "ref", request, ApiOptions.None)); + Assert.Throws(() => client.GetAllForReference("fake", "repo", null, request, ApiOptions.None)); + Assert.Throws(() => client.GetAllForReference("fake", "repo", "ref", null, ApiOptions.None)); + Assert.Throws(() => client.GetAllForReference("fake", "repo", "ref", request, null)); + + Assert.Throws(() => client.GetAllForReference(1, null)); + + Assert.Throws(() => client.GetAllForReference(1, null, request)); + Assert.Throws(() => client.GetAllForReference(1, "ref", null)); + + Assert.Throws(() => client.GetAllForReference(1, null, request, ApiOptions.None)); + Assert.Throws(() => client.GetAllForReference(1, "ref", null, ApiOptions.None)); + Assert.Throws(() => client.GetAllForReference(1, "ref", request, null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var request = new CheckSuiteRequest(); + + Assert.Throws(() => client.GetAllForReference("", "repo", "ref")); + Assert.Throws(() => client.GetAllForReference("fake", "", "ref")); + Assert.Throws(() => client.GetAllForReference("fake", "repo", "")); + + Assert.Throws(() => client.GetAllForReference("", "repo", "ref", request)); + Assert.Throws(() => client.GetAllForReference("fake", "", "ref", request)); + Assert.Throws(() => client.GetAllForReference("fake", "repo", "", request)); + + Assert.Throws(() => client.GetAllForReference("", "repo", "ref", request, ApiOptions.None)); + Assert.Throws(() => client.GetAllForReference("fake", "", "ref", request, ApiOptions.None)); + Assert.Throws(() => client.GetAllForReference("fake", "repo", "", request, ApiOptions.None)); + + Assert.Throws(() => client.GetAllForReference(1, "")); + + Assert.Throws(() => client.GetAllForReference(1, "", request)); + + Assert.Throws(() => client.GetAllForReference(1, "", request, ApiOptions.None)); + } + } + + public class TheUpdatePreferencesMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var preferences = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(123, true) }); + + client.UpdatePreferences("fake", "repo", preferences); + + gitHubClient.Check.Suite.Received().UpdatePreferences("fake", "repo", preferences); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var preferences = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(123, true) }); + + client.UpdatePreferences(1, preferences); + + gitHubClient.Check.Suite.Received().UpdatePreferences(1, preferences); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var preferences = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(123, true) }); + + Assert.Throws(() => client.UpdatePreferences(null, "repo", preferences)); + Assert.Throws(() => client.UpdatePreferences("fake", null, preferences)); + Assert.Throws(() => client.UpdatePreferences("fake", "repo", null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var preferences = new CheckSuitePreferences(new[] { new CheckSuitePreferenceAutoTrigger(123, true) }); + + Assert.Throws(() => client.UpdatePreferences("", "repo", preferences)); + Assert.Throws(() => client.UpdatePreferences("fake", "", preferences)); + } + } + + public class TheCreateMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var newCheckSuite = new NewCheckSuite("123abc"); + + client.Create("fake", "repo", newCheckSuite); + + gitHubClient.Check.Suite.Received().Create("fake", "repo", newCheckSuite); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var newCheckSuite = new NewCheckSuite("123abc"); + + client.Create(1, newCheckSuite); + + gitHubClient.Check.Suite.Received().Create(1, newCheckSuite); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var newCheckSuite = new NewCheckSuite("123abc"); + + Assert.Throws(() => client.Create(null, "repo", newCheckSuite)); + Assert.Throws(() => client.Create("fake", null, newCheckSuite)); + Assert.Throws(() => client.Create("fake", "repo", null)); + + Assert.Throws(() => client.Create(1, null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var newCheckSuite = new NewCheckSuite("123abc"); + + Assert.Throws(() => client.Create("", "repo", newCheckSuite)); + Assert.Throws(() => client.Create("fake", "", newCheckSuite)); + } + } + + public class TheRequestMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var request = new CheckSuiteTriggerRequest("123abc"); + + client.Request("fake", "repo", request); + + gitHubClient.Check.Suite.Received().Request("fake", "repo", request); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var request = new CheckSuiteTriggerRequest("123abc"); + + client.Request(1, request); + + gitHubClient.Check.Suite.Received().Request(1, request); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var request = new CheckSuiteTriggerRequest("123abc"); + + Assert.Throws(() => client.Request(null, "repo", request)); + Assert.Throws(() => client.Request("fake", null, request)); + Assert.Throws(() => client.Request("fake", "repo", null)); + + Assert.Throws(() => client.Request(1, null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCheckSuitesClient(gitHubClient); + + var request = new CheckSuiteTriggerRequest("123abc"); + + Assert.Throws(() => client.Request("", "repo", request)); + Assert.Throws(() => client.Request("fake", "", request)); + } + } + } +} diff --git a/Octokit.Tests/Reactive/ObservableChecksClientTests.cs b/Octokit.Tests/Reactive/ObservableChecksClientTests.cs new file mode 100644 index 0000000000..6fbfd3a1be --- /dev/null +++ b/Octokit.Tests/Reactive/ObservableChecksClientTests.cs @@ -0,0 +1,18 @@ +using System; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Clients +{ + public class ObservableChecksClientTests + { + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new ObservableChecksClient(null)); + } + } + } +} diff --git a/Octokit/Clients/CheckSuitesClient.cs b/Octokit/Clients/CheckSuitesClient.cs new file mode 100644 index 0000000000..cdcee1a857 --- /dev/null +++ b/Octokit/Clients/CheckSuitesClient.cs @@ -0,0 +1,285 @@ +using System.Linq; +using System.Net; +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// A client for GitHub's Check Suites API. + /// + /// + /// See the Check Suites API documentation for more information. + /// + public class CheckSuitesClient : ApiClient, ICheckSuitesClient + { + /// + /// Initializes a new GitHub Check Suites API client. + /// + /// An API connection + public CheckSuitesClient(IApiConnection apiConnection) : base(apiConnection) + { + } + + /// + /// Gets a single Check Suite by Id + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The Id of the check suite + public Task Get(string owner, string name, long checkSuiteId) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return ApiConnection.Get(ApiUrls.CheckSuite(owner, name, checkSuiteId), null, AcceptHeaders.ChecksApiPreview); + } + + /// + /// Gets a single Check Suite by Id + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The Id of the check suite + public Task Get(long repositoryId, long checkSuiteId) + { + return ApiConnection.Get(ApiUrls.CheckSuite(repositoryId, checkSuiteId), null, AcceptHeaders.ChecksApiPreview); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + public Task GetAllForReference(string owner, string name, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + + return GetAllForReference(owner, name, reference, new CheckSuiteRequest(), ApiOptions.None); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + public Task GetAllForReference(long repositoryId, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + + return GetAllForReference(repositoryId, reference, new CheckSuiteRequest(), ApiOptions.None); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + public Task GetAllForReference(string owner, string name, string reference, CheckSuiteRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAllForReference(owner, name, reference, request, ApiOptions.None); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + public Task GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAllForReference(repositoryId, reference, request, ApiOptions.None); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + /// Options to change the API response + public async Task GetAllForReference(string owner, string name, string reference, CheckSuiteRequest request, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + var results = await ApiConnection.GetAll(ApiUrls.CheckSuitesForReference(owner, name, reference), request.ToParametersDictionary(), AcceptHeaders.ChecksApiPreview, options).ConfigureAwait(false); + + return new CheckSuitesResponse( + results.Count > 0 ? results.Max(x => x.TotalCount) : 0, + results.SelectMany(x => x.CheckSuites).ToList()); + } + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + /// Options to change the API response + public async Task GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request, ApiOptions options) + { + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + Ensure.ArgumentNotNullOrEmptyString(reference, nameof(reference)); + + var results = await ApiConnection.GetAll(ApiUrls.CheckSuitesForReference(repositoryId, reference), request.ToParametersDictionary(), AcceptHeaders.ChecksApiPreview, options).ConfigureAwait(false); + + return new CheckSuitesResponse( + results.Count > 0 ? results.Max(x => x.TotalCount) : 0, + results.SelectMany(x => x.CheckSuites).ToList()); + } + + /// + /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The check suite preferences + public Task UpdatePreferences(string owner, string name, CheckSuitePreferences preferences) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(preferences, nameof(preferences)); + + return ApiConnection.Patch(ApiUrls.CheckSuitePreferences(owner, name), preferences, AcceptHeaders.ChecksApiPreview); + } + + /// + /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The check suite preferences + public Task UpdatePreferences(long repositoryId, CheckSuitePreferences preferences) + { + Ensure.ArgumentNotNull(preferences, nameof(preferences)); + + return ApiConnection.Patch(ApiUrls.CheckSuitePreferences(repositoryId), preferences, AcceptHeaders.ChecksApiPreview); + } + + /// + /// Creates a new Check Suite + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Details of the Check Suite to create + public Task Create(string owner, string name, NewCheckSuite newCheckSuite) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(newCheckSuite, nameof(newCheckSuite)); + + return ApiConnection.Post(ApiUrls.CheckSuites(owner, name), newCheckSuite, AcceptHeaders.ChecksApiPreview); + } + + /// + /// Creates a new Check Suite + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// Details of the Check Suite to create + public Task Create(long repositoryId, NewCheckSuite newCheckSuite) + { + Ensure.ArgumentNotNull(newCheckSuite, nameof(newCheckSuite)); + + return ApiConnection.Post(ApiUrls.CheckSuites(repositoryId), newCheckSuite, AcceptHeaders.ChecksApiPreview); + } + + /// + /// Triggers GitHub to create a new check suite, without pushing new code to a repository + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Details of the Check Suite request + public async Task Request(string owner, string name, CheckSuiteTriggerRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + + var httpStatusCode = await Connection.Post(ApiUrls.CheckSuiteRequests(owner, name), request, AcceptHeaders.ChecksApiPreview).ConfigureAwait(false); + + if (httpStatusCode != HttpStatusCode.Created) + { + throw new ApiException("Invalid Status Code returned. Expected a 201", httpStatusCode); + } + + return httpStatusCode == HttpStatusCode.Created; + } + + /// + /// Triggers GitHub to create a new check suite, without pushing new code to a repository + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// Details of the Check Suite request + public async Task Request(long repositoryId, CheckSuiteTriggerRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var httpStatusCode = await Connection.Post(ApiUrls.CheckSuiteRequests(repositoryId), request, AcceptHeaders.ChecksApiPreview).ConfigureAwait(false); + + if (httpStatusCode != HttpStatusCode.Created) + { + throw new ApiException("Invalid Status Code returned. Expected a 201", httpStatusCode); + } + + return httpStatusCode == HttpStatusCode.Created; + } + } +} \ No newline at end of file diff --git a/Octokit/Clients/ChecksClient.cs b/Octokit/Clients/ChecksClient.cs new file mode 100644 index 0000000000..17dcfcb766 --- /dev/null +++ b/Octokit/Clients/ChecksClient.cs @@ -0,0 +1,28 @@ +namespace Octokit +{ + /// + /// A client for GitHub's Checks API. + /// + /// + /// See the Checks API documentation for more information. + /// + public class ChecksClient : IChecksClient + { + /// + /// Initializes a new GitHub Checks API client. + /// + /// An API connection + public ChecksClient(ApiConnection apiConnection) + { + Suite = new CheckSuitesClient(apiConnection); + } + + /// + /// A client for GitHub's Check Suites API. + /// + /// + /// See the Check Suites API documentation for more information. + /// + public ICheckSuitesClient Suite { get; private set; } + } +} \ No newline at end of file diff --git a/Octokit/Clients/ICheckSuitesClient.cs b/Octokit/Clients/ICheckSuitesClient.cs new file mode 100644 index 0000000000..1e35b8190f --- /dev/null +++ b/Octokit/Clients/ICheckSuitesClient.cs @@ -0,0 +1,166 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// A client for GitHub's Check Suites API. + /// + /// + /// See the Check Suites API documentation for more information. + /// + public interface ICheckSuitesClient + { + /// + /// Gets a single Check Suite by Id + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The Id of the check suite + Task Get(string owner, string name, long checkSuiteId); + + /// + /// Gets a single Check Suite by Id + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The Id of the check suite + Task Get(long repositoryId, long checkSuiteId); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + Task GetAllForReference(string owner, string name, string reference); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + Task GetAllForReference(long repositoryId, string reference); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + Task GetAllForReference(string owner, string name, string reference, CheckSuiteRequest request); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + Task GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + /// Options to change the API response + Task GetAllForReference(string owner, string name, string reference, CheckSuiteRequest request, ApiOptions options); + + /// + /// Lists Check Suites for a commit reference (SHA, branch name or tag name) + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The reference (SHA, branch name or tag name) to list check suites for + /// Details to filter the request, such as by App Id or Check Name + /// Options to change the API response + Task GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request, ApiOptions options); + + /// + /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// The check suite preferences + Task UpdatePreferences(string owner, string name, CheckSuitePreferences preferences); + + /// + /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// The check suite preferences + Task UpdatePreferences(long repositoryId, CheckSuitePreferences preferences); + + /// + /// Creates a new Check Suite + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Details of the Check Suite to create + Task Create(string owner, string name, NewCheckSuite newCheckSuite); + + /// + /// Creates a new Check Suite + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// Details of the Check Suite to create + Task Create(long repositoryId, NewCheckSuite newCheckSuite); + + /// + /// Triggers GitHub to create a new check suite, without pushing new code to a repository + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Details of the Check Suite request + Task Request(string owner, string name, CheckSuiteTriggerRequest request); + + /// + /// Triggers GitHub to create a new check suite, without pushing new code to a repository + /// + /// + /// See the Check Suites API documentation for more information. + /// + /// The Id of the repository + /// Details of the Check Suite request + Task Request(long repositoryId, CheckSuiteTriggerRequest request); + } +} \ No newline at end of file diff --git a/Octokit/Clients/IChecksClient.cs b/Octokit/Clients/IChecksClient.cs new file mode 100644 index 0000000000..c973bc1e90 --- /dev/null +++ b/Octokit/Clients/IChecksClient.cs @@ -0,0 +1,19 @@ +namespace Octokit +{ + /// + /// A client for GitHub's Checks API. + /// + /// + /// See the Checks API documentation for more information. + /// + public interface IChecksClient + { + /// + /// A client for GitHub's Check Suites API. + /// + /// + /// See the Check Suites API documentation for more information. + /// + ICheckSuitesClient Suite { get; } + } +} diff --git a/Octokit/GitHubClient.cs b/Octokit/GitHubClient.cs index bb84c5eec7..c830978c21 100644 --- a/Octokit/GitHubClient.cs +++ b/Octokit/GitHubClient.cs @@ -110,6 +110,7 @@ public GitHubClient(IConnection connection) Search = new SearchClient(apiConnection); User = new UsersClient(apiConnection); Reaction = new ReactionsClient(apiConnection); + Check = new ChecksClient(apiConnection); } /// @@ -296,6 +297,14 @@ public Uri BaseAddress /// public IReactionsClient Reaction { get; private set; } + /// + /// Access GitHub's Checks API + /// + /// + /// Refer to the API documentation for more information: https://developer.github.com/v3/checks/ + /// + public IChecksClient Check { get; private set; } + static Uri FixUpBaseUri(Uri uri) { Ensure.ArgumentNotNull(uri, nameof(uri)); diff --git a/Octokit/Helpers/AcceptHeaders.cs b/Octokit/Helpers/AcceptHeaders.cs index d9bbfc424b..964982f9de 100644 --- a/Octokit/Helpers/AcceptHeaders.cs +++ b/Octokit/Helpers/AcceptHeaders.cs @@ -63,6 +63,8 @@ public static class AcceptHeaders public const string RepositoryTransferPreview = "application/vnd.github.nightshade-preview+json"; + public const string ChecksApiPreview = "application/vnd.github.antiope-preview+json"; + /// /// Combines multiple preview headers. GitHub API supports Accept header with multiple /// values separated by comma. diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 6cda2e72bc..e06d70cefb 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -3828,5 +3828,114 @@ public static Uri RepositoryLicense(long repositoryId) { return "repositories/{0}/license".FormatUri(repositoryId); } + + /// + /// Returns the that returns the specified check suite. + /// + /// The Id of the repository + /// The check run Id + /// The that returns the specified check suite. + public static Uri CheckSuite(long repositoryId, long id) + { + return "repositories/{0}/check-suites/{1}".FormatUri(repositoryId, id); + } + + /// + /// Returns the that returns the specified check suite. + /// + /// The owner of repo + /// The name of repo + /// The check run Id + /// The that returns the specified check suite. + public static Uri CheckSuite(string owner, string repo, long id) + { + return "repos/{0}/{1}/check-suites/{2}".FormatUri(owner, repo, id); + } + + /// + /// Returns the that lists the check suites for the specified reference. + /// + /// The Id of the repository + /// The git reference + /// The that returns the check suites for the specified reference. + public static Uri CheckSuitesForReference(long repositoryId, string reference) + { + return "repositories/{0}/commits/{1}/check-suites".FormatUri(repositoryId, reference); + } + + /// + /// Returns the that lists the check suites for the specified reference. + /// + /// The owner of repo + /// The name of repo + /// The git reference + /// The that returns the check suites for the specified reference. + public static Uri CheckSuitesForReference(string owner, string repo, string reference) + { + return "repos/{0}/{1}/commits/{2}/check-suites".FormatUri(owner, repo, reference); + } + + /// + /// Returns the that handles the check suites for the repository. + /// + /// The Id of the repository + /// The that handles the check suites for the repository. + public static Uri CheckSuites(long repositoryId) + { + return "repositories/{0}/check-suites".FormatUri(repositoryId); + } + + /// + /// Returns the that handles the check suites for the repository. + /// + /// The owner of repo + /// The name of repo + /// The that handles the check suites for the repository. + public static Uri CheckSuites(string owner, string repo) + { + return "repos/{0}/{1}/check-suites".FormatUri(owner, repo); + } + + /// + /// Returns the that handles the check suite requests for the repository. + /// + /// The Id of the repository + /// The that handles the check suite requests for the repository. + public static Uri CheckSuiteRequests(long repositoryId) + { + return "repositories/{0}/check-suite-requests".FormatUri(repositoryId); + } + + /// + /// Returns the that handles the check suite requests for the repository. + /// + /// The owner of repo + /// The name of repo + /// The that handles the check suite requests for the repository. + public static Uri CheckSuiteRequests(string owner, string repo) + { + return "repos/{0}/{1}/check-suite-requests".FormatUri(owner, repo); + } + + /// + /// Returns the that handles the check suite preferences for the repository. + /// + /// The Id of the repository + /// The that handles the check suite preferences for the repository. + public static Uri CheckSuitePreferences(long repositoryId) + { + return "repositories/{0}/check-suites/preferences".FormatUri(repositoryId); + } + + /// + /// Returns the that handles the check suite preferences for the repository. + /// + /// The owner of repo + /// The name of repo + /// The that handles the check suite preferences for the repository. + public static Uri CheckSuitePreferences(string owner, string repo) + { + return "repos/{0}/{1}/check-suites/preferences".FormatUri(owner, repo); + } } } diff --git a/Octokit/Http/SimpleJsonSerializer.cs b/Octokit/Http/SimpleJsonSerializer.cs index 0d0395a092..1fd2bc55bc 100644 --- a/Octokit/Http/SimpleJsonSerializer.cs +++ b/Octokit/Http/SimpleJsonSerializer.cs @@ -206,6 +206,8 @@ private static Type GetPayloadType(string activityType) { switch (activityType) { + case "CheckSuiteEvent": + return typeof(CheckSuiteEventPayload); case "CommitCommentEvent": return typeof(CommitCommentPayload); case "ForkEvent": diff --git a/Octokit/IGitHubClient.cs b/Octokit/IGitHubClient.cs index a9298a3ddc..032536b634 100644 --- a/Octokit/IGitHubClient.cs +++ b/Octokit/IGitHubClient.cs @@ -149,5 +149,13 @@ public interface IGitHubClient : IApiInfoProvider /// Refer to the API documentation for more information: https://developer.github.com/v3/reactions/ /// IReactionsClient Reaction { get; } + + /// + /// Access GitHub's Checks API. + /// + /// + /// Refer to the API documentation for more information: https://developer.github.com/v3/checks/ + /// + IChecksClient Check { get; } } } diff --git a/Octokit/Models/Common/CheckStatus.cs b/Octokit/Models/Common/CheckStatus.cs new file mode 100644 index 0000000000..c940781a23 --- /dev/null +++ b/Octokit/Models/Common/CheckStatus.cs @@ -0,0 +1,37 @@ +using Octokit.Internal; + +namespace Octokit +{ + public enum CheckStatus + { + [Parameter(Value = "queued")] + Queued, + + [Parameter(Value = "in_progress")] + InProgress, + + [Parameter(Value = "completed")] + Completed, + } + + public enum CheckConclusion + { + [Parameter(Value = "success")] + Success, + + [Parameter(Value = "failure")] + Failure, + + [Parameter(Value = "neutral")] + Neutral, + + [Parameter(Value = "cancelled")] + Cancelled, + + [Parameter(Value = "timed_out")] + TimedOut, + + [Parameter(Value = "action_required")] + ActionRequired, + } +} diff --git a/Octokit/Models/Common/CheckSuitePreferenceAutoTrigger.cs b/Octokit/Models/Common/CheckSuitePreferenceAutoTrigger.cs new file mode 100644 index 0000000000..0750446c51 --- /dev/null +++ b/Octokit/Models/Common/CheckSuitePreferenceAutoTrigger.cs @@ -0,0 +1,39 @@ +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + /// + /// Enables or disables automatic creation of CheckSuite events upon pushes to the repository + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CheckSuitePreferenceAutoTrigger + { + public CheckSuitePreferenceAutoTrigger() + { + } + + /// + /// Enables or disables automatic creation of CheckSuite events upon pushes to the repository + /// + /// The Id of the GitHub App (required) + /// Set to true to enable automatic creation of CheckSuite events upon pushes to the repository, or false to disable them (required) + public CheckSuitePreferenceAutoTrigger(long appId, bool setting) + { + AppId = appId; + Setting = setting; + } + + /// + /// The Id of the GitHub App + /// + public long AppId { get; protected set; } + + /// + /// Set to true to enable automatic creation of CheckSuite events upon pushes to the repository, or false to disable them + /// + public bool Setting { get; protected set; } + + internal string DebuggerDisplay => string.Format(CultureInfo.InvariantCulture, "{0}: {1}", AppId, Setting); + } +} \ No newline at end of file diff --git a/Octokit/Models/Common/CheckSuitePreferences.cs b/Octokit/Models/Common/CheckSuitePreferences.cs new file mode 100644 index 0000000000..8a3ad94ca4 --- /dev/null +++ b/Octokit/Models/Common/CheckSuitePreferences.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; + +namespace Octokit +{ + /// + /// Check Suite preferences + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CheckSuitePreferences + { + public CheckSuitePreferences() + { + } + + /// + /// Check Suite preferences + /// + /// Enables or disables automatic creation of CheckSuite events upon pushes to the repository. Enabled by default + public CheckSuitePreferences(IReadOnlyList autoTriggerChecks) + { + AutoTriggerChecks = autoTriggerChecks; + } + + /// + /// Enables or disables automatic creation of CheckSuite events upon pushes to the repository. Enabled by default + /// + public IReadOnlyList AutoTriggerChecks { get; protected set; } + + internal string DebuggerDisplay => string.Format(CultureInfo.InvariantCulture, "AutoTriggerChecks: {0}", string.Join(", ", AutoTriggerChecks.Select(x => x.DebuggerDisplay))); + } +} diff --git a/Octokit/Models/Request/CheckSuiteRequest.cs b/Octokit/Models/Request/CheckSuiteRequest.cs new file mode 100644 index 0000000000..58b9a52c8a --- /dev/null +++ b/Octokit/Models/Request/CheckSuiteRequest.cs @@ -0,0 +1,27 @@ +using System.Diagnostics; +using System.Globalization; +using Octokit.Internal; + +namespace Octokit +{ + /// + /// Details to filter a check suite request, such as by App Id or check run name + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CheckSuiteRequest : RequestParameters + { + /// + /// Filters check suites by GitHub App Id + /// + [Parameter(Key = "app_id")] + public long? AppId { get; set; } + + /// + /// Filters check suites by the name of the check run + /// + [Parameter(Key = "check_name")] + public string CheckName { get; set; } + + internal string DebuggerDisplay => string.Format(CultureInfo.InvariantCulture, "AppId: {0}, CheckName: {1}", AppId, CheckName); + } +} diff --git a/Octokit/Models/Request/CheckSuiteTriggerRequest.cs b/Octokit/Models/Request/CheckSuiteTriggerRequest.cs new file mode 100644 index 0000000000..564f903d31 --- /dev/null +++ b/Octokit/Models/Request/CheckSuiteTriggerRequest.cs @@ -0,0 +1,28 @@ +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + /// + /// Request to trigger the creation of a check suite + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CheckSuiteTriggerRequest + { + /// + /// Request to trigger the creation of a check suite + /// + /// The sha of the head commit (required) + public CheckSuiteTriggerRequest(string headSha) + { + HeadSha = headSha; + } + + /// + /// The sha of the head commit + /// + public string HeadSha { get; private set; } + + internal virtual string DebuggerDisplay => string.Format(CultureInfo.InvariantCulture, "HeadSha: {0}", HeadSha); + } +} \ No newline at end of file diff --git a/Octokit/Models/Request/NewCheckSuite.cs b/Octokit/Models/Request/NewCheckSuite.cs new file mode 100644 index 0000000000..d841b37ef5 --- /dev/null +++ b/Octokit/Models/Request/NewCheckSuite.cs @@ -0,0 +1,25 @@ +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class NewCheckSuite + { + /// + /// Creates a new Check Suite + /// + /// Required. The sha of the head commit. + public NewCheckSuite(string headSha) + { + HeadSha = headSha; + } + + /// + /// Required. The sha of the head commit. + /// + public string HeadSha { get; private set; } + + internal string DebuggerDisplay => string.Format(CultureInfo.InvariantCulture, "HeadSha: {0}", HeadSha); + } +} diff --git a/Octokit/Models/Response/ActivityPayloads/CheckSuiteEventPayload.cs b/Octokit/Models/Response/ActivityPayloads/CheckSuiteEventPayload.cs new file mode 100644 index 0000000000..3a0d324d8a --- /dev/null +++ b/Octokit/Models/Response/ActivityPayloads/CheckSuiteEventPayload.cs @@ -0,0 +1,11 @@ +using System.Diagnostics; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CheckSuiteEventPayload : ActivityPayload + { + public string Action { get; protected set; } + public CheckSuite CheckSuite { get; protected set; } + } +} diff --git a/Octokit/Models/Response/CheckSuite.cs b/Octokit/Models/Response/CheckSuite.cs new file mode 100644 index 0000000000..d2eac05171 --- /dev/null +++ b/Octokit/Models/Response/CheckSuite.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CheckSuite + { + public CheckSuite() + { + } + + public CheckSuite(long id, string headBranch, string headSha, CheckStatus status, CheckConclusion? conclusion, string url, string before, string after, IReadOnlyList pullRequests, GitHubApp app, Repository repository) + { + Id = id; + HeadBranch = headBranch; + HeadSha = headSha; + Status = status; + Conclusion = conclusion; + Url = url; + Before = before; + After = after; + PullRequests = pullRequests; + App = app; + Repository = repository; + } + + /// + /// The Id of this check suite + /// + public long Id { get; protected set; } + + /// + /// The head branch of the commit this check suite is associated with + /// + public string HeadBranch { get; protected set; } + + /// + /// The commit this check suite is associated with + /// + public string HeadSha { get; protected set; } + + /// + /// The summarized status of the check runs included in this check suite + /// + public StringEnum Status { get; protected set; } + + /// + /// The summarized conclusion of the check runs included in this check suite + /// + public StringEnum? Conclusion { get; protected set; } + + /// + /// The GitHub Api URL of this check suite + /// + public string Url { get; protected set; } + + /// + /// The hash of the commit prior to the HeadSha + /// + public string Before { get; protected set; } + + /// + /// The hash of the commit after the HeadSha + /// + public string After { get; protected set; } + + /// + /// The pull requests that are associated with the check suite (via the HeadSha) + /// + public IReadOnlyList PullRequests { get; protected set; } + + /// + /// The GitHub App that is associated with this check suite + /// + public GitHubApp App { get; protected set; } + + /// + /// The repository that is associated with this check suite + /// + public Repository Repository { get; protected set; } + + internal string DebuggerDisplay => string.Format(CultureInfo.InvariantCulture, "Id: {0}, HeadBranch: {1}, HeadSha: {2}, Conclusion: {3}", Id, HeadBranch, HeadSha, Conclusion); + } +} diff --git a/Octokit/Models/Response/CheckSuitePreferencesResponse.cs b/Octokit/Models/Response/CheckSuitePreferencesResponse.cs new file mode 100644 index 0000000000..ca1a1d6688 --- /dev/null +++ b/Octokit/Models/Response/CheckSuitePreferencesResponse.cs @@ -0,0 +1,31 @@ +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CheckSuitePreferencesResponse + { + public CheckSuitePreferencesResponse() + { + } + + public CheckSuitePreferencesResponse(CheckSuitePreferences preferences, Repository repository) + { + Preferences = preferences; + Repository = repository; + } + + /// + /// The check suite preferences + /// + public CheckSuitePreferences Preferences { get; protected set; } + + /// + /// The repository the check suite preferences are related to + /// + public Repository Repository { get; protected set; } + + internal string DebuggerDisplay => string.Format(CultureInfo.InvariantCulture, "Preferences: {0}, Repository: {1}", Preferences.DebuggerDisplay, Repository.DebuggerDisplay); + } +} diff --git a/Octokit/Models/Response/CheckSuitesResponse.cs b/Octokit/Models/Response/CheckSuitesResponse.cs new file mode 100644 index 0000000000..b41d8ddae6 --- /dev/null +++ b/Octokit/Models/Response/CheckSuitesResponse.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CheckSuitesResponse + { + public CheckSuitesResponse() + { + } + + public CheckSuitesResponse(int totalCount, IReadOnlyList checkSuites) + { + TotalCount = totalCount; + CheckSuites = checkSuites; + } + + /// + /// The total number of check suites that match the request filter + /// + public int TotalCount { get; protected set; } + + /// + /// The retrieved check suites + /// + public IReadOnlyList CheckSuites { get; protected set; } + + internal string DebuggerDisplay => string.Format(CultureInfo.CurrentCulture, "TotalCount: {0}, CheckSuites: {1}", TotalCount, CheckSuites.Count); + } +} diff --git a/Octokit/Models/Response/InstallationPermissions.cs b/Octokit/Models/Response/InstallationPermissions.cs index 1b89220660..1b01d031fc 100644 --- a/Octokit/Models/Response/InstallationPermissions.cs +++ b/Octokit/Models/Response/InstallationPermissions.cs @@ -9,7 +9,7 @@ public class InstallationPermissions { public InstallationPermissions() { } - public InstallationPermissions(InstallationPermissionLevel? metadata, InstallationPermissionLevel? administration, InstallationPermissionLevel? statuses, InstallationPermissionLevel? deployments, InstallationPermissionLevel? issues, InstallationPermissionLevel? pages, InstallationPermissionLevel? pullRequests, InstallationPermissionLevel? contents, InstallationPermissionLevel? singleFile, InstallationPermissionLevel? repositoryProjects, InstallationPermissionLevel? members, InstallationPermissionLevel? organizationProjects, InstallationPermissionLevel? teamDiscussions) + public InstallationPermissions(InstallationPermissionLevel? metadata, InstallationPermissionLevel? administration, InstallationPermissionLevel? statuses, InstallationPermissionLevel? deployments, InstallationPermissionLevel? issues, InstallationPermissionLevel? pages, InstallationPermissionLevel? pullRequests, InstallationPermissionLevel? contents, InstallationPermissionLevel? singleFile, InstallationPermissionLevel? repositoryProjects, InstallationPermissionLevel? members, InstallationPermissionLevel? organizationProjects, InstallationPermissionLevel? teamDiscussions, InstallationPermissionLevel? checks) { Metadata = metadata; Administration = administration; @@ -24,6 +24,7 @@ public InstallationPermissions(InstallationPermissionLevel? metadata, Installati Members = members; OrganizationProjects = organizationProjects; TeamDiscussions = teamDiscussions; + Checks = checks; } /// @@ -86,6 +87,12 @@ public InstallationPermissions(InstallationPermissionLevel? metadata, Installati /// public StringEnum? RepositoryProjects { get; protected set; } + /// + /// Checks + /// Detailed information about CI checks + /// + public StringEnum? Checks { get; protected set; } + /// /// Organization members (only applicable when installed for an Organization ) /// Organization members and teams. diff --git a/script/configure-integration-tests.ps1 b/script/configure-integration-tests.ps1 index c3943e5e0d..e06dacb83b 100644 --- a/script/configure-integration-tests.ps1 +++ b/script/configure-integration-tests.ps1 @@ -102,7 +102,6 @@ if (AskYesNoQuestion "Do you wish to setup GitHubApps integration test settings? { VerifyEnvironmentVariable "GitHub App ID" "OCTOKIT_GITHUBAPP_ID" VerifyEnvironmentVariable "GitHub App SLUG" "OCTOKIT_GITHUBAPP_SLUG" - VerifyEnvironmentVariable "GitHub App Installation ID" "OCTOKIT_GITHUBAPP_INSTALLATIONID" VerifyEnvironmentVariable "GitHub App Pem File" "OCTOKIT_GITHUBAPP_PEMFILE" }