mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-30 12:25:49 +00:00
The intake workflow re-closes a reopened PR whose author is still over the open-PR limit, so a maintainer cannot rescue PRs it auto-closed. When the reopening actor has write, maintain or admin permission, skip the limit and remove the "open PR limit" label instead. Contributor reopens behave as before, and if the permission lookup fails the limit still applies.
102 lines
4.6 KiB
YAML
102 lines
4.6 KiB
YAML
name: PR intake
|
|
|
|
on:
|
|
pull_request_target:
|
|
branches: [main]
|
|
types: [opened, reopened]
|
|
|
|
permissions: {}
|
|
|
|
concurrency:
|
|
group: pr-intake-${{ github.event.pull_request.number }}
|
|
|
|
jobs:
|
|
intake:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
permissions:
|
|
issues: write
|
|
pull-requests: write
|
|
steps:
|
|
- uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const { owner, repo } = context.repo;
|
|
const pull_number = context.payload.pull_request.number;
|
|
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number });
|
|
if (pr.state !== 'open' || pr.base.ref !== 'main') {
|
|
return;
|
|
}
|
|
if (context.payload.action === 'reopened') {
|
|
let maintainer = false;
|
|
try {
|
|
const { data: access } = await github.rest.repos.getCollaboratorPermissionLevel({
|
|
owner, repo, username: context.payload.sender.login
|
|
});
|
|
maintainer = ['admin', 'maintain', 'write'].includes(access.role_name ?? access.permission);
|
|
} catch (error) {
|
|
core.warning(`Could not check the permission of ${context.payload.sender.login}, so the open PR limit applies: ${error.message}`);
|
|
}
|
|
if (maintainer) {
|
|
try {
|
|
await github.rest.issues.removeLabel({ owner, repo, issue_number: pull_number, name: 'open PR limit' });
|
|
} catch (error) {
|
|
if (error.status !== 404) {
|
|
core.warning(`Could not remove the open PR limit label: ${error.message}`);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
const { data: mergedPRs } = await github.rest.search.issuesAndPullRequests({
|
|
q: `repo:${owner}/${repo} is:pr is:merged base:main author:${pr.user.login}`,
|
|
per_page: 1
|
|
});
|
|
if (mergedPRs.incomplete_results || !Number.isSafeInteger(mergedPRs.total_count) || mergedPRs.total_count < 0) {
|
|
throw new Error('Could not reliably count merged pull requests');
|
|
}
|
|
const merged = mergedPRs.total_count;
|
|
if (merged >= 20) {
|
|
return;
|
|
}
|
|
const allowedOpen = merged >= 1 ? 20 : 1;
|
|
const openPRs = await github.paginate(github.rest.pulls.list, {
|
|
owner, repo, state: 'open', base: 'main', per_page: 100
|
|
});
|
|
const reopened = context.payload.action === 'reopened';
|
|
const open = new Set(openPRs
|
|
.filter((p) => p.user.login === pr.user.login && (reopened || p.number < pull_number))
|
|
.map((p) => p.number));
|
|
open.add(pull_number);
|
|
if (open.size <= allowedOpen) {
|
|
return;
|
|
}
|
|
const name = 'open PR limit';
|
|
try {
|
|
await github.rest.issues.getLabel({ owner, repo, name });
|
|
} catch (error) {
|
|
if (error.status !== 404) {
|
|
throw error;
|
|
}
|
|
try {
|
|
await github.rest.issues.createLabel({
|
|
owner, repo, name, color: 'd93f0b',
|
|
description: 'Closed over the open PR limit: 1 without merged PRs, 20 with at least 1, none from 20'
|
|
});
|
|
} catch (createError) {
|
|
if (createError.status !== 422) {
|
|
throw createError;
|
|
}
|
|
await github.rest.issues.getLabel({ owner, repo, name });
|
|
}
|
|
}
|
|
await github.rest.issues.addLabels({ owner, repo, issue_number: pull_number, labels: [name] });
|
|
const body = 'Thank you for your contribution! Authors with no pull requests merged into `main` can have 1 open pull request at a time, authors with at least 1 merged can have 20, and from 20 merged there is no limit. This PR has been automatically closed and labeled "open PR limit" because that limit was reached. This is not a judgment of the quality of your changes: reopen it once one of your open pull requests is merged or closed.';
|
|
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
owner, repo, issue_number: pull_number, per_page: 100
|
|
});
|
|
if (!comments.some((comment) => comment.user.login === 'github-actions[bot]' && comment.body === body)) {
|
|
await github.rest.issues.createComment({ owner, repo, issue_number: pull_number, body });
|
|
}
|
|
await github.rest.pulls.update({ owner, repo, pull_number, state: 'closed' });
|