[feat]: Added Environments API - GetAll list only feature

This commit is contained in:
semyon-p
2022-11-17 19:49:37 +02:00
committed by GitHub
parent b998d08408
commit b0e02e9d2e
13 changed files with 606 additions and 4 deletions

View File

@@ -226,10 +226,18 @@ namespace Octokit.Reactive
/// Client for GitHub's Repository Deployments API
/// </summary>
/// <remarks>
/// See the <a href="http://developer.github.com/v3/repos/deployment/">Collaborators API documentation</a> for more details
/// See the <a href="https://docs.github.com/en/rest/deployments/deployments">Deployments API documentation</a> for more details
/// </remarks>
IObservableDeploymentsClient Deployment { get; }
/// <summary>
/// Client for GitHub's Repository Envirinments API
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/deployments/environments/">Envirinments API documentation</a> for more details
/// </remarks>
IObservableRepositoryDeployEnvironmentsClient Environment { get; }
/// <summary>
/// Client for GitHub's Repository Statistics API.
/// Note that the GitHub API uses caching on these endpoints,

View File

@@ -0,0 +1,57 @@
using Octokit.Models.Response;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Octokit.Reactive
{
public interface IObservableRepositoryDeployEnvironmentsClient
{
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
IObservable<DeploymentEnvironmentsResponse> GetAll(string owner, string name);
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="repositoryId">The Id of the repository</param>
IObservable<DeploymentEnvironmentsResponse> GetAll(long repositoryId);
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Paging options</param>
IObservable<DeploymentEnvironmentsResponse> GetAll(string owner, string name, ApiOptions options);
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="repositoryId">Repository ID</param>
/// <param name="options">Paging options</param>
IObservable<DeploymentEnvironmentsResponse> GetAll(long repositoryId, ApiOptions options);
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Reactive.Threading.Tasks;
using Octokit.Models.Response;
using Octokit.Reactive.Internal;
namespace Octokit.Reactive.Clients
{
public class ObservableEnvironmentsClient : IObservableRepositoryDeployEnvironmentsClient
{
readonly IRepositoryDeployEnvironmentsClient _client;
readonly IConnection _connection;
public ObservableEnvironmentsClient(IGitHubClient client)
{
Ensure.ArgumentNotNull(client, nameof(client));
_client = client.Repository.Environment;
_connection = client.Connection;
}
public IObservable<DeploymentEnvironmentsResponse> GetAll(string owner, string name)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
return GetAll(owner, name, ApiOptions.None);
}
public IObservable<DeploymentEnvironmentsResponse> GetAll(long repositoryId)
{
return GetAll(repositoryId, ApiOptions.None);
}
public IObservable<DeploymentEnvironmentsResponse> GetAll(string owner, string name, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(options, nameof(options));
return _connection.GetAndFlattenAllPages<DeploymentEnvironmentsResponse>(
ApiUrls.DeploymentEnvironments(owner, name), options);
}
public IObservable<DeploymentEnvironmentsResponse> GetAll(long repositoryId, ApiOptions options)
{
Ensure.ArgumentNotNull(options, nameof(options));
return _connection.GetAndFlattenAllPages<DeploymentEnvironmentsResponse>(
ApiUrls.DeploymentEnvironments(repositoryId), options);
}
}
}

View File

@@ -27,6 +27,7 @@ namespace Octokit.Reactive
Forks = new ObservableRepositoryForksClient(client);
Collaborator = new ObservableRepoCollaboratorsClient(client);
Deployment = new ObservableDeploymentsClient(client);
Environment = new ObservableEnvironmentsClient(client);
Statistics = new ObservableStatisticsClient(client);
PullRequest = new ObservablePullRequestsClient(client);
Branch = new ObservableRepositoryBranchesClient(client);
@@ -347,10 +348,19 @@ namespace Octokit.Reactive
/// Client for GitHub's Repository Deployments API
/// </summary>
/// <remarks>
/// See the <a href="http://developer.github.com/v3/repos/deployment/">Collaborators API documentation</a> for more details
/// See the <a href="https://docs.github.com/en/rest/deployments/deployments">Deployments API documentation</a> for more details
/// </remarks>
public IObservableDeploymentsClient Deployment { get; private set; }
/// <summary>
/// Client for GitHub's Repository Environments API
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/deployments/environments#about-the-deployment-environments-api/">Environments API documentation</a> for more details
/// </remarks>
public IObservableRepositoryDeployEnvironmentsClient Environment { get; private set; }
/// <summary>
/// Client for GitHub's Repository Statistics API
/// Note that the GitHub API uses caching on these endpoints,

View File

@@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NSubstitute;
using Octokit;
using Octokit.Models.Response;
using Octokit.Tests;
using Xunit;
namespace Octokit.Tests.Clients
{
public class EnvironmentsClientTests
{
public class TheGetAllMethod
{
const string name = "name";
const string owner = "owner";
const long repositoryId = 1;
[Fact]
public async Task EnsuresNonNullArguments()
{
var client = new DeploymentEnvironmentsClient(Substitute.For<IApiConnection>());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(null, name));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(owner, null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(owner, name, null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(repositoryId, null));
}
[Fact]
public async Task EnsuresNonEmptyArguments()
{
var client = new DeploymentEnvironmentsClient(Substitute.For<IApiConnection>());
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("", name));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(owner, ""));
}
[Theory]
[InlineData(" ")]
[InlineData("\n")]
[InlineData("\t")]
[InlineData(" ")]
[InlineData("\n\r")]
public async Task EnsuresNonWhitespaceArguments(string whitespace)
{
var client = new DeploymentEnvironmentsClient(Substitute.For<IApiConnection>());
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(whitespace, name));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(owner, whitespace));
}
[Fact]
public async Task RequestsCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new DeploymentEnvironmentsClient(connection);
var expectedUrl = string.Format("repos/{0}/{1}/environments", owner, name);
var res = await client.GetAll(owner, name);
connection.Received()
.Get<DeploymentEnvironmentsResponse>(
Arg.Is<Uri>(u => u.ToString() == expectedUrl));
}
[Fact]
public async Task RequestsCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new DeploymentEnvironmentsClient(connection);
var expectedUrl = string.Format("repositories/{0}/environments", repositoryId);
await client.GetAll(repositoryId);
connection.Received()
.Get<DeploymentEnvironmentsResponse>(Arg.Is<Uri>(u => u.ToString() == expectedUrl));
}
[Fact]
public async Task RequestsCorrectUrlWithApiOptions()
{
var connection = Substitute.For<IApiConnection>();
var client = new DeploymentEnvironmentsClient(connection);
var expectedUrl = string.Format("repos/{0}/{1}/environments", owner, name);
var options = new ApiOptions
{
PageSize = 10,
StartPage = 1
};
await client.GetAll(owner, name, options);
connection.Received()
.Get<DeploymentEnvironmentsResponse>(Arg.Is<Uri>(u => u.ToString() == expectedUrl),
Arg.Is<IDictionary<string, string>>(u => u["per_page"] == "10" && u["page"] == "1"));
}
[Fact]
public async Task RequestsCorrectUrlWithRepositoryIdWithApiOptions()
{
var connection = Substitute.For<IApiConnection>();
var client = new DeploymentEnvironmentsClient(connection);
var expectedUrl = string.Format("repositories/{0}/environments", repositoryId);
var options = new ApiOptions
{
PageSize = 10,
StartPage = 1
};
await client.GetAll(repositoryId, options);
connection.Received()
.Get<DeploymentEnvironmentsResponse>(Arg.Is<Uri>(u => u.ToString() == expectedUrl),
Arg.Is<IDictionary<string, string>>(u => u["per_page"] == "10" && u["page"] == "1"));
}
[Fact]
public void RequestsCorrectUrlWithPreviewAcceptHeaders()
{
var connection = Substitute.For<IApiConnection>();
var client = new DeploymentEnvironmentsClient(connection);
var expectedUrl = string.Format("repos/{0}/{1}/environments", owner, name);
client.GetAll(owner, name);
connection.Received()
.Get<DeploymentEnvironmentsResponse>(Arg.Is<Uri>(u => u.ToString() == expectedUrl));
}
}
public class TheCtor
{
[Fact]
public void EnsuresNonNullArguments()
{
Assert.Throws<ArgumentNullException>(() => new DeploymentEnvironmentsClient(null));
}
}
}
}

