Implement the GitHub graph parser (#81)

The GitHub parser transforms GraphQL api data from GitHub into our Graph
data structure. This commit focuses on properly parsing Issues, Pull
Requests, Comments, and Users.

Test Plan:
Run the unit tests. Inspect the snapshot results (particuarly those for
individual pull requests or issues, which are easier to parse) and
verify that the output is appropriate.
This commit is contained in:
Dandelion Mané 2018-03-19 12:26:32 -07:00 committed by GitHub
parent 274007c90d
commit 30600004e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 850 additions and 14 deletions

View File

@ -0,0 +1,536 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`GithubParser issue parsing parses a simple issue (https://github.com/sourcecred/example-repo/issues/1) 1`] = `
Object {
"edges": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzQ4MTg=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDA5MzQ4MTg=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
},
"nodes": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"}\\"}": Object {
"payload": Object {
"login": "dandelionmane",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzQ4MTg=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"}\\"}": Object {
"payload": Object {
"body": "This is just an example issue.",
"number": 1,
"title": "An example issue.",
},
},
},
}
`;
exports[`GithubParser issue parsing parses an issue with comments (https://github.com/sourcecred/example-repo/issues/6) 1`] = `
Object {
"edges": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDU5OTM3NzM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDU5OTM3NzM=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"childID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"parentID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDU5OTM3NzM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"CONTAINMENT\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDU5OTM3NzM=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"childID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"parentID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDU5OTM3NzM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"CONTAINMENT\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDU5OTM3NzM=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
},
"nodes": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"}\\"}": Object {
"payload": Object {
"body": "A wild COMMENT appeared!",
"url": "https://github.com/sourcecred/example-repo/issues/6#issuecomment-373768442",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"}\\"}": Object {
"payload": Object {
"body": "And the maintainer said, \\"Let there be comments!\\"",
"url": "https://github.com/sourcecred/example-repo/issues/6#issuecomment-373768538",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"}\\"}": Object {
"payload": Object {
"login": "dandelionmane",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDU5OTM3NzM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"}\\"}": Object {
"payload": Object {
"body": "This issue shall shortly have a few comments.",
"number": 6,
"title": "An issue with comments",
},
},
},
}
`;
exports[`GithubParser pull request parsing parses a pr with review comments (https://github.com/sourcecred/example-repo/pull/3) 1`] = `
Object {
"edges": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg4NTIy\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDExOlB1bGxSZXF1ZXN0MTcxODg4NTIy\\",\\"type\\":\\"PULL_REQUEST\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
},
"nodes": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg4NTIy\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"}\\"}": Object {
"payload": Object {
"body": "@wchargin could you please do the following:
- add a commit comment
- add a review comment requesting some trivial change
- i'll change it
- then approve the pr",
"number": 5,
"title": "This pull request will be more contentious. I can feel it...",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"}\\"}": Object {
"payload": Object {
"login": "dandelionmane",
},
},
},
}
`;
exports[`GithubParser pull request parsing parses a simple pull request (https://github.com/sourcecred/example-repo/pull/3) 1`] = `
Object {
"edges": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\",\\"type\\":\\"PULL_REQUEST\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"childID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"parentID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"CONTAINMENT\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\",\\"type\\":\\"PULL_REQUEST\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
},
"nodes": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"}\\"}": Object {
"payload": Object {
"body": "Oh look, it's a pull request.",
"number": 3,
"title": "Add README, merge via PR.",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"}\\"}": Object {
"payload": Object {
"body": "It seems apropos to reference something from a pull request comment... eg: #2 ",
"url": "https://github.com/sourcecred/example-repo/pull/3#issuecomment-369162222",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"}\\"}": Object {
"payload": Object {
"login": "dandelionmane",
},
},
},
}
`;
exports[`GithubParser whole repo parsing parses the entire example-repo as expected 1`] = `
Object {
"edges": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\",\\"type\\":\\"PULL_REQUEST\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg4NTIy\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDExOlB1bGxSZXF1ZXN0MTcxODg4NTIy\\",\\"type\\":\\"PULL_REQUEST\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODcwMw==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODcwMw==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODg1MA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODg1MA==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzQ4MTg=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDA5MzQ4MTg=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzQ5ODA=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDA5MzQ5ODA=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzYzNzQ=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDA5MzYzNzQ=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"authorID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"},\\\\\\"contributionID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDU5OTM3NzM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"AUTHORSHIP\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDQ6VXNlcjE0MDAwMjM=\\",\\"type\\":\\"USER\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDU5OTM3NzM=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"childID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"parentID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"CONTAINMENT\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\",\\"type\\":\\"PULL_REQUEST\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"childID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"parentID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDU5OTM3NzM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"CONTAINMENT\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDU5OTM3NzM=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"childID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"parentID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDU5OTM3NzM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"CONTAINMENT\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDU5OTM3NzM=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"childID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODcwMw==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"parentID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzQ5ODA=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"CONTAINMENT\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODcwMw==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDA5MzQ5ODA=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"childID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODg1MA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"},\\\\\\"parentID\\\\\\":{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzQ5ODA=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"CONTAINMENT\\\\\\"}\\"}": Object {
"dst": Object {
"id": "{\\"id\\":\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODg1MA==\\",\\"type\\":\\"COMMENT\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
"payload": Object {},
"src": Object {
"id": "{\\"id\\":\\"MDU6SXNzdWUzMDA5MzQ5ODA=\\",\\"type\\":\\"ISSUE\\"}",
"pluginName": "sourcecred/github-beta",
"repositoryName": "sourcecred/example-repo",
},
},
},
"nodes": Object {
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg3NzQx\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"}\\"}": Object {
"payload": Object {
"body": "Oh look, it's a pull request.",
"number": 3,
"title": "Add README, merge via PR.",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDExOlB1bGxSZXF1ZXN0MTcxODg4NTIy\\\\\\",\\\\\\"type\\\\\\":\\\\\\"PULL_REQUEST\\\\\\"}\\"}": Object {
"payload": Object {
"body": "@wchargin could you please do the following:
- add a commit comment
- add a review comment requesting some trivial change
- i'll change it
- then approve the pr",
"number": 5,
"title": "This pull request will be more contentious. I can feel it...",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM2OTE2MjIyMg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"}\\"}": Object {
"payload": Object {
"body": "It seems apropos to reference something from a pull request comment... eg: #2 ",
"url": "https://github.com/sourcecred/example-repo/pull/3#issuecomment-369162222",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODQ0Mg==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"}\\"}": Object {
"payload": Object {
"body": "A wild COMMENT appeared!",
"url": "https://github.com/sourcecred/example-repo/issues/6#issuecomment-373768442",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODUzOA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"}\\"}": Object {
"payload": Object {
"body": "And the maintainer said, \\"Let there be comments!\\"",
"url": "https://github.com/sourcecred/example-repo/issues/6#issuecomment-373768538",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODcwMw==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"}\\"}": Object {
"payload": Object {
"body": "It should also be possible to reference by exact url: https://github.com/sourcecred/example-repo/issues/6",
"url": "https://github.com/sourcecred/example-repo/issues/2#issuecomment-373768703",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDEyOklzc3VlQ29tbWVudDM3Mzc2ODg1MA==\\\\\\",\\\\\\"type\\\\\\":\\\\\\"COMMENT\\\\\\"}\\"}": Object {
"payload": Object {
"body": "We might also reference individual comments directly.
https://github.com/sourcecred/example-repo/issues/6#issuecomment-373768538",
"url": "https://github.com/sourcecred/example-repo/issues/2#issuecomment-373768850",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDQ6VXNlcjE0MDAwMjM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"USER\\\\\\"}\\"}": Object {
"payload": Object {
"login": "dandelionmane",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzQ4MTg=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"}\\"}": Object {
"payload": Object {
"body": "This is just an example issue.",
"number": 1,
"title": "An example issue.",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzQ5ODA=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"}\\"}": Object {
"payload": Object {
"body": "This issue references another issue, namely #1",
"number": 2,
"title": "A referencing issue.",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDA5MzYzNzQ=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"}\\"}": Object {
"payload": Object {
"body": "Alas, its life as an open issue had only just begun.",
"number": 4,
"title": "A closed pull request",
},
},
"{\\"pluginName\\":\\"sourcecred/github-beta\\",\\"repositoryName\\":\\"sourcecred/example-repo\\",\\"id\\":\\"{\\\\\\"id\\\\\\":\\\\\\"MDU6SXNzdWUzMDU5OTM3NzM=\\\\\\",\\\\\\"type\\\\\\":\\\\\\"ISSUE\\\\\\"}\\"}": Object {
"payload": Object {
"body": "This issue shall shortly have a few comments.",
"number": 6,
"title": "An issue with comments",
},
},
},
}
`;

