[FIX #3074] Combine PR scripts and clean up usage of merge-external-pr.sh

- Combine merge-pr.sh and merge-external-pr.sh using merge-external-pr.sh as a base
    - Modify script interface to ./scripts/merge-pr.sh <PR-ID> and remove options to run with REPO_URL BRANCH arguments
    - Works regardless of where PR is hosted and whether or not it is signed by external contributor.

Signed-off-by: Sebastian Delgado <sdalcega@gmail.com>
Signed-off-by: Eric Dvorsak <eric@dvorsak.fr>
This commit is contained in:
Sebastian Delgado 2018-01-23 12:37:10 -05:00 committed by Eric Dvorsak
parent b3e2a610f1
commit bf95603b56
No known key found for this signature in database
GPG Key ID: 932AC1CE5F05DE0C
2 changed files with 127 additions and 177 deletions

View File

@ -1,152 +0,0 @@
#!/bin/bash
set -eof pipefail
trap cleanup EXIT
fatal() {
echo "FATAL: $@" >&2
exit 1
}
warn() {
echo "$@"
}
confirm() {
read -p "$1 (type 'yes' to continue) " r
if [[ $r != yes ]]; then
exit 3
fi
}
load_config() {
[[ -f merge-external-pr.conf ]] && . merge-external-pr.conf
: ${OWNER:=status-im}
: ${REPO:=status-react}
: ${REMOTE:=origin}
: ${BRANCH:=develop}
}
check_pr_prereq() {
if ! command -v jq >/dev/null; then
fatal "jq(1) is not found, PR cannot be queried. Use REPO BRANCH"
fi
if ! command -v curl >/dev/null; then
fatal "curl(1) is not found, PR cannot be queried. Use REPO BRANCH"
fi
}
GH_URL_BASE="https://api.github.com"
get_pr_info() {
echo '[ Reading PR info ]'
if [ $# -eq 1 ]; then
check_pr_prereq
local pr=$1
local pr_info_url="$GH_URL_BASE/repos/${OWNER}/${REPO}/pulls/$pr"
set +e
local pr_info
pr_info=$(curl -fsS "$pr_info_url")
if [ $? -ne 0 ]; then
fatal "Unable to get PR info from $pr_info_url"
fi
set -e
if [[ $(echo "$pr_info" | jq -r .state) == closed ]]; then
fatal "PR $pr is closed, will not merge"
fi
if [[ $(echo "$pr_info" | jq -r .maintainer_can_modify) == true ]]; then
RW_PR_REPO=1
else
warn "PR does not allow 'edits from maintainers', so it will be kept open"
fi
PR_URL=$(echo "$pr_info" | jq -r .head.repo.ssh_url)
PR_REMOTE_NAME=pr-$pr
PR_BRANCH=$(echo "$pr_info" | jq -r .head.ref)
PR_LOCAL_BRANCH=pr-$pr
else
PR_URL="$1"
PR_REMOTE_NAME=${PR_URL##*/}
PR_REMOTE_NAME=pr-${PR_REMOTE_NAME%.git}
PR_REMOTE_NAME=pr-${PR_REPO_NAME}
PR_BRANCH="$2"
PR_LOCAL_BRANCH=pr-${PR_REPO_NAME}
fi
}
fetch_pr() {
echo '[ Fetching PR ]'
git remote add $PR_REMOTE_NAME $PR_URL
git fetch $PR_REMOTE_NAME $PR_BRANCH
}
refresh_base_branch() {
git fetch $REMOTE $BRANCH
}
rebase_pr() {
git checkout -B $PR_LOCAL_BRANCH $PR_REMOTE_NAME/$PR_BRANCH
git rebase $BRANCH
}
check_is_pr_single_commit() {
if [[ $(git rev-list $BRANCH..$PR_LOCAL_BRACNCH | wc -l) -ne 1 ]] ;then
fatal "Only squashed/single-commit PRs can be merged"
fi
}
confirm_pr() {
git log -p $BRANCH..$PR_LOCAL_BRANCH
confirm "Do you like this PR?"
}
sign_pr() {
git commit --amend --gpg-sign --signoff
}
verify_pr() {
git show --show-signature $PR_LOCAL_BRANCH
confirm "Is the signature on the commit correct?"
}
merge_pr() {
# If PR is specified and can be pushed into, do it to mark PR as closed
if [[ -n $RW_PR_REPO ]]; then
git push -f $PR_REMOTE_NAME $PR_LOCAL_BRANCH:$PR_BRANCH
fi
git checkout $BRANCH
git merge --ff-only $PR_LOCAL_BRANCH
git push $REMOTE $BRANCH
}
cleanup() {
if [[ -z $DEBUG ]]; then
git checkout -q $BRANCH
git branch -q -D $PR_LOCAL_BRANCH 2>/dev/null || :
git remote remove $PR_REMOTE_NAME 2>/dev/null || :
fi
}
run() {
if [[ $# -lt 1 ]] || [[ $# -gt 2 ]]; then
cat <<EOF >&2
Usage:
./merge-external-pr.sh REPO_URL BRANCH
./merge-external.pr.sh PR (if jq(1) and curl(1) are available)
EOF
exit 2
fi
load_config
get_pr_info "$@"
cleanup
fetch_pr
refresh_base_branch
rebase_pr
check_is_pr_single_commit
confirm_pr
sign_pr
verify_pr
merge_pr
}
run "$@"

View File

@ -2,11 +2,16 @@
set -eof pipefail set -eof pipefail
BRANCH=$1 trap cleanup EXIT
if [[ $# -eq 0 ]] ; then
echo 'Branch required as first argument' fatal() {
exit 0 echo "FATAL: $@" >&2
fi exit 1
}
warn() {
echo "$@"
}
confirm() { confirm() {
read -p "$1 (type 'yes' to continue) " r read -p "$1 (type 'yes' to continue) " r
@ -15,30 +20,127 @@ confirm() {
fi fi
} }
echo "[Merge PR from ${BRANCH}]" load_config() {
[[ -f merge-pr.conf ]] && . merge-pr.conf
: ${OWNER:=status-im}
: ${REPO:=status-react}
: ${REMOTE:=origin}
: ${BRANCH:=develop}
}
echo "[Update remote and checkout branch]" check_pr_prereq() {
git remote update origin if ! command -v jq >/dev/null; then
git checkout -B $BRANCH origin/$BRANCH && git pull fatal "jq(1) is not found, PR cannot be queried."
fi
if ! command -v curl >/dev/null; then
fatal "curl(1) is not found, PR cannot be queried."
fi
}
echo "[Rebase and squash to one commit (manual)]" GH_URL_BASE="https://api.github.com"
git rebase -i origin/develop
if [[ $(git rev-list $BRANCH..$PR_LOCAL_BRACNCH | wc -l) -ne 1 ]] ;then
confirm "There are multiple commits in this PR. Are you sure you wish to continue without squashing?"
fi
echo "[Verify signature and commit (manual), update PR]" get_pr_info() {
git show --show-signature echo '[ Reading PR info ]'
git push -f local pr=$1
local pr_info_url="$GH_URL_BASE/repos/${OWNER}/${REPO}/pulls/$pr"
set +e
local pr_info
pr_info=$(curl -fsS "$pr_info_url")
if [ $? -ne 0 ]; then
fatal "Unable to get PR info from $pr_info_url"
fi
set -e
if [[ $(echo "$pr_info" | jq -r .state) == closed ]]; then
fatal "PR $pr is closed, will not merge"
fi
if [[ $(echo "$pr_info" | jq -r .maintainer_can_modify) == true ]]; then
RW_PR_REPO=1
else
warn "PR does not allow 'edits from maintainers', so it will be kept open"
fi
PR_URL=$(echo "$pr_info" | jq -r .head.repo.ssh_url)
PR_REMOTE_NAME=pr-$pr
PR_BRANCH=$(echo "$pr_info" | jq -r .head.ref)
PR_LOCAL_BRANCH=pr-$pr
}
echo "[Checkout develop and merge with same SHA]" fetch_pr() {
git checkout develop && git pull echo '[ Fetching PR ]'
git merge --ff-only $BRANCH git remote add $PR_REMOTE_NAME $PR_URL
git fetch $PR_REMOTE_NAME $PR_BRANCH
}
echo "[Push to protected develop branch]" refresh_base_branch() {
git push git fetch $REMOTE $BRANCH
}
echo "[Clean up remote branch]" rebase_pr() {
git push origin --delete $BRANCH git checkout -B $PR_LOCAL_BRANCH $PR_REMOTE_NAME/$PR_BRANCH
git rebase $BRANCH
}
echo "[Done]" check_is_pr_single_commit() {
if [[ $(git rev-list $BRANCH..$PR_LOCAL_BRANCH | wc -l) -ne 1 ]] ;then
confirm "PR has multiple commits, continue merging without squashing them?"
fi
}
confirm_pr() {
git log -p $BRANCH..$PR_LOCAL_BRANCH
confirm "Do you like this PR?"
}
sign_pr() {
git commit --amend --gpg-sign --signoff
}
verify_pr() {
git show --show-signature $PR_LOCAL_BRANCH
confirm "Is the signature on the commit correct?"
}
merge_pr() {
# If PR is specified and can be pushed into, do it to mark PR as closed
if [[ -n $RW_PR_REPO ]]; then
git push -f $PR_REMOTE_NAME $PR_LOCAL_BRANCH:$PR_BRANCH
fi
git checkout $BRANCH
git merge --ff-only $PR_LOCAL_BRANCH
git push $REMOTE $BRANCH
}
cleanup() {
if [[ -z $DEBUG ]]; then
git checkout -q $BRANCH
git branch -q -D $PR_LOCAL_BRANCH 2>/dev/null || :
git remote remove $PR_REMOTE_NAME 2>/dev/null || :
fi
}
run() {
if [[ $# -ne 1 ]] ; then
cat <<EOF >&2
Requirements:
jq
curl
Usage:
./merge-pr.sh <PR-ID>
EOF
exit 2
fi
load_config
check_pr_prereq
get_pr_info "$@"
cleanup
fetch_pr
refresh_base_branch
rebase_pr
check_is_pr_single_commit
confirm_pr
sign_pr
verify_pr
merge_pr
}
run "$@"