Copilot commented on code in PR #51200:
URL: https://github.com/apache/arrow/pull/51200#discussion_r3956760743


##########
.github/workflows/pr_limit.yml:
##########
@@ -0,0 +1,66 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Limits the number of concurrently open pull requests a contributor
+# without write access can have. This mirrors GitHub's native
+# "pull request creation cap" setting, which requires admin rights and
+# so can only be configured for ASF repositories via .asf.yaml. Once
+# https://github.com/apache/infrastructure-asfyaml/pull/111 is merged,
+# this workflow can be replaced by the `github.pull_requests.creation_cap`
+# directive in .asf.yaml.
+
+name: PR Limit
+
+on:
+  pull_request_target:
+    types:
+      - opened
+      - reopened
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.repository }}-${{ 
github.event.number }}
+  cancel-in-progress: true
+
+permissions:
+  pull-requests: write
+  issues: write
+

Review Comment:
   The workflow checks out the repository, but `permissions` omits `contents: 
read`, which can cause `actions/checkout` to fail when the workflow token has 
no contents access. Add `contents: read` (as other pull_request_target 
workflows here do).



##########
.github/workflows/pr_limit/check.js:
##########
@@ -0,0 +1,130 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+const fs = require("fs");
+
+const WRITE_PERMISSIONS = new Set(["write", "maintain", "admin"]);
+
+/**
+ * Returns whether the user has write access to the repository.
+ *
+ * Note that `author_association` is not a reliable signal for this:
+ * ASF members show up as MEMBER regardless of their permission on this
+ * repository, and triage collaborators show up as COLLABORATOR.
+ *
+ * @param {Object} github
+ * @param {Object} context
+ * @param {String} username
+ */
+async function hasWriteAccess(github, context, username) {
+  try {
+    const {data} = await github.rest.repos.getCollaboratorPermissionLevel({
+      owner: context.repo.owner,
+      repo: context.repo.repo,
+      username: username
+    });
+    return WRITE_PERMISSIONS.has(data.permission);
+  } catch (error) {
+    if (error.status === 404) {
+      return false;
+    }
+    throw error;
+  }
+}
+
+/**
+ * Returns the number of open pull requests authored by the user in this
+ * repository, including the one that triggered the workflow.
+ *
+ * @param {Object} github
+ * @param {Object} context
+ * @param {String} username
+ */
+async function countOpenPullRequests(github, context, username) {
+  const {data} = await github.rest.search.issuesAndPullRequests({
+    q: `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open 
author:${username}`,
+    per_page: 1
+  });
+  return data.total_count;
+}
+
+/**
+ * Comments on the pull request explaining the limit, then closes it.
+ *
+ * @param {Object} github
+ * @param {Object} context
+ * @param {Number} pullRequestNumber
+ * @param {String} username
+ * @param {Number} limit
+ * @param {Number} count
+ */
+async function commentAndClose(github, context, pullRequestNumber, username, 
limit, count) {
+  const commentPath = ".github/workflows/pr_limit/comment.md";
+  const comment = fs.readFileSync(commentPath).toString()
+    .replaceAll("${PR_LIMIT}", limit)
+    .replaceAll("${OPEN_COUNT}", count)
+    .replaceAll("${USERNAME}", username);
+  await github.rest.issues.createComment({
+    owner: context.repo.owner,
+    repo: context.repo.repo,
+    issue_number: pullRequestNumber,
+    body: comment
+  });
+  await github.rest.pulls.update({
+    owner: context.repo.owner,
+    repo: context.repo.repo,
+    pull_number: pullRequestNumber,
+    state: "closed"
+  });
+}

Review Comment:
   On repeated `reopened` events while still over the limit, this will add a 
new identical comment each time, which can create noisy comment spam. Consider 
only posting the explanatory comment once (but still closing the PR each time 
it’s reopened while over the limit).



##########
.github/workflows/pr_limit/comment.md:
##########
@@ -0,0 +1,31 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+Thanks for opening a pull request!
+
+**This pull request has been automatically closed because you currently have 
${OPEN_COUNT} open pull requests, which is more than the limit of ${PR_LIMIT}.**
+
+To keep the review queue manageable, Apache Arrow limits contributors without 
write access to ${PR_LIMIT} concurrently open pull requests. This helps make 
sure each pull request gets the attention it needs and that work in progress 
does not go stale.
+
+Once one of [your other open pull 
requests](https://github.com/apache/arrow/pulls/${USERNAME}) has been merged or 
closed, you are welcome to reopen this one.

Review Comment:
   This link doesn’t resolve to the author’s PR list (`/pulls/${USERNAME}` 
isn’t a valid GitHub pulls URL). Use the pulls search query instead so the 
recipient can quickly find their open PRs.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to