Skip to content

Commit b0e02e9

Browse files
authored
[feat]: Added Environments API - GetAll list only feature
1 parent b998d08 commit b0e02e9

13 files changed

Lines changed: 606 additions & 4 deletions

Octokit.Reactive/Clients/IObservableRepositoriesClient.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,18 @@ public interface IObservableRepositoriesClient
226226
/// Client for GitHub's Repository Deployments API
227227
/// </summary>
228228
/// <remarks>
229-
/// See the <a href="http://developer.github.com/v3/repos/deployment/">Collaborators API documentation</a> for more details
229+
/// See the <a href="https://docs.github.com/en/rest/deployments/deployments">Deployments API documentation</a> for more details
230230
/// </remarks>
231231
IObservableDeploymentsClient Deployment { get; }
232232

233+
/// <summary>
234+
/// Client for GitHub's Repository Envirinments API
235+
/// </summary>
236+
/// <remarks>
237+
/// See the <a href="https://docs.github.com/en/rest/deployments/environments/">Envirinments API documentation</a> for more details
238+
/// </remarks>
239+
IObservableRepositoryDeployEnvironmentsClient Environment { get; }
240+
233241
/// <summary>
234242
/// Client for GitHub's Repository Statistics API.
235243
/// Note that the GitHub API uses caching on these endpoints,
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using Octokit.Models.Response;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Octokit.Reactive
8+
{
9+
public interface IObservableRepositoryDeployEnvironmentsClient
10+
{
11+
/// <summary>
12+
/// Gets all the environments for the specified repository. Any user with pull access
13+
/// to a repository can view deployments.
14+
/// </summary>
15+
/// <remarks>
16+
/// https://docs.github.com/en/rest/deployments/environments#list-environments
17+
/// </remarks>
18+
/// <param name="owner">The owner of the repository</param>
19+
/// <param name="name">The name of the repository</param>
20+
IObservable<DeploymentEnvironmentsResponse> GetAll(string owner, string name);
21+
22+
/// <summary>
23+
/// Gets all the environments for the specified repository. Any user with pull access
24+
/// to a repository can view deployments.
25+
/// </summary>
26+
/// <remarks>
27+
/// https://docs.github.com/en/rest/deployments/environments#list-environments
28+
/// </remarks>
29+
/// <param name="repositoryId">The Id of the repository</param>
30+
IObservable<DeploymentEnvironmentsResponse> GetAll(long repositoryId);
31+
32+
33+
/// <summary>
34+
/// Gets all the environments for the specified repository. Any user with pull access
35+
/// to a repository can view deployments.
36+
/// </summary>
37+
/// <remarks>
38+
/// https://docs.github.com/en/rest/deployments/environments#list-environments
39+
/// </remarks>
40+
/// <param name="owner">The owner of the repository</param>
41+
/// <param name="name">The name of the repository</param>
42+
/// <param name="options">Paging options</param>
43+
IObservable<DeploymentEnvironmentsResponse> GetAll(string owner, string name, ApiOptions options);
44+
45+
46+
/// <summary>
47+
/// Gets all the environments for the specified repository. Any user with pull access
48+
/// to a repository can view deployments.
49+
/// </summary>
50+
/// <remarks>
51+
/// https://docs.github.com/en/rest/deployments/environments#list-environments
52+
/// </remarks>
53+
/// <param name="repositoryId">Repository ID</param>
54+
/// <param name="options">Paging options</param>
55+
IObservable<DeploymentEnvironmentsResponse> GetAll(long repositoryId, ApiOptions options);
56+
}
57+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.Reactive.Threading.Tasks;
3+
using Octokit.Models.Response;
4+
using Octokit.Reactive.Internal;
5+
6+
namespace Octokit.Reactive.Clients
7+
{
8+
public class ObservableEnvironmentsClient : IObservableRepositoryDeployEnvironmentsClient
9+
{
10+
readonly IRepositoryDeployEnvironmentsClient _client;
11+
readonly IConnection _connection;
12+
13+
public ObservableEnvironmentsClient(IGitHubClient client)
14+
{
15+
Ensure.ArgumentNotNull(client, nameof(client));
16+
17+
_client = client.Repository.Environment;
18+
_connection = client.Connection;
19+
}
20+
21+
public IObservable<DeploymentEnvironmentsResponse> GetAll(string owner, string name)
22+
{
23+
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
24+
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
25+
26+
return GetAll(owner, name, ApiOptions.None);
27+
}
28+
29+
public IObservable<DeploymentEnvironmentsResponse> GetAll(long repositoryId)
30+
{
31+
return GetAll(repositoryId, ApiOptions.None);
32+
}
33+
34+
public IObservable<DeploymentEnvironmentsResponse> GetAll(string owner, string name, ApiOptions options)
35+
{
36+
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
37+
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
38+
Ensure.ArgumentNotNull(options, nameof(options));
39+
40+
return _connection.GetAndFlattenAllPages<DeploymentEnvironmentsResponse>(
41+
ApiUrls.DeploymentEnvironments(owner, name), options);
42+
}
43+
44+
public IObservable<DeploymentEnvironmentsResponse> GetAll(long repositoryId, ApiOptions options)
45+
{
46+
Ensure.ArgumentNotNull(options, nameof(options));
47+
48+
return _connection.GetAndFlattenAllPages<DeploymentEnvironmentsResponse>(
49+
ApiUrls.DeploymentEnvironments(repositoryId), options);
50+
}
51+
}
52+
}

Octokit.Reactive/Clients/ObservableRepositoriesClient.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public ObservableRepositoriesClient(IGitHubClient client)
2727
Forks = new ObservableRepositoryForksClient(client);
2828
Collaborator = new ObservableRepoCollaboratorsClient(client);
2929
Deployment = new ObservableDeploymentsClient(client);
30+
Environment = new ObservableEnvironmentsClient(client);
3031
Statistics = new ObservableStatisticsClient(client);
3132
PullRequest = new ObservablePullRequestsClient(client);
3233
Branch = new ObservableRepositoryBranchesClient(client);
@@ -347,10 +348,19 @@ public IObservable<Repository> GetAllForOrg(string organization, ApiOptions opti
347348
/// Client for GitHub's Repository Deployments API
348349
/// </summary>
349350
/// <remarks>
350-
/// See the <a href="http://developer.github.com/v3/repos/deployment/">Collaborators API documentation</a> for more details
351+
/// See the <a href="https://docs.github.com/en/rest/deployments/deployments">Deployments API documentation</a> for more details
351352
/// </remarks>
352353
public IObservableDeploymentsClient Deployment { get; private set; }
353354

355+
356+
/// <summary>
357+
/// Client for GitHub's Repository Environments API
358+
/// </summary>
359+
/// <remarks>
360+
/// See the <a href="https://docs.github.com/en/rest/deployments/environments#about-the-deployment-environments-api/">Environments API documentation</a> for more details
361+
/// </remarks>
362+
public IObservableRepositoryDeployEnvironmentsClient Environment { get; private set; }
363+
354364
/// <summary>
355365
/// Client for GitHub's Repository Statistics API
356366
/// Note that the GitHub API uses caching on these endpoints,
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading.Tasks;
4+
using NSubstitute;
5+
using Octokit;
6+
using Octokit.Models.Response;
7+
using Octokit.Tests;
8+
using Xunit;
9+
10+
11+
namespace Octokit.Tests.Clients
12+
{
13+
public class EnvironmentsClientTests
14+
{
15+
public class TheGetAllMethod
16+
{
17+
const string name = "name";
18+
const string owner = "owner";
19+
const long repositoryId = 1;
20+
21+
[Fact]
22+
public async Task EnsuresNonNullArguments()
23+
{
24+
var client = new DeploymentEnvironmentsClient(Substitute.For<IApiConnection>());
25+
26+
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(null, name));
27+
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(owner, null));
28+
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(owner, name, null));
29+
30+
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(repositoryId, null));
31+
}
32+
33+
[Fact]
34+
public async Task EnsuresNonEmptyArguments()
35+
{
36+
var client = new DeploymentEnvironmentsClient(Substitute.For<IApiConnection>());
37+
38+
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("", name));
39+
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(owner, ""));
40+
}
41+
42+
[Theory]
43+
[InlineData(" ")]
44+
[InlineData("\n")]
45+
[InlineData("\t")]
46+
[InlineData(" ")]
47+
[InlineData("\n\r")]
48+
public async Task EnsuresNonWhitespaceArguments(string whitespace)
49+
{
50+
var client = new DeploymentEnvironmentsClient(Substitute.For<IApiConnection>());
51+
52+
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(whitespace, name));
53+
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(owner, whitespace));
54+
}
55+
56+
[Fact]
57+
public async Task RequestsCorrectUrl()
58+
{
59+
var connection = Substitute.For<IApiConnection>();
60+
var client = new DeploymentEnvironmentsClient(connection);
61+
var expectedUrl = string.Format("repos/{0}/{1}/environments", owner, name);
62+
63+
var res = await client.GetAll(owner, name);
64+
65+
connection.Received()
66+
.Get<DeploymentEnvironmentsResponse>(
67+
Arg.Is<Uri>(u => u.ToString() == expectedUrl));
68+
}
69+
70+
[Fact]
71+
public async Task RequestsCorrectUrlWithRepositoryId()
72+
{
73+
var connection = Substitute.For<IApiConnection>();
74+
var client = new DeploymentEnvironmentsClient(connection);
75+
var expectedUrl = string.Format("repositories/{0}/environments", repositoryId);
76+
77+
await client.GetAll(repositoryId);
78+
79+
connection.Received()
80+
.Get<DeploymentEnvironmentsResponse>(Arg.Is<Uri>(u => u.ToString() == expectedUrl));
81+
}
82+
83+
[Fact]
84+
public async Task RequestsCorrectUrlWithApiOptions()
85+
{
86+
var connection = Substitute.For<IApiConnection>();
87+
var client = new DeploymentEnvironmentsClient(connection);
88+
var expectedUrl = string.Format("repos/{0}/{1}/environments", owner, name);
89+
90+
var options = new ApiOptions
91+
{
92+
PageSize = 10,
93+
StartPage = 1
94+
};
95+
96+
await client.GetAll(owner, name, options);
97+
98+
connection.Received()
99+
.Get<DeploymentEnvironmentsResponse>(Arg.Is<Uri>(u => u.ToString() == expectedUrl),
100+
Arg.Is<IDictionary<string, string>>(u => u["per_page"] == "10" && u["page"] == "1"));
101+
}
102+
103+
[Fact]
104+
public async Task RequestsCorrectUrlWithRepositoryIdWithApiOptions()
105+
{
106+
var connection = Substitute.For<IApiConnection>();
107+
var client = new DeploymentEnvironmentsClient(connection);
108+
var expectedUrl = string.Format("repositories/{0}/environments", repositoryId);
109+
110+
var options = new ApiOptions
111+
{
112+
PageSize = 10,
113+
StartPage = 1
114+
};
115+
116+
await client.GetAll(repositoryId, options);
117+
118+
connection.Received()
119+
.Get<DeploymentEnvironmentsResponse>(Arg.Is<Uri>(u => u.ToString() == expectedUrl),
120+
Arg.Is<IDictionary<string, string>>(u => u["per_page"] == "10" && u["page"] == "1"));
121+
}
122+
123+
[Fact]
124+
public void RequestsCorrectUrlWithPreviewAcceptHeaders()
125+
{
126+
var connection = Substitute.For<IApiConnection>();
127+
var client = new DeploymentEnvironmentsClient(connection);
128+
var expectedUrl = string.Format("repos/{0}/{1}/environments", owner, name);
129+
130+
client.GetAll(owner, name);
131+
connection.Received()
132+
.Get<DeploymentEnvironmentsResponse>(Arg.Is<Uri>(u => u.ToString() == expectedUrl));
133+
}
134+
}
135+
136+
public class TheCtor
137+
{
138+
[Fact]
139+
public void EnsuresNonNullArguments()
140+
{
141+
Assert.Throws<ArgumentNullException>(() => new DeploymentEnvironmentsClient(null));
142+
}
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)