]> git.corax.cc Git - foundry/commitdiff
testbot: Add bot for testing source trees
authorMatthias Kruk <m@m10k.eu>
Sun, 25 Jul 2021 05:36:26 +0000 (14:36 +0900)
committerMatthias Kruk <m@m10k.eu>
Sun, 25 Jul 2021 05:36:26 +0000 (14:36 +0900)
This commit adds testbot, a bot that listens for testrequest messages,
performs tests on the source tree specified in the request, and publishes
the result under the topic configured on the commandline.

testbot.sh [new file with mode: 0644]

diff --git a/testbot.sh b/testbot.sh
new file mode 100644 (file)
index 0000000..5fe1523
--- /dev/null
@@ -0,0 +1,221 @@
+#!/bin/bash
+
+test_source_tree() {
+       local repository="$1"
+       local branch="$2"
+       local commit="$3"
+
+       local destination
+       local err
+
+       if ! destination=$(mktemp -d); then
+               echo "Could not create temporary directory"
+               log_error "Could not create temporary directory"
+               return 1
+       fi
+
+       if ! git clone "$repository" -b "$branch" --single-branch "$destination"; then
+               local errmsg
+
+               errmsg="Could not check out $repository#$branch to $destination"
+               log_error "$errmsg"
+               echo "$errmsg"
+
+               if ! rm -rf "$destination"; then
+                       log_warn "Could not remove $destination"
+                       echo "Could not remove $destination"
+               fi
+
+               return 1
+       fi
+
+       if ! ( cd "$destination" && git checkout "$commit" ); then
+               local errmsg
+
+               errmsg="Could not check out commit $commit from $repository"
+               log_error "$errmsg"
+               echo "$errmsg"
+
+               if ! rm -rf "$destination"; then
+                       log_warn "Could not remove $destination"
+                       echo "Could not remove $destination"
+               fi
+
+               return 1
+       fi
+
+       err=0
+
+       if ! ( cd "$destination" && make test ) 2>&1; then
+               err=1
+       fi
+
+       if ! rm -rf "$destination"; then
+               log_warn "Could not remove temporary directory $destination"
+               echo "Could not remove temporary directory $destination"
+       fi
+
+       return "$err"
+}
+
+publish_result() {
+       local endpoint="$1"
+       local topic="$2"
+       local context="$3"
+       local repository="$4"
+       local branch="$5"
+       local commit="$6"
+       local result="$7"
+       local testlog="$8"
+
+       local testmsg
+       local testlogs
+
+       readarray -t testlogs <<< "$testlog"
+
+       if ! testmsg=$(foundry_msg_test_new "$context"      \
+                                           "$repository"   \
+                                           "$branch"       \
+                                           "$commit"       \
+                                           "$result"       \
+                                           "${testlogs[@]}"); then
+               log_error "Could not make test message"
+               return 1
+       fi
+
+       if ! ipc_endpoint_publish "$endpoint" "$topic" "$testmsg"; then
+               log_error "Could not publish test message on $topic"
+               return 1
+       fi
+
+       return 0
+}
+
+handle_test_request() {
+       local endpoint="$1"
+       local request="$2"
+       local topic="$3"
+
+       local context
+       local repository
+       local branch
+       local commit
+       local result
+       local testlog
+
+       if ! context=$(foundry_msg_testrequest_get_context "$request"); then
+               log_warn "Could not get context from message. Dropping."
+               return 1
+
+       elif ! repository=$(foundry_msg_testrequest_get_repository "$request"); then
+               log_warn "Could not get repository from message. Dropping."
+               return 1
+
+       elif ! branch=$(foundry_msg_testrequest_get_branch "$request"); then
+               log_warn "Could not get branch from message. Dropping."
+               return 1
+
+       elif ! commit=$(foundry_msg_testrequest_get_commit "$request"); then
+               log_warn "Could not get commit from message. Dropping."
+               return 1
+       fi
+
+       result=0
+       if ! testlog=$(mktemp --suffix="-test.log"); then
+               log_error "Could not create logfile"
+               return 1
+       fi
+
+       if ! test_source_tree "$repository" "$branch" "$commit" &> "$testlog"; then
+               result=1
+       fi
+
+       if ! foundry_context_add_log "$context" "test" "$testlog"; then
+               log_error "Could not add logfile to context $context"
+
+               if ! rm -f "$testlog"; then
+                       log_warn "Could not remove $testlog"
+               fi
+
+               return 1
+       fi
+
+       if ! publish_result "$endpoint" "$topic" "$context" "$repository" \
+                           "$branch" "$commit" "$result" "$testlog"; then
+               log_warn "Could not publish test result"
+               return 1
+       fi
+
+       return 0
+}
+
+_testbot_run() {
+       local endpoint_name="$1"
+       local topic="$2"
+
+       local endpoint
+
+       if ! endpoint=$(ipc_endpoint_open "$endpoint_name"); then
+               log_error "Could not listen on $endpoint_name"
+               return 1
+       fi
+
+       while inst_running; do
+               local msg
+               local fmsg
+               local ftype
+
+               if ! msg=$(ipc_endpoint_recv "$endpoint" 5); then
+                       continue
+               fi
+
+               if ! fmsg=$(ipc_msg_get_data "$msg") ||
+                  ! ftype=$(foundry_msg_get_type "$fmsg") ||
+                  [[ "$ftype" != "testrequest" ]]; then
+                       log_warn "Dropping invalid message"
+                       continue
+               fi
+
+               handle_test_request "$endpoint" "$fmsg" "$topic"
+       done
+
+       return 0
+}
+
+main() {
+       local endpoint_name
+       local topic
+
+       opt_add_arg "n" "name"     "rv" ""            \
+                   "The name of this instance"
+       opt_add_arg "e" "endpoint" "v"  "pub/testbot" \
+                   "The endpoint to use for IPC messaging"
+       opt_add_arg "t" "topic"    "v"  "merges"      \
+                   "The topic under which to publish notifications"
+
+       if ! opt_parse "$@"; then
+               return 1
+       fi
+
+       endpoint_name=$(opt_get "endpoint")
+       topic=$(opt_get "topic")
+
+       if ! inst_start _testbot_run "$endpoint_name" "$topic"; then
+               return 1
+       fi
+
+       return 0
+}
+
+{
+       if ! . toolbox.sh; then
+               exit 1
+       fi
+
+       if ! include "log" "opt" "ipc" "foundry/msg" "foundry/context"; then
+               exit 1
+       fi
+
+       main "$@"
+       exit "$?"
+}