mirror of
https://github.com/zulip/zulip.git
synced 2026-06-06 21:12:33 +08:00
The commit hashes that appear in the `pull/12345/head` ref are the
ones _before_ any final rebase occurs, and as such may not match to
any commit hashes which exist in `main`.
Use the GitHub GraphQL API to pull the last "merge commit" on the PR,
which is post-rebase, and use that as the target commit when
cherry-picking. Then walk backwards from that commit, including every
sequential commit which is still associated with the PR; we do this
because during the merge, commits may be added or removed, so the PR
is not reliable in the commit count.
(cherry picked from commit 06543b54b1)
103 lines
2.4 KiB
Bash
Executable File
103 lines
2.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -e
|
|
|
|
usage() {
|
|
cat >&2 <<EOF
|
|
usage: $0 PULL_REQUEST_ID COMMIT_COUNT [REMOTE]
|
|
|
|
Fetch the given GitHub pull request branch and backport it to
|
|
the current branch using 'git cherry-pick -x'.
|
|
|
|
Typical usage is:
|
|
git fetch upstream
|
|
git checkout -b 8.x upstream/8.x
|
|
$0 FIRST_PR_ID
|
|
$0 SECOND_PR_ID
|
|
git push origin +HEAD:backport-changes
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
pr_id="$1"
|
|
|
|
if [ -z "$pr_id" ]; then
|
|
usage
|
|
fi
|
|
|
|
fail() {
|
|
echo "$1"
|
|
exit 1
|
|
}
|
|
|
|
type gh >/dev/null 2>&1 \
|
|
|| fail "The 'gh' CLI tool is not installed; see https://cli.github.com/"
|
|
gh auth status 2>/dev/null || fail "Not authenticated to github"
|
|
|
|
# Find the last commit that was merged. We will look back in `main`
|
|
# for other commits from the same PR.
|
|
# shellcheck disable=SC2016
|
|
merge_commit="$(
|
|
gh api graphql \
|
|
-q '.data.repository.pullRequest.timelineItems.nodes[0].commit.oid' \
|
|
-F pr_id="$1" \
|
|
-f query='
|
|
query($pr_id:Int!) {
|
|
repository(name: "zulip", owner: "zulip") {
|
|
pullRequest(number:$pr_id) {
|
|
timelineItems(last:1, itemTypes: [MERGED_EVENT]) {
|
|
nodes {
|
|
... on MergedEvent {
|
|
commit {
|
|
oid
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'
|
|
)"
|
|
|
|
# We cannot trust the "commits" count on the PR, since only part of it
|
|
# may get merged, or it may have commits squashed during the merge.
|
|
# Walk backwards on `main` from the merge commit we found, checking
|
|
# that each of those commits is still associated with the same PR.
|
|
commit_id="$merge_commit"
|
|
while true; do
|
|
# shellcheck disable=SC2016
|
|
this_pr="$(gh api graphql -F "commit_id=$commit_id 0" \
|
|
--jq '.data.repository.ref.target.history.edges[].node.associatedPullRequests.nodes[].number' \
|
|
-f query='
|
|
query($commit_id: String!) {
|
|
repository(owner: "zulip", name:"zulip") {
|
|
ref(qualifiedName:"main") {
|
|
target {
|
|
... on Commit {
|
|
history(first:1, after: $commit_id) {
|
|
edges {
|
|
node {
|
|
oid
|
|
associatedPullRequests(first: 1) {
|
|
nodes {
|
|
number
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}')"
|
|
if [ "$this_pr" != "$pr_id" ]; then
|
|
break
|
|
fi
|
|
commit_id="$(git rev-parse "$commit_id"~)"
|
|
done
|
|
|
|
set -x
|
|
git cherry-pick -x "$commit_id~..$merge_commit"
|