From 595e35d6419e444bbf20f9d02bab5a9749219e83 Mon Sep 17 00:00:00 2001 From: notauserx <82922717+notauserx@users.noreply.github.com> Date: Fri, 19 Aug 2022 23:36:47 +0600 Subject: [PATCH] add active lock reason to PR (#2543) * add active lock reason to PR * update docs * refactor: extract lock and unlock from IIssuesClient create ILockUnlockClient so both IIssuesClient and IPullRequestClient can access lock and unlock methods. * refactor LockUnlock for reactive clients * Update doc to include lock unlock sample code * Use Assert.Null to check null value in test Co-authored-by: notauserx --- .../Clients/IObservableIssuesClient.cs | 41 ++-------- .../Clients/IObservableLockUnlockClient.cs | 47 ++++++++++++ .../Clients/IObservablePullRequestsClient.cs | 5 ++ .../Clients/ObservableIssuesClient.cs | 60 ++------------- .../Clients/ObservableLockUnlockClient.cs | 75 ++++++++++++++++++ .../Clients/ObservablePullRequestsClient.cs | 6 ++ .../Clients/IssuesClientTests.cs | 10 +-- .../Clients/IssuesEventsClientTests.cs | 72 +++++++++--------- .../Clients/PullRequestsClientTests.cs | 19 +++++ .../Reactive/ObservableIssuesClientTests.cs | 4 +- Octokit.Tests/Clients/IssuesClientTests.cs | 24 +++--- .../Reactive/ObservableIssuesClientTests.cs | 32 ++++---- Octokit/Clients/IIssuesClient.cs | 37 +-------- Octokit/Clients/ILockUnlockClient.cs | 47 ++++++++++++ Octokit/Clients/IPullRequestsClient.cs | 5 ++ Octokit/Clients/IssuesClient.cs | 66 ++-------------- Octokit/Clients/LockUnlockClient.cs | 76 +++++++++++++++++++ Octokit/Clients/PullRequestsClient.cs | 6 ++ Octokit/Models/Response/PullRequest.cs | 8 +- docs/issues.md | 20 +++++ 20 files changed, 405 insertions(+), 255 deletions(-) create mode 100644 Octokit.Reactive/Clients/IObservableLockUnlockClient.cs create mode 100644 Octokit.Reactive/Clients/ObservableLockUnlockClient.cs create mode 100644 Octokit/Clients/ILockUnlockClient.cs create mode 100644 Octokit/Clients/LockUnlockClient.cs diff --git a/Octokit.Reactive/Clients/IObservableIssuesClient.cs b/Octokit.Reactive/Clients/IObservableIssuesClient.cs index 3081488e..8057f9e2 100644 --- a/Octokit.Reactive/Clients/IObservableIssuesClient.cs +++ b/Octokit.Reactive/Clients/IObservableIssuesClient.cs @@ -44,6 +44,11 @@ namespace Octokit.Reactive /// IObservableIssueTimelineClient Timeline { get; } + /// + /// Client for locking/unlocking conversation on an issue + /// + IObservableLockUnlockClient LockUnlock { get; } + /// /// Gets a single Issue by number. /// @@ -316,41 +321,5 @@ namespace Octokit.Reactive /// An instance describing the changes to make to the issue /// IObservable Update(long repositoryId, int number, IssueUpdate issueUpdate); - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - /// The reason for locking the issue - IObservable Lock(string owner, string name, int number, LockReason? lockReason = null); - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The Id of the repository - /// The issue number - /// The reason for locking the issue - IObservable Lock(long repositoryId, int number, LockReason? lockReason = null); - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - IObservable Unlock(string owner, string name, int number); - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The Id of the repository - /// The issue number - IObservable Unlock(long repositoryId, int number); } } \ No newline at end of file diff --git a/Octokit.Reactive/Clients/IObservableLockUnlockClient.cs b/Octokit.Reactive/Clients/IObservableLockUnlockClient.cs new file mode 100644 index 00000000..b897141b --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableLockUnlockClient.cs @@ -0,0 +1,47 @@ +using System; +using System.Reactive; + +namespace Octokit.Reactive +{ + /// + /// Client to manage locking/unlocking a conversation for an Issue or a Pull request + /// + public interface IObservableLockUnlockClient + { + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The reason for locking the issue + IObservable Lock(string owner, string name, int number, LockReason? lockReason = null); + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The Id of the repository + /// The issue number + /// The reason for locking the issue + IObservable Lock(long repositoryId, int number, LockReason? lockReason = null); + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + IObservable Unlock(string owner, string name, int number); + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The Id of the repository + /// The issue number + IObservable Unlock(long repositoryId, int number); + } +} diff --git a/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs b/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs index 007886af..997d6622 100644 --- a/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs +++ b/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs @@ -26,6 +26,11 @@ namespace Octokit.Reactive /// IObservablePullRequestReviewRequestsClient ReviewRequest { get; } + /// + /// Client for locking/unlocking a conversation on a pull request + /// + IObservableLockUnlockClient LockUnlock { get; } + /// /// Gets a single Pull Request by number. /// diff --git a/Octokit.Reactive/Clients/ObservableIssuesClient.cs b/Octokit.Reactive/Clients/ObservableIssuesClient.cs index 2f2df7c9..033408d3 100644 --- a/Octokit.Reactive/Clients/ObservableIssuesClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssuesClient.cs @@ -48,6 +48,11 @@ namespace Octokit.Reactive /// public IObservableIssueTimelineClient Timeline { get; private set; } + /// + /// Client for locking/unlocking conversation on an issue + /// + public IObservableLockUnlockClient LockUnlock { get; protected set; } + public ObservableIssuesClient(IGitHubClient client) { Ensure.ArgumentNotNull(client, nameof(client)); @@ -60,6 +65,7 @@ namespace Octokit.Reactive Milestone = new ObservableMilestonesClient(client); Comment = new ObservableIssueCommentsClient(client); Timeline = new ObservableIssueTimelineClient(client); + LockUnlock = new ObservableLockUnlockClient(client); } /// @@ -473,58 +479,6 @@ namespace Octokit.Reactive return _client.Update(repositoryId, number, issueUpdate).ToObservable(); } - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - /// The reason for locking the issue - public IObservable Lock(string owner, string name, int number, LockReason? lockReason = null) - { - Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); - Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - - return _client.Lock(owner, name, number, lockReason).ToObservable(); - } - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The Id of the repository - /// The issue number - /// The reason for locking the issue - public IObservable Lock(long repositoryId, int number, LockReason? lockReason = null) - { - return _client.Lock(repositoryId, number, lockReason).ToObservable(); - } - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - public IObservable Unlock(string owner, string name, int number) - { - Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); - Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - - return _client.Unlock(owner, name, number).ToObservable(); - } - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The Id of the repository - /// The issue number - public IObservable Unlock(long repositoryId, int number) - { - return _client.Unlock(repositoryId, number).ToObservable(); - } + } } diff --git a/Octokit.Reactive/Clients/ObservableLockUnlockClient.cs b/Octokit.Reactive/Clients/ObservableLockUnlockClient.cs new file mode 100644 index 00000000..3010741a --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableLockUnlockClient.cs @@ -0,0 +1,75 @@ +using System; +using System.Reactive; +using System.Reactive.Threading.Tasks; + +namespace Octokit.Reactive +{ + /// + /// Client to manage locking/unlocking a conversation for an Issue or a Pull request + /// + public class ObservableLockUnlockClient : IObservableLockUnlockClient + { + readonly ILockUnlockClient _client; + + public ObservableLockUnlockClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, nameof(client)); + + _client = client.Issue.LockUnlock; + } + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The reason for locking the issue + public IObservable Lock(string owner, string name, int number, LockReason? lockReason = null) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return _client.Lock(owner, name, number, lockReason).ToObservable(); + } + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The Id of the repository + /// The issue number + /// The reason for locking the issue + public IObservable Lock(long repositoryId, int number, LockReason? lockReason = null) + { + return _client.Lock(repositoryId, number, lockReason).ToObservable(); + } + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + public IObservable Unlock(string owner, string name, int number) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return _client.Unlock(owner, name, number).ToObservable(); + } + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The Id of the repository + /// The issue number + public IObservable Unlock(long repositoryId, int number) + { + return _client.Unlock(repositoryId, number).ToObservable(); + } + } +} diff --git a/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs b/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs index 9fbafba8..0f343760 100644 --- a/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs +++ b/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs @@ -30,6 +30,11 @@ namespace Octokit.Reactive /// public IObservablePullRequestReviewRequestsClient ReviewRequest { get; private set; } + /// + /// Client for locking/unlocking a conversation on a pull request + /// + public IObservableLockUnlockClient LockUnlock { get; private set; } + public ObservablePullRequestsClient(IGitHubClient client) { Ensure.ArgumentNotNull(client, nameof(client)); @@ -39,6 +44,7 @@ namespace Octokit.Reactive Review = new ObservablePullRequestReviewsClient(client); ReviewComment = new ObservablePullRequestReviewCommentsClient(client); ReviewRequest = new ObservablePullRequestReviewRequestsClient(client); + LockUnlock = new ObservableLockUnlockClient(client); } /// diff --git a/Octokit.Tests.Integration/Clients/IssuesClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesClientTests.cs index 16bf28f7..2a92b35b 100644 --- a/Octokit.Tests.Integration/Clients/IssuesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssuesClientTests.cs @@ -241,12 +241,12 @@ public class IssuesClientTests : IDisposable var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); Assert.False(issue.Locked); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number); Assert.NotNull(retrieved); Assert.True(retrieved.Locked); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number); Assert.NotNull(retrieved); Assert.False(retrieved.Locked); @@ -259,7 +259,7 @@ public class IssuesClientTests : IDisposable var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); Assert.False(issue.Locked); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number, LockReason.OffTopic); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number, LockReason.OffTopic); var retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number); Assert.NotNull(retrieved); Assert.True(retrieved.Locked); @@ -273,12 +273,12 @@ public class IssuesClientTests : IDisposable var issue = await _issuesClient.Create(_context.Repository.Id, newIssue); Assert.False(issue.Locked); - await _issuesClient.Lock(_context.Repository.Id, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.Repository.Id, issue.Number); var retrieved = await _issuesClient.Get(_context.Repository.Id, issue.Number); Assert.NotNull(retrieved); Assert.True(retrieved.Locked); - await _issuesClient.Unlock(_context.Repository.Id, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.Repository.Id, issue.Number); retrieved = await _issuesClient.Get(_context.Repository.Id, issue.Number); Assert.NotNull(retrieved); Assert.False(retrieved.Locked); diff --git a/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs index 9daa2834..a223d65e 100644 --- a/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs @@ -63,9 +63,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -83,9 +83,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -103,9 +103,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -124,9 +124,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -145,9 +145,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var startOptions = new ApiOptions { @@ -174,9 +174,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var startOptions = new ApiOptions { @@ -259,9 +259,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -279,9 +279,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -299,9 +299,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -320,9 +320,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -341,9 +341,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var startOptions = new ApiOptions { @@ -370,9 +370,9 @@ public class IssuesEventsClientTests : IDisposable { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var startOptions = new ApiOptions { diff --git a/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs b/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs index 8985e28b..d8c6cc41 100644 --- a/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs @@ -653,6 +653,25 @@ public class PullRequestsClientTests : IDisposable Assert.Equal(pullRequest.Body, result.Body); } + [IntegrationTest] + public async Task CanLockAndUnlock() + { + await CreateTheWorld(); + + var newPullRequest = new NewPullRequest("a pull request to lock", branchName, "main"); + var pullRequest = await _fixture.Create(Helper.UserName, _context.RepositoryName, newPullRequest); + + await _fixture.LockUnlock.Lock(Helper.UserName, _context.RepositoryName, pullRequest.Number, LockReason.OffTopic); + var retrived = await _fixture.Get(Helper.UserName, _context.RepositoryName, pullRequest.Number); + + Assert.Equal(retrived.ActiveLockReason, LockReason.OffTopic); + + await _fixture.LockUnlock.Unlock(Helper.UserName, _context.RepositoryName, pullRequest.Number); + var unlocked = await _fixture.Get(Helper.UserName, _context.RepositoryName, pullRequest.Number); + + Assert.Null(unlocked.ActiveLockReason); + } + [IntegrationTest] public async Task CanFindClosedPullRequest() { diff --git a/Octokit.Tests.Integration/Reactive/ObservableIssuesClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableIssuesClientTests.cs index bedb3d37..146228e9 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableIssuesClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableIssuesClientTests.cs @@ -118,11 +118,11 @@ public class ObservableIssuesClientTests : IDisposable var createResult = await _client.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); Assert.False(createResult.Locked); - await _client.Lock(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); + await _client.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); var lockResult = await _client.Get(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); Assert.True(lockResult.Locked); - await _client.Unlock(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); + await _client.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); var unlockIssueResult = await _client.Get(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); Assert.False(unlockIssueResult.Locked); } diff --git a/Octokit.Tests/Clients/IssuesClientTests.cs b/Octokit.Tests/Clients/IssuesClientTests.cs index 5eaceb81..6cfc3e78 100644 --- a/Octokit.Tests/Clients/IssuesClientTests.cs +++ b/Octokit.Tests/Clients/IssuesClientTests.cs @@ -478,7 +478,7 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new IssuesClient(connection); - client.Lock("fake", "repo", 42); + client.LockUnlock.Lock("fake", "repo", 42); connection.Received().Put(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/42/lock"), Arg.Any()); } @@ -489,7 +489,7 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new IssuesClient(connection); - client.Lock(1, 42); + client.LockUnlock.Lock(1, 42); connection.Received().Put(Arg.Is(u => u.ToString() == "repositories/1/issues/42/lock"), Arg.Any()); } @@ -500,11 +500,11 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new IssuesClient(connection); - await Assert.ThrowsAsync(() => client.Lock(null, "name", 1)); - await Assert.ThrowsAsync(() => client.Lock("owner", null, 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Lock(null, "name", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Lock("owner", null, 1)); - await Assert.ThrowsAsync(() => client.Lock("", "name", 1)); - await Assert.ThrowsAsync(() => client.Lock("owner", "", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Lock("", "name", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Lock("owner", "", 1)); } } @@ -516,7 +516,7 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new IssuesClient(connection); - client.Unlock("fake", "repo", 42); + client.LockUnlock.Unlock("fake", "repo", 42); connection.Received().Delete(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/42/lock")); } @@ -527,7 +527,7 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new IssuesClient(connection); - client.Unlock(1, 42); + client.LockUnlock.Unlock(1, 42); connection.Received().Delete(Arg.Is(u => u.ToString() == "repositories/1/issues/42/lock")); } @@ -538,11 +538,11 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new IssuesClient(connection); - await Assert.ThrowsAsync(() => client.Unlock(null, "name", 1)); - await Assert.ThrowsAsync(() => client.Unlock("owner", null, 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Unlock(null, "name", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Unlock("owner", null, 1)); - await Assert.ThrowsAsync(() => client.Unlock("", "name", 1)); - await Assert.ThrowsAsync(() => client.Unlock("owner", "", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Unlock("", "name", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Unlock("owner", "", 1)); } } diff --git a/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs b/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs index 347f17ad..6245620a 100644 --- a/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs @@ -645,9 +645,9 @@ public class ObservableIssuesClientTests var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - client.Lock("fake", "repo", 42); + client.LockUnlock.Lock("fake", "repo", 42); - gitHubClient.Issue.Received().Lock("fake", "repo", 42); + gitHubClient.Issue.Received().LockUnlock.Lock("fake", "repo", 42); } [Fact] @@ -656,9 +656,9 @@ public class ObservableIssuesClientTests var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - client.Lock(1, 42); + client.LockUnlock.Lock(1, 42); - gitHubClient.Issue.Received().Lock(1, 42); + gitHubClient.Issue.Received().LockUnlock.Lock(1, 42); } [Fact] @@ -667,11 +667,11 @@ public class ObservableIssuesClientTests var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - Assert.Throws(() => client.Lock(null, "name", 42)); - Assert.Throws(() => client.Lock("owner", null, 42)); + Assert.Throws(() => client.LockUnlock.Lock(null, "name", 42)); + Assert.Throws(() => client.LockUnlock.Lock("owner", null, 42)); - Assert.Throws(() => client.Lock("", "name", 42)); - Assert.Throws(() => client.Lock("owner", "", 42)); + Assert.Throws(() => client.LockUnlock.Lock("", "name", 42)); + Assert.Throws(() => client.LockUnlock.Lock("owner", "", 42)); } } @@ -683,9 +683,9 @@ public class ObservableIssuesClientTests var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - client.Unlock("fake", "repo", 42); + client.LockUnlock.Unlock("fake", "repo", 42); - gitHubClient.Issue.Received().Unlock("fake", "repo", 42); + gitHubClient.Issue.Received().LockUnlock.Unlock("fake", "repo", 42); } [Fact] @@ -694,9 +694,9 @@ public class ObservableIssuesClientTests var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - client.Unlock(1, 42); + client.LockUnlock.Unlock(1, 42); - gitHubClient.Issue.Received().Unlock(1, 42); + gitHubClient.Issue.Received().LockUnlock.Unlock(1, 42); } [Fact] @@ -705,11 +705,11 @@ public class ObservableIssuesClientTests var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - Assert.Throws(() => client.Unlock(null, "name", 42)); - Assert.Throws(() => client.Unlock("owner", null, 42)); + Assert.Throws(() => client.LockUnlock.Unlock(null, "name", 42)); + Assert.Throws(() => client.LockUnlock.Unlock("owner", null, 42)); - Assert.Throws(() => client.Unlock("", "name", 42)); - Assert.Throws(() => client.Unlock("owner", "", 42)); + Assert.Throws(() => client.LockUnlock.Unlock("", "name", 42)); + Assert.Throws(() => client.LockUnlock.Unlock("owner", "", 42)); } } diff --git a/Octokit/Clients/IIssuesClient.cs b/Octokit/Clients/IIssuesClient.cs index 63f5611d..c8dc2c1a 100644 --- a/Octokit/Clients/IIssuesClient.cs +++ b/Octokit/Clients/IIssuesClient.cs @@ -41,6 +41,8 @@ namespace Octokit IIssueTimelineClient Timeline { get; } + ILockUnlockClient LockUnlock { get; } + /// /// Gets a single Issue by number. /// @@ -314,40 +316,5 @@ namespace Octokit /// Task Update(long repositoryId, int number, IssueUpdate issueUpdate); - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - /// The reason for locking the issue - Task Lock(string owner, string name, int number, LockReason? lockReason = null); - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The Id of the repository - /// The issue number - /// The reason for locking the issue - Task Lock(long repositoryId, int number, LockReason? lockReason = null); - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - Task Unlock(string owner, string name, int number); - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The Id of the repository - /// The issue number - Task Unlock(long repositoryId, int number); } } \ No newline at end of file diff --git a/Octokit/Clients/ILockUnlockClient.cs b/Octokit/Clients/ILockUnlockClient.cs new file mode 100644 index 00000000..da5f6ff8 --- /dev/null +++ b/Octokit/Clients/ILockUnlockClient.cs @@ -0,0 +1,47 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// Client to manage locking/unlocking a conversation for an Issue or a Pull request + /// + public interface ILockUnlockClient + { + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The reason for locking the issue + Task Lock(string owner, string name, int number, LockReason? lockReason = null); + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The Id of the repository + /// The issue number + /// The reason for locking the issue + Task Lock(long repositoryId, int number, LockReason? lockReason = null); + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + Task Unlock(string owner, string name, int number); + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The Id of the repository + /// The issue number + Task Unlock(long repositoryId, int number); + + } +} diff --git a/Octokit/Clients/IPullRequestsClient.cs b/Octokit/Clients/IPullRequestsClient.cs index 639c9c4f..e35d22d6 100644 --- a/Octokit/Clients/IPullRequestsClient.cs +++ b/Octokit/Clients/IPullRequestsClient.cs @@ -28,6 +28,11 @@ namespace Octokit /// IPullRequestReviewRequestsClient ReviewRequest { get; } + /// + /// Client for locking/unlocking a coversation on a pull request + /// + ILockUnlockClient LockUnlock { get; } + /// /// Get a pull request by number. /// diff --git a/Octokit/Clients/IssuesClient.cs b/Octokit/Clients/IssuesClient.cs index 508e6c21..01c8c4d5 100644 --- a/Octokit/Clients/IssuesClient.cs +++ b/Octokit/Clients/IssuesClient.cs @@ -23,6 +23,7 @@ namespace Octokit Milestone = new MilestonesClient(apiConnection); Comment = new IssueCommentsClient(apiConnection); Timeline = new IssueTimelineClient(apiConnection); + LockUnlock = new LockUnlockClient(apiConnection); } /// @@ -57,6 +58,11 @@ namespace Octokit /// public IIssueTimelineClient Timeline { get; private set; } + /// + /// Client for locking and unlocking a conversation on a Issue or Pull request + /// + public ILockUnlockClient LockUnlock { get; private set; } + /// /// Gets a single Issue by number. /// @@ -491,64 +497,6 @@ namespace Octokit Ensure.ArgumentNotNull(issueUpdate, nameof(issueUpdate)); return ApiConnection.Patch(ApiUrls.Issue(repositoryId, number), issueUpdate); - } - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - /// The reason for locking the issue - [ManualRoute("PUT", "/repos/{owner}/{repo}/issues/{issue_number}/lock")] - public Task Lock(string owner, string name, int number, LockReason? lockReason = null) - { - Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); - Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - - return ApiConnection.Put(ApiUrls.IssueLock(owner, name, number), lockReason.HasValue ? new { LockReason = lockReason } : new object()); - } - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The Id of the repository - /// The issue number - /// The reason for locking the issue - [ManualRoute("PUT", "/repositories/{id}/issues/{number}/lock")] - public Task Lock(long repositoryId, int number, LockReason? lockReason = null) - { - return ApiConnection.Put(ApiUrls.IssueLock(repositoryId, number), lockReason.HasValue ? new { LockReaons = lockReason } : new object()); - } - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - [ManualRoute("DELETE", "/repos/{owner}/{repo}/issues/{issue_number}/lock")] - public Task Unlock(string owner, string name, int number) - { - Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); - Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - - return ApiConnection.Delete(ApiUrls.IssueLock(owner, name, number)); - } - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The Id of the repository - /// The issue number - [ManualRoute("DELETE", "/repositories/{id}/issues/{number}/lock")] - public Task Unlock(long repositoryId, int number) - { - return ApiConnection.Delete(ApiUrls.IssueLock(repositoryId, number)); - } + } } } diff --git a/Octokit/Clients/LockUnlockClient.cs b/Octokit/Clients/LockUnlockClient.cs new file mode 100644 index 00000000..4acf702d --- /dev/null +++ b/Octokit/Clients/LockUnlockClient.cs @@ -0,0 +1,76 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// Client to manage locking/unlocking a conversation for an Issue or a Pull request + /// + public class LockUnlockClient : ApiClient, ILockUnlockClient + { + /// + /// Instantiates a new GitHub Issue Lock API client. + /// + /// An API connection + public LockUnlockClient(IApiConnection apiConnection) : base(apiConnection) + { + + } + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The reason for locking the issue + [ManualRoute("PUT", "/repos/{owner}/{repo}/issues/{issue_number}/lock")] + public Task Lock(string owner, string name, int number, LockReason? lockReason = null) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return ApiConnection.Put(ApiUrls.IssueLock(owner, name, number), lockReason.HasValue ? new { LockReason = lockReason } : new object()); + } + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The Id of the repository + /// The issue number + /// The reason for locking the issue + [ManualRoute("PUT", "/repositories/{id}/issues/{number}/lock")] + public Task Lock(long repositoryId, int number, LockReason? lockReason = null) + { + return ApiConnection.Put(ApiUrls.IssueLock(repositoryId, number), lockReason.HasValue ? new { LockReaons = lockReason } : new object()); + } + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + [ManualRoute("DELETE", "/repos/{owner}/{repo}/issues/{issue_number}/lock")] + public Task Unlock(string owner, string name, int number) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return ApiConnection.Delete(ApiUrls.IssueLock(owner, name, number)); + } + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The Id of the repository + /// The issue number + [ManualRoute("DELETE", "/repositories/{id}/issues/{number}/lock")] + public Task Unlock(long repositoryId, int number) + { + return ApiConnection.Delete(ApiUrls.IssueLock(repositoryId, number)); + } + } +} diff --git a/Octokit/Clients/PullRequestsClient.cs b/Octokit/Clients/PullRequestsClient.cs index 07c63b97..34bf1cda 100644 --- a/Octokit/Clients/PullRequestsClient.cs +++ b/Octokit/Clients/PullRequestsClient.cs @@ -18,6 +18,7 @@ namespace Octokit Review = new PullRequestReviewsClient(apiConnection); ReviewComment = new PullRequestReviewCommentsClient(apiConnection); ReviewRequest = new PullRequestReviewRequestsClient(apiConnection); + LockUnlock = new LockUnlockClient(apiConnection); } /// @@ -35,6 +36,11 @@ namespace Octokit /// public IPullRequestReviewRequestsClient ReviewRequest { get; set; } + /// + /// Client for locking/unlocking a coversation on a pull request + /// + public ILockUnlockClient LockUnlock { get; set; } + /// /// Get a pull request by number. /// diff --git a/Octokit/Models/Response/PullRequest.cs b/Octokit/Models/Response/PullRequest.cs index 9ca99408..e7690c7d 100644 --- a/Octokit/Models/Response/PullRequest.cs +++ b/Octokit/Models/Response/PullRequest.cs @@ -16,7 +16,7 @@ namespace Octokit Number = number; } - public PullRequest(long id, string nodeId, string url, string htmlUrl, string diffUrl, string patchUrl, string issueUrl, string statusesUrl, int number, ItemState state, string title, string body, DateTimeOffset createdAt, DateTimeOffset updatedAt, DateTimeOffset? closedAt, DateTimeOffset? mergedAt, GitReference head, GitReference @base, User user, User assignee, IReadOnlyList assignees, bool draft, bool? mergeable, MergeableState? mergeableState, User mergedBy, string mergeCommitSha, int comments, int commits, int additions, int deletions, int changedFiles, Milestone milestone, bool locked, bool? maintainerCanModify, IReadOnlyList requestedReviewers, IReadOnlyList requestedTeams, IReadOnlyList