Copilot commented on code in PR #55484:
URL: https://github.com/apache/arrow/pull/55484#discussion_r4536145175
##########
dev/release/post-10-bump-versions.sh:
##########
@@ -94,13 +103,37 @@ if [ ${BUMP_LINUX_PACKAGES} -gt 0 ]; then
fi
if [ ${BUMP_PUSH} -gt 0 ]; then
- echo "Pushing changes to the default branch in apache/arrow"
- git push upstream ${DEFAULT_BRANCH}
+ echo "Pushing changes to the ${branch_name} branch in your fork"
+ git push -u origin "${branch_name}"
+ github_url=$(git remote get-url origin | \
+ sed \
+ -e 's,^[email protected]:,https://github.com/,' \
+ -e 's,\.git$,,')
+ echo "Create a pull request with the following title and merge it:"
+ echo " ${pull_request_title}"
+ echo " ${github_url}/pull/new/${branch_name}"
fi
if [ ${BUMP_TAG} -gt 0 -a ${is_major_release} -gt 0 ]; then
dev_tag=apache-arrow-${next_version}.dev
- echo "Tagging ${dev_tag}"
- git tag ${dev_tag} ${DEFAULT_BRANCH}
- git push upstream ${dev_tag}
+ if [ ${BUMP_PUSH} -gt 0 ]; then
Review Comment:
`BUMP_PUSH=0` is documented as the way to review the generated commits
before pushing, but `BUMP_TAG` still defaults to 1. For a major release, that
invocation now immediately searches upstream for the not-yet-created PR and
exits with “The pull request isn't merged yet” instead of completing the
preparation step. Distinguish a tag-only rerun from an ordinary no-push
preparation run, and defer tagging for the latter as well.
##########
.github/workflows/dev_pr/merged.js:
##########
@@ -0,0 +1,216 @@
+// 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 helpers = require("./helpers.js");
+
+const VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
+
+/**
+ * Compares two versions like "23.0.0" numerically.
+ *
+ * @param {String} a
+ * @param {String} b
+ * @returns {Number} negative if a < b, positive if a > b, 0 otherwise.
+ */
+function compareVersions(a, b) {
+ const aParts = a.split(".").map(Number);
+ const bParts = b.split(".").map(Number);
+ for (let i = 0; i < aParts.length; i++) {
+ if (aParts[i] !== bParts[i]) {
+ return aParts[i] - bParts[i];
+ }
+ }
+ return 0;
+}
+
+/**
+ * Chooses the version a pull request merged into main is released in.
+ * This mirrors get_candidate_fix_version() in dev/merge_arrow_pr.py.
+ *
+ * @param {Array<String>} versions - The titles of the open milestones.
+ * @param {Array<String>} maintenanceBranches - The maint-X.Y.Z branches.
+ * @returns {String} the version or null if no version can be chosen.
+ */
+function detectFixVersion(versions, maintenanceBranches) {
+ versions = versions.filter((version) => VERSION_PATTERN.test(version));
+ const majorVersions = versions.filter((version) =>
version.endsWith(".0.0"));
+ if (versions.length > majorVersions.length) {
+ // If there is a future major release, suggest that
+ versions = majorVersions;
+ }
+ versions = versions
+ .filter((version) => !maintenanceBranches.includes(`maint-${version}`))
+ .sort(compareVersions);
+ return versions.length > 0 ? versions[0] : null;
+}
+
+/**
+ * Removes the PR workflow state labels from the merged pull request.
+ *
+ * @param {Object} github
+ * @param {Object} context
+ * @param {Object} pullRequest
+ */
+async function clearStateLabels(github, context, pullRequest) {
+ for (const label of pullRequest.labels) {
+ // All PR workflow state labels starts with "awaiting"
+ if (!label.name.startsWith("awaiting")) {
+ continue;
+ }
+ try {
+ await github.rest.issues.removeLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: pullRequest.number,
+ name: label.name
+ });
+ } catch (error) {
+ // The label may be already removed.
+ if (error.status !== 404) {
+ throw error;
+ }
+ }
+ }
+}
+
+/**
+ * Assigns the milestone of the release the pull request is part of to the
+ * GitHub Issue. It's the milestone of the pull request if it has one.
+ * Otherwise an already assigned milestone is kept or the next major
+ * release is used.
+ *
+ * @param {Object} github
+ * @param {Object} context
+ * @param {Object} pullRequest
+ * @param {Object} issueInfo
+ */
+async function assignMilestone(github, context, pullRequest, issueInfo) {
+ if (pullRequest.milestone) {
+ if (issueInfo.milestone?.number !== pullRequest.milestone.number) {
+ await github.rest.issues.update({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: issueInfo.number,
+ milestone: pullRequest.milestone.number
+ });
+ }
+ return;
+ }
+ if (issueInfo.milestone) {
+ return;
+ }
+ const milestones = await
github.paginate(github.rest.issues.listMilestones, {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ state: "open",
+ per_page: 100
+ });
+ const branches = await github.paginate(github.rest.repos.listBranches, {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ per_page: 100
+ });
+ const fixVersion = detectFixVersion(
+ milestones.map((milestone) => milestone.title),
+ branches
+ .map((branch) => branch.name)
+ .filter((name) => name.startsWith("maint-")));
+ if (!fixVersion) {
+ console.log(`No milestone found for GitHub issue
#${issueInfo.number}`);
+ return;
+ }
+ await github.rest.issues.update({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: issueInfo.number,
+ milestone: milestones.find((milestone) => milestone.title ===
fixVersion).number
+ });
+}
+
+/**
+ * Closes the GitHub Issue and comments which pull request resolved it
+ * after that. GitHub may have closed the issue already if the pull
+ * request description has "Closes #XXX".
+ *
+ * @param {Object} github
+ * @param {Object} context
+ * @param {Object} pullRequest
+ * @param {Object} issueInfo
+ */
+async function closeGitHubIssue(github, context, pullRequest, issueInfo) {
+ const issue = {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: issueInfo.number,
+ };
+ if (issueInfo.state !== "closed") {
+ await github.rest.issues.update({...issue, state: "closed"});
+ }
+ // The merge script may have added the same comment.
+ const body = `Issue resolved by pull request
${pullRequest.number}\n${pullRequest.html_url}`;
+ const comments = await github.paginate(
+ github.rest.issues.listComments, {...issue, per_page: 100});
+ if (comments.some((comment) => comment.body === body)) {
+ return;
+ }
+ await github.rest.issues.createComment({...issue, body});
+}
+
+/**
+ * Does what is needed after a pull request is merged.
+ *
+ * @param {Object} github
+ * @param {Object} context
+ * @param {Object} pullRequest
+ */
+async function resolve(github, context, pullRequest) {
+ await clearStateLabels(github, context, pullRequest);
+ const issue = helpers.detectIssue(pullRequest.title);
+ if (!issue || issue.kind !== "github") {
+ return;
+ }
+ const issueInfo = await helpers.getGitHubInfo(github, context, issue.id,
pullRequest.number);
+ if (!issueInfo) {
+ throw new Error(`GitHub issue #${issue.id} could not be retrieved.`);
+ }
+ await assignMilestone(github, context, pullRequest, issueInfo);
Review Comment:
With `CI: skip merge check`, a title whose GH number refers to another pull
request reaches this path unchecked. The issues endpoint returns PRs too, so
this assigns a milestone to that PR and then closes it as resolved. Reject
`issueInfo.pull_request` here before making any updates, independently of
whether pre-merge validation was bypassed.
--
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]