#!/usr/bin/env bash # TODO: Check installed: git, jq function detech() { command=${@:2} log=$1 "$command" &>$log & disown } function die() { write_log "Oops: $@" 1>&2 ; exit 1; } function get_log_timestamps() { $event=$1 $log_file=$2 grep -oP "^(\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\] $event at \K([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}))$" $log_file } function get_os() { function get_os_line() { file="" property=$1 if [[ -f "/etc/os-release" ]]; then file="/etc/os-release" elif [[ -f "/usr/etc/os-release" ]]; then file="/usr/etc/os-release" fi if [[ ! -z $file ]]; then echo $(grep -oP "(?<=^$property=).+" $file | tr -d '"') fi } os_name=$(get_os_line "NAME") os_version=$(get_os_line "VERSION") os_pretty=$(get_os_line "PRETTY_NAME") if [[ ! -z $os_pretty ]]; then echo "$os_pretty" elif [[ ! -z $os_name ]]; then echo "$os_name $os_version" else echo "Unknown OS" fi } function now() { echo $(date +"%Y-%m-%d %H:%M:%S") } function query_json() { echo "$1" | jq $2 -r } function split_string() { echo $1 | cut -d"$2" -f$3 } function write_log() { echo "[$(now)] $@" } function write_separator() { char=$1 echo "$(printf "%0.s$char" {1..80})" } payload=$1 service=$2 event=$3 id=$4 started_time=$(now) base_dir="$(dirname "$(realpath -s "$0")")" build_base_dir="$base_dir/wd" log_base_dir="$base_dir/logs" script_base_dir="$base_dir/repos" mkdir -p $build_base_dir mkdir -p $log_base_dir if [[ -z $event ]]; then if [[ ! -z $x_github_event ]]; then event=$x_github_event else die "Missing event" fi fi if [[ -z $service ]]; then service="github" fi if [[ -z $id ]]; then if [[ ! -z $x_github_delivery ]]; then id=$x_github_delivery else id=$(cat /proc/sys/kernel/random/uuid) fi fi if [[ ! -z "$payload" ]]; then payload_type=$(echo $payload | jq type -r) if [[ $? != 0 ]]; then die "Bad body format (expecting JSON)" else if [[ ! $payload_type = "object" ]]; then die "Bad body format (expecting JSON object but got $payload_type)" fi fi else die "Missing payload" fi # TODO: Test Gitea if ! { [[ $service == "github" ]] || [[ $service == "gitea" ]]; }; then die "Service '$service' not supported" fi repo=$(query_json "$payload" ".repository.full_name") repo_author=$(split_string $repo "/" 1) repo_name=$(split_string $repo "/" 2) instance="$(date +"%y%m%d%H%M%S")_${repo_name}_$id" script_path="$script_base_dir/$service/$repo_author/$repo_name" build_path="$build_base_dir/$instance" log_path="$log_base_dir/$instance.txt" if [[ -f "$script_path/$event.sh" ]]; then script_path="$script_path/$event.sh" elif [[ -f "$script_path/default.sh" ]]; then script_path="$script_path/default.sh" else script_path="" fi if [[ ! -z $script_path ]]; then function invoke_script() { write_log "Started at $(now)" export _hook_event=$event export _hook_id=$id export _hook_payload=$payload export _repo_clone_url=$(query_json "$payload" ".repository.clone_url") export _wd=$build_path export -f query_json export -f now export -f split_string export -f write_log write_log "Creating working directory..." mkdir -p $build_path write_log "Setting path to '$build_path'..." cd $build_path chmod +x $script_path if { [[ $event == "push" ]]; }; then export _branch=$(split_string $(query_json "$payload" ".ref") "/" 3) export _commit_hash=$(query_json "$payload" ".head_commit.id") export _commit_message=$(query_json "$payload" ".head_commit.message") export _commit_timestamp=$(query_json "$payload" ".head_commit.timestamp") write_log "Cloning repository from '$_repo_clone_url'..." git clone --recurse-submodules -q $_repo_clone_url $build_path write_log "Resetting repository to '$_commit_hash'..." git reset --hard -q $_commit_hash fi write_log "Executing script..." write_separator "=" $script_path write_separator "=" write_log "Removing working directory..." rm -rf $build_path write_log "Finished at $(now)" } detech "$log_path" invoke_script echo " Repo: $service:$repo" echo " Event: $event ($id)" echo "Instance: $instance" echo " Script: $script_path" echo " Working: $build_path" echo " Log: $log_path" echo " Host: $(hostname) ($(get_os))" echo " Started: $started_time" else if [[ $event == "ping" ]]; then echo "Pong!" echo "" echo "If you're seeing this, that means you've done something right. To trigger scripts on events place them in '$script_base_dir/$service/$repo_author/$repo_name/.sh'." else die "No handler for $event on $service:$repo" fi fi