diff options
Diffstat (limited to 'assets/ci.sh')
| -rwxr-xr-x | assets/ci.sh | 313 | 
1 files changed, 313 insertions, 0 deletions
| diff --git a/assets/ci.sh b/assets/ci.sh new file mode 100755 index 0000000..94b8bed --- /dev/null +++ b/assets/ci.sh @@ -0,0 +1,313 @@ +#!/bin/bash +# shellcheck disable=SC2001,SC2181 + +################################################ SETUP ################################################ +dep_build_core=( +    libasound2-dev +    libevdev-dev +    liblua5.3-dev +    libola-dev +    libjack-jackd2-dev +    python3-dev +    libssl-dev +	build-essential +	pkg-config +	git +) + +dep_build_win=( +    mingw-w64 +) + +dep_build_debian=( +	git-buildpackage +	debhelper +) + +exitcode="0" + +############################################## FUNCTIONS ############################################## + +ARGS(){ +	for i in "$@"; do +		case "$i" in +			--target=*|-t=*) +				TARGETS="${i#*=}" +			;; +			--deploy) +				deploy="1" +			;; +			--deps) +				install_deps="1" +			;; +			-v|--verbose) +				verbose="1" +			;; +			-af|--allow-failure) +				allow_failure="1" +			;; +			-h|--help|*) +				print_help +				exit "0" +			;; +		esac +		shift +	done +	[[ -z $TARGETS ]] && print_help && printf "\nNo target specified!\n" && exit "1"	# If no target(s) are specified exit. +} + +print_help() { +	printf "Usage: %s [OPTIONS]\n\n" "$0" +	printf -- "-t=<argument>, <argument>\t--target=<argument>, <argument>\n\n" +	printf -- "--deploy\tPackage release/nightly versions to the ./deployment/\$target directory.\n" +	printf -- "--deps\t\tCheck and install all dependencies needed for the specified target without the need to manualy run the dependency install targets/s.\n" +	printf -- "-af, --allow-failure\tAlways exit with code 0.\n" +	printf -- "-v, --verbose\tEnables detailed log output.\n\n" +	printf "Valid test targets are: \t\"check-spelling\" - \"1\", \"check-codespelling\" - \"2\", \"analyze-complexity\" - \"3\", \"analyze-shellscript\" - \"4\", \"stats\" - \"5\".\n" +	printf "Valid build targets are: \t\"build-linux\" - \"10\", \"build-windows\" - \"11\", \"build-debian\" - \"12\".\n" +	printf "Valid dependency install targets are: \t\"deps-linux\", \"deps-windows\", \"deps-debian\", \"deps-osx\" \"deps-tests\", \"deps-all\".\n\n" +} + +install_dependencies(){ +    start_apt update -y -qq > /dev/null || error_handler "There was an error doing apt update." +	for dependency in "$@"; do +		if [ "$(dpkg-query -W -f='${Status}' "$dependency" 2>/dev/null | grep -c "ok installed")" -eq 0 ]; then +            deps+=("$dependency")   # Add not installed dependency to the "to be installed array". +		else +			[[ -n $verbose ]] && printf "%s already installed!\n" "$dependency"   # If the dependency is already installed print it. +		fi +	done + +if [ ! "${#deps[@]}" -ge "1" ]; then    # If nothing needs to get installed don't start apt. +    [[ -n $verbose ]] && echo "All dependencies are fulfilled."    # Dependency array empty! Not running apt! +else +    [[ -z $verbose ]] && echo "Starting dependency installation." +    [[ -n $verbose ]] && echo "Then following dependencies are going to be installed:"    # Dependency array contains items. Running apt. +	[[ -n $verbose ]] && echo "${deps[@]}" | sed 's/ /, /g' +    start_apt install -y -qq --no-install-suggests --no-install-recommends "${deps[@]}" > /dev/null || error_handler "There was an error doing dependency installation!" +fi +	[[ -n $verbose ]] && printf "\n" +} + +start_apt(){ +    i="0" +	if command -v fuser &> /dev/null; then +		while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do +			[ "$i" -eq "0" ] && printf "\nWaiting for other software managers to finish" +			[ "$i" -le "16" ] && printf "." # Print a max of 16 dots if waiting. +			((i=i+1)) +			sleep "1s" +		done +		[ "$i" -ge "1" ] && printf "ready!\n" +	fi +	DEBIAN_FRONTEND=noninteractive apt-get "$@" +} + +# Build targets and corresponding deployment. + +build-linux(){ +	[[ -n $install_deps ]] && install_dependencies "${dep_build_core[@]}" +	make full +} + +build-linux-deploy(){ +	#printf "\nLinux Deployment started..\n" +	mkdir -p ./deployment/linux/backends +	mkdir -p ./deployment/linux/docs +	cp ./midimonster ./deployment/linux/ +	cp ./backends/*.so ./deployment/linux/backends/ +	cp ./monster.cfg ./deployment/linux/monster.cfg +	cp ./backends/*.md ./deployment/linux/docs/ +	cp -r ./configs ./deployment/linux/ +	cd ./deployment/linux || error_handler "Error doing cd to ./deployment" +	filename="midimonster-$(git describe)-$OS.tgz" +	touch "$filename" && tar --exclude=*.tgz -czf "$filename" "./" +	find . ! -iname "*.zip" ! -iname "*.tgz" -delete +} + +build-windows(){ +	[[ -n $install_deps ]] && install_dependencies "${dep_build_core[@]}" "${dep_build_win[@]}" +	make windows +} + +build-windows-deploy(){ +	#printf "\nWindows Deployment started..\n" +	mkdir -p ./deployment/windows/backends +	mkdir -p ./deployment/windows/docs +	strip midimonster.exe backends/*.dll	# Strip the Windows binaries as they become huge quickly. +	cp ./midimonster.exe ./deployment/windows/ +	cp ./backends/*.dll ./deployment/windows/backends/ +	cp ./backends/*.dll.disabled ./deployment/windows/backends/ +	cp ./monster.cfg ./deployment/windows/monster.cfg +	cp ./backends/*.md ./deployment/windows/docs/ +	cp -r ./configs ./deployment/windows/ +	cd ./deployment/windows || error_handler "Error doing cd to ./deployment/windows" +	zip -r "./midimonster-$(git describe)-windows.zip" "./" +	find . ! -iname "*.zip" ! -iname "*.tgz" -delete +} + +build-debian(){ +	[[ -n $install_deps ]] && install_dependencies "${dep_build_core[@]}" "${dep_build_debian[@]}" +	git checkout debian/master +	gbp buildpackage +} + +build-debian-deploy(){ +	#printf "\nDebian Package Deployment started..\n" +	mkdir -p ./deployment/debian/ +	cp ./*.deb ./deployment/debian/ +} + +# Tests + +ckeck-spelling(){		# Check spelling. +	[[ -n $install_deps ]] && install_dependencies "lintian" +	spellcheck_files=$(find . -type f | grep -v ".git/")	# Create list of files to be spellchecked. +	sl_results=$(xargs spellintian 2>&1 <<< "$spellcheck_files")	# Run spellintian to find spelling errors +	sl_errors=$(wc -l <<< "$sl_results") +	sl_errors_dups=$( (grep -c "\(duplicate word\)") <<< "$sl_results") +	sl_errors_nodups=$( (grep -cv "\(duplicate word\)") <<< "$sl_results") + +	if [ "$sl_errors" -gt "1" ]; then +		printf "Spellintian found %s errors (%s spelling, %s duplicate words):\n\n" "$sl_errors" "$sl_errors_nodups" "$sl_errors_dups" +		printf "%s\n\n" "$sl_results" +		exitcode=1 +	else +		printf "Spellintian reports no errors\n" +	fi +} + +check-codespelling(){	# Check code for common misspellings. +	[[ -n $install_deps ]] && install_dependencies "codespell" +	spellcheck_files=$(find . -type f | grep -v ".git/")	# Create list of files to be spellchecked. +	cs_results=$(xargs codespell --quiet 2 <<< "$spellcheck_files" 2>&1) +	cs_errors=$(wc -l <<< "$cs_results") +	if [ "$cs_errors" -gt "1" ]; then +		printf "Codespell found %s errors:\n\n" "$cs_errors" +		printf "%s\n\n" "$cs_results" +		exitcode=1 +	else +		printf "Codespell reports no errors\n" +	fi +} + +analyze-complexity(){	# code complexity analyser. +	[[ -n $install_deps ]] && install_dependencies "python3" "python3-pip" +	if [ -z "$(which ~/.local/bin/lizard)" ]; then +		printf "Installing lizard...\n" +		pip3 install lizard >/dev/null +	fi +	printf "Running lizard for code complexity analysis\n" +	~/.local/bin/lizard ./ +	if [ "$?" -ne "0" ]; then +		exitcode=1 +	fi +} + +analyze-shellscript(){	# Shellscript analysis tool. +	[[ -n $install_deps ]] && install_dependencies "shellcheck" +	printf "Running shellcheck:\n" +	shell_files="$(find . -type f -iname \*.sh)" +	xargs shellcheck -Cnever -s bash <<< "$shell_files" +	if [ "$?" -ne "0" ]; then +		exitcode=1 +	fi +} + +stats(){				# Code statistics. +	[[ -n $install_deps ]] && install_dependencies "cloc" +	printf "Code statistics:\n" +	cloc ./ +} + +target_queue(){ +	printf "\n" +	IFS=',|.' read -ra Queue <<< "$TARGETS" +	for i in "${Queue[@]}"; do +		case "$i" in +			check-spelling|1) +				ckeck-spelling +			;; +			check-codespelling|2) +				check-codespelling +			;; +			analyze-complexity|3) +				analyze-complexity +			;; +			analyze-shellscript|4) +				analyze-shellscript +			;; +			stats|5) +				stats +			;; +			build-linux|10) +				OS="linux" +				build-linux +				[[ -n $deploy ]] && build-linux-deploy	# Deploy build artifacts if the deploy flag is set. +			;; +			build-windows|build-win|11) +				build-windows +				[[ -n $deploy ]] && build-windows-deploy	# Deploy build artifacts if the deploy flag is set. +			;; +			build-debian|build-deb|12) +				build-debian +				[[ -n $deploy ]] && build-debian-deploy	# Deploy build artifacts if the deploy flag is set. +			;; +			build-osx|13) +				OS="osx" +				printf "\nNot implemented yet!\n" +				#build-linux +				#[[ -n $deploy ]] && build-linux-deploy		# Deploy build artifacts if the deploy flag is set. +			;; +			deps-linux) +				# Target to install all needed dependencies for linux builds. +				install_dependencies "${dep_build_core[@]}" +			;; +			deps-windows|deps-win) +				# Target to install all needed dependencies for windows builds. +				install_dependencies "${dep_build_core[@]}" "${dep_build_win[@]}" +			;; +			deps-debian|deps-deb) +				# Target to install all needed dependencies for debian packaging. +				install_dependencies "${dep_build_core[@]}" "${dep_build_debian[@]}" +			;; +			deps-osx) +				# Target to install all needed dependencies for osx. +				printf "\nNot implemented yet!\n" +			;; +			deps-tests) +				install_dependencies "lintian" "codespell" "python3" "python3-pip" "shellcheck" "cloc" +				# Install lizard if not found. +				if [ -z "$(which ~/.local/bin/lizard)" ]; then +					pip3 install lizard >/dev/null +				fi +			;; +			deps-all) +				# Target to install all needed dependencies for this ci script. +				install_dependencies "${dep_build_core[@]}" "${dep_build_win[@]}" "${dep_build_debian[@]}" "lintian" "codespell" "python3" "python3-pip" "shellcheck" "cloc" +			;; +			*) +				printf "Target '%s' not valid!\n" "$i" +			;; +		esac +		printf "\n" +	done +} + +error_handler(){ +	[[ -n $1 ]] && printf "\n%s\n" "$1" +	printf "\nAborting" +	for i in {1..3}; do sleep 0.3s && printf "." && sleep 0.2s; done +	printf "\n" +	exit "1" +} + +################################################ Main ################################################# +trap error_handler SIGINT SIGTERM + +ARGS "$@"	# Parse arguments. +target_queue	# Start requestet targets. + +# Allow failure handler. +[[ -z $allow_failure ]] && exit "$exitcode" +exit "0"
\ No newline at end of file | 
