|
| 1 | +name: PR Gate |
| 2 | + |
| 3 | +on: |
| 4 | + pull_request_target: |
| 5 | + types: [opened, reopened, synchronize] |
| 6 | + |
| 7 | +permissions: |
| 8 | + pull-requests: write |
| 9 | + issues: write |
| 10 | + contents: read |
| 11 | + |
| 12 | +jobs: |
| 13 | + gate: |
| 14 | + runs-on: ubuntu-latest |
| 15 | + steps: |
| 16 | + - uses: actions/checkout@v4 |
| 17 | + - name: Close pull requests from unapproved contributors |
| 18 | + uses: actions/github-script@v7 |
| 19 | + with: |
| 20 | + script: | |
| 21 | + const fs = require('fs'); |
| 22 | + const approvedPath = '.github/APPROVED_CONTRIBUTORS'; |
| 23 | + const approved = fs.existsSync(approvedPath) |
| 24 | + ? fs.readFileSync(approvedPath, 'utf8') |
| 25 | + .split(/\r?\n/) |
| 26 | + .map(line => line.trim().toLowerCase()) |
| 27 | + .filter(line => line && !line.startsWith('#')) |
| 28 | + : []; |
| 29 | + const pr = context.payload.pull_request; |
| 30 | + const user = pr.user.login.toLowerCase(); |
| 31 | + const authorAssociation = pr.author_association; |
| 32 | + const trusted = approved.includes(user) || ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(authorAssociation); |
| 33 | + if (trusted) return; |
| 34 | + await github.rest.issues.createComment({ |
| 35 | + owner: context.repo.owner, |
| 36 | + repo: context.repo.repo, |
| 37 | + issue_number: pr.number, |
| 38 | + body: 'Thanks for the contribution. Journalit is public-source for transparency and Obsidian review, but the private repository remains the source of truth. Public pull requests are limited to approved contributors, so this PR is being closed automatically. Please use Discord first: https://discord.gg/AkSw3D9h8b.' |
| 39 | + }); |
| 40 | + await github.rest.pulls.update({ |
| 41 | + owner: context.repo.owner, |
| 42 | + repo: context.repo.repo, |
| 43 | + pull_number: pr.number, |
| 44 | + state: 'closed' |
| 45 | + }); |
0 commit comments