Introduce a pulsarbot action for triggering github actions (#3)

*Motivation*

Provide an alternative way to trigger github actions.
diff --git a/README.md b/README.md
index 953e2d3..22a67ae 100644
--- a/README.md
+++ b/README.md
@@ -5,4 +5,5 @@
 ## Github Actions
 
 - [diff-only](diff-only/README.md) action
-- [setup-maven](setup-maven/README.md)
+- [pulsarbot](pulsarbot/README.md)
+- [setup-maven](setup-maven/README.md)
\ No newline at end of file
diff --git a/pulsarbot/Dockerfile b/pulsarbot/Dockerfile
new file mode 100644
index 0000000..936ea5c
--- /dev/null
+++ b/pulsarbot/Dockerfile
@@ -0,0 +1,15 @@
+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 && rm -rf /var/cache/apk/*
+
+COPY entrypoint.sh /entrypoint.sh
+ENTRYPOINT ["/entrypoint.sh"]
\ No newline at end of file
diff --git a/pulsarbot/README.md b/pulsarbot/README.md
new file mode 100644
index 0000000..6ab1710
--- /dev/null
+++ b/pulsarbot/README.md
@@ -0,0 +1,12 @@
+# Pulsar Bot
+
+`pulsarbot` is a github action that reacts to comments and trigger coresponding tasks.
+
+All pulsarbot commands start with `/pulsarbot`.
+
+The accepted commands are:
+
+- `/pulsarbot run-failure-checks`: Run all the failed checks.
+- `/pulsarbot rerun-failure-checks`: Rerun all the failed checks. Same as `/pulsarbot run-failure-checks`.
+- `/pulsarbot run <check-name>`: Run a specified check only if the check is failed.
+- `/pulsarbot rerun <check-name>`: Same as `/pulsarbot run <check-name>`
\ No newline at end of file
diff --git a/pulsarbot/entrypoint.sh b/pulsarbot/entrypoint.sh
new file mode 100755
index 0000000..5e83946
--- /dev/null
+++ b/pulsarbot/entrypoint.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+set -e
+
+cat ${GITHUB_EVENT_PATH}
+COMMENT_BODY=$(jq -r '.comment.body' "${GITHUB_EVENT_PATH}")
+
+BOT_COMMAND_PREFIX="/pulsarbot"
+
+if [[ ${COMMENT_BODY} != "${BOT_COMMAND_PREFIX}"* ]]; then
+    echo "Not a pulsarbot command, skipping it ..."
+    exit
+fi
+
+
+read -r -a commands <<< "${COMMENT_BODY}" 
+BOT_COMMAND=${commands[1]}
+CHECK_NAME=""
+if [ "${BOT_COMMAND}" == "rerun-failure-checks" ]; then
+    CHECK_NAME="_all"
+elif [ "${BOT_COMMAND}" == "run-failure-checks" ]; then
+    CHECK_NAME="_all"
+elif [ "${BOT_COMMAND}" == "run" ]; then
+    CHECK_NAME=${commands[2]}
+elif [ "${BOT_COMMAND}" == "rerun" ]; then
+    CHECK_NAME=${commands[2]}
+else
+    echo "Invalid bot command '${BOT_COMMAND}', skip ..."
+    exit
+fi
+
+if [[ "${CHECK_NAME}" == "" ]]; then
+    echo "Invalid check name '${CHECK_NAME}', skip ..."
+    exit
+fi
+
+PR_NUM=$(jq -r '.issue.number' "${GITHUB_EVENT_PATH}")
+
+# get head sha
+curl -s -H "Accept: application/vnd.github.antiope-preview+json" https://api.github.com/repos/apache/pulsar/git/ref/pull/${PR_NUM}/head > result-headsha.txt
+HEAD_SHA=$(jq -r '.object.sha' result-headsha.txt)
+
+# get checkrun results
+curl -s -H "Accept: application/vnd.github.antiope-preview+json" https://api.github.com/repos/apache/pulsar/commits/${HEAD_SHA}/check-runs > result-check-runs.txt
+
+# find the failures 
+for row in $(cat result-check-runs.txt | jq -r '.check_runs[] | select(.status == "completed" and (.conclusion == "failure" or .conclusion == "cancelled")) | @base64'); do
+    _jq() {
+        echo ${row} | base64 --decode | jq -r ${1}
+    }
+
+    name=$(echo $(_jq '.name'))
+    check_suite_id=$(echo $(_jq '.check_suite.id'))
+    if [[ "${CHECK_NAME}" == "_all" || "${CHECK_NAME}" == "${name}" ]]; then
+        echo "rerun action ${name}, check_suite_id = ${check_suite_id}"
+        curl -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github.antiope-preview+json" -X POST https://api.github.com/repos/apache/pulsar/check-suites/${check_suite_id}/rerequest
+    else
+        echo "Expect ${CHECK_NAME} but skip action ${name}, check_suite_id = ${check_suite_id}"
+    fi
+done