View File

@ -1,43 +1,259 @@
// @flow
import type {Node, Edge} from "./graph";
import type {Address} from "./address";
import {Graph} from "./graph";
const stringify = require("json-stable-stringify");
export const GITHUB_PLUGIN_NAME = "sourcecred/github-beta";
export type IssueNodePayload = {|
+type: "ISSUE",
+title: string,
+number: number,
+body: string,
|};
export type IssueNodeID = {|
+type: "ISSUE",
+id: string,
|};
export type PullRequestNodePayload = {|
+type: "PULL_REQUEST",
+title: string,
+number: number,
+body: string,
|};
export type PullRequestNodeID = {|
+type: "PULL_REQUEST",
+id: string,
|};
export type CommentNodePayload = {|
+type: "COMMENT",
+url: string,
+body: string,
|};
export type CommentNodeID = {|
+type: "COMMENT",
+id: string,
|};
export type UserNodePayload = {|
+type: "USER",
+userName: string,
+login: string,
|};
export type UserNodeID = {|
+type: "USER",
+id: string,
|};
export type BotNodePayload = {|
+login: string,
|};
export type BotNodeID = {|
+type: "BOT",
+id: string,
|};
export type OrganizationNodePayload = {|
+login: string,
|};
export type OrganizationNodeID = {|
+type: "ORGANIZATION",
+id: string,
|};
export type AuthorNodePayload =
| UserNodePayload
| BotNodePayload
| OrganizationNodePayload;
export type AuthorNodeID = UserNodeID | BotNodeID | OrganizationNodeID;
export type NodePayload =
| IssueNodePayload
| PullRequestNodePayload
| CommentNodePayload
| UserNodePayload;
export type NodeType = $ElementType<NodePayload, "type">;
| AuthorNodePayload;
export type NodeID =
| IssueNodeID
| PullRequestNodeID
| CommentNodeID
| AuthorNodeID;
export type NodeType = $ElementType<NodeID, "type">;
export type AuthorshipEdgePayload = {|
export type AuthorshipEdgePayload = {};
export type AuthorshipEdgeID = {
+type: "AUTHORSHIP",
|};
export type ReferenceEdgePayload = {|
+contributionID: NodeID,
+authorID: NodeID,
};
export type ContainmentEdgePayload = {};
export type ContainmentEdgeID = {
+type: "CONTAINMENT",
+childID: NodeID,
+parentID: NodeID,
};
export type ReferenceEdgePayload = {};
export type ReferenceEdgeID = {
+type: "REFERENCE",
|};
+referrer: NodeID,
+referent: NodeID,
};
export type EdgePayload = AuthorshipEdgePayload | ReferenceEdgePayload;
export type EdgeType = $ElementType<EdgePayload, "type">;
export type EdgePayload =
| AuthorshipEdgePayload
| ContainmentEdgePayload
| ReferenceEdgePayload;
export type EdgeID = AuthorshipEdgeID | ContainmentEdgeID | ReferenceEdgeID;
export type EdgeType = $ElementType<EdgeID, "type">;
export function getNodeType(n: Node<NodePayload>): NodeType {
return JSON.parse(n.address.id).type;
}
export function getEdgeType(e: Edge<EdgePayload>): EdgeType {
return JSON.parse(e.address.id).type;
}
export class GithubParser {
repositoryName: string;
graph: Graph<NodePayload, EdgePayload>;
constructor(repositoryName: string) {
this.repositoryName = repositoryName;
this.graph = new Graph();
}
makeAddress(id: NodeID | EdgeID): Address {
return {
pluginName: GITHUB_PLUGIN_NAME,
repositoryName: this.repositoryName,
id: stringify(id),
};
}
addAuthorship(
authoredNodeID: IssueNodeID | PullRequestNodeID | CommentNodeID,
authoredNode: Node<
IssueNodePayload | PullRequestNodePayload | CommentNodePayload
>,
authorJson: *
) {
let authorPayload: AuthorNodePayload = {login: authorJson.login};
let authorID: AuthorNodeID;
switch (authorJson.__typename) {
case "User":
authorID = {type: "USER", id: authorJson.id};
break;
case "Bot":
authorID = {type: "BOT", id: authorJson.id};
break;
case "Organization":
authorID = {type: "ORGANIZATION", id: authorJson.id};
break;
default:
throw new Error(
`Unexpected author type ${authorJson.__typename} on ${stringify(
authorJson
)}`
);
}
const authorNode: Node<AuthorNodePayload> = {
address: this.makeAddress(authorID),
payload: authorPayload,
};
this.graph.addNode(authorNode);
const authorshipID = {
type: "AUTHORSHIP",
contributionID: authoredNodeID,
authorID,
};
const authorshipEdge: Edge<AuthorshipEdgePayload> = {
address: this.makeAddress(authorshipID),
payload: {},
src: authoredNode.address,
dst: authorNode.address,
};
this.graph.addEdge(authorshipEdge);
}
addComment(
parentID: IssueNodeID | PullRequestNodeID,
parentNode: Node<IssueNodePayload | PullRequestNodePayload>,
commentJson: *
) {
const commentID: CommentNodeID = {type: "COMMENT", id: commentJson.id};
const commentNodePayload: CommentNodePayload = {
body: commentJson.body,
url: commentJson.url,
};
const commentNode: Node<CommentNodePayload> = {
address: this.makeAddress(commentID),
payload: commentNodePayload,
};
this.graph.addNode(commentNode);
this.addAuthorship(commentID, commentNode, commentJson.author);
const containmentID: ContainmentEdgeID = {
type: "CONTAINMENT",
childID: commentID,
parentID: parentID,
};
const containmentEdge = {
address: this.makeAddress(containmentID),
payload: {},
src: parentNode.address,
dst: commentNode.address,
};
this.graph.addEdge(containmentEdge);
}
addIssue(issueJson: *) {
const issueID: IssueNodeID = {type: "ISSUE", id: issueJson.id};
const issuePayload: IssueNodePayload = {
number: issueJson.number,
title: issueJson.title,
body: issueJson.body,
};
const issueNode: Node<IssueNodePayload> = {
address: this.makeAddress(issueID),
payload: issuePayload,
};
this.graph.addNode(issueNode);
this.addAuthorship(issueID, issueNode, issueJson.author);
issueJson.comments.nodes.forEach((c) =>
this.addComment(issueID, issueNode, c)
);
}
addPullRequest(prJson: *) {
const pullRequestID: PullRequestNodeID = {
type: "PULL_REQUEST",
id: prJson.id,
};
const pullRequestPayload: PullRequestNodePayload = {
number: prJson.number,
title: prJson.title,
body: prJson.body,
};
const pullRequestNode: Node<PullRequestNodePayload> = {
address: this.makeAddress(pullRequestID),
payload: pullRequestPayload,
};
this.graph.addNode(pullRequestNode);
this.addAuthorship(pullRequestID, pullRequestNode, prJson.author);
prJson.comments.nodes.forEach((c) =>
this.addComment(pullRequestID, pullRequestNode, c)
);
}
addData(dataJson: *) {
dataJson.repository.issues.nodes.forEach((i) => this.addIssue(i));
dataJson.repository.pullRequests.nodes.forEach((pr) =>
this.addPullRequest(pr)
);
}
}

