Contributor Assistant #21284
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
| name: Contributor Assistant | |
| on: | |
| pull_request_target: | |
| types: [opened] | |
| check_suite: | |
| types: [completed] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| checks: read | |
| jobs: | |
| check-dco: | |
| runs-on: ubuntu-latest | |
| # Only run for PR opened events or when check suite completes with failure | |
| if: | | |
| github.event_name == 'pull_request_target' || | |
| (github.event_name == 'check_suite' && | |
| github.event.check_suite.conclusion == 'failure' && | |
| github.event.check_suite.pull_requests[0] != null) | |
| steps: | |
| - name: Get Pull Request and Check DCO Status | |
| id: check_dco | |
| uses: actions/github-script@v8 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| let prNumber; | |
| // Get PR number based on event type | |
| if (context.eventName === 'pull_request_target') { | |
| prNumber = context.issue.number; | |
| } else if (context.eventName === 'check_suite') { | |
| const pulls = context.payload.check_suite.pull_requests; | |
| if (pulls && pulls.length > 0) { | |
| prNumber = pulls[0].number; | |
| } else { | |
| console.log('No PR associated with this check suite'); | |
| return; | |
| } | |
| } | |
| // Get PR details | |
| const { data: pr } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber | |
| }); | |
| // Get check runs for this PR | |
| const { data: checkRuns } = await github.rest.checks.listForRef({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| ref: pr.head.sha | |
| }); | |
| // Find the DCO check | |
| const dcoCheck = checkRuns.check_runs.find(run => run.name === 'DCO'); | |
| if (!dcoCheck) { | |
| console.log('No DCO check found'); | |
| return; | |
| } | |
| // If DCO check passed, no need to comment | |
| if (dcoCheck.conclusion === 'success') { | |
| console.log('DCO check passed, no comment needed'); | |
| return; | |
| } | |
| console.log(`DCO check failed for PR #${prNumber}`); | |
| // Check for existing comment | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber | |
| }); | |
| const existingComment = comments.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('<!-- dco-helper-comment -->') | |
| ); | |
| if (existingComment) { | |
| console.log('DCO helper comment already exists, skipping'); | |
| return; | |
| } | |
| // Post the comment | |
| const comment = `👋 Hi @${pr.user.login}! Thanks for your contribution to this project. | |
| It looks like one or more of your commits are missing a DCO (Developer Certificate of Origin) sign-off. The DCO is a simple way for you to certify that you have the right to submit this code under the project's license. | |
| **How to fix this:** | |
| \`\`\`bash | |
| # For future commits, use the -s flag | |
| git commit -s -m "Your commit message" | |
| # To sign off on existing commits in this PR | |
| git rebase HEAD~$(git rev-list --count origin/${pr.base.ref}..HEAD) --signoff | |
| git push --force-with-lease | |
| \`\`\` | |
| The \`-s\` flag adds this line to your commit message: | |
| \`Signed-off-by: Your Name <[email protected]>\` | |
| 📋 **[View the failing DCO check for more details](${dcoCheck.html_url})** | |
| For more information about the DCO, visit: https://developercertificate.org/ | |
| <!-- dco-helper-comment -->`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: comment | |
| }); | |
| console.log(`Posted DCO helper comment to PR #${prNumber}`); |