From a2ffdf5ca852ac908acfa7ee5fcf1c2d966c455f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dandelion=20Man=C3=A9?= Date: Fri, 14 Sep 2018 16:10:31 -0700 Subject: [PATCH] Request reactions data from GitHub (#839) This commit updates the GitHub graphql query to also fetch reactions. We update the JSON typedefs to include this new information, add continuations from comments, and update existing continuation and query code. Also, I added a safety check when updating comments for issues that was previously unnecessary but is now needed. Test plan: - `yarn test --full` passes. - Setting the page limits to 1 and running on the example-github does not error with unexhausted pages, and loads all the expected reactions. - Running on a larger repository (go-ipfs) works as expected. - I have written dependent code that consumes these reactions in the RelationalView, and works as intended, which suggests that the type signatures are correct. --- .../github/__snapshots__/graphql.test.js.snap | 27 +- .../github/example/example-github.json | 426 ++++++++++++++++++ src/plugins/github/graphql.js | 147 +++++- src/plugins/github/graphql.test.js | 1 + .../mentionsAuthorReference.test.js | 8 + 5 files changed, 605 insertions(+), 4 deletions(-) diff --git a/src/plugins/github/__snapshots__/graphql.test.js.snap b/src/plugins/github/__snapshots__/graphql.test.js.snap index 0809441..4646e39 100644 --- a/src/plugins/github/__snapshots__/graphql.test.js.snap +++ b/src/plugins/github/__snapshots__/graphql.test.js.snap @@ -259,6 +259,9 @@ fragment issues on IssueConnection { comments(first: 20) { ...comments } + reactions(first: 5) { + ...reactions + } } } fragment pulls on PullRequestConnection { @@ -283,9 +286,12 @@ fragment pulls on PullRequestConnection { comments(first: 20) { ...comments } - reviews(first: 10) { + reviews(first: 5) { ...reviews } + reactions(first: 5) { + ...reactions + } } } fragment comments on IssueCommentConnection { @@ -300,6 +306,9 @@ fragment comments on IssueCommentConnection { ...whoami } body + reactions(first: 5) { + ...reactions + } } } fragment reviews on PullRequestReviewConnection { @@ -332,6 +341,9 @@ fragment reviewComments on PullRequestReviewCommentConnection { author { ...whoami } + reactions(first: 5) { + ...reactions + } } } fragment commitHistory on CommitHistoryConnection { @@ -353,5 +365,18 @@ fragment commit on Commit { ...whoami } } +} +fragment reactions on ReactionConnection { + pageInfo { + hasNextPage + endCursor + } + nodes { + id + content + user { + ...whoami + } + } }" `; diff --git a/src/plugins/github/example/example-github.json b/src/plugins/github/example/example-github.json index 5577700..d618534 100644 --- a/src/plugins/github/example/example-github.json +++ b/src/plugins/github/example/example-github.json @@ -113,6 +113,34 @@ }, "id": "MDU6SXNzdWUzMDA5MzQ4MTg=", "number": 1, + "reactions": { + "nodes": [ + { + "content": "LAUGH", + "id": "MDg6UmVhY3Rpb24yOTQwMjEwNw==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "HEART", + "id": "MDg6UmVhY3Rpb24yOTQwMjEwOQ==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + } + ], + "pageInfo": { + "endCursor": "Y3Vyc29yOnYyOpHOAcCj_Q==", + "hasNextPage": false + } + }, "title": "An example issue.", "url": "https://github.com/sourcecred/example-github/issues/1" }, @@ -135,6 +163,14 @@ }, "body": "It should also be possible to reference by exact url: https://github.com/sourcecred/example-github/issues/6", "id": "MDEyOklzc3VlQ29tbWVudDM3Mzc2ODcwMw==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/2#issuecomment-373768703" }, { @@ -146,6 +182,14 @@ }, "body": "We might also reference individual comments directly.\r\nhttps://github.com/sourcecred/example-github/issues/6#issuecomment-373768538", "id": "MDEyOklzc3VlQ29tbWVudDM3Mzc2ODg1MA==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/2#issuecomment-373768850" }, { @@ -157,6 +201,14 @@ }, "body": "Here's a PR by direct url: https://github.com/sourcecred/example-github/pull/5", "id": "MDEyOklzc3VlQ29tbWVudDM4NTU3NjE4NQ==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/2#issuecomment-385576185" }, { @@ -168,6 +220,14 @@ }, "body": "a PR review by url: https://github.com/sourcecred/example-github/pull/5#pullrequestreview-100313899", "id": "MDEyOklzc3VlQ29tbWVudDM4NTU3NjIyMA==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/2#issuecomment-385576220" }, { @@ -179,6 +239,14 @@ }, "body": "a PR Review Comment by url: https://github.com/sourcecred/example-github/pull/5#discussion_r171460198", "id": "MDEyOklzc3VlQ29tbWVudDM4NTU3NjI0OA==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/2#issuecomment-385576248" }, { @@ -190,6 +258,14 @@ }, "body": "a user by url: https://github.com/wchargin", "id": "MDEyOklzc3VlQ29tbWVudDM4NTU3NjI3Mw==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/2#issuecomment-385576273" }, { @@ -201,6 +277,14 @@ }, "body": "Here are several references:\r\n#1 \r\n#2\r\n#3 \r\n\r\nhttps://github.com/sourcecred/example-github/pull/5#discussion_r171460198\r\nhttps://github.com/sourcecred/example-github/pull/5#pullrequestreview-100313899\r\n", "id": "MDEyOklzc3VlQ29tbWVudDM4NTU3NjkyMA==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/2#issuecomment-385576920" }, { @@ -212,6 +296,14 @@ }, "body": "This comment has no references.", "id": "MDEyOklzc3VlQ29tbWVudDM4NTU3NjkzNg==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/2#issuecomment-385576936" } ], @@ -222,6 +314,14 @@ }, "id": "MDU6SXNzdWUzMDA5MzQ5ODA=", "number": 2, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "title": "A referencing issue.", "url": "https://github.com/sourcecred/example-github/issues/2" }, @@ -243,6 +343,14 @@ }, "id": "MDU6SXNzdWUzMDA5MzYzNzQ=", "number": 4, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "title": "A closed pull request", "url": "https://github.com/sourcecred/example-github/issues/4" }, @@ -265,6 +373,14 @@ }, "body": "A wild COMMENT appeared!", "id": "MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/6#issuecomment-373768442" }, { @@ -276,6 +392,14 @@ }, "body": "And the maintainer said, \"Let there be comments!\"", "id": "MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/6#issuecomment-373768538" }, { @@ -287,6 +411,14 @@ }, "body": "This comment references an #2, which itself references an issue. This comment is thus allows us to test that in-references are not included when requesting a Post's references.", "id": "MDEyOklzc3VlQ29tbWVudDM4NTIyMzMxNg==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/6#issuecomment-385223316" }, { @@ -298,6 +430,14 @@ }, "body": "Hi! I'm a bot! Beep boop beep!!", "id": "MDEyOklzc3VlQ29tbWVudDQxNzEwNDA0Nw==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/6#issuecomment-417104047" } ], @@ -308,6 +448,14 @@ }, "id": "MDU6SXNzdWUzMDU5OTM3NzM=", "number": 6, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "title": "An issue with comments", "url": "https://github.com/sourcecred/example-github/issues/6" }, @@ -329,6 +477,14 @@ }, "id": "MDU6SXNzdWUzMDY5ODM1NTI=", "number": 7, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "title": "An issue with an extremely long title, which even has a VerySuperFragicalisticialiManyCharacterUberLongTriplePlusGood word in it, and should really be truncated intelligently or something", "url": "https://github.com/sourcecred/example-github/issues/7" }, @@ -350,6 +506,14 @@ }, "id": "MDU6SXNzdWUzMDY5ODUzNjc=", "number": 8, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "title": "Issue with Unicode: ศดแˆฒ๐ฃณๆฅข๐Ÿ‘ :heart: ๐ค”๐ค๐ค€๐ค‘๐ค๐ค‰๐ค”๐คŒ๐ค„๐ค๐ค โค๏ธ", "url": "https://github.com/sourcecred/example-github/issues/8" }, @@ -371,6 +535,14 @@ }, "id": "MDU6SXNzdWUzMzcwOTU0NzM=", "number": 10, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "title": "Paired with multireference", "url": "https://github.com/sourcecred/example-github/issues/10" }, @@ -388,6 +560,14 @@ "author": null, "body": "Hello. :ghost: ", "id": "MDEyOklzc3VlQ29tbWVudDQyMDgxMTg3Mg==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/11#issuecomment-420811872" }, { @@ -399,12 +579,68 @@ }, "body": "[Here is a screenshot of the thread at this point, prior to account deletion.](https://user-images.githubusercontent.com/4317806/45455614-8c4fe600-b69c-11e8-902e-aec65d7403e6.png)\r\n\r\nThe user has GraphQL ID `MDQ6VXNlcjQzMjIyMTkw` and database ID `43222190`.\r\n\r\nThe previous comment has GraphQL ID `MDEyOklzc3VlQ29tbWVudDQyMDgxMTg3Mg==` and database `420811872`.\r\n", "id": "MDEyOklzc3VlQ29tbWVudDQyMDgxMzAxMw==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/11#issuecomment-420813013" }, { "author": null, "body": "My time in this life draws to a close. :wave: ", "id": "MDEyOklzc3VlQ29tbWVudDQyMDgxMzIwNg==", + "reactions": { + "nodes": [ + { + "content": "THUMBS_UP", + "id": "MDg6UmVhY3Rpb24yOTQ1MDk5Nw==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "THUMBS_DOWN", + "id": "MDg6UmVhY3Rpb24yOTQ1MTAwMQ==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "LAUGH", + "id": "MDg6UmVhY3Rpb24yOTQ1MTAwMw==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "HOORAY", + "id": "MDg6UmVhY3Rpb24yOTQ1MTAwOA==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + } + ], + "pageInfo": { + "endCursor": "Y3Vyc29yOnYyOpHOAcFjAA==", + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/11#issuecomment-420813206" }, { @@ -416,6 +652,14 @@ }, "body": ":skull: :ghost:\r\nRIP", "id": "MDEyOklzc3VlQ29tbWVudDQyMDgxMzYyMQ==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/issues/11#issuecomment-420813621" } ], @@ -426,6 +670,14 @@ }, "id": "MDU6SXNzdWUzNTk2Njc4Mjk=", "number": 11, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "title": "An issue with a comment from a deleted user", "url": "https://github.com/sourcecred/example-github/issues/11" }, @@ -447,6 +699,24 @@ }, "id": "MDU6SXNzdWUzNjAwOTExMDc=", "number": 12, + "reactions": { + "nodes": [ + { + "content": "THUMBS_UP", + "id": "MDg6UmVhY3Rpb24yOTQwMjEwMw==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + } + ], + "pageInfo": { + "endCursor": "Y3Vyc29yOnYyOpHOAcCj9w==", + "hasNextPage": false + } + }, "title": "An issue with commit references", "url": "https://github.com/sourcecred/example-github/issues/12" }, @@ -468,6 +738,74 @@ }, "id": "MDU6SXNzdWUzNjAwOTEzMTQ=", "number": 13, + "reactions": { + "nodes": [ + { + "content": "THUMBS_UP", + "id": "MDg6UmVhY3Rpb24yOTQwMjEzNA==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "THUMBS_DOWN", + "id": "MDg6UmVhY3Rpb24yOTQwMjEzOQ==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "LAUGH", + "id": "MDg6UmVhY3Rpb24yOTQwMjE0MA==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "HOORAY", + "id": "MDg6UmVhY3Rpb24yOTQwMjE0MQ==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "CONFUSED", + "id": "MDg6UmVhY3Rpb24yOTQwMjE0NQ==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "HEART", + "id": "MDg6UmVhY3Rpb24yOTQwMjE0OA==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + } + ], + "pageInfo": { + "endCursor": "Y3Vyc29yOnYyOpHOAcCkJA==", + "hasNextPage": false + } + }, "title": "An issue with reactions", "url": "https://github.com/sourcecred/example-github/issues/13" } @@ -506,6 +844,14 @@ }, "body": "It seems apropos to reference something from a pull request comment... eg: #2 ", "id": "MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/pull/3#issuecomment-369162222" } ], @@ -531,6 +877,14 @@ "url": "https://github.com/sourcecred/example-github/commit/0a223346b4e6dec0127b1e6aa892c4ee0424b66a" }, "number": 3, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "reviews": { "nodes": [ ], @@ -562,6 +916,34 @@ }, "body": "In retrospect, this was an excellent PR.", "id": "MDEyOklzc3VlQ29tbWVudDM5NjQzMDQ2NA==", + "reactions": { + "nodes": [ + { + "content": "HEART", + "id": "MDg6UmVhY3Rpb24yOTQ1MTA1Mw==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "CONFUSED", + "id": "MDg6UmVhY3Rpb24yOTQ1MTA1NQ==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + } + ], + "pageInfo": { + "endCursor": "Y3Vyc29yOnYyOpHOAcFjLw==", + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/pull/5#issuecomment-396430464" } ], @@ -587,6 +969,14 @@ "url": "https://github.com/sourcecred/example-github/commit/6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6" }, "number": 5, + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "reviews": { "nodes": [ { @@ -608,6 +998,14 @@ }, "body": "seems a bit capricious", "id": "MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE3MTQ2MDE5OA==", + "reactions": { + "nodes": [ + ], + "pageInfo": { + "endCursor": null, + "hasNextPage": false + } + }, "url": "https://github.com/sourcecred/example-github/pull/5#discussion_r171460198" } ], @@ -670,6 +1068,34 @@ "id": "MDExOlB1bGxSZXF1ZXN0MTg1ODA2MTU3", "mergeCommit": null, "number": 9, + "reactions": { + "nodes": [ + { + "content": "HEART", + "id": "MDg6UmVhY3Rpb24yOTQ1MTAxMg==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + }, + { + "content": "THUMBS_UP", + "id": "MDg6UmVhY3Rpb24yOTQ1MTAxNA==", + "user": { + "__typename": "User", + "id": "MDQ6VXNlcjE0MDAwMjM=", + "login": "decentralion", + "url": "https://github.com/decentralion" + } + } + ], + "pageInfo": { + "endCursor": "Y3Vyc29yOnYyOpHOAcFjBg==", + "hasNextPage": false + } + }, "reviews": { "nodes": [ ], diff --git a/src/plugins/github/graphql.js b/src/plugins/github/graphql.js index 68a5e94..def00b4 100644 --- a/src/plugins/github/graphql.js +++ b/src/plugins/github/graphql.js @@ -50,9 +50,10 @@ export const PAGE_LIMIT = 50; const PAGE_SIZE_ISSUES = 50; const PAGE_SIZE_PRS = 50; const PAGE_SIZE_COMMENTS = 20; -const PAGE_SIZE_REVIEWS = 10; +const PAGE_SIZE_REVIEWS = 5; const PAGE_SIZE_REVIEW_COMMENTS = 10; const PAGE_SIZE_COMMIT_HISTORY = 100; +const PAGE_SIZE_REACTIONS = 5; /** * What's in a continuation? If we want to fetch more comments for the @@ -86,7 +87,7 @@ const PAGE_SIZE_COMMIT_HISTORY = 100; * the continuation into a query, and not of the continuation itself. */ export type Continuation = {| - +enclosingNodeType: "REPOSITORY" | "ISSUE" | "PULL" | "REVIEW", + +enclosingNodeType: "REPOSITORY" | "ISSUE" | "PULL" | "REVIEW" | "COMMENT", +enclosingNodeId: string, +selections: $ReadOnlyArray, +destinationPath: $ReadOnlyArray, @@ -216,6 +217,7 @@ export function continuationsFromContinuation( ISSUE: continuationsFromIssue, PULL: continuationsFromPR, REVIEW: continuationsFromReview, + COMMENT: continuationsFromComment, }[source.enclosingNodeType]; return continuationsFromEnclosingType( result, @@ -324,7 +326,7 @@ function* continuationsFromIssue( path: $ReadOnlyArray ): Iterator { const b = build; - if (result.comments.pageInfo.hasNextPage) { + if (result.comments && result.comments.pageInfo.hasNextPage) { yield { enclosingNodeType: "ISSUE", enclosingNodeId: nodeId, @@ -343,6 +345,32 @@ function* continuationsFromIssue( destinationPath: path, }; } + if (result.reactions && result.reactions.pageInfo.hasNextPage) { + yield { + enclosingNodeType: "ISSUE", + enclosingNodeId: nodeId, + selections: [ + b.inlineFragment("Issue", [ + b.field( + "reactions", + { + first: b.literal(PAGE_LIMIT), + after: b.literal(result.reactions.pageInfo.endCursor), + }, + [b.fragmentSpread("reactions")] + ), + ]), + ], + destinationPath: path, + }; + } + if (result.comments) { + for (let i = 0; i < result.comments.nodes.length; i++) { + const comment = result.comments.nodes[i]; + const subpath = [...path, "comments", "nodes", i]; + yield* continuationsFromComment(comment, comment.id, subpath); + } + } } function* continuationsFromPR( @@ -370,6 +398,25 @@ function* continuationsFromPR( destinationPath: path, }; } + if (result.reactions && result.reactions.pageInfo.hasNextPage) { + yield { + enclosingNodeType: "PULL", + enclosingNodeId: nodeId, + selections: [ + b.inlineFragment("PullRequest", [ + b.field( + "reactions", + { + first: b.literal(PAGE_LIMIT), + after: b.literal(result.reactions.pageInfo.endCursor), + }, + [b.fragmentSpread("reactions")] + ), + ]), + ], + destinationPath: path, + }; + } if (result.reviews && result.reviews.pageInfo.hasNextPage) { yield { enclosingNodeType: "PULL", @@ -396,6 +443,13 @@ function* continuationsFromPR( yield* continuationsFromReview(issue, issue.id, subpath); } } + if (result.comments) { + for (let i = 0; i < result.comments.nodes.length; i++) { + const comment = result.comments.nodes[i]; + const subpath = [...path, "comments", "nodes", i]; + yield* continuationsFromComment(comment, comment.id, subpath); + } + } } function* continuationsFromReview( @@ -425,6 +479,33 @@ function* continuationsFromReview( } } +function* continuationsFromComment( + result: any, + nodeId: string, + path: $ReadOnlyArray +): Iterator { + const b = build; + if (result.reactions && result.reactions.pageInfo.hasNextPage) { + yield { + enclosingNodeType: "COMMENT", + enclosingNodeId: nodeId, + selections: [ + b.inlineFragment("IssueComment", [ + b.field( + "reactions", + { + first: b.literal(PAGE_LIMIT), + after: b.literal(result.reactions.pageInfo.endCursor), + }, + [b.fragmentSpread("reactions")] + ), + ]), + ], + destinationPath: path, + }; + } +} + /** * Execute the given query, returning all pages of data throughout the * query. That is: post the query, then find any entities that require @@ -730,6 +811,7 @@ export type IssueJSON = {| +number: number, +author: NullableAuthorJSON, +comments: ConnectionJSON, + +reactions: ConnectionJSON, |}; function issuesFragment(): FragmentDefinition { @@ -746,6 +828,9 @@ function issuesFragment(): FragmentDefinition { b.field("comments", {first: b.literal(PAGE_SIZE_COMMENTS)}, [ b.fragmentSpread("comments"), ]), + b.field("reactions", {first: b.literal(PAGE_SIZE_REACTIONS)}, [ + b.fragmentSpread("reactions"), + ]), ]), ]); } @@ -762,6 +847,7 @@ export type PullJSON = {| +comments: ConnectionJSON, +reviews: ConnectionJSON, +mergeCommit: ?CommitJSON, + +reactions: ConnectionJSON, |}; function pullsFragment(): FragmentDefinition { const b = build; @@ -783,6 +869,9 @@ function pullsFragment(): FragmentDefinition { b.field("reviews", {first: b.literal(PAGE_SIZE_REVIEWS)}, [ b.fragmentSpread("reviews"), ]), + b.field("reactions", {first: b.literal(PAGE_SIZE_REACTIONS)}, [ + b.fragmentSpread("reactions"), + ]), ]), ]); } @@ -792,6 +881,7 @@ export type CommentJSON = {| +url: string, +body: string, +author: NullableAuthorJSON, + +reactions: ConnectionJSON, |}; function commentsFragment(): FragmentDefinition { const b = build; @@ -803,6 +893,9 @@ function commentsFragment(): FragmentDefinition { b.field("url"), makeAuthor(), b.field("body"), + b.field("reactions", {first: b.literal(PAGE_SIZE_REACTIONS)}, [ + b.fragmentSpread("reactions"), + ]), ]), ]); } @@ -821,6 +914,7 @@ export type ReviewJSON = {| +author: NullableAuthorJSON, +state: ReviewState, +comments: ConnectionJSON, + +reactions: ConnectionJSON, |}; function reviewsFragment(): FragmentDefinition { const b = build; @@ -844,6 +938,7 @@ export type ReviewCommentJSON = {| +url: string, +body: string, +author: NullableAuthorJSON, + +reactions: ConnectionJSON, |}; function reviewCommentsFragment(): FragmentDefinition { const b = build; @@ -854,6 +949,9 @@ function reviewCommentsFragment(): FragmentDefinition { b.field("url"), b.field("body"), makeAuthor(), + b.field("reactions", {first: b.literal(PAGE_SIZE_REACTIONS)}, [ + b.fragmentSpread("reactions"), + ]), ]), ]); } @@ -885,6 +983,48 @@ function commitHistoryFragment(): FragmentDefinition { ]); } +export const Reactions: {| + +THUMBS_UP: "THUMBS_UP", + +THUMBS_DOWN: "THUMBS_DOWN", + +LAUGH: "LAUGH", + +CONFUSED: "CONFUSED", + +HEART: "HEART", + +HOORAY: "HOORAY", +|} = Object.freeze({ + THUMBS_UP: "THUMBS_UP", + THUMBS_DOWN: "THUMBS_DOWN", + LAUGH: "LAUGH", + CONFUSED: "CONFUSED", + HEART: "HEART", + HOORAY: "HOORAY", +}); + +export type ReactionContent = + | typeof Reactions.THUMBS_UP + | typeof Reactions.THUMBS_DOWN + | typeof Reactions.LAUGH + | typeof Reactions.CONFUSED + | typeof Reactions.HEART + | typeof Reactions.HOORAY; + +export type ReactionJSON = {| + +id: string, + +content: ReactionContent, + +user: NullableAuthorJSON, +|}; + +function reactionsFragment(): FragmentDefinition { + const b = build; + return b.fragment("reactions", "ReactionConnection", [ + makePageInfo(), + b.field("nodes", {}, [ + b.field("id"), + b.field("content"), + b.field("user", {}, [b.fragmentSpread("whoami")]), + ]), + ]); +} + /** * These fragments are used to construct the root query, and also to * fetch more pages of specific entity types. @@ -899,6 +1039,7 @@ export function createFragments(): FragmentDefinition[] { reviewCommentsFragment(), commitHistoryFragment(), commitFragment(), + reactionsFragment(), ]; } diff --git a/src/plugins/github/graphql.test.js b/src/plugins/github/graphql.test.js index 9d44c25..36c29ea 100644 --- a/src/plugins/github/graphql.test.js +++ b/src/plugins/github/graphql.test.js @@ -685,6 +685,7 @@ describe("plugins/github/graphql", () => { ); const result = requiredFragments(query); expect(result.map((fd) => fd.name).sort()).toEqual([ + "reactions", "reviewComments", "reviews", "whoami", diff --git a/src/plugins/github/heuristics/mentionsAuthorReference.test.js b/src/plugins/github/heuristics/mentionsAuthorReference.test.js index d92ac38..e14a09e 100644 --- a/src/plugins/github/heuristics/mentionsAuthorReference.test.js +++ b/src/plugins/github/heuristics/mentionsAuthorReference.test.js @@ -73,6 +73,7 @@ describe("plugins/github/heuristics/mentionsAuthorReference", () => { body: "hi @amethyst", author: authors.steven(), comments: connection([]), + reactions: connection([]), }, { id: "issue:2", @@ -81,36 +82,42 @@ describe("plugins/github/heuristics/mentionsAuthorReference", () => { title: "an issue with many types of references", body: "it is me, @steven\n\nPaired with: @pearl", author: authors.steven(), + reactions: connection([]), comments: connection([ { id: "comment:2_1", url: issueCommentUrl(2, 1), body: "parry parry thrust @pearl\nparry parry thrust @steven", author: authors.holo(), + reactions: connection([]), }, { id: "comment:2_2", url: issueCommentUrl(2, 2), body: "@holo-pearl: stop!", author: authors.steven(), + reactions: connection([]), }, { id: "comment:2_3", url: issueCommentUrl(2, 3), body: "@amethyst @garnet why aren't you helping", author: authors.pearl(), + reactions: connection([]), }, { id: "comment:2_4", url: issueCommentUrl(2, 4), body: "@amethyst! come quickly, @amethyst!", author: authors.garnet(), + reactions: connection([]), }, { id: "comment:2_5", url: issueCommentUrl(2, 5), body: "i am busy fighting @boomerang-blade guy", author: authors.amethyst(), + reactions: connection([]), }, ]), }, @@ -125,6 +132,7 @@ describe("plugins/github/heuristics/mentionsAuthorReference", () => { mergeCommit: null, additions: 0, deletions: 0, + reactions: connection([]), comments: connection([]), author: authors.steven(), reviews: connection([]),