From 77213430f1a1fd87bae61b6339d2fa3bb1802bc4 Mon Sep 17 00:00:00 2001 From: Union Palenshus Date: Wed, 20 Apr 2022 14:29:10 -0700 Subject: [PATCH 001/265] Adding support for the Device Flow Oauth authentication pattern (#2310) Adding support for the Device Flow Oauth authentication pattern --- .../Clients/IObservableOauthClient.cs | 22 ++++++ .../Clients/ObservableOauthClient.cs | 28 ++++++++ Octokit.Tests/Clients/OauthClientTests.cs | 66 ++++++++++++++++- Octokit/Clients/IOAuthClient.cs | 22 ++++++ Octokit/Clients/OAuthClient.cs | 71 +++++++++++++++++++ Octokit/Helpers/ApiUrls.cs | 9 +++ .../Models/Request/OauthDeviceFlowRequest.cs | 54 ++++++++++++++ .../Request/OauthTokenRequestForDeviceFlow.cs | 55 ++++++++++++++ .../Response/OauthDeviceFlowResponse.cs | 61 ++++++++++++++++ Octokit/Models/Response/OauthToken.cs | 42 ++++++++--- 10 files changed, 418 insertions(+), 12 deletions(-) create mode 100644 Octokit/Models/Request/OauthDeviceFlowRequest.cs create mode 100644 Octokit/Models/Request/OauthTokenRequestForDeviceFlow.cs create mode 100644 Octokit/Models/Response/OauthDeviceFlowResponse.cs diff --git a/Octokit.Reactive/Clients/IObservableOauthClient.cs b/Octokit.Reactive/Clients/IObservableOauthClient.cs index 2afa944c00..88c7a3547d 100644 --- a/Octokit.Reactive/Clients/IObservableOauthClient.cs +++ b/Octokit.Reactive/Clients/IObservableOauthClient.cs @@ -24,5 +24,27 @@ public interface IObservableOauthClient /// /// IObservable CreateAccessToken(OauthTokenRequest request); + + /// + /// Makes a request to initiate the device flow authentication. + /// + /// + /// Returns a user verification code and verification URL that the you will use to prompt the user to authenticate. + /// This request also returns a device verification code that you must use to receive an access token to check the status of user authentication. + /// + /// + /// + IObservable InitiateDeviceFlow(OauthDeviceFlowRequest request); + + /// + /// Makes a request to get an access token using the response from . + /// + /// + /// Will poll the access token endpoint, until the device and user codes expire or the user has successfully authorized the app with a valid user code. + /// + /// The client Id you received from GitHub when you registered the application. + /// The response you received from + /// + IObservable CreateAccessTokenForDeviceFlow(string clientId, OauthDeviceFlowResponse deviceFlowResponse); } } diff --git a/Octokit.Reactive/Clients/ObservableOauthClient.cs b/Octokit.Reactive/Clients/ObservableOauthClient.cs index 62cce34790..fb51cd5c4d 100644 --- a/Octokit.Reactive/Clients/ObservableOauthClient.cs +++ b/Octokit.Reactive/Clients/ObservableOauthClient.cs @@ -40,5 +40,33 @@ public IObservable CreateAccessToken(OauthTokenRequest request) { return _client.Oauth.CreateAccessToken(request).ToObservable(); } + + /// + /// Makes a request to initiate the device flow authentication. + /// + /// + /// Returns a user verification code and verification URL that the you will use to prompt the user to authenticate. + /// This request also returns a device verification code that you must use to receive an access token to check the status of user authentication. + /// + /// + /// + public IObservable InitiateDeviceFlow(OauthDeviceFlowRequest request) + { + return _client.Oauth.InitiateDeviceFlow(request).ToObservable(); + } + + /// + /// Makes a request to get an access token using the response from . + /// + /// + /// Will poll the access token endpoint, until the device and user codes expire or the user has successfully authorized the app with a valid user code. + /// + /// The client Id you received from GitHub when you registered the application. + /// The response you received from + /// + public IObservable CreateAccessTokenForDeviceFlow(string clientId, OauthDeviceFlowResponse deviceFlowResponse) + { + return _client.Oauth.CreateAccessTokenForDeviceFlow(clientId, deviceFlowResponse).ToObservable(); + } } } diff --git a/Octokit.Tests/Clients/OauthClientTests.cs b/Octokit.Tests/Clients/OauthClientTests.cs index b2bf4228ac..a6f5187024 100644 --- a/Octokit.Tests/Clients/OauthClientTests.cs +++ b/Octokit.Tests/Clients/OauthClientTests.cs @@ -65,7 +65,7 @@ public class TheCreateAccessTokenMethod [Fact] public async Task PostsWithCorrectBodyAndContentType() { - var responseToken = new OauthToken(null, null, null); + var responseToken = new OauthToken(null, null, null, null, null, null); var response = Substitute.For>(); response.Body.Returns(responseToken); var connection = Substitute.For(); @@ -99,7 +99,7 @@ public async Task PostsWithCorrectBodyAndContentType() [Fact] public async Task PostsWithCorrectBodyAndContentTypeForGHE() { - var responseToken = new OauthToken(null, null, null); + var responseToken = new OauthToken(null, null, null, null, null, null); var response = Substitute.For>(); response.Body.Returns(responseToken); var connection = Substitute.For(); @@ -130,6 +130,68 @@ public async Task PostsWithCorrectBodyAndContentTypeForGHE() await calledBody.ReadAsStringAsync()); } + [Fact] + public async Task InitiateDeviceFlowPostsWithCorrectBodyAndContentType() + { + var responseToken = new OauthDeviceFlowResponse("devicecode", "usercode", "uri", 10, 5); + var response = Substitute.For>(); + response.Body.Returns(responseToken); + var connection = Substitute.For(); + connection.BaseAddress.Returns(new Uri("https://api.github.com/")); + Uri calledUri = null; + FormUrlEncodedContent calledBody = null; + Uri calledHostAddress = null; + connection.Post( + Arg.Do(uri => calledUri = uri), + Arg.Do(body => calledBody = body as FormUrlEncodedContent), + "application/json", + null, + Arg.Do(uri => calledHostAddress = uri)) + .Returns(_ => Task.FromResult(response)); + var client = new OauthClient(connection); + + var token = await client.InitiateDeviceFlow(new OauthDeviceFlowRequest("clientid")); + + Assert.Same(responseToken, token); + Assert.Equal("login/device/code", calledUri.ToString()); + Assert.NotNull(calledBody); + Assert.Equal("https://github.com/", calledHostAddress.ToString()); + Assert.Equal( + "client_id=clientid", + await calledBody.ReadAsStringAsync()); + } + + [Fact] + public async Task CreateAccessTokenForDeviceFlowPostsWithCorrectBodyAndContentType() + { + var responseToken = new OauthToken(null, null, null, null, null, null); + var response = Substitute.For>(); + response.Body.Returns(responseToken); + var connection = Substitute.For(); + connection.BaseAddress.Returns(new Uri("https://api.github.com/")); + Uri calledUri = null; + FormUrlEncodedContent calledBody = null; + Uri calledHostAddress = null; + connection.Post( + Arg.Do(uri => calledUri = uri), + Arg.Do(body => calledBody = body as FormUrlEncodedContent), + "application/json", + null, + Arg.Do(uri => calledHostAddress = uri)) + .Returns(_ => Task.FromResult(response)); + var client = new OauthClient(connection); + + var token = await client.CreateAccessTokenForDeviceFlow("clientid", new OauthDeviceFlowResponse("devicecode", "usercode", "uri", 10, 5)); + + Assert.Same(responseToken, token); + Assert.Equal("login/oauth/access_token", calledUri.ToString()); + Assert.NotNull(calledBody); + Assert.Equal("https://github.com/", calledHostAddress.ToString()); + Assert.Equal( + "client_id=clientid&device_code=devicecode&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code", + await calledBody.ReadAsStringAsync()); + } + [Fact] public async Task DeserializesOAuthScopeFormat() { diff --git a/Octokit/Clients/IOAuthClient.cs b/Octokit/Clients/IOAuthClient.cs index b0bde0191a..2d8af15299 100644 --- a/Octokit/Clients/IOAuthClient.cs +++ b/Octokit/Clients/IOAuthClient.cs @@ -28,5 +28,27 @@ public interface IOauthClient /// /// Task CreateAccessToken(OauthTokenRequest request); + + /// + /// Makes a request to initiate the device flow authentication. + /// + /// + /// Returns a user verification code and verification URL that the you will use to prompt the user to authenticate. + /// This request also returns a device verification code that you must use to receive an access token to check the status of user authentication. + /// + /// + /// + Task InitiateDeviceFlow(OauthDeviceFlowRequest request); + + /// + /// Makes a request to get an access token using the response from . + /// + /// + /// Will poll the access token endpoint, until the device and user codes expire or the user has successfully authorized the app with a valid user code. + /// + /// The client Id you received from GitHub when you registered the application. + /// The response you received from + /// + Task CreateAccessTokenForDeviceFlow(string clientId, OauthDeviceFlowResponse deviceFlowResponse); } } diff --git a/Octokit/Clients/OAuthClient.cs b/Octokit/Clients/OAuthClient.cs index 655fe00be9..75b477f988 100644 --- a/Octokit/Clients/OAuthClient.cs +++ b/Octokit/Clients/OAuthClient.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Net.Http; using System.Threading.Tasks; @@ -69,5 +70,75 @@ public async Task CreateAccessToken(OauthTokenRequest request) var response = await connection.Post(endPoint, body, "application/json", null, hostAddress).ConfigureAwait(false); return response.Body; } + + /// + /// Makes a request to initiate the device flow authentication. + /// + /// + /// Returns a user verification code and verification URL that the you will use to prompt the user to authenticate. + /// This request also returns a device verification code that you must use to receive an access token to check the status of user authentication. + /// + /// + /// + [ManualRoute("POST", "/login/device/code")] + public async Task InitiateDeviceFlow(OauthDeviceFlowRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + var endPoint = ApiUrls.OauthDeviceCode(); + + var body = new FormUrlEncodedContent(request.ToParametersDictionary()); + + var response = await connection.Post(endPoint, body, "application/json", null, hostAddress).ConfigureAwait(false); + return response.Body; + } + + /// + /// Makes a request to get an access token using the response from . + /// + /// + /// Will poll the access token endpoint, until the device and user codes expire or the user has successfully authorized the app with a valid user code. + /// + /// The client Id you received from GitHub when you registered the application. + /// The response you received from + /// + [ManualRoute("POST", "/login/oauth/access_token")] + public async Task CreateAccessTokenForDeviceFlow(string clientId, OauthDeviceFlowResponse deviceFlowResponse) + { + Ensure.ArgumentNotNullOrEmptyString(clientId, nameof(clientId)); + Ensure.ArgumentNotNull(deviceFlowResponse, nameof(deviceFlowResponse)); + + var endPoint = ApiUrls.OauthAccessToken(); + + int pollingDelay = deviceFlowResponse.Interval; + + while (true) + { + var request = new OauthTokenRequestForDeviceFlow(clientId, deviceFlowResponse.DeviceCode); + var body = new FormUrlEncodedContent(request.ToParametersDictionary()); + var response = await connection.Post(endPoint, body, "application/json", null, hostAddress).ConfigureAwait(false); + + if (response.Body.Error != null) + { + switch (response.Body.Error) + { + case "authorization_pending": + break; + case "slow_down": + pollingDelay += 5; + break; + case "expired_token": + default: + throw new ApiException(string.Format(CultureInfo.InvariantCulture, "{0}: {1}\n{2}", response.Body.Error, response.Body.ErrorDescription, response.Body.ErrorUri), null); + } + + await Task.Delay(TimeSpan.FromSeconds(pollingDelay)); + } + else + { + return response.Body; + } + } + } } } diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 74f0ff3f9c..48b5660ac5 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -2350,6 +2350,15 @@ public static Uri OauthAuthorize() return "login/oauth/authorize".FormatUri(); } + /// + /// Creates the relative for initiating the OAuth device Flow + /// + /// + public static Uri OauthDeviceCode() + { + return "login/device/code".FormatUri(); + } + /// /// Creates the relative to request an OAuth access token. /// diff --git a/Octokit/Models/Request/OauthDeviceFlowRequest.cs b/Octokit/Models/Request/OauthDeviceFlowRequest.cs new file mode 100644 index 0000000000..5e3ba24cbb --- /dev/null +++ b/Octokit/Models/Request/OauthDeviceFlowRequest.cs @@ -0,0 +1,54 @@ +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Globalization; +using Octokit.Internal; + +namespace Octokit +{ + /// + /// Used to create an Oauth device flow initiation request. + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class OauthDeviceFlowRequest + : RequestParameters + { + /// + /// Creates an instance of the OAuth login request with the required parameter. + /// + /// The client Id you received from GitHub when you registered the application. + public OauthDeviceFlowRequest(string clientId) + { + Ensure.ArgumentNotNullOrEmptyString(clientId, nameof(clientId)); + + ClientId = clientId; + Scopes = new Collection(); + } + + /// + /// The client Id you received from GitHub when you registered the application. + /// + [Parameter(Key = "client_id")] + public string ClientId { get; private set; } + + /// + /// A set of scopes to request. If not provided, scope defaults to an empty list of scopes for users that don’t + /// have a valid token for the app. For users who do already have a valid token for the app, the user won't be + /// shown the OAuth authorization page with the list of scopes. Instead, this step of the flow will + /// automatically complete with the same scopes that were used last time the user completed the flow. + /// + /// + /// See the scopes documentation for more + /// information about scopes. + /// + [Parameter(Key = "scope")] + public Collection Scopes { get; private set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "ClientId: {0}, Scopes: {1}", ClientId, Scopes); + } + } + } +} diff --git a/Octokit/Models/Request/OauthTokenRequestForDeviceFlow.cs b/Octokit/Models/Request/OauthTokenRequestForDeviceFlow.cs new file mode 100644 index 0000000000..b53e1406ac --- /dev/null +++ b/Octokit/Models/Request/OauthTokenRequestForDeviceFlow.cs @@ -0,0 +1,55 @@ +using System.Diagnostics; +using System.Globalization; +using Octokit.Internal; + +namespace Octokit +{ + /// + /// Used to create an Oauth login request for the device flow. + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + internal class OauthTokenRequestForDeviceFlow : RequestParameters + { + /// + /// Creates an instance of the OAuth login request with the required parameter. + /// + /// The client Id you received from GitHub when you registered the application. + /// The device code you received from the device flow initiation call. + public OauthTokenRequestForDeviceFlow(string clientId, string deviceCode) + { + Ensure.ArgumentNotNullOrEmptyString(clientId, nameof(clientId)); + Ensure.ArgumentNotNullOrEmptyString(deviceCode, nameof(deviceCode)); + + ClientId = clientId; + DeviceCode = deviceCode; + } + + /// + /// The client Id you received from GitHub when you registered the application. + /// + [Parameter(Key = "client_id")] + public string ClientId { get; private set; } + + /// + /// The device code you received from the device flow initiation call. + /// + [Parameter(Key = "device_code")] + public string DeviceCode { get; private set; } + + /// + /// The authorization grant type. + /// + [Parameter(Key = "grant_type")] + public string GrantType => "urn:ietf:params:oauth:grant-type:device_code"; + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "ClientId: {0}, DeviceCode: {1}", + ClientId, + DeviceCode); + } + } + } +} diff --git a/Octokit/Models/Response/OauthDeviceFlowResponse.cs b/Octokit/Models/Response/OauthDeviceFlowResponse.cs new file mode 100644 index 0000000000..2f3ab0ad94 --- /dev/null +++ b/Octokit/Models/Response/OauthDeviceFlowResponse.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class OauthDeviceFlowResponse + { + public OauthDeviceFlowResponse() { } + + public OauthDeviceFlowResponse(string deviceCode, string userCode, string verificationUri, int expiresIn, int interval) + { + DeviceCode = deviceCode; + UserCode = userCode; + VerificationUri = verificationUri; + ExpiresIn = expiresIn; + Interval = interval; + } + + /// + /// The device verification code is 40 characters and used to verify the device. + /// + public string DeviceCode { get; private set; } + + /// + /// The user verification code is displayed on the device so the user can enter the code in a browser. This code is 8 characters with a hyphen in the middle. + /// + public string UserCode { get; private set; } + + /// + /// The verification URL where users need to enter the UserCode: https://github.com/login/device. + /// + public string VerificationUri { get; private set; } + + /// + /// The number of seconds before the DeviceCode and UserCode expire. The default is 900 seconds or 15 minutes. + /// + public int ExpiresIn { get; private set; } + + /// + /// The minimum number of seconds that must pass before you can make a new access token request (POST https://github.com/login/oauth/access_token) to complete the device authorization. + /// For example, if the interval is 5, then you cannot make a new request until 5 seconds pass. If you make more than one request over 5 seconds, then you will hit the rate limit + /// and receive a slow_down error. + /// + public int Interval { get; private set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "DeviceCode: {0}, UserCode: {1}, VerificationUri: {2}, ExpiresIn: {3}, Interval: {4}", + DeviceCode, + UserCode, + VerificationUri, + ExpiresIn, + Interval); + } + } + } +} diff --git a/Octokit/Models/Response/OauthToken.cs b/Octokit/Models/Response/OauthToken.cs index e61f2b1ea2..b7ecd50b88 100644 --- a/Octokit/Models/Response/OauthToken.cs +++ b/Octokit/Models/Response/OauthToken.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; +using Octokit.Internal; namespace Octokit { @@ -9,36 +10,57 @@ public class OauthToken { public OauthToken() { } - public OauthToken(string tokenType, string accessToken, IReadOnlyList scope) + public OauthToken(string tokenType, string accessToken, IReadOnlyList scope, string error, string errorDescription, string errorUri) { - TokenType = tokenType; - AccessToken = accessToken; - Scope = scope; + this.TokenType = tokenType; + this.AccessToken = accessToken; + this.Scope = scope; + this.Error = error; + this.ErrorDescription = errorDescription; + this.ErrorUri = errorUri; } /// /// The type of OAuth token /// - public string TokenType { get; protected set; } + public string TokenType { get; private set; } /// /// The secret OAuth access token. Use this to authenticate Octokit.net's client. /// - public string AccessToken { get; protected set; } + public string AccessToken { get; private set; } /// /// The list of scopes the token includes. /// - public IReadOnlyList Scope { get; protected set; } + public IReadOnlyList Scope { get; private set; } + + /// + /// Gets or sets the error code or the response. + /// + [Parameter(Key = "error")] + public string Error { get; private set; } + + /// + /// Gets or sets the error description. + /// + [Parameter(Key = "error_description")] + public string ErrorDescription { get; private set; } + + /// + /// Gets or sets the error uri. + /// + [Parameter(Key = "error_uri")] + public string ErrorUri { get; private set; } internal string DebuggerDisplay { get { return string.Format(CultureInfo.InvariantCulture, "TokenType: {0}, AccessToken: {1}, Scopes: {2}", - TokenType, - AccessToken, - Scope); + this.TokenType, + this.AccessToken, + this.Scope); } } } From c4e6fcdbccc9a34e1b5c84e948edc34f2d9990d5 Mon Sep 17 00:00:00 2001 From: Nick Floyd <139819+nickfloyd@users.noreply.github.com> Date: Wed, 27 Apr 2022 14:49:19 -0500 Subject: [PATCH 002/265] Updates the repo docs with the current release workflow (#2438) * updates the repo docs with the current release workflow --- DEPLOYMENT.md | 66 ++- ReleaseNotes.md | 997 ------------------------------------------- docs/contributing.md | 20 +- mkdocs.yml | 2 +- 4 files changed, 72 insertions(+), 1013 deletions(-) delete mode 100644 ReleaseNotes.md diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index bc84029763..1de4dc0525 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -1,19 +1,59 @@ ## Deploying a new release -When we're ready to deploy a new release, we need to do the following steps: +### Requirements + +Creating a new release and deploying the package to nuget are administrative tasks and require that you have/do the following: +1. Admin access to the [GitHub](https://www.nuget.org/profiles/GitHub) NuGet organization +2. Admin rights to the [octokit.net](https://github.com/octokit/octokit.net) repository +3. For any PRs that should be noted in the release notes, each pull request must have a comment formatted like `release_notes: description` where description represents the details of the change. + +### Prepare the changeset & publish to nuget.org 1. Create a branch named `release`. -2. Update [`ReleaseNotes.md`](ReleaseNotes.md). Note that the format is -important as we parse the version out and use that for the NuGet packages. -3. Push the branch to GitHub and create a pull request. This will kick off the -MyGet build of the NuGet package with this new version. - If you're impatient, you can run `.\build CreatePackages` and get the packages locally. -4. Test! -5. When you're satisfied with this release, push the package -[from MyGet](https://www.myget.org/feed/Packages/octokit) to NuGet. -6. Create a tag `git tag v#.#.#`. For example, to create a tag for 1.0.0 +2. Push the branch to GitHub and create a pull request. This will kick off the CI builds to verify the changes. +3. Test! +4. [Generate](https://github.com/shiftkey/octokit.releasenotes) the release notes. `Octokit.ReleaseNotes generate v0.50.0 [BASE] [HEAD]` + Any PRs that should be noted in the release notes, each pull request must have a comment formatted like `release_notes: description` where description represents the details of the change. Make sure for the commit range any changeset in a PR that should be represented has a comment on the PR prefixed with `release_notes:` and corresponding label (details below) +5. When you're satisfied with this release, create a tag `git tag v#.#.#`. For example, to create a tag for 1.0.0 `git tag v1.0.0` -7. Push the tag to the server. `git push --tags` -8. Accept the pull request. +6. Push the tag to the server. `git push --tags` +7. When the tag is successfully pushed, the [publish workflow](https://github.com/octokit/octokit.net/blob/main/.github/workflows/publish.yml) will run and build and push the package to nuget +8. Verify that the package has been uploaded to [nuget.org](https://www.nuget.org/packages/Octokit/) +8. Accept the pull request 9. Create a [new release](https://github.com/octokit/octokit.net/releases/new) -using the tag you just created and pasting in the release notes you just wrote up +using the tag you just created and pasting in the release notes you just generated + +--- + +### Details on the release notes generator + +Release notes [generator](https://github.com/shiftkey/octokit.releasenotes): this is used to pull details using the GitHub API to generate the release notes. + +The generator helps in that it produces release notes that are consistently formatted based on information directly from the change scope (from the previous release to the current tip i.e. the `release` branch). + +The nuances are mostly around how it gets and parses release notes from the PRs found in the changeset. The following are the comment prefixes that the generator currently supports: + +* `release_notes` - Having this in the comment with a corresponding "category" label on the PR will put the given note under the "Release Notes" section of the output in the group for the given label +* `advisories` - Having this in the comment will put the given note into the "Advisories and Breaking Changes" section of the output + +In addition to formatted comment parsing, the generator also looks at the following labels to generate categories with in the release notes. + +* `category: bug` - This will add the comment in the PR prefixed with `release_notes` into the `Fixes` group +* `category: docs-and-samples` - This will add the comment in the PR prefixed with `release_notes` into the `Documentation Updates` group +* `category: feature` - This will add the comment in the PR prefixed with `release_notes` into the `Features/Enhancements` group +* `category: housekeeping` - This will add the comment in the PR prefixed with `release_notes` into the `Housekeeping` group + +When these labels are added to a given PR the generator will produce and categorize comment in the release notes formatted like: + +`Comment content` - `PR Id and link` via `Contributor` +ex. "Cleans up some mentions of `master` branch in codebase - [#2306](https://github.com/octokit/octokit.net/pull/2306) via [@shiftkey](https://github.com/shiftkey)" + +---- +### Troubleshooting + +When running the release notes generator on a mac if dotnet has not been added to the PATH or there is not alias defined in your dotfiles you'll need to execute the command as follows: + +`dotnet run generate [BASE] [HEAD]` +(where `[BASE]` is the last release label (i.e. v0.50.0) and `[HEAD]` represents the `release` branch tip that was generated above) + +The tool looks for a environment variable named `OCTOKIT_OAUTHTOKEN`. This token requires a minimal scope to execute and pull the data from the repository via API. Keep in mind that if a token is not provided then you will most likely run into rate limit errors because the requests are being made anonymously. diff --git a/ReleaseNotes.md b/ReleaseNotes.md deleted file mode 100644 index fbdb2f26b6..0000000000 --- a/ReleaseNotes.md +++ /dev/null @@ -1,997 +0,0 @@ -### New in 0.32.0 (released 09/09/2018) - -## Advisories and Breaking Changes - -- Due to upstream breaking changes in the CheckRuns API, using check runs against github.com will require using the new/renamed fields on `CheckRunAnnotation` response and `NewCheckRunAnnotation` request models. However the old fields are maintained in octokit.net (marked as deprecated) to continue supporting GitHub Enterprise 2.14, which will not receive these changes. Users of GHE 2.14 should use the old fields, whilst users of github.com should update to use the new fields - -## Release Notes - -### Milestone: GitHub Apps - -**Features/Enhancements** - -- Adjust GitHub App Installation Access Token route in line with [announced API changes](https://developer.github.com/changes/2018-08-16-renaming-and-deprecation-of-github-app-installation-access-token-route/) - [#1860](https://github.com/octokit/octokit.net/pull/1860) via [@ryangribble](https://github.com/ryangribble) -- Implement additional endpoints for GitHub Apps to find installations for a given organization, repository or user - [#1854](https://github.com/octokit/octokit.net/pull/1854) via [@StanleyGoldman](https://github.com/StanleyGoldman), [@ryangribble](https://github.com/ryangribble) -- Implement GitHub Apps Installation API to allow listing all repositories a GitHub App Installation or GitHub App authenticated user has access to - [#1854](https://github.com/octokit/octokit.net/pull/1854) via [@StanleyGoldman](https://github.com/StanleyGoldman), [@ryangribble](https://github.com/ryangribble) -- Implement new/changed fields on `CheckRunAnnotation` response and `NewCheckRunAnnotation` request models - replace `Filename` with `Path`, `WarningLevel` with `AnnotationLevel` and add `StartColumn` and `EndColumn` - [#1857](https://github.com/octokit/octokit.net/pull/1857) via [@ryangribble](https://github.com/ryangribble) -- Add new method `CheckSuitesClient.Rerequest()` and mark the old `CheckSuitesClient.Request()` method as deprecated (this will no longer function on github.com but will continue to be supported on GitHub Enterprise 2.14) - [#1857](https://github.com/octokit/octokit.net/pull/1857) via [@ryangribble](https://github.com/ryangribble) - -**Fixes** - -- Adjust `StartedAt` and `Status` fields of `NewCheckRun` and `CheckRunUpdate` requests, to allow `null` values, avoiding resetting these to default values when not specified - [#1852](https://github.com/octokit/octokit.net/pull/1852) via [@Cyberboss](https://github.com/Cyberboss), [@ryangribble](https://github.com/ryangribble) - -**Documentation Updates** - -- Fixed code samples in GitHub Apps sample docs to use the correct sub client property name - [#1853](https://github.com/octokit/octokit.net/pull/1853) via [@d-a-s](https://github.com/d-a-s) - - -### Milestone: None - -**Fixes** - -- `IssueLabelsClient.RemoveFromIssue()` no longer fails with a HTTP 400 "Bad Request" error from the GitHub Api - [#1868](https://github.com/octokit/octokit.net/pull/1868) via [@ryangribble](https://github.com/ryangribble) - - -### New in 0.31.0 (released 21/07/2018) - -## Advisories and Breaking Changes - -- None - -## Release Notes - -### Milestone: GitHub Apps - -**Features/Enhancements** - -- Implemented Check Suites component of [New Checks Api (Public Beta)](https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/) - [#1846](https://github.com/octokit/octokit.net/pull/1846) via [@ryangribble](https://github.com/ryangribble), [@Cyberboss](https://github.com/Cyberboss) -- Implemented Check Runs component of [New Checks Api (Public Beta)](https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/) - [#1847](https://github.com/octokit/octokit.net/pull/1847) via [@ryangribble](https://github.com/ryangribble), [@Cyberboss](https://github.com/Cyberboss) - - -### Milestone: None - -**Features/Enhancements** - -- Add new `EventInfoState` values (`MarkedAsDuplicate`, `UnmarkedAsDuplicate` and `CommentDeleted`) - [#1818](https://github.com/octokit/octokit.net/pull/1818) via [@mirsaeedi](https://github.com/mirsaeedi) -- Add GraphQL NodeId property to all affected response models - [#1806](https://github.com/octokit/octokit.net/pull/1806) via [@ryangribble](https://github.com/ryangribble) -- Implemented [New API parameters for Project Card archiving (Preview)](https://developer.github.com/changes/2018-06-27-project-card-archiving/) including `ProjectCard.Archived`, `ProjectCardUpdate.Archived` and new `ProjectCardRequest` request - [#1842](https://github.com/octokit/octokit.net/pull/1842) via [@ryangribble](https://github.com/ryangribble) -- Implement support for [Archiving repositories](https://developer.github.com/changes/2017-11-08-archiving-repositories/) including adding `Archived` property to `Repository` response model, adding the ability to archive a repository via `UpdateRepository.Archived` request, and filtering repo/issues searches with `SearchRepositoriesRequest.Archived` and `SearchIssuesRequest.Archived` - [#1845](https://github.com/octokit/octokit.net/pull/1845) via [@jguevara](https://github.com/jguevara), [@ryangribble](https://github.com/ryangribble) - -**Fixes** - -- Fix exception in `RepositoriesClient.GetAllLanguages()` when no languages exist - [#1831](https://github.com/octokit/octokit.net/pull/1831) via [@ryangribble](https://github.com/ryangribble) - -**Housekeeping** - -- Remove nuget dependency on `SourceLink.Create.GitHub` package - [#1822](https://github.com/octokit/octokit.net/pull/1822) via [@ryangribble](https://github.com/ryangribble) - -**Documentation Updates** - -- Clarify the rate limit `Reset` field is in UTC - [#1819](https://github.com/octokit/octokit.net/pull/1819) via [@mirsaeedi](https://github.com/mirsaeedi) -- Revise GitHub Apps walkthrough documentation to provide more clarity - [#1824](https://github.com/octokit/octokit.net/pull/1824) via [@ryangribble](https://github.com/ryangribble) - - -### New in 0.30.0 (released 17/06/2018) - -## Advisories and Breaking Changes - -- Note that the `IssuesLabelsClient.RemoveFromIssue()` methods which previously had no return value, will now return an `IReadonlyList