diff --git a/.github/scripts/pr-redirect.js b/.github/scripts/pr-redirect.js index b347c84a4..e6dcd5a70 100644 --- a/.github/scripts/pr-redirect.js +++ b/.github/scripts/pr-redirect.js @@ -44,6 +44,22 @@ function createRedirect({ github, context, core }) { return writeAccess.get(username) } + const mergedPullRequests = new Map() + async function hasMergedPullRequest(login) { + if (!mergedPullRequests.has(login)) { + const { search } = await github.graphql( + `query ($query: String!) { + search(query: $query, type: ISSUE, first: 1) { + issueCount + } + }`, + { query: `repo:${owner}/${repo} is:pr is:merged author:${login}` }, + ) + mergedPullRequests.set(login, search.issueCount > 0) + } + return mergedPullRequests.get(login) + } + async function findReasonToSkip(pr, approved) { // anyone can open a PR between two branches of this repository, only an installed app is trusted here if (pr.head.repo?.full_name === `${owner}/${repo}` && pr.user.type === 'Bot') { @@ -58,6 +74,10 @@ function createRedirect({ github, context, core }) { if (approved.has(pr.user.id)) { return 'the author is an approved contributor' } + // a merged PR vouches for a person, not for an app + if (pr.user.type === 'User' && (await hasMergedPullRequest(pr.user.login))) { + return 'the author has a merged pull request' + } return null } @@ -132,7 +152,7 @@ function createRedirect({ github, context, core }) { ? `Please keep the discussion in ${issues.map((issue) => `#${issue.number}`).join(', ')}.` : `If there is no issue for this change yet, please [open one](https://github.com/${owner}/${repo}/issues/new/choose) to discuss it with the team first.` return createComment(POLICY_MARKER, pr, [ - `Unfortunately, the team accepts pull requests only from maintainers and approved contributors, or for issues with the \`${APPROVED_LABEL}\` label, so this pull request was closed automatically. We are sorry about that, it is not a judgement of your work. The number of pull requests grew beyond what the team can review, and this policy gives maintainers the space to triage and prioritize issues at their own pace.`, + `Unfortunately, the team accepts pull requests only from maintainers, from anyone who contributed before, from approved contributors, or for issues with the \`${APPROVED_LABEL}\` label, so this pull request was closed automatically. We are sorry about that, it is not a judgement of your work. The number of pull requests grew beyond what the team can review, and this policy gives maintainers the space to triage and prioritize issues at their own pace.`, '', `${nextStep} Your changes are not lost: a maintainer can reopen this pull request if the team decides to go forward with it. See our [pull request policy](${policyUrl}) for more context.`, ]) diff --git a/AGENTS.md b/AGENTS.md index 5aff90368..9cd0706f0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -262,4 +262,4 @@ PRs are squash-merged, so the PR title becomes the commit message. Nothing in CI This repository has a limit of 1 PR if you don't have write access. DO NOT try to bypass it by creating draft PRs. If you cannot create a pull request, let a human know that you will not breach this repository's policy because it will ban the PR author in Vitest organisation. -A PR from a user who is not an approved contributor is closed automatically as soon as it is opened, unless it fixes an open issue with the `approved` label that has no other open PR (see "Pull Request Policy" in CONTRIBUTING.md). Tell your operator about this policy before you open a PR. DO NOT try to bypass it. +A PR from a user who has not contributed before and is not an approved contributor is closed automatically as soon as it is opened, unless it fixes an open issue with the `approved` label that has no other open PR (see "Pull Request Policy" in CONTRIBUTING.md). Tell your operator about this policy before you open a PR. DO NOT try to bypass it. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77d70d246..eefa56c21 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -83,7 +83,7 @@ npm i https://pkg.pr.new/vitest@{commit} ## Pull Request Policy -The team accepts pull requests from members of the Vitest team, from [approved contributors](https://github.com/vitest-dev/vitest/blob/approved-contributors/APPROVED_CONTRIBUTORS), and for open issues with the [`approved`](https://github.com/vitest-dev/vitest/issues?q=is%3Aissue%20state%3Aopen%20label%3Aapproved) label. Any other pull request is closed automatically as soon as it is opened. +The team accepts pull requests from members of the Vitest team, from anyone who contributed before, from [approved contributors](https://github.com/vitest-dev/vitest/blob/approved-contributors/APPROVED_CONTRIBUTORS), and for open issues with the [`approved`](https://github.com/vitest-dev/vitest/issues?q=is%3Aissue%20state%3Aopen%20label%3Aapproved) label. Any other pull request is closed automatically as soon as it is opened. To work on an approved issue, open the pull request against `main` and link the issue in its description with a [closing keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), for example `Fixes #123`. The team accepts one pull request per issue: if another pull request for the same issue is already open, the new one is closed automatically. @@ -249,7 +249,7 @@ flowchart TD ### Pull Request Redirect -The [`AI Policy`](./.github/workflows/ai-policy.yml) workflow applies the [pull request policy](#pull-request-policy) when a pull request is opened or reopened. It comments on the pull request, pointing to the linked issues or asking to open a new one, and closes it. It never touches pull requests from members of the `vitest-dev` organization, from repository collaborators, or from apps that push branches to this repository (for example, Renovate). Users with write access to the repository control the rest: +The [`AI Policy`](./.github/workflows/ai-policy.yml) workflow applies the [pull request policy](#pull-request-policy) when a pull request is opened or reopened. It comments on the pull request, pointing to the linked issues or asking to open a new one, and closes it. It never touches pull requests from members of the `vitest-dev` organization, from repository collaborators, from anyone who contributed before, or from apps that push branches to this repository (for example, Renovate). Users with write access to the repository control the rest: - Add the `approved` label to an issue to accept a pull request for it from anyone. The workflow keeps such a pull request open if it links the issue with a closing keyword, the issue is open, and no other open pull request links the same issue. The label does not reopen pull requests that the workflow closed before. - Reopen a pull request to keep it open. If someone without write access reopens it, the workflow applies the policy again.