Skip to content

Commit c2aee1a

Browse files
[FEAT]: Create a GitHub App from a manifest
* Create a GitHub App from a manifest * Add missing InstallationPermissions * observable and tests * Remove ManualRoute on Observable route --------- Co-authored-by: Nick Floyd <139819+nickfloyd@users.noreply.github.com>
1 parent b208057 commit c2aee1a

File tree

11 files changed

+282
-13
lines changed

11 files changed

+282
-13
lines changed

Octokit.Reactive/Clients/IObservableGitHubAppsClient.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,13 @@ public interface IObservableGitHubAppsClient
110110
/// <remarks>https://developer.github.com/v3/apps/#find-user-installation</remarks>
111111
/// <param name="user">The name of the user</param>
112112
IObservable<Installation> GetUserInstallationForCurrent(string user);
113+
114+
/// <summary>
115+
/// Creates a GitHub app by completing the handshake necessary when implementing the GitHub App Manifest flow.
116+
/// https://docs.github.com/apps/sharing-github-apps/registering-a-github-app-from-a-manifest
117+
/// </summary>
118+
/// <remarks>https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest</remarks>
119+
/// <param name="code">Temporary code in a code parameter.</param>
120+
IObservable<GitHubAppFromManifest> CreateAppFromManifest(string code);
113121
}
114122
}

Octokit.Reactive/Clients/ObservableGitHubAppsClient.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,5 +175,18 @@ public IObservable<Installation> GetUserInstallationForCurrent(string user)
175175

176176
return _client.GetUserInstallationForCurrent(user).ToObservable();
177177
}
178+
179+
/// <summary>
180+
/// Creates a GitHub app by completing the handshake necessary when implementing the GitHub App Manifest flow.
181+
/// https://docs.github.com/apps/sharing-github-apps/registering-a-github-app-from-a-manifest
182+
/// </summary>
183+
/// <remarks>https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest</remarks>
184+
/// <param name="code">Temporary code in a code parameter.</param>
185+
public IObservable<GitHubAppFromManifest> CreateAppFromManifest(string code)
186+
{
187+
Ensure.ArgumentNotNullOrEmptyString(code, nameof(code));
188+
189+
return _client.CreateAppFromManifest(code).ToObservable();
190+
}
178191
}
179192
}