View File

@@ -0,0 +1,115 @@
using Octokit.Models.Response;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Octokit
{
/// <summary>
/// A client for GitHub's Repository Deployment Environments API.
/// Gets Deployment Environments.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/deployments/environments">Repository Deployment Environments API documentation</a> for more information.
/// </remarks>
public class DeploymentEnvironmentsClient : ApiClient, IRepositoryDeployEnvironmentsClient
{
/// <summary>
/// Instantiates a new GitHub Repository Environments API client.
/// </summary>
/// <param name="apiConnection">An API connection</param>
public DeploymentEnvironmentsClient(IApiConnection apiConnection) : base(apiConnection) { }
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view environments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
[ManualRoute("GET", "/repos/{owner}/{repo}/environments")]
public Task<DeploymentEnvironmentsResponse> GetAll(string owner, string name)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
return GetAll(owner, name, ApiOptions.None);
}
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view environments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="repositoryId">The Id of the repository</param>
[ManualRoute("GET", "/repositories/{id}/environments")]
public Task<DeploymentEnvironmentsResponse> GetAll(long repositoryId)
{
return GetAll(repositoryId, ApiOptions.None);
}
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view environments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Paging options</param>
[ManualRoute("GET", "/repos/{owner}/{repo}/environments")]
public Task<DeploymentEnvironmentsResponse> GetAll(string owner, string name, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(options, nameof(options));
Dictionary<string, string> prms = null;
if (options != ApiOptions.None)
{
prms = new Dictionary<string, string>();
prms.Add("per_page", options.PageSize.ToString());
prms.Add("page", options.StartPage.ToString());
}
if (prms != null)
return ApiConnection.Get<DeploymentEnvironmentsResponse>(ApiUrls.DeploymentEnvironments(owner, name), prms);
else
return ApiConnection.Get<DeploymentEnvironmentsResponse>(ApiUrls.DeploymentEnvironments(owner, name));
}
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view environments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="repositoryId">Repository ID</param>
/// <param name="options">Paging options</param>
[ManualRoute("GET", "/repositories/{id}/environments")]
public Task<DeploymentEnvironmentsResponse> GetAll(long repositoryId, ApiOptions options)
{
Ensure.ArgumentNotNull(options, nameof(options));
Dictionary<string, string> prms = null;
if (options != ApiOptions.None)
{
prms = new Dictionary<string, string>();
prms.Add("per_page", options.PageSize.ToString());
prms.Add("page", options.StartPage.ToString());
}
if (prms != null)
return ApiConnection.Get<DeploymentEnvironmentsResponse>(ApiUrls.DeploymentEnvironments(repositoryId), prms);
else
return ApiConnection.Get<DeploymentEnvironmentsResponse>(ApiUrls.DeploymentEnvironments(repositoryId));
}
}
}

