From 160a72381e5102c90080d54771bbf8898100a13c Mon Sep 17 00:00:00 2001 From: Matisse Hack Date: Fri, 30 Aug 2024 16:59:52 -0700 Subject: [PATCH 1/8] Fix runner group access return type (#2965) * Fix runner group access return type * Fix tests * Fix observables --- .../Extensions.cs | 8 ----- ...ableActionsSelfHostedRunnerGroupsClient.cs | 8 ++--- ...ableActionsSelfHostedRunnerGroupsClient.cs | 12 +++---- ...ctionsSelfHostedRunnerGroupsClientTests.cs | 4 +-- .../ActionsSelfHostedRunnerGroupsClient.cs | 22 +++++++++---- .../IActionsSelfHostedRunnerGroupsClient.cs | 8 ++--- .../Models/Response/OrganizationsResponse.cs | 32 +++++++++++++++++++ .../Models/Response/RepositoriesResponse.cs | 4 +-- 8 files changed, 66 insertions(+), 32 deletions(-) create mode 100644 Octokit/Models/Response/OrganizationsResponse.cs diff --git a/Octokit.AsyncPaginationExtension/Extensions.cs b/Octokit.AsyncPaginationExtension/Extensions.cs index f41c07fbfe..7e2f6221a5 100644 --- a/Octokit.AsyncPaginationExtension/Extensions.cs +++ b/Octokit.AsyncPaginationExtension/Extensions.cs @@ -235,14 +235,6 @@ public static IPaginatedList GetAllAsync(this IRepoCollaboratorsCl public static IPaginatedList GetAllAsync(this IRepoCollaboratorsClient t, long repositoryId, RepositoryCollaboratorListRequest request, int pageSize = DEFAULT_PAGE_SIZE) => pageSize > 0 ? new PaginatedList(options => t.GetAll(repositoryId, request, options), pageSize) : throw new ArgumentOutOfRangeException(nameof(pageSize), pageSize, "The page size must be positive."); - /// - public static IPaginatedList ListAllRunnerGroupOrganizationsForEnterpriseAsync(this IActionsSelfHostedRunnerGroupsClient t, string enterprise, long runnerGroupId, int pageSize = DEFAULT_PAGE_SIZE) - => pageSize > 0 ? new PaginatedList(options => t.ListAllRunnerGroupOrganizationsForEnterprise(enterprise, runnerGroupId, options), pageSize) : throw new ArgumentOutOfRangeException(nameof(pageSize), pageSize, "The page size must be positive."); - - /// - public static IPaginatedList ListAllRunnerGroupRepositoriesForOrganizationAsync(this IActionsSelfHostedRunnerGroupsClient t, string org, long runnerGroupId, int pageSize = DEFAULT_PAGE_SIZE) - => pageSize > 0 ? new PaginatedList(options => t.ListAllRunnerGroupRepositoriesForOrganization(org, runnerGroupId, options), pageSize) : throw new ArgumentOutOfRangeException(nameof(pageSize), pageSize, "The page size must be positive."); - /// public static IPaginatedList GetAllAsync(this IProjectColumnsClient t, int projectId, int pageSize = DEFAULT_PAGE_SIZE) => pageSize > 0 ? new PaginatedList(options => t.GetAll(projectId, options), pageSize) : throw new ArgumentOutOfRangeException(nameof(pageSize), pageSize, "The page size must be positive."); diff --git a/Octokit.Reactive/Clients/IObservableActionsSelfHostedRunnerGroupsClient.cs b/Octokit.Reactive/Clients/IObservableActionsSelfHostedRunnerGroupsClient.cs index 4e6aaa2987..04c6e90d9b 100644 --- a/Octokit.Reactive/Clients/IObservableActionsSelfHostedRunnerGroupsClient.cs +++ b/Octokit.Reactive/Clients/IObservableActionsSelfHostedRunnerGroupsClient.cs @@ -117,7 +117,7 @@ public interface IObservableActionsSelfHostedRunnerGroupsClient /// /// The enterprise name /// The runner group id - IObservable ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId); + IObservable ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId); /// /// List organization access to a self-hosted runner group in an enterprise @@ -128,7 +128,7 @@ public interface IObservableActionsSelfHostedRunnerGroupsClient /// The enterprise name /// The runner group id /// Options for changing the API response - IObservable ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId, ApiOptions options); + IObservable ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId, ApiOptions options); /// /// List repository access to a self-hosted runner group in an organization @@ -138,7 +138,7 @@ public interface IObservableActionsSelfHostedRunnerGroupsClient /// /// The organization name /// The runner group id - IObservable ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId); + IObservable ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId); /// /// List repository access to a self-hosted runner group in an organization @@ -149,7 +149,7 @@ public interface IObservableActionsSelfHostedRunnerGroupsClient /// The organization name /// The runner group id /// Options for changing the API response - IObservable ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId, ApiOptions options); + IObservable ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId, ApiOptions options); } } diff --git a/Octokit.Reactive/Clients/ObservableActionsSelfHostedRunnerGroupsClient.cs b/Octokit.Reactive/Clients/ObservableActionsSelfHostedRunnerGroupsClient.cs index 7f7c0ec5a5..bb4369125e 100644 --- a/Octokit.Reactive/Clients/ObservableActionsSelfHostedRunnerGroupsClient.cs +++ b/Octokit.Reactive/Clients/ObservableActionsSelfHostedRunnerGroupsClient.cs @@ -175,7 +175,7 @@ public IObservable ListAllRunnersForOrganizationRunnerGroup(stri /// /// The enterprise name /// The runner group ID - public IObservable ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId) + public IObservable ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId) { return ListAllRunnerGroupOrganizationsForEnterprise(enterprise, runnerGroupId, ApiOptions.None); } @@ -189,12 +189,12 @@ public IObservable ListAllRunnerGroupOrganizationsForEnterprise(st /// The enterprise name /// The runner group ID /// Options for changing the API response - public IObservable ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId, ApiOptions options) + public IObservable ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(enterprise, nameof(enterprise)); Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.ActionsListEnterpriseRunnerGroupOrganizations(enterprise, runnerGroupId), options); + return _client.ListAllRunnerGroupOrganizationsForEnterprise(enterprise, runnerGroupId, options).ToObservable(); } /// @@ -205,7 +205,7 @@ public IObservable ListAllRunnerGroupOrganizationsForEnterprise(st /// /// The organization name /// The runner group ID - public IObservable ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId) + public IObservable ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId) { return ListAllRunnerGroupRepositoriesForOrganization(org, runnerGroupId, ApiOptions.None); } @@ -219,12 +219,12 @@ public IObservable ListAllRunnerGroupRepositoriesForOrganization(str /// The organization name /// The runner group ID /// Options for changing the API response - public IObservable ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId, ApiOptions options) + public IObservable ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.ActionsListOrganizationRunnerGroupRepositories(org, runnerGroupId), options); + return _client.ListAllRunnerGroupRepositoriesForOrganization(org, runnerGroupId, options).ToObservable(); } } diff --git a/Octokit.Tests/Clients/ActionsSelfHostedRunnerGroupsClientTests.cs b/Octokit.Tests/Clients/ActionsSelfHostedRunnerGroupsClientTests.cs index a1886ad8d2..f9af6067ff 100644 --- a/Octokit.Tests/Clients/ActionsSelfHostedRunnerGroupsClientTests.cs +++ b/Octokit.Tests/Clients/ActionsSelfHostedRunnerGroupsClientTests.cs @@ -217,7 +217,7 @@ public async Task RequestsCorrectUrl() await client.ListAllRunnerGroupOrganizationsForEnterprise("fake", 1); - connection.Received().GetAll( + connection.Received().GetAll( Arg.Is(u => u.ToString() == "enterprises/fake/actions/runner-groups/1/organizations"), Args.ApiOptions); } @@ -248,7 +248,7 @@ public async Task RequestsCorrectUrl() await client.ListAllRunnerGroupRepositoriesForOrganization("fake", 1, ApiOptions.None); - connection.Received().GetAll( + connection.Received().GetAll( Arg.Is(u => u.ToString() == "orgs/fake/actions/runner-groups/1/repositories"), Args.ApiOptions); } diff --git a/Octokit/Clients/ActionsSelfHostedRunnerGroupsClient.cs b/Octokit/Clients/ActionsSelfHostedRunnerGroupsClient.cs index 5520af6e06..a5bf26fecb 100644 --- a/Octokit/Clients/ActionsSelfHostedRunnerGroupsClient.cs +++ b/Octokit/Clients/ActionsSelfHostedRunnerGroupsClient.cs @@ -203,7 +203,7 @@ public async Task ListAllRunnersForOrganizationRunnerGroup(strin /// The enterprise name /// The runner group id [ManualRoute("GET", "/enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations")] - public Task> ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId) + public Task ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId) { return ListAllRunnerGroupOrganizationsForEnterprise(enterprise, runnerGroupId, ApiOptions.None); } @@ -218,11 +218,16 @@ public Task> ListAllRunnerGroupOrganizationsForEnter /// The runner group id /// Options for changing the API response [ManualRoute("GET", "/enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations")] - public Task> ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId, ApiOptions options) + public async Task ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(enterprise, nameof(enterprise)); - return ApiConnection.GetAll(ApiUrls.ActionsListEnterpriseRunnerGroupOrganizations(enterprise, runnerGroupId), options); + var results = await ApiConnection.GetAll(ApiUrls.ActionsListEnterpriseRunnerGroupOrganizations(enterprise, runnerGroupId), options).ConfigureAwait(false); + + return new OrganizationsResponse( + results.Count > 0 ? results.Max(x => x.TotalCount) : 0, + results.SelectMany(x => x.Organizations).ToList() + ); } /// @@ -234,7 +239,7 @@ public Task> ListAllRunnerGroupOrganizationsForEnter /// The organization name /// The runner group id [ManualRoute("GET", "/orgs/{org}/actions/runner-groups/{runner_group_id}/repositories")] - public Task> ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId) + public Task ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId) { return ListAllRunnerGroupRepositoriesForOrganization(org, runnerGroupId, ApiOptions.None); } @@ -249,11 +254,16 @@ public Task> ListAllRunnerGroupRepositoriesForOrganiza /// The runner group id /// Options for changing the API response [ManualRoute("GET", "/orgs/{org}/actions/runner-groups/{runner_group_id}/repositories")] - public Task> ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId, ApiOptions options) + public async Task ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); - return ApiConnection.GetAll(ApiUrls.ActionsListOrganizationRunnerGroupRepositories(org, runnerGroupId), options); + var results = await ApiConnection.GetAll(ApiUrls.ActionsListOrganizationRunnerGroupRepositories(org, runnerGroupId), options).ConfigureAwait(false); + + return new RepositoriesResponse( + results.Count > 0 ? results.Max(x => x.TotalCount) : 0, + results.SelectMany(x => x.Repositories).ToList() + ); } } } diff --git a/Octokit/Clients/IActionsSelfHostedRunnerGroupsClient.cs b/Octokit/Clients/IActionsSelfHostedRunnerGroupsClient.cs index 6e419407b3..5007467795 100644 --- a/Octokit/Clients/IActionsSelfHostedRunnerGroupsClient.cs +++ b/Octokit/Clients/IActionsSelfHostedRunnerGroupsClient.cs @@ -119,7 +119,7 @@ public interface IActionsSelfHostedRunnerGroupsClient /// /// The enterprise name /// The runner group id - Task> ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId); + Task ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId); /// /// List organization access to a self-hosted runner group in an enterprise @@ -130,7 +130,7 @@ public interface IActionsSelfHostedRunnerGroupsClient /// The enterprise name /// The runner group id /// Options for changing the API response - Task> ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId, ApiOptions options); + Task ListAllRunnerGroupOrganizationsForEnterprise(string enterprise, long runnerGroupId, ApiOptions options); /// /// List repository access to a self-hosted runner group in an organization @@ -140,7 +140,7 @@ public interface IActionsSelfHostedRunnerGroupsClient /// /// The organization name /// The runner group id - Task> ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId); + Task ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId); /// /// List repository access to a self-hosted runner group in an organization @@ -151,6 +151,6 @@ public interface IActionsSelfHostedRunnerGroupsClient /// The organization name /// The runner group id /// Options for changing the API response - Task> ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId, ApiOptions options); + Task ListAllRunnerGroupRepositoriesForOrganization(string org, long runnerGroupId, ApiOptions options); } } diff --git a/Octokit/Models/Response/OrganizationsResponse.cs b/Octokit/Models/Response/OrganizationsResponse.cs new file mode 100644 index 0000000000..3f4bbbf19b --- /dev/null +++ b/Octokit/Models/Response/OrganizationsResponse.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class OrganizationsResponse + { + public OrganizationsResponse() + { + } + + public OrganizationsResponse(int totalCount, IReadOnlyList organizations) + { + TotalCount = totalCount; + Organizations = organizations; + } + + /// + /// The total number of organizations + /// + public int TotalCount { get; private set; } + + /// + /// The retrieved organizations + /// + public IReadOnlyList Organizations { get; private set; } + + internal string DebuggerDisplay => string.Format(CultureInfo.CurrentCulture, "TotalCount: {0}, Organizations: {1}", TotalCount, Organizations.Count); + } +} diff --git a/Octokit/Models/Response/RepositoriesResponse.cs b/Octokit/Models/Response/RepositoriesResponse.cs index cf17e710b2..69ef9e3b68 100644 --- a/Octokit/Models/Response/RepositoriesResponse.cs +++ b/Octokit/Models/Response/RepositoriesResponse.cs @@ -18,12 +18,12 @@ public RepositoriesResponse(int totalCount, IReadOnlyList repositori } /// - /// The total number of check suites that match the request filter + /// The total number of repositories /// public int TotalCount { get; private set; } /// - /// The retrieved check suites + /// The retrieved repositories /// public IReadOnlyList Repositories { get; private set; } From d315b32033bbc4790b44bc413809f6ac0960b65d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 09:27:17 -0700 Subject: [PATCH 2/8] Bump Microsoft.NET.Test.Sdk from 17.11.0 to 17.11.1 (#2966) Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.11.0 to 17.11.1. - [Release notes](https://github.com/microsoft/vstest/releases) - [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md) - [Commits](https://github.com/microsoft/vstest/compare/v17.11.0...v17.11.1) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj | 2 +- Octokit.Tests.Integration/Octokit.Tests.Integration.csproj | 2 +- Octokit.Tests/Octokit.Tests.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj index ec7ad3d4f3..fa465276e4 100644 --- a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj +++ b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj @@ -33,7 +33,7 @@ - + diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 58e3b13418..e4cafd12ca 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -34,7 +34,7 @@ - + diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index ae01e13da4..3f1e74d074 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -33,7 +33,7 @@ - + From 8b0945c1b50c1555df538abc92a42f7b1dd2bed6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:14:40 -0700 Subject: [PATCH 3/8] Bump xunit from 2.9.0 to 2.9.1 (#2968) Bumps [xunit](https://github.com/xunit/xunit) from 2.9.0 to 2.9.1. - [Commits](https://github.com/xunit/xunit/compare/2.9.0...2.9.1) --- updated-dependencies: - dependency-name: xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj | 2 +- Octokit.Tests.Integration/Octokit.Tests.Integration.csproj | 2 +- Octokit.Tests/Octokit.Tests.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj index fa465276e4..777d7bf045 100644 --- a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj +++ b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj @@ -34,7 +34,7 @@ - + diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index e4cafd12ca..32495ad128 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -36,7 +36,7 @@ - + diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index 3f1e74d074..c7bc4d6971 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -35,7 +35,7 @@ - + From 28ae4ef85339e3cd8ef65a4e293790fb811d224a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 14:09:49 -0500 Subject: [PATCH 4/8] Bump xunit from 2.9.1 to 2.9.2 (#2972) Bumps [xunit](https://github.com/xunit/xunit) from 2.9.1 to 2.9.2. - [Commits](https://github.com/xunit/xunit/compare/v2-2.9.1...v2-2.9.2) --- updated-dependencies: - dependency-name: xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj | 2 +- Octokit.Tests.Integration/Octokit.Tests.Integration.csproj | 2 +- Octokit.Tests/Octokit.Tests.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj index 777d7bf045..20b809e083 100644 --- a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj +++ b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj @@ -34,7 +34,7 @@ - + diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 32495ad128..f13ff55621 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -36,7 +36,7 @@ - + diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index c7bc4d6971..19a8a6819b 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -35,7 +35,7 @@ - + From bd51f93930980bc3c3401ccc10b700fc5215b225 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:24:57 -0500 Subject: [PATCH 5/8] Bump NSubstitute from 5.1.0 to 5.3.0 (#2979) Bumps [NSubstitute](https://github.com/nsubstitute/NSubstitute) from 5.1.0 to 5.3.0. - [Release notes](https://github.com/nsubstitute/NSubstitute/releases) - [Changelog](https://github.com/nsubstitute/NSubstitute/blob/main/CHANGELOG.md) - [Commits](https://github.com/nsubstitute/NSubstitute/compare/v5.1.0...v5.3.0) --- updated-dependencies: - dependency-name: NSubstitute dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Octokit.Tests/Octokit.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index 19a8a6819b..4ca5500879 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -29,7 +29,7 @@ - + From 82ce1d503160d24ea1e096722922f4ff50d675b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:25:10 -0500 Subject: [PATCH 6/8] Bump Cake.Frosting from 4.0.0 to 4.2.0 in /build (#2978) Bumps [Cake.Frosting](https://github.com/cake-build/cake) from 4.0.0 to 4.2.0. - [Release notes](https://github.com/cake-build/cake/releases) - [Changelog](https://github.com/cake-build/cake/blob/develop/ReleaseNotes.md) - [Commits](https://github.com/cake-build/cake/compare/v4.0.0...v4.2.0) --- updated-dependencies: - dependency-name: Cake.Frosting dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build/Build.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Build.csproj b/build/Build.csproj index a719b91b10..ac858f4788 100644 --- a/build/Build.csproj +++ b/build/Build.csproj @@ -9,7 +9,7 @@ - + From 6eefc5921be18ee14f860516a9d568a5615ab5c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:30:38 -0800 Subject: [PATCH 7/8] Bump Microsoft.NET.Test.Sdk and Microsoft.NETFramework.ReferenceAssemblies (#2984) Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) and [Microsoft.NETFramework.ReferenceAssemblies](https://github.com/Microsoft/dotnet). These dependencies needed to be updated together. Updates `Microsoft.NET.Test.Sdk` from 17.11.1 to 17.12.0 - [Release notes](https://github.com/microsoft/vstest/releases) - [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md) - [Commits](https://github.com/microsoft/vstest/compare/v17.11.1...v17.12.0) Updates `Microsoft.NETFramework.ReferenceAssemblies` from 1.0.3 to 1.0.3 - [Commits](https://github.com/Microsoft/dotnet/commits) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: Microsoft.NETFramework.ReferenceAssemblies dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj | 2 +- Octokit.Tests.Integration/Octokit.Tests.Integration.csproj | 2 +- Octokit.Tests/Octokit.Tests.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj index 20b809e083..94cbc9dc43 100644 --- a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj +++ b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj @@ -33,7 +33,7 @@ - + diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index f13ff55621..64664094ab 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -34,7 +34,7 @@ - + diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index 4ca5500879..90d44fcbc7 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -33,7 +33,7 @@ - + From f9fb116eabe0028b7e61d25bbe81403673338824 Mon Sep 17 00:00:00 2001 From: Colby Williams Date: Fri, 27 Dec 2024 14:05:00 -0600 Subject: [PATCH 8/8] [FEAT]: Add support for Public Keys API (#2945) * Add support for /mets/public_keys/ * "files.insertFinalNewline": false * revert and make setttings.json change csharp only * formatting * remove final new line --------- Co-authored-by: Nick Floyd <139819+nickfloyd@users.noreply.github.com> --- .gitignore | 5 +- .vscode/settings.json | 8 +- .../Clients/IObservableMetaClient.cs | 5 ++ .../Clients/IObservablePublicKeysClient.cs | 20 +++++ .../Clients/ObservableMetaClient.cs | 7 ++ .../Clients/ObservablePublicKeysClient.cs | 34 +++++++ .../Clients/PublicKeysClientTest.cs | 28 ++++++ .../Clients/PublicKeysClientTests.cs | 90 +++++++++++++++++++ Octokit.Tests/Models/MetaPublicKeysTests.cs | 44 +++++++++ .../ObservablePublicKeysClientTests.cs | 33 +++++++ Octokit/Clients/IMetaClient.cs | 5 ++ Octokit/Clients/IPublicKeysClient.cs | 20 +++++ Octokit/Clients/MetaClient.cs | 6 ++ Octokit/Clients/PublicKeysClient.cs | 33 +++++++ Octokit/Helpers/ApiUrls.cs | 10 +++ Octokit/Models/Common/PublicKeyType.cs | 19 ++++ Octokit/Models/Response/MetaPublicKey.cs | 29 ++++++ Octokit/Models/Response/MetaPublicKeys.cs | 24 +++++ 18 files changed, 418 insertions(+), 2 deletions(-) create mode 100644 Octokit.Reactive/Clients/IObservablePublicKeysClient.cs create mode 100644 Octokit.Reactive/Clients/ObservablePublicKeysClient.cs create mode 100644 Octokit.Tests.Integration/Clients/PublicKeysClientTest.cs create mode 100644 Octokit.Tests/Clients/PublicKeysClientTests.cs create mode 100644 Octokit.Tests/Models/MetaPublicKeysTests.cs create mode 100644 Octokit.Tests/Reactive/ObservablePublicKeysClientTests.cs create mode 100644 Octokit/Clients/IPublicKeysClient.cs create mode 100644 Octokit/Clients/PublicKeysClient.cs create mode 100644 Octokit/Models/Common/PublicKeyType.cs create mode 100644 Octokit/Models/Response/MetaPublicKey.cs create mode 100644 Octokit/Models/Response/MetaPublicKeys.cs diff --git a/.gitignore b/.gitignore index 4184f93872..db81db57cf 100644 --- a/.gitignore +++ b/.gitignore @@ -105,4 +105,7 @@ tools/* coverage-results/* # Rider -**/.idea/* \ No newline at end of file +**/.idea/* + +# macOS +.DS_Store \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 0c1ea17bae..77504b0729 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,5 +11,11 @@ "files.insertFinalNewline": true, "editor.detectIndentation": false, "editor.tabSize": 2, - "editor.insertSpaces": true + "editor.insertSpaces": true, + "[csharp]": { + "editor.tabSize": 4 + }, + "explorer.fileNesting.patterns": { + "*.cs": "I${capture}.cs", + }, } diff --git a/Octokit.Reactive/Clients/IObservableMetaClient.cs b/Octokit.Reactive/Clients/IObservableMetaClient.cs index 97d63d19e3..3555670358 100644 --- a/Octokit.Reactive/Clients/IObservableMetaClient.cs +++ b/Octokit.Reactive/Clients/IObservableMetaClient.cs @@ -10,6 +10,11 @@ namespace Octokit.Reactive /// public interface IObservableMetaClient { + /// + /// Returns a client to get public keys for validating request signatures. + /// + IObservablePublicKeysClient PublicKeys { get; } + /// /// Retrieves information about GitHub.com, the service or a GitHub Enterprise installation. /// diff --git a/Octokit.Reactive/Clients/IObservablePublicKeysClient.cs b/Octokit.Reactive/Clients/IObservablePublicKeysClient.cs new file mode 100644 index 0000000000..02aae89a0a --- /dev/null +++ b/Octokit.Reactive/Clients/IObservablePublicKeysClient.cs @@ -0,0 +1,20 @@ +using System; + +namespace Octokit.Reactive +{ + /// + /// A client for GitHub's meta public keys API. + /// + /// + /// See the Secret scanning documentation for more details. + /// + public interface IObservablePublicKeysClient + { + /// + /// Retrieves public keys for validating request signatures. + /// + /// Thrown when a general API error occurs. + /// An containing public keys for validating request signatures. + IObservable Get(PublicKeyType keysType); + } +} diff --git a/Octokit.Reactive/Clients/ObservableMetaClient.cs b/Octokit.Reactive/Clients/ObservableMetaClient.cs index 3df88872d7..d8283ed623 100644 --- a/Octokit.Reactive/Clients/ObservableMetaClient.cs +++ b/Octokit.Reactive/Clients/ObservableMetaClient.cs @@ -18,9 +18,16 @@ public ObservableMetaClient(IGitHubClient client) { Ensure.ArgumentNotNull(client, nameof(client)); + PublicKeys = new ObservablePublicKeysClient(client); + _client = client.Meta; } + /// + /// Returns a client to manage get public keys for validating request signatures. + /// + public IObservablePublicKeysClient PublicKeys { get; private set; } + /// /// Retrieves information about GitHub.com, the service or a GitHub Enterprise installation. /// diff --git a/Octokit.Reactive/Clients/ObservablePublicKeysClient.cs b/Octokit.Reactive/Clients/ObservablePublicKeysClient.cs new file mode 100644 index 0000000000..5339645561 --- /dev/null +++ b/Octokit.Reactive/Clients/ObservablePublicKeysClient.cs @@ -0,0 +1,34 @@ +using System; +using System.Reactive.Linq; +using System.Reactive.Threading.Tasks; + +namespace Octokit.Reactive +{ + /// + /// A client for GitHub's public keys API. + /// + /// + /// See the Secret scanning documentation for more details. + /// + public class ObservablePublicKeysClient : IObservablePublicKeysClient + { + private readonly IPublicKeysClient _client; + + public ObservablePublicKeysClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, nameof(client)); + + _client = client.Meta.PublicKeys; + } + + /// + /// Retrieves public keys for validating request signatures. + /// + /// Thrown when a general API error occurs. + /// An containing public keys for validating request signatures. + public IObservable Get(PublicKeyType keysType) + { + return _client.Get(keysType).ToObservable(); + } + } +} diff --git a/Octokit.Tests.Integration/Clients/PublicKeysClientTest.cs b/Octokit.Tests.Integration/Clients/PublicKeysClientTest.cs new file mode 100644 index 0000000000..a6b2effb1f --- /dev/null +++ b/Octokit.Tests.Integration/Clients/PublicKeysClientTest.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using Xunit; + +namespace Octokit.Tests.Integration.Clients +{ + public class PublicKeysClientTests + { + public class TheGetMethod + { + [IntegrationTest] + public async Task CanRetrievePublicKeys() + { + var github = Helper.GetAnonymousClient(); + + var result = await github.Meta.PublicKeys.Get(PublicKeyType.SecretScanning); + + Assert.NotNull(result); + Assert.Equal(2, result.PublicKeys.Count); + + Assert.NotNull(result.PublicKeys[0].KeyIdentifier); + Assert.NotNull(result.PublicKeys[0].Key); + + Assert.NotNull(result.PublicKeys[1].KeyIdentifier); + Assert.NotNull(result.PublicKeys[1].Key); + } + } + } +} diff --git a/Octokit.Tests/Clients/PublicKeysClientTests.cs b/Octokit.Tests/Clients/PublicKeysClientTests.cs new file mode 100644 index 0000000000..ee416a6604 --- /dev/null +++ b/Octokit.Tests/Clients/PublicKeysClientTests.cs @@ -0,0 +1,90 @@ +using System; +using System.Threading.Tasks; +using NSubstitute; +using Xunit; + +namespace Octokit.Tests.Clients +{ + public class PublicKeysClientTests + { + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new PublicKeysClient(null)); + } + } + + public class TheGetMethod + { + [Fact] + public async Task RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new PublicKeysClient(connection); + + await client.Get(PublicKeyType.CopilotApi); + + connection.Received() + .Get(Arg.Is(u => u.ToString() == "meta/public_keys/copilot_api")); + } + + [Fact] + public async Task RequestsCopilotApiPublicKeysEndpoint() + { + var publicKeys = new MetaPublicKeys(publicKeys: new[] { + new MetaPublicKey("4fe6b016179b74078ade7581abf4e84fb398c6fae4fb973972235b84fcd70ca3", "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELPuPiLVQbHY/clvpNnY+0BzYIXgo\nS0+XhEkTWUZEEznIVpS3rQseDTG6//gEWr4j9fY35+dGOxwOx3Z9mK3i7w==\n-----END PUBLIC KEY-----\n", true), + new MetaPublicKey("df3454252d91570ae1bc597182d1183c7a8d42ff0ae96e0f2be4ba278d776546", "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEl5xbyr5bmETCJzqAvDnYl1ZKJrkf\n89Nyq5j06TTKrnHXXDw4FYNY1uF2S/w6EOaxbf9BxOidCLvjJ8ZgKzNpww==\n-----END PUBLIC KEY-----\n", false) + }); + + var apiConnection = Substitute.For(); + apiConnection.Get(Arg.Is(u => u.ToString() == "meta/public_keys/copilot_api")).Returns(Task.FromResult(publicKeys)); + + var client = new PublicKeysClient(apiConnection); + + var result = await client.Get(PublicKeyType.CopilotApi); + + Assert.Equal(2, result.PublicKeys.Count); + Assert.Equal("4fe6b016179b74078ade7581abf4e84fb398c6fae4fb973972235b84fcd70ca3", result.PublicKeys[0].KeyIdentifier); + Assert.Equal("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELPuPiLVQbHY/clvpNnY+0BzYIXgo\nS0+XhEkTWUZEEznIVpS3rQseDTG6//gEWr4j9fY35+dGOxwOx3Z9mK3i7w==\n-----END PUBLIC KEY-----\n", result.PublicKeys[0].Key); + Assert.True(result.PublicKeys[0].IsCurrent); + + Assert.Equal("df3454252d91570ae1bc597182d1183c7a8d42ff0ae96e0f2be4ba278d776546", result.PublicKeys[1].KeyIdentifier); + Assert.Equal("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEl5xbyr5bmETCJzqAvDnYl1ZKJrkf\n89Nyq5j06TTKrnHXXDw4FYNY1uF2S/w6EOaxbf9BxOidCLvjJ8ZgKzNpww==\n-----END PUBLIC KEY-----\n", result.PublicKeys[1].Key); + Assert.False(result.PublicKeys[1].IsCurrent); + + apiConnection.Received() + .Get(Arg.Is(u => u.ToString() == "meta/public_keys/copilot_api")); + } + + [Fact] + public async Task RequestSecretScanningPublicKeysEndpoint() + { + var publicKeys = new MetaPublicKeys(publicKeys: new[] { + new MetaPublicKey("90a421169f0a406205f1563a953312f0be898d3c7b6c06b681aa86a874555f4a", "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9MJJHnMfn2+H4xL4YaPDA4RpJqUq\nkCmRCBnYERxZanmcpzQSXs1X/AljlKkbJ8qpVIW4clayyef9gWhFbNHWAA==\n-----END PUBLIC KEY-----\n", false), + new MetaPublicKey("bcb53661c06b4728e59d897fb6165d5c9cda0fd9cdf9d09ead458168deb7518c", "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYAGMWO8XgCamYKMJS6jc/qgvSlAd\nAjPuDPRcXU22YxgBrz+zoN19MzuRyW87qEt9/AmtoNP5GrobzUvQSyJFVw==\n-----END PUBLIC KEY-----\n", true) + }); + + var apiConnection = Substitute.For(); + apiConnection.Get(Arg.Is(u => u.ToString() == "meta/public_keys/secret_scanning")).Returns(Task.FromResult(publicKeys)); + + var client = new PublicKeysClient(apiConnection); + + var result = await client.Get(PublicKeyType.SecretScanning); + + Assert.Equal(2, result.PublicKeys.Count); + Assert.Equal("90a421169f0a406205f1563a953312f0be898d3c7b6c06b681aa86a874555f4a", result.PublicKeys[0].KeyIdentifier); + Assert.Equal("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9MJJHnMfn2+H4xL4YaPDA4RpJqUq\nkCmRCBnYERxZanmcpzQSXs1X/AljlKkbJ8qpVIW4clayyef9gWhFbNHWAA==\n-----END PUBLIC KEY-----\n", result.PublicKeys[0].Key); + Assert.False(result.PublicKeys[0].IsCurrent); + + Assert.Equal("bcb53661c06b4728e59d897fb6165d5c9cda0fd9cdf9d09ead458168deb7518c", result.PublicKeys[1].KeyIdentifier); + Assert.Equal("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYAGMWO8XgCamYKMJS6jc/qgvSlAd\nAjPuDPRcXU22YxgBrz+zoN19MzuRyW87qEt9/AmtoNP5GrobzUvQSyJFVw==\n-----END PUBLIC KEY-----\n", result.PublicKeys[1].Key); + Assert.True(result.PublicKeys[1].IsCurrent); + + apiConnection.Received() + .Get(Arg.Is(u => u.ToString() == "meta/public_keys/secret_scanning")); + } + } + } +} diff --git a/Octokit.Tests/Models/MetaPublicKeysTests.cs b/Octokit.Tests/Models/MetaPublicKeysTests.cs new file mode 100644 index 0000000000..9e5f64ea89 --- /dev/null +++ b/Octokit.Tests/Models/MetaPublicKeysTests.cs @@ -0,0 +1,44 @@ +using Octokit.Internal; +using Xunit; + +namespace Octokit.Tests.Models +{ + public class MetaPublicKeysTests + { + [Fact] + public void CanBeDeserialized() + { + const string json = @"{ + ""public_keys"": [ + { + ""key_identifier"": ""90a421169f0a406205f1563a953312f0be898d3c7b6c06b681aa86a874555f4a"", + ""key"": ""-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9MJJHnMfn2+H4xL4YaPDA4RpJqUq\nkCmRCBnYERxZanmcpzQSXs1X/AljlKkbJ8qpVIW4clayyef9gWhFbNHWAA==\n-----END PUBLIC KEY-----\n"", + ""is_current"": false + }, + { + ""key_identifier"": ""bcb53661c06b4728e59d897fb6165d5c9cda0fd9cdf9d09ead458168deb7518c"", + ""key"": ""-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYAGMWO8XgCamYKMJS6jc/qgvSlAd\nAjPuDPRcXU22YxgBrz+zoN19MzuRyW87qEt9/AmtoNP5GrobzUvQSyJFVw==\n-----END PUBLIC KEY-----\n"", + ""is_current"": true + } + ] +} +"; + var serializer = new SimpleJsonSerializer(); + + var keys = serializer.Deserialize(json); + + Assert.NotNull(keys); + Assert.Equal(2, keys.PublicKeys.Count); + + var key1 = keys.PublicKeys[0]; + Assert.Equal("90a421169f0a406205f1563a953312f0be898d3c7b6c06b681aa86a874555f4a", key1.KeyIdentifier); + Assert.Equal("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9MJJHnMfn2+H4xL4YaPDA4RpJqUq\nkCmRCBnYERxZanmcpzQSXs1X/AljlKkbJ8qpVIW4clayyef9gWhFbNHWAA==\n-----END PUBLIC KEY-----\n", key1.Key); + Assert.False(key1.IsCurrent); + + var key2 = keys.PublicKeys[1]; + Assert.Equal("bcb53661c06b4728e59d897fb6165d5c9cda0fd9cdf9d09ead458168deb7518c", key2.KeyIdentifier); + Assert.Equal("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYAGMWO8XgCamYKMJS6jc/qgvSlAd\nAjPuDPRcXU22YxgBrz+zoN19MzuRyW87qEt9/AmtoNP5GrobzUvQSyJFVw==\n-----END PUBLIC KEY-----\n", key2.Key); + Assert.True(key2.IsCurrent); + } + } +} diff --git a/Octokit.Tests/Reactive/ObservablePublicKeysClientTests.cs b/Octokit.Tests/Reactive/ObservablePublicKeysClientTests.cs new file mode 100644 index 0000000000..14939de515 --- /dev/null +++ b/Octokit.Tests/Reactive/ObservablePublicKeysClientTests.cs @@ -0,0 +1,33 @@ +using System; +using NSubstitute; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Reactive +{ + public class ObservablePublicKeysClientTests + { + public class TheGetMethod + { + [Fact] + public void CallsIntoClient() + { + var gitHubClient = Substitute.For(); + var client = new ObservablePublicKeysClient(gitHubClient); + + client.Get(PublicKeyType.SecretScanning); + + gitHubClient.Meta.PublicKeys.Received(1).Get(PublicKeyType.SecretScanning); + } + } + + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new ObservablePublicKeysClient((IGitHubClient)null)); + } + } + } +} diff --git a/Octokit/Clients/IMetaClient.cs b/Octokit/Clients/IMetaClient.cs index f4c21714d0..9c7900608f 100644 --- a/Octokit/Clients/IMetaClient.cs +++ b/Octokit/Clients/IMetaClient.cs @@ -10,6 +10,11 @@ namespace Octokit /// public interface IMetaClient { + /// + /// Returns a client to get public keys for validating request signatures. + /// + IPublicKeysClient PublicKeys { get; } + /// /// Retrieves information about GitHub.com, the service or a GitHub Enterprise installation. /// diff --git a/Octokit/Clients/IPublicKeysClient.cs b/Octokit/Clients/IPublicKeysClient.cs new file mode 100644 index 0000000000..eae756c8d5 --- /dev/null +++ b/Octokit/Clients/IPublicKeysClient.cs @@ -0,0 +1,20 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// A client for GitHub's meta public keys API. + /// + /// + /// See the Secret scanning documentation for more details. + /// + public interface IPublicKeysClient + { + /// + /// Retrieves public keys for validating request signatures. + /// + /// Thrown when a general API error occurs. + /// An containing public keys for validating request signatures. + Task Get(PublicKeyType keysType); + } +} diff --git a/Octokit/Clients/MetaClient.cs b/Octokit/Clients/MetaClient.cs index c683a34bba..52a61f14a6 100644 --- a/Octokit/Clients/MetaClient.cs +++ b/Octokit/Clients/MetaClient.cs @@ -18,8 +18,14 @@ public class MetaClient : ApiClient, IMetaClient public MetaClient(IApiConnection apiConnection) : base(apiConnection) { + PublicKeys = new PublicKeysClient(apiConnection); } + /// + /// Returns a client to manage get public keys for validating request signatures. + /// + public IPublicKeysClient PublicKeys { get; private set; } + /// /// Retrieves information about GitHub.com, the service or a GitHub Enterprise installation. /// diff --git a/Octokit/Clients/PublicKeysClient.cs b/Octokit/Clients/PublicKeysClient.cs new file mode 100644 index 0000000000..cc34141f5d --- /dev/null +++ b/Octokit/Clients/PublicKeysClient.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// A client for GitHub's public keys API. + /// + /// + /// See the Secret scanning documentation for more details. + /// + public class PublicKeysClient : ApiClient, IPublicKeysClient + { + /// + /// Initializes a new GitHub Meta Public Keys API client. + /// + /// An API connection. + public PublicKeysClient(IApiConnection apiConnection) + : base(apiConnection) + { + } + + /// + /// Retrieves public keys for validating request signatures. + /// + /// Thrown when a general API error occurs. + /// An containing public keys for validating request signatures. + [ManualRoute("GET", "/meta/public_keys/{keysType}")] + public Task Get(PublicKeyType keysType) + { + return ApiConnection.Get(ApiUrls.PublicKeys(keysType)); + } + } +} diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 62c752a596..b70ae025b8 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -4833,6 +4833,16 @@ public static Uri Meta() return "meta".FormatUri(); } + /// + /// Returns the that returns meta in + /// response to a GET request. + /// + /// The to meta. + public static Uri PublicKeys(PublicKeyType keysType) + { + return "meta/public_keys/{0}".FormatUri(keysType.ToParameter()); + } + /// /// Returns the that returns all organization credentials in /// response to a GET request. diff --git a/Octokit/Models/Common/PublicKeyType.cs b/Octokit/Models/Common/PublicKeyType.cs new file mode 100644 index 0000000000..3a8c09a64f --- /dev/null +++ b/Octokit/Models/Common/PublicKeyType.cs @@ -0,0 +1,19 @@ +using Octokit.Internal; + +namespace Octokit +{ + public enum PublicKeyType + { + /// + /// Copilot API public keys for validating request signatures + /// + [Parameter(Value = "copilot_api")] + CopilotApi, + + /// + /// Secret scanning public keys for validating request signatures + /// + [Parameter(Value = "secret_scanning")] + SecretScanning + } +} diff --git a/Octokit/Models/Response/MetaPublicKey.cs b/Octokit/Models/Response/MetaPublicKey.cs new file mode 100644 index 0000000000..05b6a86c96 --- /dev/null +++ b/Octokit/Models/Response/MetaPublicKey.cs @@ -0,0 +1,29 @@ +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class MetaPublicKey + { + public MetaPublicKey() { } + + public MetaPublicKey(string keyIdentifier, string key, bool isCurrent) + { + KeyIdentifier = keyIdentifier; + Key = key; + IsCurrent = isCurrent; + } + + public string KeyIdentifier { get; protected set; } + + public string Key { get; protected set; } + + public bool IsCurrent { get; protected set; } + + internal string DebuggerDisplay + { + get { return string.Format(CultureInfo.InvariantCulture, "KeyIdentifier: {0} IsCurrent: {1}", KeyIdentifier, IsCurrent); } + } + } +} diff --git a/Octokit/Models/Response/MetaPublicKeys.cs b/Octokit/Models/Response/MetaPublicKeys.cs new file mode 100644 index 0000000000..7927ab7a6e --- /dev/null +++ b/Octokit/Models/Response/MetaPublicKeys.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class MetaPublicKeys + { + public MetaPublicKeys() { } + + public MetaPublicKeys(IReadOnlyList publicKeys) + { + PublicKeys = publicKeys; + } + + public IReadOnlyList PublicKeys { get; protected set; } + + internal string DebuggerDisplay + { + get { return string.Format(CultureInfo.InvariantCulture, "PublicKeys: {0}", PublicKeys.Count); } + } + } +}