Octokit.Tests/Clients/GitHubAppsClientTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,5 +273,37 @@ public void GetsFromCorrectUrl()
273273
connection.Received().Get<Installation>(Arg.Is<Uri>(u => u.ToString() == "users/ducks/installation"), null);
274274
}
275275
}
276+
277+
public class TheCreateAppFromManifestMethod
278+
{
279+
[Fact]
280+
public async Task EnsuresNonNullArguments()
281+
{
282+
var connection = Substitute.For<IApiConnection>();
283+
var client = new GitHubAppsClient(connection);
284+
285+
await Assert.ThrowsAsync<ArgumentNullException>(() => client.CreateAppFromManifest(null));
286+
}
287+
288+
[Fact]
289+
public async Task EnsuresNonEmptyArguments()
290+
{
291+
var connection = Substitute.For<IApiConnection>();
292+
var client = new GitHubAppsClient(connection);
293+
294+
await Assert.ThrowsAsync<ArgumentException>(() => client.CreateAppFromManifest(""));
295+
}
296+
297+
[Fact]
298+
public void PostsFromCorrectUrl()
299+
{
300+
var connection = Substitute.For<IApiConnection>();
301+
var client = new GitHubAppsClient(connection);
302+
303+
client.CreateAppFromManifest("abc123");
304+
305+
connection.Received().Post<GitHubAppFromManifest>(Arg.Is<Uri>(u => u.ToString() == "app-manifests/abc123/conversions"));
306+
}
307+
}
276308
}
277309
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using Octokit.Internal;
2+
using Xunit;
3+
4+
namespace Octokit.Tests.Models
5+
{
6+
public class GitHubAppFromManifestTests
7+
{
8+
[Fact]
9+
public void CanBeDeserialized()
10+
{
11+
// from https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest
12+
const string json = @"{
13+
""id"": 1,
14+
""slug"": ""octoapp"",
15+
""node_id"": ""MDxOkludGVncmF0aW9uMQ=="",
16+
""owner"": {
17+
""login"": ""github"",
18+
""id"": 1,
19+
""node_id"": ""MDEyOk9yZ2FuaXphdGlvbjE="",
20+
""url"": ""https://api.github.com/orgs/github"",
21+
""repos_url"": ""https://api.github.com/orgs/github/repos"",
22+
""events_url"": ""https://api.github.com/orgs/github/events"",
23+
""avatar_url"": ""https://github.com/images/error/octocat_happy.gif"",
24+
""gravatar_id"": """",
25+
""html_url"": ""https://github.com/octocat"",
26+
""followers_url"": ""https://api.github.com/users/octocat/followers"",
27+
""following_url"": ""https://api.github.com/users/octocat/following{/other_user}"",
28+
""gists_url"": ""https://api.github.com/users/octocat/gists{/gist_id}"",
29+
""starred_url"": ""https://api.github.com/users/octocat/starred{/owner}{/repo}"",
30+
""subscriptions_url"": ""https://api.github.com/users/octocat/subscriptions"",
31+
""organizations_url"": ""https://api.github.com/users/octocat/orgs"",
32+
""received_events_url"": ""https://api.github.com/users/octocat/received_events"",
33+
""type"": ""User"",
34+
""site_admin"": true
35+
},
36+
""name"": ""Octocat App"",
37+
""description"": ""A short description of the app"",
38+
""external_url"": ""https://example.com"",
39+
""html_url"": ""https://github.com/apps/octoapp"",
40+
""created_at"": ""2017-07-08T16:18:44-04:00"",
41+
""updated_at"": ""2017-07-08T16:18:44-04:00"",
42+
""permissions"": {
43+
""metadata"": ""read"",
44+
""contents"": ""read"",
45+
""issues"": ""write"",
46+
""single_file"": ""write""
47+
},
48+
""events"": [
49+
""push"",
50+
""pull_request""
51+
],
52+
""client_id"": ""Iv1.8a61f9b3a7aba766"",
53+
""client_secret"": ""1726be1638095a19edd134c77bde3aa2ece1e5d8"",
54+
""webhook_secret"": ""e340154128314309424b7c8e90325147d99fdafa"",
55+
""pem"": ""-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAuEPzOUE+kiEH1WLiMeBytTEF856j0hOVcSUSUkZxKvqczkWM\n9vo1gDyC7ZXhdH9fKh32aapba3RSsp4ke+giSmYTk2mGR538ShSDxh0OgpJmjiKP\nX0Bj4j5sFqfXuCtl9SkH4iueivv4R53ktqM+n6hk98l6hRwC39GVIblAh2lEM4L/\n6WvYwuQXPMM5OG2Ryh2tDZ1WS5RKfgq+9ksNJ5Q9UtqtqHkO+E63N5OK9sbzpUUm\noNaOl3udTlZD3A8iqwMPVxH4SxgATBPAc+bmjk6BMJ0qIzDcVGTrqrzUiywCTLma\nszdk8GjzXtPDmuBgNn+o6s02qVGpyydgEuqmTQIDAQABAoIBACL6AvkjQVVLn8kJ\ndBYznJJ4M8ECo+YEgaFwgAHODT0zRQCCgzd+Vxl4YwHmKV2Lr+y2s0drZt8GvYva\nKOK8NYYZyi15IlwFyRXmvvykF1UBpSXluYFDH7KaVroWMgRreHcIys5LqVSIb6Bo\ngDmK0yBLPp8qR29s2b7ScZRtLaqGJiX+j55rNzrZwxHkxFHyG9OG+u9IsBElcKCP\nkYCVE8ZdYexfnKOZbgn2kZB9qu0T/Mdvki8yk3I2bI6xYO24oQmhnT36qnqWoCBX\nNuCNsBQgpYZeZET8mEAUmo9d+ABmIHIvSs005agK8xRaP4+6jYgy6WwoejJRF5yd\nNBuF7aECgYEA50nZ4FiZYV0vcJDxFYeY3kYOvVuKn8OyW+2rg7JIQTremIjv8FkE\nZnwuF9ZRxgqLxUIfKKfzp/5l5LrycNoj2YKfHKnRejxRWXqG+ZETfxxlmlRns0QG\nJ4+BYL0CoanDSeA4fuyn4Bv7cy/03TDhfg/Uq0Aeg+hhcPE/vx3ebPsCgYEAy/Pv\neDLssOSdeyIxf0Brtocg6aPXIVaLdus+bXmLg77rJIFytAZmTTW8SkkSczWtucI3\nFI1I6sei/8FdPzAl62/JDdlf7Wd9K7JIotY4TzT7Tm7QU7xpfLLYIP1bOFjN81rk\n77oOD4LsXcosB/U6s1blPJMZ6AlO2EKs10UuR1cCgYBipzuJ2ADEaOz9RLWwi0AH\nPza2Sj+c2epQD9ZivD7Zo/Sid3ZwvGeGF13JyR7kLEdmAkgsHUdu1rI7mAolXMaB\n1pdrsHureeLxGbRM6za3tzMXWv1Il7FQWoPC8ZwXvMOR1VQDv4nzq7vbbA8z8c+c\n57+8tALQHOTDOgQIzwK61QKBgERGVc0EJy4Uag+VY8J4m1ZQKBluqo7TfP6DQ7O8\nM5MX73maB/7yAX8pVO39RjrhJlYACRZNMbK+v/ckEQYdJSSKmGCVe0JrGYDuPtic\nI9+IGfSorf7KHPoMmMN6bPYQ7Gjh7a++tgRFTMEc8956Hnt4xGahy9NcglNtBpVN\n6G8jAoGBAMCh028pdzJa/xeBHLLaVB2sc0Fe7993WlsPmnVE779dAz7qMscOtXJK\nfgtriltLSSD6rTA9hUAsL/X62rY0wdXuNdijjBb/qvrx7CAV6i37NK1CjABNjsfG\nZM372Ac6zc1EqSrid2IjET1YqyIW2KGLI1R2xbQc98UGlt48OdWu\n-----END RSA PRIVATE KEY-----\n""
56+
}";
57+
58+
var app = new SimpleJsonSerializer().Deserialize<GitHubAppFromManifest>(json);
59+
60+
Assert.Equal(1, app.Id);
61+
Assert.Equal("octoapp", app.Slug);
62+
Assert.Equal("MDxOkludGVncmF0aW9uMQ==", app.NodeId);
63+
Assert.Equal("Octocat App", app.Name);
64+
Assert.Equal("A short description of the app", app.Description);
65+
Assert.Equal("https://example.com", app.ExternalUrl);
66+
Assert.Equal("https://github.com/apps/octoapp", app.HtmlUrl);
67+
Assert.Equal(InstallationReadWritePermissionLevel.Write, app.Permissions.SingleFile);
68+
Assert.Contains("push", app.Events);
69+
70+
Assert.Equal("Iv1.8a61f9b3a7aba766", app.ClientId);
71+
Assert.Equal("1726be1638095a19edd134c77bde3aa2ece1e5d8", app.ClientSecret);
72+
Assert.Equal("e340154128314309424b7c8e90325147d99fdafa", app.WebhookSecret);
73+
Assert.Equal("-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAuEPzOUE+kiEH1WLiMeBytTEF856j0hOVcSUSUkZxKvqczkWM\n9vo1gDyC7ZXhdH9fKh32aapba3RSsp4ke+giSmYTk2mGR538ShSDxh0OgpJmjiKP\nX0Bj4j5sFqfXuCtl9SkH4iueivv4R53ktqM+n6hk98l6hRwC39GVIblAh2lEM4L/\n6WvYwuQXPMM5OG2Ryh2tDZ1WS5RKfgq+9ksNJ5Q9UtqtqHkO+E63N5OK9sbzpUUm\noNaOl3udTlZD3A8iqwMPVxH4SxgATBPAc+bmjk6BMJ0qIzDcVGTrqrzUiywCTLma\nszdk8GjzXtPDmuBgNn+o6s02qVGpyydgEuqmTQIDAQABAoIBACL6AvkjQVVLn8kJ\ndBYznJJ4M8ECo+YEgaFwgAHODT0zRQCCgzd+Vxl4YwHmKV2Lr+y2s0drZt8GvYva\nKOK8NYYZyi15IlwFyRXmvvykF1UBpSXluYFDH7KaVroWMgRreHcIys5LqVSIb6Bo\ngDmK0yBLPp8qR29s2b7ScZRtLaqGJiX+j55rNzrZwxHkxFHyG9OG+u9IsBElcKCP\nkYCVE8ZdYexfnKOZbgn2kZB9qu0T/Mdvki8yk3I2bI6xYO24oQmhnT36qnqWoCBX\nNuCNsBQgpYZeZET8mEAUmo9d+ABmIHIvSs005agK8xRaP4+6jYgy6WwoejJRF5yd\nNBuF7aECgYEA50nZ4FiZYV0vcJDxFYeY3kYOvVuKn8OyW+2rg7JIQTremIjv8FkE\nZnwuF9ZRxgqLxUIfKKfzp/5l5LrycNoj2YKfHKnRejxRWXqG+ZETfxxlmlRns0QG\nJ4+BYL0CoanDSeA4fuyn4Bv7cy/03TDhfg/Uq0Aeg+hhcPE/vx3ebPsCgYEAy/Pv\neDLssOSdeyIxf0Brtocg6aPXIVaLdus+bXmLg77rJIFytAZmTTW8SkkSczWtucI3\nFI1I6sei/8FdPzAl62/JDdlf7Wd9K7JIotY4TzT7Tm7QU7xpfLLYIP1bOFjN81rk\n77oOD4LsXcosB/U6s1blPJMZ6AlO2EKs10UuR1cCgYBipzuJ2ADEaOz9RLWwi0AH\nPza2Sj+c2epQD9ZivD7Zo/Sid3ZwvGeGF13JyR7kLEdmAkgsHUdu1rI7mAolXMaB\n1pdrsHureeLxGbRM6za3tzMXWv1Il7FQWoPC8ZwXvMOR1VQDv4nzq7vbbA8z8c+c\n57+8tALQHOTDOgQIzwK61QKBgERGVc0EJy4Uag+VY8J4m1ZQKBluqo7TfP6DQ7O8\nM5MX73maB/7yAX8pVO39RjrhJlYACRZNMbK+v/ckEQYdJSSKmGCVe0JrGYDuPtic\nI9+IGfSorf7KHPoMmMN6bPYQ7Gjh7a++tgRFTMEc8956Hnt4xGahy9NcglNtBpVN\n6G8jAoGBAMCh028pdzJa/xeBHLLaVB2sc0Fe7993WlsPmnVE779dAz7qMscOtXJK\nfgtriltLSSD6rTA9hUAsL/X62rY0wdXuNdijjBb/qvrx7CAV6i37NK1CjABNjsfG\nZM372Ac6zc1EqSrid2IjET1YqyIW2KGLI1R2xbQc98UGlt48OdWu\n-----END RSA PRIVATE KEY-----\n", app.Pem);
74+
75+
Assert.Equal(1, app.Owner.Id);
76+
Assert.Equal("github", app.Owner.Login);
77+
Assert.Equal("https://api.github.com/orgs/github", app.Owner.Url);
78+
Assert.Equal(AccountType.User, app.Owner.Type);
79+
}
80+
}
81+
}

Octokit.Tests/Reactive/ObservableGitHubAppsClientTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,5 +287,37 @@ public void GetsFromCorrectUrl()
287287
gitHubClient.GitHubApps.Received().GetUserInstallationForCurrent("ducks");
288288
}
289289
}
290+
291+
public class TheCreateAppFromManifestMethod
292+
{
293+
[Fact]
294+
public void EnsuresNonNullArguments()
295+
{
296+
var gitHubClient = Substitute.For<IGitHubClient>();
297+
var client = new ObservableGitHubAppsClient(gitHubClient);
298+
299+
Assert.Throws<ArgumentNullException>(() => client.CreateAppFromManifest(null));
300+
}
301+
302+
[Fact]
303+
public void EnsuresNonEmptyArguments()
304+
{
305+
var gitHubClient = Substitute.For<IGitHubClient>();
306+
var client = new ObservableGitHubAppsClient(gitHubClient);
307+
308+
Assert.Throws<ArgumentException>(() => client.CreateAppFromManifest(""));
309+
}
310+
311+
[Fact]
312+
public void GetsFromCorrectUrl()
313+
{
314+
var gitHubClient = Substitute.For<IGitHubClient>();
315+
var client = new ObservableGitHubAppsClient(gitHubClient);
316+
317+
client.CreateAppFromManifest("abc123");
318+
319+
gitHubClient.GitHubApps.Received().CreateAppFromManifest("abc123");
320+
}
321+
}
290322
}
291323
}

Octokit/Clients/GitHubAppsClient.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,5 +192,19 @@ public Task<Installation> GetUserInstallationForCurrent(string user)
192192

193193
return ApiConnection.Get<Installation>(ApiUrls.UserInstallation(user), null);
194194
}
195+
196+
/// <summary>
197+
/// Creates a GitHub app by completing the handshake necessary when implementing the GitHub App Manifest flow.
198+
/// https://docs.github.com/apps/sharing-github-apps/registering-a-github-app-from-a-manifest
199+
/// </summary>
200+
/// <remarks>https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest</remarks>
201+
/// <param name="code">Temporary code in a code parameter.</param>
202+
[ManualRoute("POST", "/app-manifests/{code}/conversions")]
203+
public Task<GitHubAppFromManifest> CreateAppFromManifest(string code)
204+
{
205+
Ensure.ArgumentNotNullOrEmptyString(code, nameof(code));
206+
207+
return ApiConnection.Post<GitHubAppFromManifest>(ApiUrls.AppManifestConversions(code));
208+
}
195209
}
196210
}

Octokit/Clients/IGitHubAppsClient.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,13 @@ public interface IGitHubAppsClient
112112
/// <remarks>https://developer.github.com/v3/apps/#find-user-installation</remarks>
113113
/// <param name="user">The name of the user</param>
114114
Task<Installation> GetUserInstallationForCurrent(string user);
115+
116+
/// <summary>
117+
/// Creates a GitHub app by completing the handshake necessary when implementing the GitHub App Manifest flow.
118+
/// https://docs.github.com/apps/sharing-github-apps/registering-a-github-app-from-a-manifest
119+
/// </summary>
120+
/// <remarks>https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest</remarks>
121+
/// <param name="code">Temporary code in a code parameter.</param>
122+
Task<GitHubAppFromManifest> CreateAppFromManifest(string code);
115123
}
116-
}
124+
}

Octokit/Helpers/ApiUrls.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,15 @@ public static Uri NotificationSubscription(int notificationId)
403403
return "notifications/threads/{0}/subscription".FormatUri(notificationId);
404404
}
405405

406+
/// <summary>
407+
/// Returns the <see cref="Uri"/> to complete the handshake necessary when implementing the GitHub App Manifest flow.
408+
/// </summary>
409+
/// <param name="code">Temporary code in a code parameter.</param>
410+
public static Uri AppManifestConversions(string code)
411+
{
412+
return "app-manifests/{0}/conversions".FormatUri(code);
413+
}
414+
406415
/// <summary>
407416
/// Returns the <see cref="Uri"/> for creating a new installation token.
408417
/// </summary>

Octokit/Models/Response/GitHubApp.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ public class GitHubApp
1313
{
1414
public GitHubApp() { }
1515

16-
public GitHubApp(long id, string slug, string name, User owner, string description, string externalUrl, string htmlUrl, DateTimeOffset createdAt, DateTimeOffset updatedAt, InstallationPermissions permissions, IReadOnlyList<string> events)
16+
public GitHubApp(long id, string slug, string nodeId, string name, User owner, string description, string externalUrl, string htmlUrl, DateTimeOffset createdAt, DateTimeOffset updatedAt, InstallationPermissions permissions, IReadOnlyList<string> events)
1717
{
1818
Id = id;
1919
Slug = slug;
20+
NodeId = nodeId;
2021
Name = name;
2122
Owner = owner;
2223
Description = description;
@@ -31,57 +32,62 @@ public GitHubApp(long id, string slug, string name, User owner, string descripti
3132
/// <summary>
3233
/// The Id of the GitHub App.
3334
/// </summary>
34-
public long Id { get; private set; }
35+
public long Id { get; protected set; }
3536

3637
/// <summary>
3738
/// The url-friendly version of the GitHub App name.
3839
/// </summary>
39-
public string Slug { get; private set; }
40+
public string Slug { get; protected set; }
41+
42+
/// <summary>
43+
/// GraphQL Node Id
44+
/// </summary>
45+
public string NodeId { get; protected set; }
4046

4147
/// <summary>
4248
/// The Name of the GitHub App.
4349
/// </summary>
44-
public string Name { get; private set; }
50+
public string Name { get; protected set; }
4551

4652
/// <summary>
4753
/// The Owner of the GitHub App.
4854
/// </summary>
49-
public User Owner { get; private set; }
55+
public User Owner { get; protected set; }
5056

5157
/// <summary>
5258
/// The Description of the GitHub App.
5359
/// </summary>
54-
public string Description { get; private set; }
60+
public string Description { get; protected set; }
5561

5662
/// <summary>
5763
/// The URL to the GitHub App's external website.
5864
/// </summary>
59-
public string ExternalUrl { get; private set; }
65+
public string ExternalUrl { get; protected set; }
6066

6167
/// <summary>
6268
/// The URL to view the GitHub App on GitHub.
6369
/// </summary>
64-
public string HtmlUrl { get; private set; }
70+
public string HtmlUrl { get; protected set; }
6571

6672
/// <summary>
6773
/// Date the GitHub App was created.
6874
/// </summary>
69-
public DateTimeOffset CreatedAt { get; private set; }
75+
public DateTimeOffset CreatedAt { get; protected set; }
7076

7177
/// <summary>
7278
/// Date the GitHub App was last updated.
7379
/// </summary>
74-
public DateTimeOffset UpdatedAt { get; private set; }
80+
public DateTimeOffset UpdatedAt { get; protected set; }
7581

7682
/// <summary>
7783
/// The Permissions granted to the Installation
7884
/// </summary>
79-
public InstallationPermissions Permissions { get; private set; }
85+
public InstallationPermissions Permissions { get; protected set; }
8086

8187
/// <summary>
8288
/// The Events subscribed to by the Installation
8389
/// </summary>
84-
public IReadOnlyList<string> Events { get; private set; }
90+
public IReadOnlyList<string> Events { get; protected set; }
8591

8692
internal string DebuggerDisplay
8793
{
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
5+
namespace Octokit
6+
{
7+
/// <summary>
8+
/// Represents a GitHub application from a manifest.
9+
/// https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest
10+
/// </summary>
11+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
12+
public class GitHubAppFromManifest : GitHubApp
13+
{
14+
public GitHubAppFromManifest() { }
15+
16+
public GitHubAppFromManifest(long id, string slug, string nodeId, string name, User owner, string description, string externalUrl, string htmlUrl, DateTimeOffset createdAt, DateTimeOffset updatedAt, InstallationPermissions permissions, IReadOnlyList<string> events, string clientId, string clientSecret, string webhookSecret, string pem)
17+
: base(id, slug, nodeId, name, owner, description, externalUrl, htmlUrl, createdAt, updatedAt, permissions, events)
18+
{
19+
ClientId = clientId;
20+
ClientSecret = clientSecret;
21+
WebhookSecret = webhookSecret;
22+
Pem = pem;
23+
}
24+
25+
/// <summary>
26+
/// The Client Id of the GitHub App.
27+
/// </summary>
28+
public string ClientId { get; private set; }
29+
30+
/// <summary>
31+
/// The Client Secret of the GitHub App.
32+
/// </summary>
33+
public string ClientSecret { get; private set; }
34+
35+
/// <summary>
36+
/// The Webhook Secret of the GitHub App.
37+
/// </summary>
38+
public string WebhookSecret { get; private set; }
39+
40+
/// <summary>
41+
/// The PEM of the GitHub App.
42+
/// </summary>
43+
public string Pem { get; private set; }
44+
}
45+
}

0 commit comments

Comments
 (0)