View File

@ -0,0 +1,84 @@
// @flow
import {GithubParser, getNodeType, getEdgeType} from "./githubPlugin";
import exampleRepoData from "./githubDemoData/example-repo.json";
describe("GithubParser", () => {
describe("whole repo parsing", () => {
const parser = new GithubParser("sourcecred/example-repo");
parser.addData(exampleRepoData.data);
const graph = parser.graph;
it("parses the entire example-repo as expected", () => {
expect(graph).toMatchSnapshot();
});
it("every comment has an author and container", () => {
const comments = graph
.getAllNodes()
.filter((n) => getNodeType(n) === "COMMENT");
expect(comments).not.toHaveLength(0);
comments.forEach((c) => {
const authorEdges = graph
.getOutEdges(c.address)
.filter((e) => getEdgeType(e) === "AUTHORSHIP");
expect(authorEdges.length).toBe(1);
const containerEdges = graph
.getInEdges(c.address)
.filter((e) => getEdgeType(e) === "CONTAINMENT");
expect(containerEdges.length).toBe(1);
});
});
it("every pull request and issue has an author", () => {
const issuesAndPRs = graph
.getAllNodes()
.filter(
(n) => ["ISSUE", "PULL_REQUEST"].indexOf(getNodeType(n)) !== -1
);
expect(issuesAndPRs).not.toHaveLength(0);
issuesAndPRs.forEach((x) => {
const outEdges = graph.getOutEdges(x.address);
const authorEdges = outEdges.filter(
(e) => getEdgeType(e) === "AUTHORSHIP"
);
expect(authorEdges.length).toBe(1);
});
});
});
describe("issue parsing", () => {
it("parses a simple issue (https://github.com/sourcecred/example-repo/issues/1)", () => {
const issue1 = exampleRepoData.data.repository.issues.nodes[0];
expect(issue1.number).toBe(1);
const parser = new GithubParser("sourcecred/example-repo");
parser.addIssue(issue1);
expect(parser.graph).toMatchSnapshot();
});
it("parses an issue with comments (https://github.com/sourcecred/example-repo/issues/6)", () => {
const issue6 = exampleRepoData.data.repository.issues.nodes[3];
expect(issue6.number).toBe(6);
const parser = new GithubParser("sourcecred/example-repo");
parser.addIssue(issue6);
expect(parser.graph).toMatchSnapshot();
});
});
describe("pull request parsing", () => {
it("parses a simple pull request (https://github.com/sourcecred/example-repo/pull/3)", () => {
const pr3 = exampleRepoData.data.repository.pullRequests.nodes[0];
expect(pr3.number).toBe(3);
const parser = new GithubParser("sourcecred/example-repo");
parser.addPullRequest(pr3);
expect(parser.graph).toMatchSnapshot();
});
it("parses a pr with review comments (https://github.com/sourcecred/example-repo/pull/3)", () => {
const pr5 = exampleRepoData.data.repository.pullRequests.nodes[1];
expect(pr5.number).toBe(5);
const parser = new GithubParser("sourcecred/example-repo");
parser.addPullRequest(pr5);
expect(parser.graph).toMatchSnapshot();
});
});
});