mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 18:25:13 +08:00
Recognize the error symbol emitted by core-validate-commit so validation failures appear outside the collapsed output. Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: https://github.com/nodejs/node/pull/65913 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Xuguang Mei <meixuguang@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
187 lines
5.8 KiB
Bash
Executable File
187 lines
5.8 KiB
Bash
Executable File
#!/bin/sh
|
||
|
||
set -xe
|
||
|
||
UPSTREAM=origin
|
||
DEFAULT_BRANCH=main
|
||
|
||
COMMIT_QUEUE_LABEL="commit-queue"
|
||
COMMIT_QUEUE_FAILED_LABEL="commit-queue-failed"
|
||
LACKS_SECOND_APPROVAL_LABEL="lacks-second-approval"
|
||
|
||
cqurl="${GITHUB_SERVER_URL:?}/${GITHUB_REPOSITORY:?}/actions/runs/${GITHUB_RUN_ID:?}"
|
||
|
||
escape_code_block_or_line() {
|
||
case $1 in
|
||
*"
|
||
"*|'') fence='```' sep='
|
||
' ;;
|
||
*[![:space:]]*) fence='`' sep=' ' ;;
|
||
*) fence='`' sep='' ;;
|
||
esac
|
||
while case $1 in *"$fence"*) ;; *) false ;; esac; do
|
||
fence=$fence'`'
|
||
done
|
||
printf '%s%s%s%s%s\n' "$fence" "$sep" "$1" "$sep" "$fence"
|
||
}
|
||
|
||
edit_pr_labels() {
|
||
pr=$1
|
||
failure_mode=$2
|
||
shift 2
|
||
if gh -R "$GITHUB_REPOSITORY" pr edit "$pr" "$@"; then
|
||
return
|
||
fi
|
||
if [ "$failure_mode" = warn ]; then
|
||
echo "::warning::Failed to update labels for PR $pr"
|
||
return
|
||
fi
|
||
return 1
|
||
}
|
||
|
||
remove_labels_if_present() {
|
||
pr=$1
|
||
shift
|
||
labels=
|
||
for label in "$@"; do
|
||
if jq -e --arg label "$label" \
|
||
'map(.name) | index($label)' < labels.json > /dev/null; then
|
||
labels="${labels}${labels:+,}${label}"
|
||
fi
|
||
done
|
||
|
||
if [ -n "$labels" ]; then
|
||
edit_pr_labels "$pr" warn --remove-label "$labels"
|
||
fi
|
||
}
|
||
|
||
commit_queue_failed() {
|
||
pr=$1
|
||
reported_failure=${2:-}
|
||
|
||
edit_pr_labels "$pr" required --add-label "$COMMIT_QUEUE_FAILED_LABEL" \
|
||
--remove-label "$COMMIT_QUEUE_LABEL"
|
||
remove_labels_if_present "$pr" "$LACKS_SECOND_APPROVAL_LABEL"
|
||
|
||
last_output_line=$(awk 'NF { line = $0 } END { sub(/^[[:space:]]*/, "", line); print line }' output)
|
||
# shellcheck disable=SC2016
|
||
missing_policy_message='ℹ Add `commit-queue-squash` label to land the PR as one commit, or `commit-queue-rebase` to land as separate commits.'
|
||
if [ "$last_output_line" = "$missing_policy_message" ]; then
|
||
failure_body='This pull request has multiple commits, but no landing policy was selected.
|
||
|
||
Add https://github.com/nodejs/node/labels/commit-queue-squash to land it as one commit, or https://github.com/nodejs/node/labels/commit-queue-rebase to land the commits separately.'
|
||
else
|
||
if [ -z "$reported_failure" ]; then
|
||
reported_failure=$(grep -e '✘' -e '✖' -e '⚠' output | tail -n 10)
|
||
fi
|
||
if [ -z "$reported_failure" ]; then
|
||
reported_failure=$(tail -n 10 output)
|
||
fi
|
||
if [ -z "$reported_failure" ]; then
|
||
reported_failure='No failure reason was reported.'
|
||
fi
|
||
failure_body=$(escape_code_block_or_line "$reported_failure")
|
||
fi
|
||
|
||
raw_output=$(cat output)
|
||
|
||
body="### Commit Queue failed
|
||
|
||
$failure_body
|
||
|
||
The pull request was removed from the Commit Queue and labeled https://github.com/nodejs/node/labels/commit-queue-failed. After resolving the failure, remove that label and add https://github.com/nodejs/node/labels/commit-queue to retry.
|
||
|
||
<details>
|
||
<summary>Full Commit Queue output</summary>
|
||
|
||
$(escape_code_block_or_line "$raw_output")
|
||
|
||
</details>
|
||
|
||
[View workflow run]($cqurl)"
|
||
echo "$body"
|
||
|
||
gh -R "$GITHUB_REPOSITORY" pr comment "$pr" --body "$body"
|
||
|
||
rm output
|
||
}
|
||
|
||
SHOULD_ABORT=
|
||
|
||
for pr in "$@"; do
|
||
gh -R "$GITHUB_REPOSITORY" pr view "$pr" --json labels --jq ".labels" > labels.json
|
||
|
||
if jq -e 'map(.name) | index("commit-queue-squash")' < labels.json; then
|
||
MULTIPLE_COMMIT_POLICY="--fixupAll"
|
||
elif jq -e 'map(.name) | index("commit-queue-rebase")' < labels.json; then
|
||
MULTIPLE_COMMIT_POLICY=""
|
||
else
|
||
MULTIPLE_COMMIT_POLICY="--oneCommitMax"
|
||
fi
|
||
|
||
if [ -n "$SHOULD_ABORT" ]; then
|
||
# If `git node land --abort` fails, we're in unknown state. Better to stop
|
||
# the script here, current PR was removed from the queue so it shouldn't
|
||
# interfere again in the future.
|
||
git node land --abort --yes
|
||
SHOULD_ABORT=
|
||
fi
|
||
|
||
git node land --autorebase --yes $MULTIPLE_COMMIT_POLICY "$pr" >output 2>&1 || echo "Failed to land #${pr}"
|
||
# cat here otherwise we'll be suppressing the output of git node land
|
||
cat output
|
||
|
||
# TODO(mmarchini): workaround for ncu not returning the expected status code,
|
||
# if the "Landed in..." message was not on the output we assume land failed
|
||
if ! grep -q '. Post "Landed in .*/pull/'"${pr}" output; then
|
||
commit_queue_failed "$pr"
|
||
# Using a variable as there's no point in aborting if there are no PRs left in the queue.
|
||
SHOULD_ABORT=1
|
||
continue
|
||
fi
|
||
|
||
if [ -z "$MULTIPLE_COMMIT_POLICY" ]; then
|
||
start_sha=$(git rev-parse $UPSTREAM/$DEFAULT_BRANCH)
|
||
end_sha=$(git rev-parse HEAD)
|
||
commits="${start_sha}...${end_sha}"
|
||
|
||
if ! git push $UPSTREAM $DEFAULT_BRANCH >> output 2>&1; then
|
||
commit_queue_failed "$pr" \
|
||
"Failed to push the landed commits to ${UPSTREAM}/${DEFAULT_BRANCH}."
|
||
continue
|
||
fi
|
||
else
|
||
# If there's only one commit, we can use the Squash and Merge feature from GitHub.
|
||
# TODO: use `gh pr merge` when the GitHub CLI allows to customize the commit title (https://github.com/cli/cli/issues/1023).
|
||
commit_title=$(git log -1 --pretty='format:%s')
|
||
commit_body=$(git log -1 --pretty='format:%b')
|
||
commit_head=$(grep 'Fetched commits as' output | cut -d. -f3 | xargs git rev-parse)
|
||
|
||
if ! commits="$(
|
||
jq -cn \
|
||
--arg title "${commit_title}" \
|
||
--arg body "${commit_body}" \
|
||
--arg head "${commit_head}" \
|
||
'{merge_method:"squash",commit_title:$title,commit_message:$body,sha:$head}' |\
|
||
gh api -X PUT "repos/${GITHUB_REPOSITORY}/pulls/${pr}/merge" --input -\
|
||
--jq 'if .merged then .sha else halt_error end' 2>> output
|
||
)"; then
|
||
commit_queue_failed "$pr" \
|
||
'GitHub failed to squash and merge this pull request.'
|
||
continue
|
||
fi
|
||
fi
|
||
|
||
rm output
|
||
|
||
gh -R "$GITHUB_REPOSITORY" pr comment "$pr" --body "Landed in $commits"
|
||
|
||
[ -z "$MULTIPLE_COMMIT_POLICY" ] && gh -R "$GITHUB_REPOSITORY" pr close "$pr"
|
||
|
||
# Delete the commit queue labels (but ignore errors, it's no big deal if a closed PR still has them)
|
||
remove_labels_if_present "$pr" "$COMMIT_QUEUE_LABEL" \
|
||
"$LACKS_SECOND_APPROVAL_LABEL"
|
||
done
|
||
|
||
rm -f labels.json
|