View File

@@ -344,6 +344,14 @@ namespace Octokit
/// </remarks>
IDeploymentsClient Deployment { get; }
/// <summary>
/// Client for GitHub's Repository Environments API
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/deployments/environments/">Environments API documentation</a> for more details
/// </remarks>
IRepositoryDeployEnvironmentsClient Environment { get; }
/// <summary>
/// Client for GitHub's Repository Statistics API.
/// Note that the GitHub API uses caching on these endpoints,

View File

@@ -0,0 +1,61 @@
using Octokit.Models.Response;
using System.Threading.Tasks;
namespace Octokit
{
/// <summary>
/// A client for GitHub's Repository Deployment Environments API.
/// Gets Deployment Environments.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/deployments/environments">Repository Deployment Environments API documentation</a> for more information.
/// </remarks>
public interface IRepositoryDeployEnvironmentsClient
{
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
Task<DeploymentEnvironmentsResponse> GetAll(string owner, string name);
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="repositoryId">The Id of the repository</param>
Task<DeploymentEnvironmentsResponse> GetAll(long repositoryId);
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Paging options</param>
Task<DeploymentEnvironmentsResponse> GetAll(string owner, string name, ApiOptions options);
/// <summary>
/// Gets all the environments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// https://docs.github.com/en/rest/deployments/environments#list-environments
/// </remarks>
/// <param name="repositoryId">Repository ID</param>
/// <param name="options">Paging options</param>
Task<DeploymentEnvironmentsResponse> GetAll(long repositoryId, ApiOptions options);
}
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
using System.Net.Http.Headers;
namespace Octokit
{
@@ -27,6 +28,7 @@ namespace Octokit
Collaborator = new RepoCollaboratorsClient(apiConnection);
Statistics = new StatisticsClient(apiConnection);
Deployment = new DeploymentsClient(apiConnection);
Environment = new DeploymentEnvironmentsClient(apiConnection);
PullRequest = new PullRequestsClient(apiConnection);
Comment = new RepositoryCommentsClient(apiConnection);
Commit = new RepositoryCommitsClient(apiConnection);
@@ -538,6 +540,14 @@ namespace Octokit
/// </remarks>
public IDeploymentsClient Deployment { get; private set; }
/// <summary>
/// Client for GitHub's Repository Deployment Environments API
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/deployments/environments">Deployments Environments API documentation</a> for more details
/// </remarks>
public IRepositoryDeployEnvironmentsClient Environment { get; private set; }
/// <summary>
/// Client for GitHub's Repository Statistics API
/// Note that the GitHub API uses caching on these endpoints,

View File

@@ -2478,6 +2478,17 @@ namespace Octokit
return "repos/{0}/{1}/deployments".FormatUri(owner, name);
}
/// <summary>
/// Returns the <see cref="Uri"/> for the Deployment Environments API for the given repository.
/// </summary>
/// <param name="owner">Owner of the repository</param>
/// <param name="name">Name of the repository</param>
/// <returns>The <see cref="Uri"/> for the Deployments API for the given repository.</returns>
public static Uri DeploymentEnvironments(string owner, string name)
{
return "repos/{0}/{1}/environments".FormatUri(owner, name);
}
/// <summary>
/// Returns the <see cref="System.Uri"/> for the Deployment Statuses API for the given deployment.
/// </summary>
@@ -3137,6 +3148,16 @@ namespace Octokit
return "repositories/{0}/deployments".FormatUri(repositoryId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for the Deployment Environments API for the given repository.
/// </summary>
/// <param name="repositoryId">The Id of the repository</param>
/// <returns>The <see cref="Uri"/> for the Deployments API for the given repository.</returns>
public static Uri DeploymentEnvironments(long repositoryId)
{
return "repositories/{0}/environments".FormatUri(repositoryId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for the Deployment Statuses API for the given deployment.
/// </summary>

View File

@@ -7,9 +7,11 @@ namespace Octokit
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class ApiOptions
{
private static ApiOptions emptyOptions = new ApiOptions();
public static ApiOptions None
{
get { return new ApiOptions(); }
get { return emptyOptions; }
}
/// <summary>

View File

@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics;
using System.Text;
using System.Globalization;
namespace Octokit.Models.Response
{
[SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces",
Justification = "People can use fully qualified names if they want to use both.")]
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class DeploymentEnvironment
{
public DeploymentEnvironment() { }
public DeploymentEnvironment(int id, string nodeID, string name, string url, string htmlUrl, DateTimeOffset createdAt, DateTimeOffset updatedAt)
{
Id = id;
NodeId = nodeID;
Name = name;
Url = url;
HtmlUrl = htmlUrl;
CreatedAt = createdAt;
UpdatedAt = updatedAt;
}
/// <summary>
/// Id of this deployment environment
/// </summary>
public int Id { get; private set; }
/// <summary>
/// GraphQL Node Id
/// </summary>
public string NodeId{ get; private set; }
/// <summary>
/// Environment Name
/// </summary>
public string Name { get; private set; }
/// <summary>
/// Environment API URL
/// </summary>
public string Url { get; private set; }
/// <summary>
/// Environment HTML URL
/// </summary>
public string HtmlUrl { get; private set; }
/// <summary>
/// Date and time that the environment was created.
/// </summary>
public DateTimeOffset CreatedAt { get; private set; }
/// <summary>
/// Date and time that the environment was updated.
/// </summary>
public DateTimeOffset UpdatedAt { get; private set; }
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "Name: {0}, CreatedAt: {1}", Name, CreatedAt);
}
}
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics;
using System.Text;
using System.Globalization;
namespace Octokit.Models.Response
{
[SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces",
Justification = "People can use fully qualified names if they want to use both.")]
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class DeploymentEnvironmentsResponse
{
public DeploymentEnvironmentsResponse() { }
public DeploymentEnvironmentsResponse(int totalCount, IReadOnlyList<DeploymentEnvironment> environments)
{
TotalCount = totalCount;
Environments = environments;
}
/// <summary>
/// The total count of secrets for the repository
/// </summary>
public int TotalCount { get; private set; }
/// <summary>
/// The list of secrets for the repository
/// </summary>
public IReadOnlyList<DeploymentEnvironment> Environments { get; private set; }
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "Count: {0}", TotalCount);
}
}
}
}