The `pull_github_pr.sh` script has been fetching the username from the owner of the source branch. The owner of the branch is not always the author of the PR. For example the branch might come from a fork managed by organization or group of people. This lead to having the author in merge commits refered to as `null` (if the name was not set for the group) or it mentioned a name not belonging to the author of the patch. Instead looking for the owner of the source branch, the script should look for the name of the PR's author. Closes scylladb/scylladb#25363
178 lines
5.4 KiB
Bash
Executable File
178 lines
5.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Script for pulling a github pull request
|
|
# along with generating a merge commit message.
|
|
# Example usage for pull request #6007 and /next branch:
|
|
# git fetch
|
|
# git checkout origin/next
|
|
# ./scripts/pull_github_pr.sh 6007
|
|
|
|
set -e
|
|
|
|
shopt -s extglob
|
|
|
|
trap 'echo "error $? in $0 line $LINENO"' ERR
|
|
|
|
gh_hosts=~/.config/gh/hosts.yml
|
|
jenkins_url="https://jenkins.scylladb.com"
|
|
ORANGE='\033[0;33m'
|
|
NC='\033[0m'
|
|
|
|
if [[ ( -z "$GITHUB_LOGIN" || -z "$GITHUB_TOKEN" ) && -f "$gh_hosts" ]]; then
|
|
GITHUB_LOGIN=$(awk '/user:/ { print $2 }' "$gh_hosts")
|
|
GITHUB_TOKEN=$(awk '/oauth_token:/ { print $2 }' "$gh_hosts")
|
|
fi
|
|
|
|
if [[ -z "$JENKINS_USERNAME" || -z "$JENKINS_API_TOKEN" ]]; then
|
|
echo "
|
|
JENKINS_USERNAME or JENKINS_API_TOKEN is missing from env.
|
|
To create a TOKEN, browse to https://jenkins.scylladb.com, then click on your username (upper right corner) and configure. Click on Add new token and set the JENKINS_USERNAME and JENKINS_API_TOKEN environment variables accordingly.
|
|
"
|
|
exit 1
|
|
fi
|
|
|
|
for required in jq curl; do
|
|
if ! type $required >& /dev/null; then
|
|
echo Please install $required first
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
FORCE=0
|
|
|
|
while [[ $# -gt 0 ]]
|
|
do
|
|
case $1 in
|
|
"--force"|"-f")
|
|
FORCE=1
|
|
shift 1
|
|
;;
|
|
+([0-9]))
|
|
PR_NUM=$1
|
|
shift 1
|
|
;;
|
|
*)
|
|
echo "error: unrecognized option: $1, see $0 -h for usage" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$PR_NUM" ]; then
|
|
echo Please provide a github pull request number
|
|
exit 1
|
|
fi
|
|
|
|
curl() {
|
|
local opts=()
|
|
if [[ -n "$GITHUB_LOGIN" && -n "$GITHUB_TOKEN" ]]; then
|
|
opts+=(--user "${GITHUB_LOGIN}:${GITHUB_TOKEN}")
|
|
fi
|
|
command curl "${opts[@]}" "$@"
|
|
}
|
|
|
|
set_jenkins_job() {
|
|
branch=$(git rev-parse --abbrev-ref HEAD)
|
|
version="${branch#next-}"
|
|
product=$(awk -F'=' '/^PRODUCT/ {print $2}' <SCYLLA-VERSION-GEN)
|
|
case "$product" in
|
|
scylla) folder_prefix="scylla";;
|
|
scylla-enterprise) folder_prefix="enterprise";;
|
|
*) echo "None supported product, valid options scylla|scylla-enterprise"
|
|
exit 1
|
|
esac
|
|
|
|
case "$branch" in
|
|
next) jenkins_job="scylla-master/job/next";;
|
|
next-enterprise) jenkins_job="scylla-enterprise/job/next";;
|
|
next*) jenkins_job="$folder_prefix-$version/job/next";;
|
|
*) echo "You are running the script from branch: $branch. Valid branches: next|next-enterprise|next-*"
|
|
exit 1
|
|
esac
|
|
}
|
|
|
|
check_jenkins_job_status() {
|
|
set_jenkins_job
|
|
|
|
lastCompletedJobName="$jenkins_url/job/$jenkins_job/lastCompletedBuild"
|
|
getBuildResult=$(curl -s --user $JENKINS_USERNAME:$JENKINS_API_TOKEN $lastCompletedJobName/api/json?tree=result)
|
|
if [[ "$getBuildResult" == "*Unauthorized*" ]]; then
|
|
echo -e "${ORANGE}WARNING:${NC} Failed to authenticate with Jenkins. please check your JENKINS_USERNAME and JENKINS_API_TOKEN setting"
|
|
exit 1
|
|
fi
|
|
lastCompleted=$(echo "$getBuildResult" | jq -r '.result')
|
|
|
|
if [[ "$lastCompleted" == "SUCCESS" ]]; then
|
|
echo "$lastCompletedJobName is stable"
|
|
else
|
|
echo -e "${ORANGE}WARNING:${NC} $lastCompletedJobName is not stable"
|
|
fi
|
|
}
|
|
|
|
if [[ $FORCE -eq 0 ]]; then
|
|
check_jenkins_job_status
|
|
fi
|
|
|
|
NL=$'\n'
|
|
|
|
# convert full repo URL to its project/repo part, in case of failure default to origin/master:
|
|
REMOTE_SLASH_BRANCH="$(git rev-parse --abbrev-ref --symbolic-full-name @{upstream} \
|
|
|| git rev-parse --abbrev-ref --symbolic-full-name master@{upstream} \
|
|
|| echo 'origin/master')"
|
|
REMOTE="${REMOTE_SLASH_BRANCH%/*}"
|
|
REMOTE_URL="$(git config --get "remote.$REMOTE.url")"
|
|
PROJECT=`sed 's/git@github.com://;s#https://github.com/##;s/\.git$//;' <<<"${REMOTE_URL}"`
|
|
PR_PREFIX=https://api.github.com/repos/$PROJECT/pulls
|
|
|
|
echo "Fetching info on PR #$PR_NUM... "
|
|
PR_DATA=$(curl -s $PR_PREFIX/$PR_NUM)
|
|
MESSAGE=$(jq -r .message <<< $PR_DATA)
|
|
if [ "$MESSAGE" != null ]
|
|
then
|
|
# Error message, probably "Not Found".
|
|
echo "$MESSAGE"
|
|
exit 1
|
|
fi
|
|
PR_TITLE=$(jq -r .title <<< $PR_DATA)
|
|
echo " $PR_TITLE"
|
|
PR_DESCR=$(jq -r .body <<< $PR_DATA)
|
|
PR_LOGIN=$(jq -r .user.login <<< $PR_DATA)
|
|
echo -n "Fetching full name of author $PR_LOGIN... "
|
|
USER_NAME=$(curl -s "https://api.github.com/users/$PR_LOGIN" | jq -r .name)
|
|
echo "$USER_NAME"
|
|
|
|
git fetch "$REMOTE" pull/$PR_NUM/head
|
|
|
|
nr_commits=$(git log --pretty=oneline HEAD..FETCH_HEAD | wc -l)
|
|
|
|
closes="${NL}${NL}Closes ${PROJECT}#${PR_NUM}${NL}"
|
|
|
|
if [[ $nr_commits == 1 ]]; then
|
|
commit=$(git log --pretty=oneline HEAD..FETCH_HEAD | awk '{print $1}')
|
|
message="$(git log -1 "$commit" --format="format:%s%n%n%b")"
|
|
if ! git cherry-pick $commit
|
|
then
|
|
echo "Cherry-pick failed. You are now in a subshell. Either resolve with git cherry-pick --continue or git cherry-pick --abort, then exit the subshell"
|
|
head_before=$(git rev-parse HEAD)
|
|
bash
|
|
head_after=$(git rev-parse HEAD)
|
|
if [[ "$head_before" = "$head_after" ]]; then
|
|
exit 1
|
|
fi
|
|
fi
|
|
git commit --amend -m "${message}${closes}"
|
|
else
|
|
git merge --no-ff --log=1000 FETCH_HEAD -m "Merge '$PR_TITLE' from $USER_NAME" -m "${PR_DESCR}${closes}"
|
|
fi
|
|
git commit --amend # for a manual double-check
|
|
|
|
# Check PR tests status
|
|
PR_HEAD_SHA=$(jq -r .head.sha <<< $PR_DATA)
|
|
PR_TESTS_STATUS=$(curl -s "https://api.github.com/repos/$PROJECT/commits/$PR_HEAD_SHA/status" | jq -r .state)
|
|
if [ "$PR_TESTS_STATUS" != "success" ]; then
|
|
ORANGE='\033[0;33m'
|
|
NC='\033[0m'
|
|
echo -e "${ORANGE}\nWARNING:${NC} Some of the tests that ran for this PR were not completed successfully,\n" \
|
|
"please make sure all tests are done successfully before merge this PR.\n"
|
|
fi
|