diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 0000000..5cc1e52 --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,24 @@ +name: Build & Test + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 9.0.x + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore + - name: SS14.Labeller.Tests + run: dotnet test SS14.Labeller.Tests/SS14.Labeller.Tests.csproj -v n \ No newline at end of file diff --git a/.gitignore b/.gitignore index add57be..d003cbb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ bin/ obj/ /packages/ riderModule.iml -/_ReSharper.Caches/ \ No newline at end of file +/_ReSharper.Caches/ +/.vs/** diff --git a/README.md b/README.md index f64f0f8..8db4944 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,45 @@ This app requires the `Pull request reviews`, `Pull requests` and `Issues` event The token must have the `Issues` and `Pull requests` scopes enabled for read and write access. +## Testing and debug + +You will need set up proxy for messages from github to your local machine. For that you can use https://smee.io +You can use 'Use the CLI' version of proxy: +1. Install smee cli using npm (if you dont have it - follow those instructions here https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) +``` npm install --global smee-client ``` +2. visit https://smee.io, click 'Start a new channel' and copy link that will be generated on top. +3. In console use smee cli to start proxy forwarding to your local machine```smee -u https://smee.io/{place-you-channel-code-here} -P //webhook``` + +Upon launching it will output line like +``` +Forwarding https://smee.io/5999VPv39Kc69sxj to http://127.0.0.1:3000/webhooks +``` +That means that every message it receives, including +* its payload +* its headers + +will be proxied to http://127.0.0.1:3000/webhooks, so you need to configure your debug launch to use that port. To do that you can set launchSettings.json to following: +``` +{ + "profiles": { + "SS14.Labeller": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:3000" + } + } +} +``` + +Now we need set up repository. Create new repository or use existing one. +1. Go to 'Settings' tab of repository, then to 'Webhooks' (https://github.com/{owner}/{repository}/settings/hooks) +2. click 'Add webhook' option +3. Input url that smee.io gave your on previous step (should look like https://smee.io/5999VPv39Kc69sxj) into Payload URL +4. select content-type ```application/json``` +5. Input secret word into Secret +6. In block 'which events would you like to trigger this webhook' select 'Let me select individual events' and check only event types you need to debug (currently supported are Issue/Pull Request/ Pull Request Review) +7. Set env variables GITHUB_WEBHOOK_SECRET using secret you passed in step 5, and GITHUB_TOKEN using PAT token for interaction (can be created in profile https://github.com/settings/personal-access-tokens) +Now you are all set up to try and create issure/ PR and get some events debugging! \ No newline at end of file diff --git a/SS14.Labeller.Tests/CustomWebApplicationFactory.cs b/SS14.Labeller.Tests/CustomWebApplicationFactory.cs new file mode 100644 index 0000000..8fd7f9a --- /dev/null +++ b/SS14.Labeller.Tests/CustomWebApplicationFactory.cs @@ -0,0 +1,27 @@ +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using NSubstitute; +using SS14.Labeller.GitHubApi; + +namespace SS14.Labeller.Tests; + +[ExcludeFromCodeCoverage] +public class CustomWebApplicationFactory : WebApplicationFactory +{ + public IGitHubApiClient GitHubApiClient { get; private set; } + + /// + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + GitHubApiClient = Substitute.For(); + + base.ConfigureWebHost(builder); + builder.ConfigureServices(sp => + { + sp.Replace(new ServiceDescriptor(typeof(IGitHubApiClient), GitHubApiClient)); + }); + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/IntegrationTests.cs b/SS14.Labeller.Tests/IntegrationTests.cs new file mode 100644 index 0000000..c2c7b83 --- /dev/null +++ b/SS14.Labeller.Tests/IntegrationTests.cs @@ -0,0 +1,327 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using NSubstitute; +using NUnit.Framework; +using SS14.Labeller.Helpers; +using SS14.Labeller.Labels; +using SS14.Labeller.Models; + +namespace SS14.Labeller.Tests; + +[ExcludeFromCodeCoverage] +public class IntegrationTests +{ + private const string HookSecret = "asdasdasdasdasdasdasdadsadad"; + + private CustomWebApplicationFactory _applicationFactory; + + private HttpClient _client; + + [SetUp] + public void Setup() + { + Environment.SetEnvironmentVariable("GITHUB_WEBHOOK_SECRET", HookSecret); + Environment.SetEnvironmentVariable("GITHUB_TOKEN", "DUMMY"); + + + _applicationFactory = new CustomWebApplicationFactory(); + _client = _applicationFactory.CreateClient(); + } + + [Test] + public async Task Ping() + { + var result = await _client.GetAsync("/"); + var content = await result.Content.ReadAsStringAsync(); + Assert.That(content.Contains("nik", StringComparison.InvariantCultureIgnoreCase)); + Assert.That(content.Contains("cat", StringComparison.InvariantCultureIgnoreCase)); + } + + [Test] + public async Task PullRequest() + { + // Arrange + const string fileName = "pull_request.json"; + var requestContent = await CreateRequestContent(fileName, "pull_request"); + + // Act + var result = await _client.PostAsync("/webhook", requestContent); + + // Assert + var respText = await result.Content.ReadAsStringAsync(); + Assert.That( + result.StatusCode, + Is.EqualTo(HttpStatusCode.NoContent), + $"Invalid response status - {result.StatusCode}, response text: \r\n{respText}." + ); + + } + + [Test] + public async Task PullRequestReview_ReviewByNonMaintainer_DoNothing() + { + // Arrange + const string fileName = "pull_request_review_approve.json"; + var requestContent = await CreateRequestContent(fileName, "pull_request_review"); + + _applicationFactory.GitHubApiClient.GetPermission( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + "NonFildrance" + ).Returns(Task.FromResult("user")); + + // Act + var result = await _client.PostAsync("/webhook", requestContent); + + // Assert + var respText = await result.Content.ReadAsStringAsync(); + Assert.That( + result.StatusCode, + Is.EqualTo(HttpStatusCode.NoContent), + $"Invalid response status - {result.StatusCode}, response text: \r\n{respText}." + ); + + _applicationFactory.GitHubApiClient + .DidNotReceive() + .AddLabel( + Arg.Any(), + Arg.Any(), + Arg.Any() + ); + } + + [Test] + public async Task PullRequestReview_ApproveByMaintainer_SwitchStatusLabels() + { + // Arrange + const string fileName = "pull_request_review_approve.json"; + var requestContent = await CreateRequestContent(fileName, "pull_request_review"); + + _applicationFactory.GitHubApiClient.GetPermission( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + "Fildrance" + ).Returns(Task.FromResult("write")); + + // Act + var result = await _client.PostAsync("/webhook", requestContent); + + // Assert + var respText = await result.Content.ReadAsStringAsync(); + Assert.That( + result.StatusCode, + Is.EqualTo(HttpStatusCode.NoContent), + $"Invalid response status - {result.StatusCode}, response text: \r\n{respText}." + ); + + _applicationFactory.GitHubApiClient + .Received() + .AddLabel( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + 4, + StatusLabels.Approved + ); + + _applicationFactory.GitHubApiClient + .Received() + .RemoveLabel( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + 4, + StatusLabels.RequireReview + ); + } + + [Test] + public async Task PullRequestReview_RequestChangesByMaintainer_SwitchStatusLabels() + { + // Arrange + const string fileName = "pull_request_review_request_changes.json"; + var requestContent = await CreateRequestContent(fileName, "pull_request_review"); + + _applicationFactory.GitHubApiClient.GetPermission( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + "Fildrance" + ).Returns(Task.FromResult("write")); + + // Act + var result = await _client.PostAsync("/webhook", requestContent); + + // Assert + var respText = await result.Content.ReadAsStringAsync(); + Assert.That( + result.StatusCode, + Is.EqualTo(HttpStatusCode.NoContent), + $"Invalid response status - {result.StatusCode}, response text: \r\n{respText}." + ); + + _applicationFactory.GitHubApiClient + .Received() + .AddLabel( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + 4, + StatusLabels.AwaitingChanges + ); + + _applicationFactory.GitHubApiClient + .Received() + .RemoveLabel( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + 4, + StatusLabels.RequireReview + ); + } + + [Test] + public async Task PullRequestReview_CommentedMergedByMaintainer_DoNothing() + { + // Arrange + const string fileName = "pull_request_review_approve_merged.json"; + var requestContent = await CreateRequestContent(fileName, "pull_request_review"); + + _applicationFactory.GitHubApiClient.GetPermission( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + "Fildrance" + ).Returns(Task.FromResult("write")); + + // Act + var result = await _client.PostAsync("/webhook", requestContent); + + // Assert + var respText = await result.Content.ReadAsStringAsync(); + Assert.That( + result.StatusCode, + Is.EqualTo(HttpStatusCode.NoContent), + $"Invalid response status - {result.StatusCode}, response text: \r\n{respText}." + ); + + _applicationFactory.GitHubApiClient + .DidNotReceive() + .AddLabel( + Arg.Any(), + Arg.Any(), + Arg.Any() + ); + + _applicationFactory.GitHubApiClient + .DidNotReceive() + .RemoveLabel( + Arg.Any(), + Arg.Any(), + Arg.Any() + ); + } + + [Test] + public async Task PullRequestReview_CommentedByMaintainer_DoNothing() + { + // Arrange + const string fileName = "pull_request_review_commented.json"; + var requestContent = await CreateRequestContent(fileName, "pull_request_review"); + + _applicationFactory.GitHubApiClient.GetPermission( + Arg.Is(x => x.Name == "SS14.Labeller" && x.Owner.Login == "Fildrance"), + "Fildrance" + ).Returns(Task.FromResult("write")); + + // Act + var result = await _client.PostAsync("/webhook", requestContent); + + // Assert + var respText = await result.Content.ReadAsStringAsync(); + Assert.That( + result.StatusCode, + Is.EqualTo(HttpStatusCode.NoContent), + $"Invalid response status - {result.StatusCode}, response text: \r\n{respText}." + ); + + _applicationFactory.GitHubApiClient + .DidNotReceive() + .AddLabel( + Arg.Any(), + Arg.Any(), + Arg.Any() + ); + + _applicationFactory.GitHubApiClient + .DidNotReceive() + .RemoveLabel( + Arg.Any(), + Arg.Any(), + Arg.Any() + ); + } + + [Test] + public async Task Issue_Created_AddedUntriagedLabel() + { + // Arrange + const string fileName = "issue_created.json"; + var requestContent = await CreateRequestContent(fileName, "issues"); + + // Act + var result = await _client.PostAsync("/webhook", requestContent); + + // Assert + var respText = await result.Content.ReadAsStringAsync(); + Assert.That( + result.StatusCode, + Is.EqualTo(HttpStatusCode.NoContent), + $"Invalid response status - {result.StatusCode}, response text: \r\n{respText}." + ); + + _applicationFactory.GitHubApiClient + .Received() + .AddLabel( + Arg.Is(x => x.Name == "Kaizen" && x.Owner.Login == "Fildrance"), + 31, + StatusLabels.Untriaged + ); + } + [Test] + public async Task Issue_Closed_NoLabelsAssigned() + { + // Arrange + const string fileName = "issue_closed.json"; + var requestContent = await CreateRequestContent(fileName, "issues"); + + // Act + var result = await _client.PostAsync("/webhook", requestContent); + + // Assert + var respText = await result.Content.ReadAsStringAsync(); + Assert.That( + result.StatusCode, + Is.EqualTo(HttpStatusCode.NoContent), + $"Invalid response status - {result.StatusCode}, response text: \r\n{respText}." + ); + + _applicationFactory.GitHubApiClient + .DidNotReceive() + .AddLabel( + Arg.Any(), + Arg.Any(), + Arg.Any() + ); + } + + private static async Task CreateRequestContent(string requestFileName, string eventType) + { + var filePath = Path.Combine("Resources", requestFileName); + var text = await File.ReadAllTextAsync(filePath); + var requestContent = new StringContent(text, Encoding.UTF8); + + var msgHash = EncodingHelper.ToHmacSha256(Encoding.UTF8.GetBytes(text), HookSecret); + requestContent.Headers.Add("X-Hub-Signature-256", $"sha256={msgHash}"); + requestContent.Headers.Add("X-GitHub-Event", eventType); + return requestContent; + } + + [TearDown] + public void TearDown() + { + _applicationFactory.Dispose(); + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/Resources/issue_closed.json b/SS14.Labeller.Tests/Resources/issue_closed.json new file mode 100644 index 0000000..3718e10 --- /dev/null +++ b/SS14.Labeller.Tests/Resources/issue_closed.json @@ -0,0 +1,191 @@ +{ + "action": "closed", + "issue": { + "url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31", + "repository_url": "https://api.github.com/repos/Fildrance/Kaizen", + "labels_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/labels{/name}", + "comments_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/comments", + "events_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/events", + "html_url": "https://github.com/Fildrance/Kaizen/issues/31", + "id": 3273588935, + "node_id": "I_kwDOEYelBM7DHwDH", + "number": 31, + "title": "asdasdasda", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-07-29T13:07:20Z", + "updated_at": "2025-07-29T13:07:46Z", + "closed_at": "2025-07-29T13:07:46Z", + "author_association": "OWNER", + "active_lock_reason": null, + "sub_issues_summary": { + "total": 0, + "completed": 0, + "percent_completed": 0 + }, + "body": null, + "reactions": { + "url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/timeline", + "performed_via_github_app": null, + "state_reason": "duplicate" + }, + "repository": { + "id": 294102276, + "node_id": "MDEwOlJlcG9zaXRvcnkyOTQxMDIyNzY=", + "name": "Kaizen", + "full_name": "Fildrance/Kaizen", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/Kaizen", + "description": "Simple tool for forming and keeping track of employees skill development.", + "fork": false, + "url": "https://api.github.com/repos/Fildrance/Kaizen", + "forks_url": "https://api.github.com/repos/Fildrance/Kaizen/forks", + "keys_url": "https://api.github.com/repos/Fildrance/Kaizen/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/Kaizen/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/Kaizen/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/Kaizen/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/Kaizen/events", + "assignees_url": "https://api.github.com/repos/Fildrance/Kaizen/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/Kaizen/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/Kaizen/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/Kaizen/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/Kaizen/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/Kaizen/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/Kaizen/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/Kaizen/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/Kaizen/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/Kaizen/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/Kaizen/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/Kaizen/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/Kaizen/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/Kaizen/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/Kaizen/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/Kaizen/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/Kaizen/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/Kaizen/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/Kaizen/merges", + "archive_url": "https://api.github.com/repos/Fildrance/Kaizen/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/Kaizen/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/Kaizen/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/Kaizen/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/Kaizen/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/Kaizen/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/Kaizen/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/Kaizen/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/Kaizen/deployments", + "created_at": "2020-09-09T12:11:04Z", + "updated_at": "2023-11-30T18:45:58Z", + "pushed_at": "2024-04-10T19:17:31Z", + "git_url": "git://github.com/Fildrance/Kaizen.git", + "ssh_url": "git@github.com:Fildrance/Kaizen.git", + "clone_url": "https://github.com/Fildrance/Kaizen.git", + "svn_url": "https://github.com/Fildrance/Kaizen", + "homepage": null, + "size": 1053, + "stargazers_count": 0, + "watchers_count": 0, + "language": "CSS", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 4, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 4, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/Resources/issue_created.json b/SS14.Labeller.Tests/Resources/issue_created.json new file mode 100644 index 0000000..36aec29 --- /dev/null +++ b/SS14.Labeller.Tests/Resources/issue_created.json @@ -0,0 +1,191 @@ +{ + "action": "opened", + "issue": { + "url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31", + "repository_url": "https://api.github.com/repos/Fildrance/Kaizen", + "labels_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/labels{/name}", + "comments_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/comments", + "events_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/events", + "html_url": "https://github.com/Fildrance/Kaizen/issues/31", + "id": 3273588935, + "node_id": "I_kwDOEYelBM7DHwDH", + "number": 31, + "title": "asdasdasda", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-07-29T13:07:20Z", + "updated_at": "2025-07-29T13:07:20Z", + "closed_at": null, + "author_association": "OWNER", + "active_lock_reason": null, + "sub_issues_summary": { + "total": 0, + "completed": 0, + "percent_completed": 0 + }, + "body": null, + "reactions": { + "url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/31/timeline", + "performed_via_github_app": null, + "state_reason": null + }, + "repository": { + "id": 294102276, + "node_id": "MDEwOlJlcG9zaXRvcnkyOTQxMDIyNzY=", + "name": "Kaizen", + "full_name": "Fildrance/Kaizen", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/Kaizen", + "description": "Simple tool for forming and keeping track of employees skill development.", + "fork": false, + "url": "https://api.github.com/repos/Fildrance/Kaizen", + "forks_url": "https://api.github.com/repos/Fildrance/Kaizen/forks", + "keys_url": "https://api.github.com/repos/Fildrance/Kaizen/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/Kaizen/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/Kaizen/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/Kaizen/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/Kaizen/events", + "assignees_url": "https://api.github.com/repos/Fildrance/Kaizen/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/Kaizen/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/Kaizen/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/Kaizen/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/Kaizen/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/Kaizen/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/Kaizen/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/Kaizen/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/Kaizen/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/Kaizen/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/Kaizen/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/Kaizen/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/Kaizen/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/Kaizen/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/Kaizen/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/Kaizen/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/Kaizen/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/Kaizen/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/Kaizen/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/Kaizen/merges", + "archive_url": "https://api.github.com/repos/Fildrance/Kaizen/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/Kaizen/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/Kaizen/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/Kaizen/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/Kaizen/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/Kaizen/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/Kaizen/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/Kaizen/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/Kaizen/deployments", + "created_at": "2020-09-09T12:11:04Z", + "updated_at": "2023-11-30T18:45:58Z", + "pushed_at": "2024-04-10T19:17:31Z", + "git_url": "git://github.com/Fildrance/Kaizen.git", + "ssh_url": "git@github.com:Fildrance/Kaizen.git", + "clone_url": "https://github.com/Fildrance/Kaizen.git", + "svn_url": "https://github.com/Fildrance/Kaizen", + "homepage": null, + "size": 1053, + "stargazers_count": 0, + "watchers_count": 0, + "language": "CSS", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 5, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 5, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/Resources/pull_request.json b/SS14.Labeller.Tests/Resources/pull_request.json new file mode 100644 index 0000000..9044a80 --- /dev/null +++ b/SS14.Labeller.Tests/Resources/pull_request.json @@ -0,0 +1,497 @@ +{ + "action": "opened", + "number": 4, + "pull_request": { + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "id": 2703279519, + "node_id": "PR_kwDOPUEZkc6hIMWf", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4", + "diff_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.diff", + "patch_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.patch", + "issue_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4", + "number": 4, + "state": "open", + "locked": false, + "title": "Feature/refactor rewrite", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "efgqergv qrvqerqe ", + "created_at": "2025-07-29T08:38:50Z", + "updated_at": "2025-07-29T08:38:50Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": null, + "assignee": null, + "assignees": [], + "requested_reviewers": [], + "requested_teams": [], + "labels": [], + "milestone": null, + "draft": false, + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits", + "review_comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments", + "review_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd", + "head": { + "label": "Fildrance:feature/refactor-rewrite", + "ref": "feature/refactor-rewrite", + "sha": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "base": { + "label": "Fildrance:master", + "ref": "master", + "sha": "1877490be1c89faac9e3e31bca5a22a2c252c9c3", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "_links": { + "self": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" }, + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4" }, + "issue": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4" }, + "comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments" }, + "review_comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments" }, + "review_comment": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}" }, + "commits": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits" }, + "statuses": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd" } + }, + "author_association": "OWNER", + "auto_merge": null, + "active_lock_reason": null, + "merged": false, + "mergeable": null, + "rebaseable": null, + "mergeable_state": "unknown", + "merged_by": null, + "comments": 0, + "review_comments": 0, + "maintainer_can_modify": false, + "commits": 4, + "additions": 714, + "deletions": 335, + "changed_files": 25 + }, + "repository": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/Resources/pull_request_review_approve.json b/SS14.Labeller.Tests/Resources/pull_request_review_approve.json new file mode 100644 index 0000000..f8166c6 --- /dev/null +++ b/SS14.Labeller.Tests/Resources/pull_request_review_approve.json @@ -0,0 +1,520 @@ +{ + "action": "submitted", + "review": { + "id": 3067411540, + "node_id": "PRR_kwDOPUEZkc621PxU", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "asdasdasd", + "commit_id": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "submitted_at": "2025-07-29T12:53:31Z", + "state": "approved", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4#pullrequestreview-3067411540", + "pull_request_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "author_association": "OWNER", + "_links": { + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4#pullrequestreview-3067411540" }, + "pull_request": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" } + } + }, + "pull_request": { + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "id": 2703279519, + "node_id": "PR_kwDOPUEZkc6hIMWf", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4", + "diff_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.diff", + "patch_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.patch", + "issue_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4", + "number": 4, + "state": "open", + "locked": false, + "title": "Feature/refactor rewrite", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "efgqergv qrvqerqe ", + "created_at": "2025-07-29T08:38:50Z", + "updated_at": "2025-07-29T12:53:31Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": "9898a74cc909dbf5608d0118e77ce3bfc2986f63", + "assignee": null, + "assignees": [], + "requested_reviewers": [], + "requested_teams": [], + "labels": [], + "milestone": null, + "draft": false, + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits", + "review_comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments", + "review_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd", + "head": { + "label": "Fildrance:feature/refactor-rewrite", + "ref": "feature/refactor-rewrite", + "sha": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "base": { + "label": "Fildrance:master", + "ref": "master", + "sha": "1877490be1c89faac9e3e31bca5a22a2c252c9c3", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "_links": { + "self": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" }, + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4" }, + "issue": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4" }, + "comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments" }, + "review_comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments" }, + "review_comment": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}" }, + "commits": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits" }, + "statuses": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd" } + }, + "author_association": "OWNER", + "auto_merge": null, + "active_lock_reason": null + }, + "repository": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/Resources/pull_request_review_approve_merged.json b/SS14.Labeller.Tests/Resources/pull_request_review_approve_merged.json new file mode 100644 index 0000000..9b3b5ff --- /dev/null +++ b/SS14.Labeller.Tests/Resources/pull_request_review_approve_merged.json @@ -0,0 +1,520 @@ +{ + "action": "submitted", + "review": { + "id": 3067411540, + "node_id": "PRR_kwDOPUEZkc621PxU", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "asdasdasd", + "commit_id": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "submitted_at": "2025-07-29T12:53:31Z", + "state": "approved", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4#pullrequestreview-3067411540", + "pull_request_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "author_association": "OWNER", + "_links": { + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4#pullrequestreview-3067411540" }, + "pull_request": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" } + } + }, + "pull_request": { + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "id": 2703279519, + "node_id": "PR_kwDOPUEZkc6hIMWf", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4", + "diff_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.diff", + "patch_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.patch", + "issue_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4", + "number": 4, + "state": "open", + "locked": false, + "title": "Feature/refactor rewrite", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "efgqergv qrvqerqe ", + "created_at": "2025-07-29T08:38:50Z", + "updated_at": "2025-07-29T12:53:31Z", + "closed_at": null, + "merged_at": "2025-07-29T12:53:31Z", + "merge_commit_sha": "9898a74cc909dbf5608d0118e77ce3bfc2986f63", + "assignee": null, + "assignees": [], + "requested_reviewers": [], + "requested_teams": [], + "labels": [], + "milestone": null, + "draft": false, + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits", + "review_comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments", + "review_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd", + "head": { + "label": "Fildrance:feature/refactor-rewrite", + "ref": "feature/refactor-rewrite", + "sha": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "base": { + "label": "Fildrance:master", + "ref": "master", + "sha": "1877490be1c89faac9e3e31bca5a22a2c252c9c3", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "_links": { + "self": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" }, + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4" }, + "issue": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4" }, + "comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments" }, + "review_comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments" }, + "review_comment": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}" }, + "commits": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits" }, + "statuses": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd" } + }, + "author_association": "OWNER", + "auto_merge": null, + "active_lock_reason": null + }, + "repository": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/Resources/pull_request_review_commented.json b/SS14.Labeller.Tests/Resources/pull_request_review_commented.json new file mode 100644 index 0000000..3e48c8b --- /dev/null +++ b/SS14.Labeller.Tests/Resources/pull_request_review_commented.json @@ -0,0 +1,520 @@ +{ + "action": "submitted", + "review": { + "id": 3067411540, + "node_id": "PRR_kwDOPUEZkc621PxU", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "asdasdasd", + "commit_id": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "submitted_at": "2025-07-29T12:53:31Z", + "state": "commented", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4#pullrequestreview-3067411540", + "pull_request_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "author_association": "OWNER", + "_links": { + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4#pullrequestreview-3067411540" }, + "pull_request": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" } + } + }, + "pull_request": { + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "id": 2703279519, + "node_id": "PR_kwDOPUEZkc6hIMWf", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4", + "diff_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.diff", + "patch_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.patch", + "issue_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4", + "number": 4, + "state": "open", + "locked": false, + "title": "Feature/refactor rewrite", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "efgqergv qrvqerqe ", + "created_at": "2025-07-29T08:38:50Z", + "updated_at": "2025-07-29T12:53:31Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": "9898a74cc909dbf5608d0118e77ce3bfc2986f63", + "assignee": null, + "assignees": [], + "requested_reviewers": [], + "requested_teams": [], + "labels": [], + "milestone": null, + "draft": false, + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits", + "review_comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments", + "review_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd", + "head": { + "label": "Fildrance:feature/refactor-rewrite", + "ref": "feature/refactor-rewrite", + "sha": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "base": { + "label": "Fildrance:master", + "ref": "master", + "sha": "1877490be1c89faac9e3e31bca5a22a2c252c9c3", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "_links": { + "self": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" }, + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4" }, + "issue": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4" }, + "comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments" }, + "review_comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments" }, + "review_comment": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}" }, + "commits": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits" }, + "statuses": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd" } + }, + "author_association": "OWNER", + "auto_merge": null, + "active_lock_reason": null + }, + "repository": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/Resources/pull_request_review_request_changes.json b/SS14.Labeller.Tests/Resources/pull_request_review_request_changes.json new file mode 100644 index 0000000..0ca397d --- /dev/null +++ b/SS14.Labeller.Tests/Resources/pull_request_review_request_changes.json @@ -0,0 +1,520 @@ +{ + "action": "submitted", + "review": { + "id": 3067411540, + "node_id": "PRR_kwDOPUEZkc621PxU", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "asdasdasd", + "commit_id": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "submitted_at": "2025-07-29T12:53:31Z", + "state": "changes_requested", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4#pullrequestreview-3067411540", + "pull_request_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "author_association": "OWNER", + "_links": { + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4#pullrequestreview-3067411540" }, + "pull_request": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" } + } + }, + "pull_request": { + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4", + "id": 2703279519, + "node_id": "PR_kwDOPUEZkc6hIMWf", + "html_url": "https://github.com/Fildrance/SS14.Labeller/pull/4", + "diff_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.diff", + "patch_url": "https://github.com/Fildrance/SS14.Labeller/pull/4.patch", + "issue_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4", + "number": 4, + "state": "open", + "locked": false, + "title": "Feature/refactor rewrite", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "body": "efgqergv qrvqerqe ", + "created_at": "2025-07-29T08:38:50Z", + "updated_at": "2025-07-29T12:53:31Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": "9898a74cc909dbf5608d0118e77ce3bfc2986f63", + "assignee": null, + "assignees": [], + "requested_reviewers": [], + "requested_teams": [], + "labels": [], + "milestone": null, + "draft": false, + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits", + "review_comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments", + "review_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd", + "head": { + "label": "Fildrance:feature/refactor-rewrite", + "ref": "feature/refactor-rewrite", + "sha": "a4570c5ff15453dda13f4cdddd972aa865116efd", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "base": { + "label": "Fildrance:master", + "ref": "master", + "sha": "1877490be1c89faac9e3e31bca5a22a2c252c9c3", + "user": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "repo": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "_links": { + "self": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4" }, + "html": { "href": "https://github.com/Fildrance/SS14.Labeller/pull/4" }, + "issue": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4" }, + "comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/4/comments" }, + "review_comments": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/comments" }, + "review_comment": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/comments{/number}" }, + "commits": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls/4/commits" }, + "statuses": { "href": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/a4570c5ff15453dda13f4cdddd972aa865116efd" } + }, + "author_association": "OWNER", + "auto_merge": null, + "active_lock_reason": null + }, + "repository": { + "id": 1027676561, + "node_id": "R_kgDOPUEZkQ", + "name": "SS14.Labeller", + "full_name": "Fildrance/SS14.Labeller", + "private": false, + "owner": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/Fildrance/SS14.Labeller", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/Fildrance/SS14.Labeller", + "forks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/forks", + "keys_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/teams", + "hooks_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/hooks", + "issue_events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/events{/number}", + "events_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/events", + "assignees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/assignees{/user}", + "branches_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/branches{/branch}", + "tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/tags", + "blobs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/languages", + "stargazers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/stargazers", + "contributors_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contributors", + "subscribers_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscribers", + "subscription_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/subscription", + "commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/contents/{+path}", + "compare_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/merges", + "archive_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/downloads", + "issues_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/issues{/number}", + "pulls_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/labels{/name}", + "releases_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/releases{/id}", + "deployments_url": "https://api.github.com/repos/Fildrance/SS14.Labeller/deployments", + "created_at": "2025-07-28T11:15:00Z", + "updated_at": "2025-07-28T11:15:00Z", + "pushed_at": "2025-07-28T20:57:09Z", + "git_url": "git://github.com/Fildrance/SS14.Labeller.git", + "ssh_url": "git@github.com:Fildrance/SS14.Labeller.git", + "clone_url": "https://github.com/Fildrance/SS14.Labeller.git", + "svn_url": "https://github.com/Fildrance/SS14.Labeller", + "homepage": null, + "size": 38, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Fildrance", + "id": 14752842, + "node_id": "MDQ6VXNlcjE0NzUyODQy", + "avatar_url": "https://avatars.githubusercontent.com/u/14752842?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Fildrance", + "html_url": "https://github.com/Fildrance", + "followers_url": "https://api.github.com/users/Fildrance/followers", + "following_url": "https://api.github.com/users/Fildrance/following{/other_user}", + "gists_url": "https://api.github.com/users/Fildrance/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Fildrance/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Fildrance/subscriptions", + "organizations_url": "https://api.github.com/users/Fildrance/orgs", + "repos_url": "https://api.github.com/users/Fildrance/repos", + "events_url": "https://api.github.com/users/Fildrance/events{/privacy}", + "received_events_url": "https://api.github.com/users/Fildrance/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } +} \ No newline at end of file diff --git a/SS14.Labeller.Tests/SS14.Labeller.Tests.csproj b/SS14.Labeller.Tests/SS14.Labeller.Tests.csproj new file mode 100644 index 0000000..525e30f --- /dev/null +++ b/SS14.Labeller.Tests/SS14.Labeller.Tests.csproj @@ -0,0 +1,28 @@ + + + + net9.0 + enable + false + + + + + + + + + + + + + + + + + + Always + + + + \ No newline at end of file diff --git a/SS14.Labeller.sln b/SS14.Labeller.sln index b2afdd8..736dd99 100644 --- a/SS14.Labeller.sln +++ b/SS14.Labeller.sln @@ -1,7 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35818.85 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SS14.Labeller", "SS14.Labeller\SS14.Labeller.csproj", "{23A01977-7FE4-491F-BBE8-E8C412D8D753}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SS14.Labeller.Tests", "SS14.Labeller.Tests\SS14.Labeller.Tests.csproj", "{E6AD98D5-0330-4056-9042-B8DB3F569B38}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +22,15 @@ Global {23A01977-7FE4-491F-BBE8-E8C412D8D753}.Debug|Any CPU.Build.0 = Debug|Any CPU {23A01977-7FE4-491F-BBE8-E8C412D8D753}.Release|Any CPU.ActiveCfg = Release|Any CPU {23A01977-7FE4-491F-BBE8-E8C412D8D753}.Release|Any CPU.Build.0 = Release|Any CPU + {E6AD98D5-0330-4056-9042-B8DB3F569B38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6AD98D5-0330-4056-9042-B8DB3F569B38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E6AD98D5-0330-4056-9042-B8DB3F569B38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6AD98D5-0330-4056-9042-B8DB3F569B38}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A157FDD9-57C3-4411-8594-7999E99B124B} EndGlobalSection EndGlobal diff --git a/SS14.Labeller/GitHubApi/GitHubApiClient.cs b/SS14.Labeller/GitHubApi/GitHubApiClient.cs new file mode 100644 index 0000000..ca0eb39 --- /dev/null +++ b/SS14.Labeller/GitHubApi/GitHubApiClient.cs @@ -0,0 +1,67 @@ +using System.Text.Json; +using System.Text; +using SS14.Labeller.Models; + +namespace SS14.Labeller.GitHubApi; + +public class GitHubApiClient(HttpClient httpClient) : IGitHubApiClient +{ + private const string BaseUrl = "https://api.github.com"; + + public async Task AddLabel(Repository repo, int number, string label) + { + var request = new AddLabelRequest { labels = [label] }; + var json = JsonSerializer.Serialize(request, SourceGenerationContext.Default.AddLabelRequest); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + await httpClient.PostAsync($"{BaseUrl}/repos/{repo.Owner.Login}/{repo.Name}/issues/{number}/labels", content); + } + + public async Task RemoveLabel(Repository repo, int number, string label) + { + await httpClient.DeleteAsync($"{BaseUrl}/repos/{repo.Owner.Login}/{repo.Name}/issues/{number}/labels/{Uri.EscapeDataString(label)}"); + } + + public async Task> GetChangedFiles(Repository repo, int prNumber) + { + // TODO: Ratelimit? Might explode on big PRs??? + + var files = new List(); + var page = 1; + while (true) + { + var res = await httpClient.GetAsync($"{BaseUrl}/repos/{repo.Owner.Login}/{repo.Name}/pulls/{prNumber}/files?per_page=100&page={page}"); + if (!res.IsSuccessStatusCode) + break; // TODO: Logging? + + var content = await res.Content.ReadAsStringAsync(); + var json = JsonDocument.Parse(content); + var batch = json.RootElement.EnumerateArray().Select(f => f.GetProperty("filename").GetString()!).ToList(); + if (batch.Count == 0) break; + + files.AddRange(batch); + if (batch.Count < 100) break; + + page++; + } + return files; + } + + /// + public async Task GetPermission(Repository repo, string? user) + { + var permRes = await httpClient.GetAsync($"{BaseUrl}/repos/{repo.Owner.Login}/{repo.Name}/collaborators/{user}/permission"); + if (!permRes.IsSuccessStatusCode) + { + throw new Exception("Failed to get permissions! Does the github token have enough access?"); + } + var permJson = JsonDocument.Parse(await permRes.Content.ReadAsStringAsync()); + return permJson.RootElement.GetProperty("permission").GetString(); + } +} + +public class AddLabelRequest +{ + // ReSharper disable once InconsistentNaming + public string[] labels { get; set; } = []; +} \ No newline at end of file diff --git a/SS14.Labeller/GitHubApi/IGitHubApiClient.cs b/SS14.Labeller/GitHubApi/IGitHubApiClient.cs new file mode 100644 index 0000000..706d243 --- /dev/null +++ b/SS14.Labeller/GitHubApi/IGitHubApiClient.cs @@ -0,0 +1,11 @@ +using SS14.Labeller.Models; + +namespace SS14.Labeller.GitHubApi; + +public interface IGitHubApiClient +{ + Task AddLabel(Repository repo, int number, string label); + Task RemoveLabel(Repository repo, int number, string label); + Task> GetChangedFiles(Repository repo, int prNumber); + Task GetPermission(Repository repo, string? user); +} \ No newline at end of file diff --git a/SS14.Labeller/Handlers/LabelIssueHandler.cs b/SS14.Labeller/Handlers/LabelIssueHandler.cs new file mode 100644 index 0000000..092f6e3 --- /dev/null +++ b/SS14.Labeller/Handlers/LabelIssueHandler.cs @@ -0,0 +1,25 @@ +using SS14.Labeller.GitHubApi; +using SS14.Labeller.Labels; +using SS14.Labeller.Models; + +namespace SS14.Labeller.Handlers; + +public class LabelIssueHandler(IGitHubApiClient client) : RequestHandlerBase +{ + /// + public override string EventType => "issues"; + + /// + protected override async Task HandleInternal(IssuesEvent request, CancellationToken ct) + { + var action = request.Action; + if (action == "opened") + { + var number = request.Issue.Number; + var labels = request.Issue.Labels; + + if (labels.Length == 0) + await client.AddLabel(request.Repository, number, StatusLabels.Untriaged); + } + } +} \ No newline at end of file diff --git a/SS14.Labeller/Handlers/LabelPullRequestHandler.cs b/SS14.Labeller/Handlers/LabelPullRequestHandler.cs new file mode 100644 index 0000000..55b06df --- /dev/null +++ b/SS14.Labeller/Handlers/LabelPullRequestHandler.cs @@ -0,0 +1,102 @@ +using Microsoft.Extensions.FileSystemGlobbing; +using SS14.Labeller.GitHubApi; +using SS14.Labeller.Labels; +using SS14.Labeller.Models; + +namespace SS14.Labeller.Handlers; + +public class LabelPullRequestHandler(IGitHubApiClient client) : RequestHandlerBase +{ + /// + public override string EventType => "pull_request"; + + /// + protected override async Task HandleInternal(PullRequestEvent request, CancellationToken ct) + { + // I null-supress the shit out of these because i assume the github webhook json will basically never update and will always return valid data + + var pr = request.PullRequest; + + var number = pr.Number; + var labels = pr.Labels + .Select(x => x.Name) + .ToArray(); + + // basic labels + var repository = request.Repository; + + if (request.Action == "opened") + { + if (labels.Length == 0) + await client.AddLabel(repository, number, StatusLabels.Untriaged); + + var targetBranch = pr.Base.Ref; + if (targetBranch == "stable" && !labels.Contains(BranchLabels.Stable)) + await client.AddLabel(repository, number, BranchLabels.Stable); + else if (targetBranch == "staging" && !labels.Contains(BranchLabels.Staging)) + await client.AddLabel(repository, number, BranchLabels.Staging); + + var permission = await client.GetPermission(repository, pr.User.Login); + if (permission is "write" or "admin") + await client.AddLabel(repository, number, StatusLabels.Approved); + else if (!labels.Contains(StatusLabels.RequireReview)) + await client.AddLabel(repository, number, StatusLabels.RequireReview); + } + + if (request.Action is "synchronize" or "opened") + { + var totalDiff = pr.Additions + pr.Deletions; + + // remove the existing size/* labels + foreach (var label in labels) + { + if (label?.StartsWith(SizeLabels.Prefix, StringComparison.OrdinalIgnoreCase) == true) + { + await client.RemoveLabel(repository, number, label); + } + } + + var sizeLabel = SizeLabels.TryGetLabelFor(totalDiff); + if (sizeLabel is not null && !labels.Contains(sizeLabel)) + { + await client.AddLabel(repository, number, sizeLabel); + } + } + + var changedFiles = await client.GetChangedFiles(repository, number); + + var matcher = new Matcher(); + matcher.AddInclude("**/*.rsi/*.png"); // Sprites + matcher.AddInclude("Resources/Maps/**/*.yml"); // Map + matcher.AddInclude("Resources/Prototypes/Maps/**/*.yml"); + matcher.AddInclude("**/*.xaml*"); // UI + matcher.AddInclude("**/*.swsl"); // Shaders + matcher.AddInclude("**/*.ogg"); // Audio + + var sprites = new Matcher().AddInclude("**/*.rsi/*.png"); + var maps = new Matcher().AddInclude("Resources/Maps/**/*.yml") + .AddInclude("Resources/Prototypes/Maps/**/*.yml"); + var ui = new Matcher().AddInclude("**/*.xaml*"); + var shaders = new Matcher().AddInclude("**/*.swsl"); + var audio = new Matcher().AddInclude("**/*.ogg"); + var cs = new Matcher().AddInclude("**/*.cs"); + + if (sprites.Match(changedFiles).HasMatches) + await client.AddLabel(repository, number, ChangesLabels.Sprites); + + if (maps.Match(changedFiles).HasMatches) + await client.AddLabel(repository, number, ChangesLabels.Map); + + if (ui.Match(changedFiles).HasMatches) + await client.AddLabel(repository, number, ChangesLabels.Ui); + + if (shaders.Match(changedFiles).HasMatches) + await client.AddLabel(repository, number, ChangesLabels.Shaders); + + if (audio.Match(changedFiles).HasMatches) + await client.AddLabel(repository, number, ChangesLabels.Audio); + + if (!cs.Match(changedFiles).HasMatches) + await client.AddLabel(repository, number, ChangesLabels.NoCSharp); + } +} \ No newline at end of file diff --git a/SS14.Labeller/Handlers/LabelPullRequestReviewHandler.cs b/SS14.Labeller/Handlers/LabelPullRequestReviewHandler.cs new file mode 100644 index 0000000..efb92cf --- /dev/null +++ b/SS14.Labeller/Handlers/LabelPullRequestReviewHandler.cs @@ -0,0 +1,47 @@ +using SS14.Labeller.GitHubApi; +using SS14.Labeller.Labels; +using SS14.Labeller.Models; + +namespace SS14.Labeller.Handlers; + +public class LabelPullRequestReviewHandler(IGitHubApiClient client) + : RequestHandlerBase +{ + /// + public override string EventType => "pull_request_review"; + + /// + protected override async Task HandleInternal(PullRequestReviewEvent request, CancellationToken ct) + { + var pr = request.PullRequest; + var repo = request.Repository; + var user = request.Review.User.Login; + + // only process if the review state is "approved" or "changes_requested" (ignore comments and other states) + var state = request.Review.State; + if (state != "approved" && state != "changes_requested") + return; + + // Ignore reviews if PR is closed or merged + // "closed" means closed or merged, but let's also check for merged explicitly if available + bool isClosed = request.Review.State == "closed"; + bool isMerged = pr.MergedAt != null; + if (isClosed || isMerged) + return; + + var number = pr.Number; + var permission = await client.GetPermission(repo, user); + if (permission is "write" or "admin") + { + await client.RemoveLabel(repo, number, StatusLabels.RequireReview); + + await (state switch + { + "approved" + => client.AddLabel(repo, number, StatusLabels.Approved), + "changes_requested" + => client.AddLabel(repo, number, StatusLabels.AwaitingChanges) + }); + } + } +} \ No newline at end of file diff --git a/SS14.Labeller/Handlers/RequestHandlerBase.cs b/SS14.Labeller/Handlers/RequestHandlerBase.cs new file mode 100644 index 0000000..80f5e2a --- /dev/null +++ b/SS14.Labeller/Handlers/RequestHandlerBase.cs @@ -0,0 +1,35 @@ +using SS14.Labeller.Models; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; + +namespace SS14.Labeller.Handlers; + +public abstract class RequestHandlerBase +{ + + + public abstract string EventType { get; } + + public abstract Task Handle(byte[] bodyBytes, CancellationToken ct); +} + +public abstract class RequestHandlerBase : RequestHandlerBase where T : EventBase +{ + /// + public override Task Handle(byte[] bodyBytes, CancellationToken ct) + { + var bodyString = Encoding.UTF8.GetString(bodyBytes); + + var deserialized = (T?)JsonSerializer.Deserialize(bodyString, typeof(T), SourceGenerationContext.DeserializationContext); + if (deserialized == null) + { + throw new InvalidOperationException($"Failed to parse request into {typeof(T).Name} according with event type {EventType}."); + } + + return HandleInternal(deserialized, ct); + + } + + protected abstract Task HandleInternal(T request, CancellationToken ct); +} \ No newline at end of file diff --git a/SS14.Labeller/Helpers/EncodingHelper.cs b/SS14.Labeller/Helpers/EncodingHelper.cs new file mode 100644 index 0000000..f442dde --- /dev/null +++ b/SS14.Labeller/Helpers/EncodingHelper.cs @@ -0,0 +1,15 @@ +using System.Security.Cryptography; +using System.Text; + +namespace SS14.Labeller.Helpers; + +public static class EncodingHelper +{ + public static string ToHmacSha256(byte[] data, string secret) + { + var key = Encoding.UTF8.GetBytes(secret); + using var hmac = new HMACSHA256(key); + var hashBytes = hmac.ComputeHash(data); + return Convert.ToHexString(hashBytes).ToLowerInvariant(); + } +} \ No newline at end of file diff --git a/SS14.Labeller/Helpers/SecurityHelper.cs b/SS14.Labeller/Helpers/SecurityHelper.cs new file mode 100644 index 0000000..9618cf8 --- /dev/null +++ b/SS14.Labeller/Helpers/SecurityHelper.cs @@ -0,0 +1,32 @@ +using System.Diagnostics.CodeAnalysis; +using System.Security.Cryptography; +using System.Text; + +namespace SS14.Labeller.Helpers; + +public static class SecurityHelper +{ + public static bool IsRequestAuthorized( + byte[] body, + string gitHubSecret, + IHeaderDictionary headerDictionary, + [NotNullWhen(false)] out IResult? unauthorized + ) + { + unauthorized = null; + if (!headerDictionary.TryGetValue("X-Hub-Signature-256", out var signatureHeader)) + { + unauthorized = Results.BadRequest("Missing signature header."); + return false; + } + + var expectedSignature = "sha256=" + EncodingHelper.ToHmacSha256(body, gitHubSecret); + if (!CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(expectedSignature), Encoding.UTF8.GetBytes(signatureHeader!))) + { + unauthorized = Results.Unauthorized(); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/SS14.Labeller/Labels/BranchLabels.cs b/SS14.Labeller/Labels/BranchLabels.cs new file mode 100644 index 0000000..5ec270b --- /dev/null +++ b/SS14.Labeller/Labels/BranchLabels.cs @@ -0,0 +1,9 @@ +namespace SS14.Labeller.Labels; + +public static class BranchLabels +{ + const string Prefix = "Branch: "; + + public const string Stable = Prefix + "Stable"; + public const string Staging = Prefix + "Staging"; +} \ No newline at end of file diff --git a/SS14.Labeller/Labels/ChangesLabels.cs b/SS14.Labeller/Labels/ChangesLabels.cs new file mode 100644 index 0000000..ce495cc --- /dev/null +++ b/SS14.Labeller/Labels/ChangesLabels.cs @@ -0,0 +1,13 @@ +namespace SS14.Labeller.Labels; + +public static class ChangesLabels +{ + const string Prefix = "Changes: "; + + public const string Audio = Prefix + "Audio"; + public const string Map = Prefix + "Map"; + public const string NoCSharp = Prefix + "No C#"; + public const string Shaders = Prefix + "Shaders"; + public const string Sprites = Prefix + "Sprites"; + public const string Ui = Prefix + "UI"; +} \ No newline at end of file diff --git a/SS14.Labeller/Labels/SizeLabels.cs b/SS14.Labeller/Labels/SizeLabels.cs new file mode 100644 index 0000000..73ded10 --- /dev/null +++ b/SS14.Labeller/Labels/SizeLabels.cs @@ -0,0 +1,31 @@ +namespace SS14.Labeller.Labels; + +public static class SizeLabels +{ + public const string Prefix = "size/"; + + static IReadOnlyDictionary sizes = new Dictionary() + { + { 0, Prefix + "XS" }, + { 10, Prefix + "S" }, + { 100, Prefix + "M" }, + { 1000, Prefix + "L" }, + { 5000, Prefix + "XL" }, + }; + + public static string? TryGetLabelFor(int totalDiff) + { + string? sizeLabel = null; + // ReSharper disable once LoopCanBeConvertedToQuery no fuck you, the resulting LINQ query is unreadable + foreach (var kvp in sizes.OrderByDescending(k => k.Key)) + { + if (totalDiff < kvp.Key) + continue; + + sizeLabel = kvp.Value; + break; + } + + return sizeLabel; + } +} \ No newline at end of file diff --git a/SS14.Labeller/Labels/StatusLabels.cs b/SS14.Labeller/Labels/StatusLabels.cs new file mode 100644 index 0000000..e322ad1 --- /dev/null +++ b/SS14.Labeller/Labels/StatusLabels.cs @@ -0,0 +1,11 @@ +namespace SS14.Labeller.Labels; + +public static class StatusLabels +{ + const string Prefix = "S: "; + + public const string Untriaged = Prefix + "Untriaged"; + public const string RequireReview = Prefix + "Needs Review"; // no idea why its called this + public const string AwaitingChanges = Prefix + "Awaiting Changes"; + public const string Approved = Prefix + "Approved"; +} \ No newline at end of file diff --git a/SS14.Labeller/Models/EventBase.cs b/SS14.Labeller/Models/EventBase.cs new file mode 100644 index 0000000..646f4d9 --- /dev/null +++ b/SS14.Labeller/Models/EventBase.cs @@ -0,0 +1,25 @@ +namespace SS14.Labeller.Models; + +public abstract class EventBase +{ + public required string Action { get; init; } + + public required Repository Repository { get; init; } +} + +public class Repository +{ + public required User Owner { get; init; } + + public required string Name { get; set; } +} + +public class User +{ + public required string Login { get; set; } +} + +public class Label +{ + public string? Name { get; set; } +} \ No newline at end of file diff --git a/SS14.Labeller/Models/IssuesEvent.cs b/SS14.Labeller/Models/IssuesEvent.cs new file mode 100644 index 0000000..7095701 --- /dev/null +++ b/SS14.Labeller/Models/IssuesEvent.cs @@ -0,0 +1,13 @@ +namespace SS14.Labeller.Models; + +public class IssuesEvent : EventBase +{ + public required Issue Issue { get; init; } +} + +public sealed record Issue +{ + public int Number { get; set; } + + public Label[] Labels { get; init; } = null!; +} diff --git a/SS14.Labeller/Models/PullRequestEvent.cs b/SS14.Labeller/Models/PullRequestEvent.cs new file mode 100644 index 0000000..390fb81 --- /dev/null +++ b/SS14.Labeller/Models/PullRequestEvent.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; + +namespace SS14.Labeller.Models; + +public class PullRequestEvent : EventBase +{ + [JsonPropertyName("pull_request")] + public required PullRequest PullRequest { get; set; } +} + +public class PullRequest +{ + public int Number { get; set; } + public required Label[] Labels { get; set; } + public required User User { get; set; } + public required BranchInfo Base { get; set; } + public int Additions { get; set; } + public int Deletions { get; set; } + [JsonPropertyName("merged_at")] + public string? MergedAt { get; set; } +} + +public class BranchInfo +{ + public required string Ref { get; set; } + +} \ No newline at end of file diff --git a/SS14.Labeller/Models/PullRequestReviewEvent.cs b/SS14.Labeller/Models/PullRequestReviewEvent.cs new file mode 100644 index 0000000..8689d6b --- /dev/null +++ b/SS14.Labeller/Models/PullRequestReviewEvent.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; + +namespace SS14.Labeller.Models; + +public class PullRequestReviewEvent : EventBase +{ + [JsonPropertyName("pull_request")] + public required PullRequest PullRequest { get; set; } + + public required Review Review { get; set; } +} + +public class Review +{ + public required User User { get; set; } + public required string State { get; set; } +} \ No newline at end of file diff --git a/SS14.Labeller/Program.cs b/SS14.Labeller/Program.cs index fea7436..f681866 100644 --- a/SS14.Labeller/Program.cs +++ b/SS14.Labeller/Program.cs @@ -1,350 +1,95 @@ using System.Net.Http.Headers; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; -using Microsoft.Extensions.FileSystemGlobbing; +using Microsoft.AspNetCore.Mvc; +using SS14.Labeller; +using SS14.Labeller.GitHubApi; +using SS14.Labeller.Handlers; +using SS14.Labeller.Helpers; -const string githubApiBase = "https://api.github.com"; - -const string labelStatusPrefix = "S: "; -const string labelStatusUntriaged = labelStatusPrefix + "Untriaged"; -const string labelStatusRequireReview = labelStatusPrefix + "Needs Review"; // no idea why its called this -const string labelStatusAwaitingChanges = labelStatusPrefix + "Awaiting Changes"; -const string labelStatusApproved = labelStatusPrefix + "Approved"; - -const string labelBranchPrefix = "Branch: "; -const string labelBranchStable = labelBranchPrefix + "Stable"; -const string labelBranchStaging = labelBranchPrefix + "Staging"; - -const string labelChangesPrefix = "Changes: "; -const string labelChangesAudio = labelChangesPrefix + "Audio"; -const string labelChangesMap = labelChangesPrefix + "Map"; -const string labelChangesNoCSharp = labelChangesPrefix + "No C#"; -const string labelChangesShaders = labelChangesPrefix + "Shaders"; -const string labelChangesSprites = labelChangesPrefix + "Sprites"; -const string labelChangesUi = labelChangesPrefix + "UI"; - -const string labelSizePrefix = "size/"; -var sizes = new Dictionary() -{ - { 0, labelSizePrefix + "XS" }, - { 10, labelSizePrefix + "S" }, - { 100, labelSizePrefix + "M" }, - { 1000, labelSizePrefix + "L" }, - { 5000, labelSizePrefix + "XL" }, -}; - -var builder = WebApplication.CreateSlimBuilder(args); - -builder.Services.ConfigureHttpJsonOptions(options => +public partial class Program { - options.SerializerOptions.TypeInfoResolverChain.Insert(0, GitHubJsonContext.Default); -}); - -builder.Logging.ClearProviders(); -builder.Logging.AddConsole(); - -builder.Services.AddHttpLogging(options => -{ - options.LoggingFields = Microsoft.AspNetCore.HttpLogging.HttpLoggingFields.All; -}); -builder.Services.AddHttpClient(); - -var app = builder.Build(); - -app.UseHttpLogging(); - -var githubSecret = Environment.GetEnvironmentVariable("GITHUB_WEBHOOK_SECRET"); -var githubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"); - -if (githubSecret == null || githubToken == null) -{ - throw new InvalidOperationException("Missing required GITHUB_SECRET and GITHUB_TOKEN in ENV."); -} - -app.MapGet("/", () => Results.Ok("Nik is a cat!")); - -app.MapPost("/webhook", async (HttpContext context, IHttpClientFactory clientFactory) => -{ - using var memStream = new MemoryStream(); - await context.Request.Body.CopyToAsync(memStream); - var bodyBytes = memStream.ToArray(); - var bodyString = Encoding.UTF8.GetString(bodyBytes); - - if (!context.Request.Headers.TryGetValue("X-Hub-Signature-256", out var signatureHeader)) - return Results.BadRequest("Missing signature header."); - - var expectedSignature = "sha256=" + ToHmacSha256(bodyBytes, githubSecret); - if (!CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(expectedSignature), Encoding.UTF8.GetBytes(signatureHeader!))) - return Results.Unauthorized(); - - var githubEvent = context.Request.Headers["X-GitHub-Event"].FirstOrDefault(); - if (string.IsNullOrEmpty(githubEvent)) - return Results.BadRequest("Missing GitHub event."); - - var json = JsonDocument.Parse(bodyString); - var client = clientFactory.CreateClient(); - client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("SS14.Labeller", "1.0")); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", githubToken); - client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github+json")); - - switch (githubEvent) + public static void Main(string[] args) { - case "pull_request": - await PrHandler(json, client); - break; - - case "issues": - await IssuesHandler(json, client); - break; - - case "pull_request_review": - await PrReviewHandler(json, client); - break; - } + var githubSecret = Environment.GetEnvironmentVariable("GITHUB_WEBHOOK_SECRET"); + var githubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"); - return Results.Ok(); -}); - -app.Run(); -return; - -async Task PrReviewHandler(JsonDocument json, HttpClient client) -{ - var review = json.RootElement.GetProperty("review"); - var pr = json.RootElement.GetProperty("pull_request"); - var repo = json.RootElement.GetProperty("repository"); - var user = review.GetProperty("user").GetProperty("login").GetString(); - var state = review.GetProperty("state").GetString(); - - // only process if the review state is "approved" or "changes_requested" (ignore comments and other states) - if (state != "approved" && state != "changes_requested") - return; - - // Ignore reviews if PR is closed or merged - var prState = pr.GetProperty("state").GetString(); - // "closed" means closed or merged, but let's also check for merged explicitly if available - bool isClosed = prState == "closed"; - bool isMerged = pr.TryGetProperty("merged_at", out var mergedAtProp) && mergedAtProp.ValueKind != JsonValueKind.Null; - if (isClosed || isMerged) - return; - - var owner = repo.GetProperty("owner").GetProperty("login").GetString()!; - var repoName = repo.GetProperty("name").GetString()!; - var number = pr.GetProperty("number").GetInt32(); - - var permRes = await client.GetAsync($"{githubApiBase}/repos/{owner}/{repoName}/collaborators/{user}/permission"); - if (!permRes.IsSuccessStatusCode) - { - throw new Exception("Failed to get permissions! Does the github token have enough access?"); - } - - var permJson = JsonDocument.Parse(await permRes.Content.ReadAsStringAsync()); - var permission = permJson.RootElement.GetProperty("permission").GetString(); - if (permission is "write" or "admin") - { - await RemoveLabel(client, owner, repoName, number, labelStatusRequireReview); - - if (state == "approved") - { - await AddLabel(client, owner, repoName, number, labelStatusApproved); - } - else if (state == "changes_requested") + if (githubSecret == null || githubToken == null) { - await AddLabel(client, owner, repoName, number, labelStatusAwaitingChanges); + throw new InvalidOperationException("Missing required GITHUB_SECRET and GITHUB_TOKEN in ENV."); } - } -} -async Task IssuesHandler(JsonDocument json, HttpClient client) -{ - var action = json.RootElement.GetProperty("action").GetString(); - if (action == "opened") - { - var issue = json.RootElement.GetProperty("issue"); - var repo = json.RootElement.GetProperty("repository"); - var owner = repo.GetProperty("owner").GetProperty("login").GetString()!; - var repoName = repo.GetProperty("name").GetString()!; - var number = issue.GetProperty("number").GetInt32(); - var labels = issue.GetProperty("labels").EnumerateArray().Select(l => l.GetProperty("name").GetString()).ToList(); + var builder = WebApplication.CreateSlimBuilder(args); - if (labels.Count == 0) - await AddLabel(client, owner, repoName, number, labelStatusUntriaged); - } -} - -async Task PrHandler(JsonDocument json, HttpClient client) -{ - // I null-supress the shit out of these because i assume the github webhook json will basically never update and will always return valid data - - var action = json.RootElement.GetProperty("action").GetString(); - var pr = json.RootElement.GetProperty("pull_request"); - var repo = json.RootElement.GetProperty("repository"); - var owner = repo.GetProperty("owner").GetProperty("login").GetString()!; - var repoName = repo.GetProperty("name").GetString()!; - var number = pr.GetProperty("number").GetInt32(); - var labels = pr.GetProperty("labels").EnumerateArray().Select(l => l.GetProperty("name").GetString()).ToList(); - var targetBranch = pr.GetProperty("base").GetProperty("ref").GetString(); - var author = pr.GetProperty("user").GetProperty("login").GetString()!; - - // basic labels - if (action == "opened") - { - async Task ApplyRequiresReviewIfNotAlready() + builder.Services.ConfigureHttpJsonOptions(options => { - if (!labels.Contains(labelStatusRequireReview)) - await AddLabel(client, owner, repoName, number, labelStatusRequireReview); - } + options.SerializerOptions.TypeInfoResolverChain.Insert(0, SourceGenerationContext.Default); + }); - if (labels.Count == 0) - await AddLabel(client, owner, repoName, number, labelStatusUntriaged); + builder.Logging.ClearProviders(); + builder.Logging.AddConsole(); - if (targetBranch == "stable" && !labels.Contains(labelBranchStable)) - await AddLabel(client, owner, repoName, number, labelBranchStable); - else if (targetBranch == "staging" && !labels.Contains(labelBranchStaging)) - await AddLabel(client, owner, repoName, number, labelBranchStaging); - - var permRes = await client.GetAsync($"{githubApiBase}/repos/{owner}/{repoName}/collaborators/{author}/permission"); - if (!permRes.IsSuccessStatusCode) + builder.Services.AddHttpLogging(options => { - throw new Exception("Failed to get permissions! Does the github token have enough access?"); - } - - var permJson = JsonDocument.Parse(await permRes.Content.ReadAsStringAsync()); - var permission = permJson.RootElement.GetProperty("permission").GetString(); - if (permission is "write" or "admin") + options.LoggingFields = Microsoft.AspNetCore.HttpLogging.HttpLoggingFields.All; + }); + builder.Services.AddHttpClient(client => { - await AddLabel(client, owner, repoName, number, labelStatusApproved); - } - else - { - await ApplyRequiresReviewIfNotAlready(); - } - } - - if (action is "synchronize" or "opened") - { - var additions = pr.GetProperty("additions").GetInt32(); - var deletions = pr.GetProperty("deletions").GetInt32(); - var totalDiff = additions + deletions; - - // remove the existing size/* labels - foreach (var label in labels) - { - if (label != null && label.StartsWith(labelSizePrefix, StringComparison.OrdinalIgnoreCase)) + client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("SS14.Labeller", "1.0")); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", githubToken); + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github+json")); + }); + + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + + builder.Services.AddSingleton>( + sp => sp.GetServices() + .ToDictionary(x => x.EventType) + ); + + var app = builder.Build(); + + app.UseHttpLogging(); + + app.MapGet("/", () => Results.Ok("Nik is a cat!")); + + app.MapPost( + "/webhook", + async ( + HttpContext context, + [FromHeader(Name = "X-GitHub-Event")] string githubEvent, + [FromServices] IReadOnlyDictionary handlers, + [FromServices] ILogger logger + ) => { - await RemoveLabel(client, owner, repoName, number, label); - } - } - - string? sizeLabel = null; - // ReSharper disable once LoopCanBeConvertedToQuery no fuck you, the resulting LINQ query is unreadable - foreach (var kvp in sizes.OrderByDescending(k => k.Key)) - { - if (totalDiff < kvp.Key) - continue; - - sizeLabel = kvp.Value; - break; - } - - if (sizeLabel is not null && !labels.Contains(sizeLabel)) - { - await AddLabel(client, owner, repoName, number, sizeLabel); - } - } - - var changedFiles = await GetChangedFiles(client, owner, repoName, number); - - var matcher = new Matcher(); - matcher.AddInclude("**/*.rsi/*.png"); // Sprites - matcher.AddInclude("Resources/Maps/**/*.yml"); // Map - matcher.AddInclude("Resources/Prototypes/Maps/**/*.yml"); - matcher.AddInclude("**/*.xaml*"); // UI - matcher.AddInclude("**/*.swsl"); // Shaders - matcher.AddInclude("**/*.ogg"); // Audio - - var sprites = new Matcher().AddInclude("**/*.rsi/*.png"); - var maps = new Matcher().AddInclude("Resources/Maps/**/*.yml").AddInclude("Resources/Prototypes/Maps/**/*.yml"); - var ui = new Matcher().AddInclude("**/*.xaml*"); - var shaders = new Matcher().AddInclude("**/*.swsl"); - var audio = new Matcher().AddInclude("**/*.ogg"); - var cs = new Matcher().AddInclude("**/*.cs"); - - if (sprites.Match(changedFiles).HasMatches) - await AddLabel(client, owner, repoName, number, labelChangesSprites); - - if (maps.Match(changedFiles).HasMatches) - await AddLabel(client, owner, repoName, number, labelChangesMap); - - if (ui.Match(changedFiles).HasMatches) - await AddLabel(client, owner, repoName, number, labelChangesUi); - - if (shaders.Match(changedFiles).HasMatches) - await AddLabel(client, owner, repoName, number, labelChangesShaders); - - if (audio.Match(changedFiles).HasMatches) - await AddLabel(client, owner, repoName, number, labelChangesAudio); - - if (!cs.Match(changedFiles).HasMatches) - await AddLabel(client, owner, repoName, number, labelChangesNoCSharp); -} - -string ToHmacSha256(byte[] data, string secret) -{ - var key = Encoding.UTF8.GetBytes(secret); - using var hmac = new HMACSHA256(key); - var hashBytes = hmac.ComputeHash(data); - return Convert.ToHexString(hashBytes).ToLowerInvariant(); -} - -async Task> GetChangedFiles(HttpClient client, string owner, string repo, int prNumber) -{ - // TODO: Ratelimit? Might explode on big PRs??? - - var files = new List(); - var page = 1; - while (true) - { - var res = await client.GetAsync($"{githubApiBase}/repos/{owner}/{repo}/pulls/{prNumber}/files?per_page=100&page={page}"); - if (!res.IsSuccessStatusCode) - break; // TODO: Logging? - - var content = await res.Content.ReadAsStringAsync(); - var json = JsonDocument.Parse(content); - var batch = json.RootElement.EnumerateArray().Select(f => f.GetProperty("filename").GetString()!).ToList(); - if (batch.Count == 0) break; - - files.AddRange(batch); - if (batch.Count < 100) break; - - page++; + if (string.IsNullOrEmpty(githubEvent)) + return Results.BadRequest("Missing GitHub event."); + + var request = context.Request; + + using var memStream = new MemoryStream(); + await request.Body.CopyToAsync(memStream); + var bodyBytes = memStream.ToArray(); + + var headers = request.Headers; + if (!SecurityHelper.IsRequestAuthorized(bodyBytes, githubSecret, headers, out var errorResponse)) + return errorResponse; + + if (handlers.TryGetValue(githubEvent, out var handler)) + { + await handler.Handle(bodyBytes, context.RequestAborted); + } + else + { + logger.LogWarning( + "Unexpected 'X-GitHub-Event' header, cannot handle event of type '{eventType}'.", + githubEvent + ); + } + + return Results.NoContent(); + }); + + app.Run(); } - return files; } - -async Task AddLabel(HttpClient client, string owner, string repo, int number, string label) -{ - var request = new AddLabelRequest { labels = [label] }; - var json = JsonSerializer.Serialize(request, GitHubJsonContext.Default.AddLabelRequest); - var content = new StringContent(json, Encoding.UTF8, "application/json"); - - await client.PostAsync($"{githubApiBase}/repos/{owner}/{repo}/issues/{number}/labels", content); -} - -async Task RemoveLabel(HttpClient client, string owner, string repo, int number, string label) -{ - await client.DeleteAsync($"{githubApiBase}/repos/{owner}/{repo}/issues/{number}/labels/{Uri.EscapeDataString(label)}"); -} - -[JsonSerializable(typeof(AddLabelRequest))] -public partial class GitHubJsonContext : JsonSerializerContext -{ -} - -public class AddLabelRequest -{ - // ReSharper disable once InconsistentNaming - public string[] labels { get; set; } = []; -} \ No newline at end of file diff --git a/SS14.Labeller/SS14.Labeller.csproj b/SS14.Labeller/SS14.Labeller.csproj index 5ecec67..52f2551 100644 --- a/SS14.Labeller/SS14.Labeller.csproj +++ b/SS14.Labeller/SS14.Labeller.csproj @@ -1,4 +1,4 @@ - + net9.0 enable diff --git a/SS14.Labeller/SourceGenerationContext.cs b/SS14.Labeller/SourceGenerationContext.cs new file mode 100644 index 0000000..e20777b --- /dev/null +++ b/SS14.Labeller/SourceGenerationContext.cs @@ -0,0 +1,20 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using SS14.Labeller.GitHubApi; +using SS14.Labeller.Models; + +namespace SS14.Labeller; + +[JsonSerializable(typeof(AddLabelRequest))] +[JsonSerializable(typeof(IssuesEvent))] +[JsonSerializable(typeof(PullRequestEvent))] +[JsonSerializable(typeof(PullRequestReviewEvent))] +public partial class SourceGenerationContext : JsonSerializerContext +{ + private static readonly JsonSerializerOptions JsonSerializerOptions = new() + { + PropertyNameCaseInsensitive = true + }; + + public static SourceGenerationContext DeserializationContext { get; } = new(JsonSerializerOptions); +} \ No newline at end of file