diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..85c6be68a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +--- + + +![Ignore Until Your PR has been created!](../blob/main/.github/ignore_unless_human.png?raw=true) +--- \ No newline at end of file diff --git a/.github/ignore_unless_human.png b/.github/ignore_unless_human.png new file mode 100644 index 000000000..da29dd66a Binary files /dev/null and b/.github/ignore_unless_human.png differ diff --git a/.github/workflows/first_time_contributor_detect.yml b/.github/workflows/first_time_contributor_detect.yml new file mode 100644 index 000000000..da8c8bb68 --- /dev/null +++ b/.github/workflows/first_time_contributor_detect.yml @@ -0,0 +1,51 @@ +name: Detect first-time contributors + +on: + pull_request_target: + types: [opened] + +permissions: + pull-requests: write + issues: write + +jobs: + detect: + runs-on: ubuntu-latest + if: >- + (github.repository == 'azahar-emu/azahar') && + (github.event.pull_request.author_association != 'COLLABORATOR') && + (github.event.pull_request.author_association != 'CONTRIBUTOR') && + (github.event.pull_request.author_association != 'MANNEQUIN') && + (github.event.pull_request.author_association != 'MEMBER') && + (github.event.pull_request.author_association != 'OWNER') + steps: + - name: Detect PR if author is first-time contributor + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo; + const pr = context.payload.pull_request; + + // Add needs verification label so that the reopen action runs on comment. + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: pr.number, + labels: ['needs verification'], + }); + + // Close the pull request and wait for verification. + await github.rest.pulls.update({ + owner, + repo, + pull_number: pr.number, + state: 'closed', + }); + + // Show the new contributor how to verify (they need to write a short poem about the Wii and 3DS being lovers) + await github.rest.issues.createComment({ + owner, + repo, + issue_number: pr.number, + body: 'Welcome to the Azahar Emulator repository! Due to the surge of AI bots we have decided to add an extra verification step to new contributors. Please follow the exact instructions in your own written Pull Request description to reopen it.', + }); diff --git a/.github/workflows/first_time_contributor_reopen.yml b/.github/workflows/first_time_contributor_reopen.yml new file mode 100644 index 000000000..b42400902 --- /dev/null +++ b/.github/workflows/first_time_contributor_reopen.yml @@ -0,0 +1,79 @@ +name: Verify first-time contributors + +on: + issue_comment: + types: [created] + +permissions: + pull-requests: write + issues: write + +jobs: + verify: + runs-on: ubuntu-latest + if: github.event.issue.pull_request && contains(github.event.issue.labels.*.name, 'needs verification') + steps: + - name: Verify and reopen PR + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo; + const issue = context.payload.issue; + const comment = context.payload.comment; + const { data: pr } = await github.rest.pulls.get({ + owner, + repo, + pull_number: issue.number, + }); + + // Only allow verification of the comment user is the author + if (comment.user.login !== pr.user.login) { + return; + } + + // Fetch user display and login names (lowercase) + const { data: user } = await github.rest.users.getByUsername({ + username: pr.user.login, + }); + const username = pr.user.login.toLowerCase(); + const displayName = (user.name || '').toLowerCase(); + + // Make comment body lowercase and split words + const body = comment.body.toLowerCase().trim().split(/\s+/); + + // Check that the user verified themselves by writing a song about the NES and the SNES. + const verified = + (body.includes(username) || + (displayName && body.includes(displayName))) && + body.includes('azahar'); + + // Only reopen the PR and remove the label if verification succeeded + if (verified) { + await github.rest.pulls.update({ + owner, + repo, + pull_number: issue.number, + state: 'open', + }); + await github.rest.issues.createComment({ + owner, + repo, + issue_number: issue.number, + body: 'Verification successful! Pull request has been reopened. Please also edit your PR description to remove the block of text between `---` to make the description easier to read.', + }); + try { + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number: issue.number, + name: 'needs verification', + }); + } catch {} + } else { + await github.rest.issues.createComment({ + owner, + repo, + issue_number: issue.number, + body: 'Verification failed! Pull request will remain closed.', + }); + }