1
1
Fork 0
scripts/ci.sh

215 lines
5.4 KiB
Bash
Executable File

#!/usr/bin/env bash
## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ##
## ci.sh ##
## ##
## A poor man's continuous ##
## integration system ##
## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
##
## Information
## (don't touch unless you are me)
##
NAME="ci.sh"
DESCRIPTION="A poor man's continuous integration system"
VERSION="0.1.1"
AUTHOR="david@socialnerds.org"
LICENSE="MIT"
WEBSITE="https://git.socialnerds.org/david/scripts"
CHANGELOG=("[2023-12-21][v0.1.1] More error handling"
"[2023-12-20][v0.1.0] Initial version")
##
## Configuration
##
EXECUTABLE="$(basename $0)"
LIBRARIES="lib.sh"
DEPENDENCIES="whoami tr head basename dirname readlink curl git cut nohup ps cat getent"
REQUIRE_ROOT=0
[[ ! $HOME ]] && HOME=$(getent passwd "$USER" | cut -d: -f6)
SCRIPTS_DIR="$HOME/ci-scripts"
TEMP_DIR="/tmp/ci-repos"
##
## Functions
##
# Print help information
function print_help() {
local i=20
printf "%s\n\n%s\n%b\n\n%s\n" \
"$DESCRIPTION" "Usage:" "$LIB_BOLD$EXECUTABLE <options> <git-repo>$LIB_CLEAR" "Options:"
printf " %-${i}s %b\n" \
"-s, --scripts <DIR>" "Specify the scripts directory (default: $SCRIPTS_DIR)" \
"-c, --checks <URL>" "Enable ${LIB_UNDERLINE}healthchecks.io${LIB_CLEAR} integration" \
"-n, --ntfy <URL>" "Enable ${LIB_UNDERLINE}ntfy.sh${LIB_CLEAR} integration" \
"-h, --help" "Print help screen and exit" \
"-i, --info" "Print script information and exit" \
"-v, --verbose" "More verbose output" \
"-q, --quiet" "No output except errors (overrides -v)"
}
##
## Preflight
##
# Load BASH libraries
SCRIPT_PATH=$(readlink -f "$0")
SCRIPT_DIR=$(dirname "$SCRIPT_PATH")
for LIBRARY in $LIBRARIES; do
if [[ -r "$SCRIPT_DIR/$LIBRARY" ]]; then
#echo "Loading library file [$SCRIPT_DIR/$LIBRARY]"
source "$SCRIPT_DIR/$LIBRARY"
else
echo "Error: Cannot load library file [$SCRIPT_DIR/$LIBRARY]"
exit 1
fi
done
# Check for root privileges
if ! lib_amiroot && [[ $REQUIRE_ROOT -eq 1 ]]; then
lib_print "!You need to have root privileges"
exit 1
fi
# Check for dependencies
MISSING_COMMANDS=$(lib_missing_commands $DEPENDENCIES)
if [[ -n "$MISSING_COMMANDS" ]]; then
lib_print "!One or more commands missing [$MISSING_COMMANDS]"
lib_print "Try installing them with your package manager"
exit 1
fi
##
## Liftoff
##
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do
case "$1" in
-n|--ntfy)
CURRENT_OPTION="$1"
shift
if lib_is_url "$1"; then
NTFY_URL="$1"
else
lib_print "!$CURRENT_OPTION expects a valid ntfy.sh URL [$1]"
exit 1
fi
;;
-c|--checks)
CURRENT_OPTION="$1"
shift
if lib_is_url "$1"; then
CHECKS_URL="$1"
else
lib_print "!$CURRENT_OPTION expects a valid healthchecks.io URL [$1]"
exit 1
fi
;;
-s|--scripts)
shift
if lib_is_absolute "$1"; then
SCRIPTS_DIR="$1"
else
SCRIPTS_DIR="$(PWD)/$1"
fi
;;
-h|--help)
H=1
;;
-i|--info)
I=1
;;
-v|--verbose)
V=1
;;
-q|--quiet)
Q=1
;;
*)
lib_print "!Unknown option [$1]"
lib_print "Try --help or -h for available options"
exit 1
;;
esac
shift
done
if [[ "$1" == '--' ]]; then
shift
fi
if [[ $I -eq 1 ]]; then
lib_print_info
exit 0
elif [[ $H -eq 1 ]]; then
print_help
exit 0
fi
if [[ -z "$1" ]]; then
print_help
exit 0
else
# Check if a valid Git URL is provided and extract parts
if [[ "$1" =~ ^(git@|https:\/\/)([^\/:]+)[:\/]([^\/]+)\/([^\/]+)(\.git)$ ]]; then
GIT_URL="$1"
GIT_HOST="${BASH_REMATCH[2]}"
GIT_USER="${BASH_REMATCH[3]}"
GIT_REPO="${BASH_REMATCH[4]}"
shift
else
lib_print "!Input does not seem to be a valid Git URL [$1]"
exit 1
fi
# Chech if the script file exists and is executable
if [[ ! -x "$SCRIPTS_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO.sh" ]]; then
lib_print "!No CI script for this repository found [$GIT_HOST/$GIT_USER/$GIT_REPO]"
exit 1
fi
# Create parent directories if missing
if [[ ! -d "$TEMP_DIR/$GIT_HOST/$GIT_USER" ]]; then
mkdir -p "$TEMP_DIR/$GIT_HOST/$GIT_USER"
fi
# Check if repo already exists and if the previous job is still running
if [[ -d "$TEMP_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO" ]]; then
if lib_is_running $(cat "$TEMP_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO.pid" 2> /dev/null); then
lib_print "!CI job is still running [$GIT_HOST/$GIT_USER/$GIT_REPO]"
exit 1
else
rm -rf "$TEMP_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO"
fi
fi
# Clone the repo and execute the CI script
git clone --quiet "$GIT_URL" "$TEMP_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO"
cd "$TEMP_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO"
nohup "$SCRIPTS_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO.sh" "$@" > "$TEMP_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO.log" 2>&1 &
echo $! > "$TEMP_DIR/$GIT_HOST/$GIT_USER/$GIT_REPO.pid"
# Inform user of a successful job execution
lib_print "CI job has been triggered [$GIT_HOST/$GIT_USER/$GIT_REPO]"
lib_ntfy "$NTFY_URL" "CI job has been triggered [$GIT_HOST/$GIT_USER/$GIT_REPO]"
lib_checks "$CHECKS_URL" "CI job has been triggered [$GIT_HOST/$GIT_USER/$GIT_REPO]"
fi
##
## Here be dragons
##
exit 0