forked from WordPress/gutenberg
-
Notifications
You must be signed in to change notification settings - Fork 0
Experimenting with compiling a contributor list for a PR. #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
desrosj
wants to merge
155
commits into
trunk
Choose a base branch
from
test/fetching-participants
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
155 commits
Select commit
Hold shift + click to select a range
c20bbad
First pass.
desrosj 05ee391
Fix syntax issue.
desrosj c5beb0c
Undo debugging.
desrosj 1f98699
Display results for context.
desrosj 2f3c4b8
Try quotes.
desrosj 3143888
Trailing `,` 🤦🏼♂️
desrosj e9d6cb8
Use named parameters.
desrosj e5ace45
Await results
desrosj eebfc0a
More work.
desrosj ab60631
Correct parenthesis.
desrosj 982b231
Try debug.
desrosj f7050bc
More tests.
desrosj ad36a96
Iterate through actual data.
desrosj ac27f87
Look up PR reviewer comments.
desrosj f136f32
Test with a GB pull.
desrosj 1cb84fc
Output debug.
desrosj c6c0b28
Correct alignment.
desrosj 06a772c
Fetch PR committers.
desrosj 27ae7e0
Correctly reference authors.
desrosj 622a1f8
Debug.
desrosj a5c239e
Test two ways of finding linked issues.
desrosj b913796
Change reference to commit author.
desrosj fb15f3d
Test a PR with user associated commits.
desrosj 60ad455
Account for authors and committers being different.
desrosj 8c7066e
Fix inline comments.
desrosj 60a7170
Debug.
desrosj 6ae6b4f
Fix syntax error.
desrosj 653f172
Back to other PR.
desrosj 6d5013f
When author or committer are null, look on the commit info.
desrosj 90a830c
Some tests.
desrosj b16834a
Syntax error.
desrosj 91c4cd3
Correct parameters.
desrosj 7f5372a
Two requests in one action.
desrosj 7f94ac0
More test.
desrosj 7c77733
More testing.
desrosj ce465e6
More edits.
desrosj 510f356
Test
desrosj 9704a2c
Test
desrosj 78aef1b
Fix typo
desrosj aa0aeff
Fix typo
desrosj 8d20b21
More variable typos.
desrosj d417203
Adjustments.
desrosj 5b2946a
🤞🏼
desrosj 1812023
Typo
desrosj 58ccb94
Change PR.
desrosj 3be93c4
Use correct endpoint.
desrosj 4dd9742
Try GraphQL.
desrosj 3481923
Define coAuthorData.
desrosj de26758
Test
desrosj 4d96ff8
Correct variables.
desrosj 760ee0c
Typoe fix.
desrosj 024914f
`Int` not `Integer`
desrosj 87d6a33
Test
desrosj 9cacf39
🤞🏼
desrosj 697f3a2
Comment out last part.
desrosj 85655b8
More debugging.
desrosj f5e2224
More.
desrosj a84513a
Digging too deep?
desrosj 363822d
Debug.
desrosj 761ca61
Add more info to author.
desrosj 2b43d5b
More user info.
desrosj 107a43a
Account for non-users making commits.
desrosj 7b821b1
Test
desrosj bc0b685
Reverse?
desrosj 2784ced
Typo
desrosj 5fa110c
Correct.
desrosj b620265
Cleanup.
desrosj 08ce9b6
Next step.
desrosj 2c3af4e
Test
desrosj 7975314
Skip bot users.
desrosj c0eef27
Fix syntax.
desrosj 0d97223
Fix error.
desrosj c81d3ff
Correct properties.
desrosj 29643da
Return data.
desrosj a925a2d
Test the returned value.
desrosj c60488b
Test
desrosj e1e9d98
More test.
desrosj 9316d15
Test querying closing issues.
desrosj b4df17a
Fix nesting.
desrosj c0feb66
Try nesting.
desrosj 7fcef4a
Try
desrosj f938523
Again?
desrosj 7212cb7
Print comments.
desrosj 3083b66
Don't map when there are none.
desrosj 8efb3ee
test
desrosj decc940
Test
desrosj 6b1502b
Indentation
desrosj 44d8b69
Expand.
desrosj 79e1670
Last?
desrosj d4a7b35
Loopdy loop
desrosj 4173b92
Check linked issues for authors and commenters.
desrosj 64c7fce
Typo
desrosj 3d790ba
New PR testing.
desrosj 6c7bd9f
Fix variable.
desrosj 69fb880
Get user data for other groups.
desrosj 77b4ec7
Spread correct.y
desrosj c880094
Try running from separate file.
desrosj c234993
Correct path.
desrosj cb72913
Keep in same file.
desrosj 02d81db
Consolidation.
desrosj 3dd8a07
Test return
desrosj 410443f
Try commenting.
desrosj 38cce8e
Correct some variables
desrosj 8a38b73
Correct typo.,
desrosj 3f8a324
Debugging.
desrosj fe5c7a9
New debug.
desrosj 075b556
Correct variable.
desrosj 1632b03
Test
desrosj 285f75f
Test.
desrosj 8d890c9
Testing.
desrosj eae943d
adjustments
desrosj 9424e58
Check for users to scan for.
desrosj c3cd403
Correct nesting.
desrosj 4d9acff
Print out `rest`
desrosj b7892d4
Test
desrosj e416e9c
Test
desrosj 44167a4
Refinement.
desrosj f653d47
Test
desrosj bebb460
Adjust.
desrosj fb78a9a
Include new line.
desrosj 83a6e68
Use a more active PR.
desrosj e65c570
Use correct comment syntax.
desrosj afefee0
Another PR. Fix skipping empty groups.
desrosj 7d0db90
Go back.
desrosj 2b80fe8
Improve formatting.
desrosj be07a8e
Improve formatting.
desrosj 3276650
Cleanup.
desrosj a91a086
Move linked issue commenters into just commenters.
desrosj ad42827
Add some additional events for testing.
desrosj c964456
Cleanup
desrosj e108b29
Limit concurrent workflows.
desrosj c0525af
Prevent multiple workflow runs.
desrosj bdc0d2c
Testing.
desrosj 9f64782
Adjust action events.
desrosj 04e4f38
Test
desrosj 6aa8e98
Test
desrosj 7bb0234
Test
desrosj 77aa9bb
Move script to different file.
desrosj f7f8a72
Typo.
desrosj fd708f5
use `async`.
desrosj 2266e6e
Use correct context for PR number.
desrosj 258003d
Test
desrosj 548eb59
Move commenting to a separate script.
desrosj e01c27b
Adjust syntax.
desrosj d6f057a
Test
desrosj 113f992
Debug.
desrosj 0dd5062
Test
desrosj 2084571
Add message back.
desrosj 86c5ff9
Test 2.
desrosj ac79173
Coding standards fixes.
desrosj 6ef9f46
Test both formats of props.
desrosj fde1acd
Fix.
desrosj 5584351
Try again.
desrosj 0c2bfa3
Stick with regular format.
desrosj a582d03
List username instead of display name.
desrosj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| name: Props Bot | ||
|
|
||
| on: | ||
| # Gathers all of the participants for pull requests to assist in giving proper credit. | ||
| pull_request: | ||
| pull_request_review: | ||
|
|
||
| # Cancels all previous workflow runs for pull requests that have not completed. | ||
| concurrency: | ||
| # The concurrency group contains the workflow name and the branch name for pull requests | ||
| # or the commit hash for any other events. | ||
| group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| pull_request_participants: | ||
| name: Gather pull request participants | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
|
|
||
| # | ||
| steps: | ||
desrosj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - name: Checkout repository | ||
| uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0 | ||
|
|
||
| - name: Compile contributor data | ||
| uses: actions/github-script@e3cbab99d3a9b271e1b79fc96d103a4a5534998c # v5.1.0 | ||
| id: contributor-data | ||
| with: | ||
desrosj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| script: | | ||
| const contribution_collector = require( './tools/props-bot/contribution-collector.js' ); | ||
| return await contribution_collector({ | ||
| github, | ||
| context | ||
| }); | ||
|
|
||
| - name: Comment on the pull request | ||
| uses: actions/github-script@e3cbab99d3a9b271e1b79fc96d103a4a5534998c # v5.1.0 | ||
| with: | ||
| script: | | ||
| const props_bot = require( './tools/props-bot/commenting.js' ); | ||
| const generatedMessage = ${{ steps.contributor-data.outputs.result }}; | ||
|
|
||
| await props_bot({ | ||
| github, | ||
| context, | ||
| generatedMessage | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| module.exports = async ( { github, context, generatedMessage } ) => { | ||
| let commentId; | ||
|
|
||
| const commentInfo = { | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: context.payload.pull_request.number, | ||
| }; | ||
|
|
||
| const commentMessage = | ||
| 'Here is a list of everyone that appears to have contributed to this PR and any linked issues:\n\n' + | ||
| '```\n' + | ||
| generatedMessage + | ||
| '\n```'; | ||
|
|
||
| const comment = { | ||
| ...commentInfo, | ||
| body: commentMessage + '\n\n<sub>contributor-collection-action</sub>', | ||
| }; | ||
|
|
||
| const comments = ( await github.rest.issues.listComments( commentInfo ) ) | ||
| .data; | ||
| for ( const currentComment of comments ) { | ||
| if ( | ||
| currentComment.user.type === 'Bot' && | ||
| /<sub>[\s\n]*contributor-collection-action/.test( currentComment.body ) | ||
| ) { | ||
| commentId = currentComment.id; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if ( commentId ) { | ||
| console.log( `Updating previous comment #${ commentId }` ); | ||
| try { | ||
| await github.rest.issues.updateComment( { | ||
| ...context.repo, | ||
| comment_id: commentId, | ||
| body: comment.body, | ||
| } ); | ||
| } catch ( e ) { | ||
| console.log( 'Error editing previous comment: ' + e.message ); | ||
| commentId = null; | ||
| } | ||
| } | ||
|
|
||
| // no previous or edit failed | ||
| if ( ! commentId ) { | ||
| console.log( 'Creating new comment' ); | ||
| try { | ||
| await github.rest.issues.createComment( comment ); | ||
| } catch ( e ) { | ||
| console.log( `Error creating comment: ${ e.message }` ); | ||
| } | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,243 @@ | ||
| const coAuthorData = { | ||
| userData: [], | ||
| }; | ||
| const contributorTypes = [ | ||
| 'committers', | ||
| 'reviewers', | ||
| 'commenters', | ||
| 'reporters', | ||
| ]; | ||
|
|
||
| module.exports = async ( { github, context } ) => { | ||
| for ( const type of contributorTypes ) { | ||
| coAuthorData[ type ] = new Set(); | ||
| } | ||
|
|
||
| /* | ||
| * Fetch the following data for the pull request: | ||
| * - Commits with author details. | ||
| * - Reviews with author logins. | ||
| * - Comments with author logins. | ||
| * - Linked issues with author logins. | ||
| * - Comments on linked issues with author logins. | ||
| */ | ||
| const contributorData = await github.graphql( | ||
| `query($owner:String!, $name:String!, $prNumber:Int!) { | ||
| repository(owner:$owner, name:$name) { | ||
| pullRequest(number:$prNumber) { | ||
| commits(first: 100) { | ||
| nodes { | ||
| commit { | ||
| author { | ||
| user { | ||
| databaseId | ||
| login | ||
| name | ||
| } | ||
| name | ||
| } | ||
| } | ||
| } | ||
| } | ||
| reviews(first: 100) { | ||
| nodes { | ||
| author { | ||
| login | ||
| } | ||
| } | ||
| } | ||
| comments(first: 100) { | ||
| nodes { | ||
| author { | ||
| login | ||
| } | ||
| } | ||
| } | ||
| closingIssuesReferences(first:100){ | ||
| nodes { | ||
| author { | ||
| login | ||
| } | ||
| comments(first:100) { | ||
| nodes { | ||
| author { | ||
| login | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }`, | ||
| { | ||
| owner: context.repo.owner, | ||
| name: context.repo.repo, | ||
| prNumber: context.payload.pull_request.number, | ||
| } | ||
| ); | ||
|
|
||
| // Process pull request commits. | ||
| for ( const commit of contributorData.repository.pullRequest.commits | ||
| .nodes ) { | ||
| /* | ||
| * Commits are sometimes made by an email that is not associated with a GitHub account. | ||
| * For these, info that may help us guess later. | ||
| */ | ||
| if ( null === commit.commit.author.user ) { | ||
| coAuthorData.committers.add( commit.commit.author.email ); | ||
| coAuthorData.userData[ commit.commit.author.email ] = { | ||
| name: commit.commit.author.name, | ||
| email: commit.commit.author.email, | ||
| }; | ||
| } else { | ||
| if ( skipUser( commit.commit.author.user.login ) ) { | ||
| continue; | ||
| } | ||
|
|
||
| coAuthorData.committers.add( commit.commit.author.user.login ); | ||
| coAuthorData.userData[ commit.commit.author.user.login ] = | ||
| commit.commit.author.user; | ||
| } | ||
| } | ||
|
|
||
| // Process pull request reviews. | ||
| for ( const review of contributorData.repository.pullRequest.reviews | ||
| .nodes ) { | ||
| if ( skipUser( review.author.login ) ) { | ||
| continue; | ||
| } | ||
|
|
||
| coAuthorData.reviewers.add( review.author.login ); | ||
| } | ||
|
|
||
| // Process pull request comments. | ||
| for ( const comment of contributorData.repository.pullRequest.comments | ||
| .nodes ) { | ||
| if ( skipUser( comment.author.login ) ) { | ||
| continue; | ||
| } | ||
|
|
||
| coAuthorData.commenters.add( comment.author.login ); | ||
| } | ||
|
|
||
| // Process reporters and commenters for linked issues. | ||
| for ( const linkedIssue of contributorData.repository.pullRequest | ||
| .closingIssuesReferences.nodes ) { | ||
| if ( ! skipUser( linkedIssue.author.login ) ) { | ||
| coAuthorData.reporters.add( linkedIssue.author.login ); | ||
| } | ||
|
|
||
| for ( const issueComment of linkedIssue.comments.nodes ) { | ||
| if ( skipUser( issueComment.author.login ) ) { | ||
| continue; | ||
| } | ||
|
|
||
| coAuthorData.commenters.add( issueComment.author.login ); | ||
| } | ||
| } | ||
|
|
||
| // We already have user info for committers, we need to grab it for everyone else. | ||
| if ( | ||
| [ | ||
| ...coAuthorData.reviewers, | ||
| ...coAuthorData.commenters, | ||
| ...coAuthorData.reporters, | ||
| ].length > 0 | ||
| ) { | ||
| const userData = await github.graphql( | ||
| '{' + | ||
| [ | ||
| ...coAuthorData.reviewers, | ||
| ...coAuthorData.commenters, | ||
| ...coAuthorData.reporters, | ||
| ].map( | ||
| ( user ) => | ||
| escapeForGql( user ) + | ||
| `: user(login: "${ user }") {databaseId, login, name, email}` | ||
| ) + | ||
| '}' | ||
| ); | ||
|
|
||
| Object.values( userData ).forEach( ( user ) => { | ||
| coAuthorData.userData[ user.login ] = user; | ||
| } ); | ||
| } | ||
|
|
||
| console.debug( coAuthorData ); | ||
|
|
||
| return contributorTypes | ||
| .map( ( priority ) => { | ||
| // Skip an empty set of contributors. | ||
| if ( coAuthorData[ priority ].length === 0 ) { | ||
| return []; | ||
| } | ||
|
|
||
| // Add a header for each section. | ||
| const header = | ||
| '# ' + | ||
| priority.replace( /^./, ( char ) => char.toUpperCase() ) + | ||
| '\n'; | ||
|
|
||
| // Generate each Co-authored-by entry, and join them into a single string. | ||
| return ( | ||
| header + | ||
| [ ...coAuthorData[ priority ] ] | ||
| .map( ( username ) => { | ||
| const { | ||
| name, | ||
| databaseId, | ||
| email, | ||
| } = coAuthorData.userData[ username ]; | ||
| const commitEmail = | ||
| email || | ||
| `${ databaseId }+${ username }@users.noreply.github.com`; | ||
|
|
||
| return `Co-authored-by: ${ username } <${ commitEmail }>`; | ||
| } ) | ||
| .join( '\n' ) | ||
| ); | ||
| } ) | ||
| .join( '\n\n' ); | ||
| }; | ||
|
|
||
| const escapeForGql = ( string ) => '_' + string.replace( /[./-]/g, '_' ); | ||
|
|
||
| /** | ||
| * Checks if a user should be skipped. | ||
| * | ||
| * @param {string} username Username to check. | ||
| * | ||
| * @return {boolean} true if the username should be skipped. false otherwise. | ||
| */ | ||
| function skipUser( username ) { | ||
| const skippedUsers = [ 'github-actions' ]; | ||
|
|
||
| if ( | ||
| -1 === skippedUsers.indexOf( username ) && | ||
| ! contributorAlreadyPresent( username ) | ||
| ) { | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Checks if a user has already been added to the list of contributors to receive props. | ||
| * | ||
| * Contributors should only appear in the props list once, even when contributing in multiple ways. | ||
| * | ||
| * @param {string} username The username to check. | ||
| * | ||
| * @return {boolean} true if the username is already in the list. false otherwise. | ||
| */ | ||
| function contributorAlreadyPresent( username ) { | ||
| for ( const contributorType of contributorTypes ) { | ||
| if ( coAuthorData[ contributorType ].has( username ) ) { | ||
| return true; | ||
| } | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.