diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000000..80e71eebf9 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,36 @@ +Github Pull Request Helper Scripts +====================================== + +这里提供一些脚本辅助github CI机器人,方便标签和合并代码: + + +* approve.sh + +合并一个PR,使用方法: + + ./scripts/approve.sh [check_reviewers] + +合并一个PR之前,将会做如下检查: + +1. 该PR的状态为open +2. 该PR的mergeable状态为true (如果有冲突,则mergeable=false) +3. 该PR的所有CI检查都通过 +4. 如果命令行的check_reviewers为非空字符串,则还会检查是否所有requested reviewers都lgtm了这个PR + +需要注意的是,在执行脚本之前,请确认已经人肉review过代码,并且认为可以合并了再执行。脚本只是为了方便合并,并且确保合并前没有忽略的检查,并不是为了替代人肉code review。 + + +* approve_all.sh + +合并一组PR,使用方法: + + ./scripts/approve_all.sh + +这组PR由master上的主PR和backport到各个分支的cherry pick PR组成。对Master上的PR会做所有4项检查,对其他PR只做前3项检查。 + + +* lgtm.sh + +给一个PR打上lgtm的标签。使用方法: + + ./scripts/lgtm.sh diff --git a/scripts/advchecks.py b/scripts/advchecks.py new file mode 100755 index 0000000000..438d4e5935 --- /dev/null +++ b/scripts/advchecks.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +import json + +def find_lgtms(comments): + commenters = [] + for comment in comments: + body = comment["body"].strip() + if body == "/lgtm": + commenters.append("%s(%s)" % (comment["user"]["login"], comment["user"]["id"])) + return commenters + +def find_reviewers(pulls): + reviewers = [] + for reviewer in pulls["requested_reviewers"]: + reviewers.append("%s(%s)" % (reviewer["login"], reviewer["id"])) + return reviewers + +if __name__ == '__main__': + import sys + + if len(sys.argv) < 3: + print(sys.argv[0], "", "") + sys.exit(-1) + + with open(sys.argv[1]) as pullfile: + pulls = json.load(pullfile) + with open(sys.argv[2]) as commentfile: + comments = json.load(commentfile) + rvs = find_reviewers(pulls) + cms = find_lgtms(comments) + if len(rvs) == 0: + print("No reviwer is assigned, give up check...") + os.exit(-1) + print("Assigned reviwers: %s" % ", ".join(rvs)) + print("Lgtm reviwers: %s" % ", ".join(cms)) + req = [] + for rv in rvs: + if rv not in cms: + req.append(rv) + if len(req) > 0: + print("Reviewers %s needs /lgtm" % ",".join(req)) + sys.exit(-1) diff --git a/scripts/approve.sh b/scripts/approve.sh index c94ba0f943..62f59da86d 100755 --- a/scripts/approve.sh +++ b/scripts/approve.sh @@ -1,7 +1,11 @@ #!/bin/bash +pushd $(dirname "$BASH_SOURCE") > /dev/null +CUR_DIR=$(pwd) +popd > /dev/null + PR=$1 -MSG=$2 +REVIEWER_CHECK=$2 if [ -z "$PR" ]; then echo "Usage: $0 " @@ -53,6 +57,10 @@ function label() { local MSG=$2 local LABEL=$3 + if check_label $PRN $LABEL > /dev/null; then + echo "Label $LABEL success!" + return 0 + fi for try in $(seq 3) do echo "Send $MSG ..." @@ -121,6 +129,23 @@ if ! label "$PR" "/lgtm" "lgtm"; then exit 1 fi +if [ -n "$REVIEWER_CHECK" ]; then + echo "Check all requested reviwers /lgtm the pull request: " + pullfile=$(mktemp) + commentfile=$(mktemp) + function cleanup { + rm -rf "$pullfile" "$commentfile" + } + trap cleanup EXIT + hub api repos/{owner}/{repo}/pulls/$PR > $pullfile + hub api repos/{owner}/{repo}/issues/$PR/comments > $commentfile + if ! $CUR_DIR/advchecks.py $pullfile $commentfile; then + echo "Not all assigned reviwers comment lgtm, give up..." + exit 1 + fi + echo "passed!" +fi + if ! label "$PR" "/approve" "approved"; then echo "Label approved failed" exit 1 diff --git a/scripts/approve_all.sh b/scripts/approve_all.sh index 93d31c3ad0..33477bc819 100755 --- a/scripts/approve_all.sh +++ b/scripts/approve_all.sh @@ -34,12 +34,15 @@ done echo "Going to merge the following pull requests ${PRNS[@]}:" +REVIEWER_CHECK=yes for PRN in "${PRNS[@]}" do - $CUR_DIR/approve.sh $PRN + $CUR_DIR/approve.sh $PRN $REVIEWER_CHECK if [ "$?" -ne "0" ]; then echo "Merge failed, exit." exit 1 fi + if [ -n "$REVIEWER_CHECK" ]; then + REVIEWER_CHECK= + fi done - diff --git a/scripts/label.sh b/scripts/label.sh new file mode 100755 index 0000000000..c995ed9b0f --- /dev/null +++ b/scripts/label.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +PRN=$1 +MSG=$2 +LABEL=$3 + +function check_label() { + local PRN=$1 + local LABEL=$2 + hub api repos/{owner}/{repo}/issues/${PRN}/labels | python -m json.tool | grep '"name": "'$LABEL'"' +} + +function label() { + local PRN=$1 + local MSG=$2 + local LABEL=$3 + + for try in $(seq 3) + do + echo "Send $MSG ..." + hub api repos/{owner}/{repo}/issues/$PRN/comments -f "body=$MSG" > /dev/null + if [ "$?" -ne "0" ]; then + echo "Send $MSG fail!" + return 1 + fi + for chk in $(seq 30) + do + sleep 1 + if check_label $PRN $LABEL > /dev/null; then + echo "Label $LABEL success!" + return 0 + fi + done + done + return 1 +} + +if [ -z "$LABEL" ]; then + echo "Usage: $0