Add a github action for automatically cherry-pick PRs (#13)

**Motivation**

We want to make the pulsar can cherry-pick automatically. This action will make a closed PR can cherry-pick by the command `/pulsarbot cherry-pick to branch-X.Y`.

When a PR is merged, the bot will say, 
```
Hey. If you want to cherry-pick this pr to a target branch, please comments '/pulsarbot, /pulsarbot cherry-pick to branch-X.Y'.
```
Then you can comment /pulsarbot cherry-pick to branch-X.Y, the bot will open a new PR for cherry-picking the closed PR.

If we open a new PR to do the cherry-pick, we can also use the CI to check the branch.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..485dee6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea
diff --git a/cherry-pick/Dockerfile b/cherry-pick/Dockerfile
new file mode 100644
index 0000000..f087f2c
--- /dev/null
+++ b/cherry-pick/Dockerfile
@@ -0,0 +1,21 @@
+FROM alpine:latest
+
+LABEL version="1.0.0"
+LABEL repository="http://github.com/apache/pulsar-test-infra"
+LABEL homepage="http://github.com/apache/pulsar-test-infra/pulsarbot"
+LABEL maintainer="Apache Pulsar Team"
+LABEL "com.github.actions.name"="pulsarbot"
+LABEL "com.github.actions.description"="Pulsar Bot"
+LABEL "com.github.actions.icon"="git-commit"
+LABEL "com.github.actions.color"="gray-dark"
+
+RUN apk add --update git jq bash curl coreutils && rm -rf /var/cache/apk/*
+
+RUN curl -LO -s https://github.com/cli/cli/releases/download/v1.2.0/gh_1.2.0_linux_386.tar.gz && \
+    tar -xf gh_1.2.0_linux_386.tar.gz
+
+ENV PATH=${PATH}:/gh_1.2.0_linux_386/bin
+
+COPY entrypoint.sh /entrypoint.sh
+
+ENTRYPOINT ["/entrypoint.sh"]
diff --git a/cherry-pick/README.md b/cherry-pick/README.md
new file mode 100644
index 0000000..2163a08
--- /dev/null
+++ b/cherry-pick/README.md
@@ -0,0 +1,11 @@
+# Cherry-pick for Github Action
+
+This action used for cherry-picking the PRs automatically.
+
+When you close a PR then the bot will prompt you:
+
+```bash
+Hey. If you want to cherry-pick this pr to a target branch, please comments '/pulsarbot cherry-pick to branch-x.y'.
+```
+
+Then you can comment `'/pulsarbot cherry-pick to branch-x.y'`, and the bot will create a new PR to merge it into the target branch.
diff --git a/cherry-pick/action.yml b/cherry-pick/action.yml
new file mode 100644
index 0000000..34f5349
--- /dev/null
+++ b/cherry-pick/action.yml
@@ -0,0 +1,25 @@
+name: 'cherry-pick'
+description: 'Automatically cherry-pick PRs for apache pulsar'
+inputs:
+  type:
+    description: 'Give a prompt or execute the cherry-pick, available options [cherry-pick] or [prompt-comment]'
+    required: true
+    default: 'cherry-pick'
+  github_user:
+    description: 'The github user who to do the commit the changes'
+    required: true
+  github_email:
+    description: 'The github user email who to do the commit changes'
+    required: true
+  github_repos:
+    description: 'The '
+    required: true
+    default: 'apache/pulsar'
+runs:
+  using: 'docker'
+  image: 'Dockerfile'
+  args:
+    - ${{ inputs.type }}
+    - ${{ inputs.github_user }}
+    - ${{ inputs.github_email }}
+    - ${{ inputs.github_repos }}
diff --git a/cherry-pick/entrypoint.sh b/cherry-pick/entrypoint.sh
new file mode 100755
index 0000000..72efc42
--- /dev/null
+++ b/cherry-pick/entrypoint.sh
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+set -x
+
+cat ${GITHUB_EVENT_PATH}
+
+GITHUB_TOKEN=${GITHUB_TOKEN:-""}
+
+configure_args() {
+    readonly GITHUB_USER=${1}
+    readonly GITHUB_EMAIL=${2}
+    readonly GITHUB_REPOS=${3}
+}
+
+# Get the PR merged sha and the title
+cherrypick_args() {
+    readonly COMMENT_BODY=$(jq -r '.comment.body' ${GITHUB_EVENT_PATH})
+    readonly PR_NUMBER=$(jq -r '.issue.number' "$GITHUB_EVENT_PATH")
+
+    readonly BOT_BRANCH_NAME="pulsarbot/cherry-pick-${PR_NUMBER}"
+    readonly BOT_PR_TITLE_PREFIX="[bot-cherry-pick]"
+    if [[ "" == "${GITHUB_TOKEN}" ]]; then
+       readonly PR_INFO=$(curl -s --request GET \
+            --url https://api.github.com/repos/${GITHUB_REPOS}/pulls/${PR_NUMBER} \
+            --header 'Accept: application/vnd.github.sailor-v-preview+json')
+    else
+        readonly PR_INFO=$(curl -s --request GET \
+            --url https://api.github.com/repos/${GITHUB_REPOS}/pulls/${PR_NUMBER} \
+            --header "Authorization: token ${GITHUB_TOKEN}" \
+            --header 'Accept: application/vnd.github.sailor-v-preview+json')
+    fi
+
+    readonly PR_MERGE_COMMIT_SHA=`echo ${PR_INFO} | jq -r .merge_commit_sha`
+    readonly PR_TITLE=`echo ${PR_INFO} | jq -r .title`
+}
+
+# setup github for commit the changes
+git_setup() {
+   git config user.name "${GITHUB_USER}"
+   git config user.email "${GITHUB_EMAIL}"
+}
+
+check_pr_is_merged() {
+    MERGED=`echo ${PR_INFO} | jq -r .merged`
+    if [[ "false" == ${MERGED} ]]; then
+        echo "PR is not merged"
+        exit 0
+    fi
+}
+
+cherrypick() {
+    check_pr_is_merged
+    TARGET_BRANCH=`echo ${COMMENT_BODY} | grep -o "branch-[0-9].[0-9]"`
+    if [[ "" == ${TARGET_BRANCH} ]]; then
+        echo "Wrong target branch"
+        exit 1
+    fi
+    git fetch --all
+    git checkout ${TARGET_BRANCH}
+    git checkout -b ${BOT_BRANCH_NAME}
+    git status
+    git cherry-pick "${PR_MERGE_COMMIT_SHA}" -X Recursive
+    status=$?
+    if [[ ${status} != 0 ]]; then
+        git add .
+        git commit --allow-empty -m "${BOT_PR_TITLE_PREFIX}${PR_TITLE}"
+    fi
+    git push origin ${BOT_BRANCH_NAME}
+    gh pr create --title "${BOT_PR_TITLE_PREFIX}${PR_TITLE}" --fill --base ${TARGET_BRANCH}
+}
+
+pr_close_prompt_args() {
+    readonly PR_NUMBER=$(jq -r '.number' "${GITHUB_EVENT_PATH}")
+    readonly PR_INFO=$(curl -s --request GET \
+        --url https://api.github.com/repos/${GITHUB_REPOS}/pulls/${PR_NUMBER} \
+        --header "Authorization: token ${GITHUB_TOKEN}" \
+        --header 'Accept: application/vnd.github.sailor-v-preview+json')
+}
+
+pr_close_prompt() {
+    check_pr_is_merged
+    COMMENTS_URL=`echo ${PR_INFO} | jq -r ._links.comments.href`
+    REVIEWS=`echo ${PR_INFO} | jq '.requested_reviewers[] | .login'`
+    users=""
+    for review in ${REVIEWS}; do
+        users="${users}, @${review}"
+    done
+    if [[ "" == ${users} ]]; then
+        PROMPT_SENTENCE="Hey. If you want to cherry-pick this pr to a target branch, please comments '/pulsarbot cherry-pick to branch-x.y'."
+    else
+        PROMPT_SENTENCE="Hey, ${users}. If you want to cherry-pick this pr to a target branch, please comments '/pulsarbot cherry-pick to branch-x.y'."
+    fi
+
+    if [[ "" == "${GITHUB_TOKEN}" ]]; then
+        curl --request POST \
+            --url ${COMMENTS_URL} \
+            --data "{\"body\": \"${PROMPT_SENTENCE}\"}"
+    else
+        curl --request POST \
+            --url ${COMMENTS_URL} \
+            --header "Authorization: token ${GITHUB_TOKEN}" \
+            --data "{\"body\": \"${PROMPT_SENTENCE}\"}"
+    fi
+}
+
+echo ${1}
+case ${1} in
+    cherry-pick)
+        shift
+        configure_args ${@}
+        git_setup
+        cherrypick_args
+        cherrypick
+        ;;
+    prompt-comment)
+        shift
+        configure_args ${@}
+        pr_close_prompt_args
+        pr_close_prompt
+        ;;
+esac
+