zulip/tools/backport-pull-request

103 lines
2.4 KiB
Plaintext
Raw Permalink Normal View History

2024-01-16 01:58:34 +01:00
#!/usr/bin/env bash
2024-01-16 01:58:34 +01:00
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
2024-01-16 01:58:34 +01:00
git push origin +HEAD:backport-changes
EOF
exit 1
}
pr_id="$1"
2024-01-16 01:58:34 +01:00
if [ -z "$pr_id" ]; then
2024-01-16 01:58:34 +01:00
usage
fi
fail() {
echo "$1"
exit 1
}
2024-01-16 01:58:34 +01:00
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"
2024-01-16 01:58:34 +01:00
# 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"