aboutsummaryrefslogtreecommitdiffhomepage
path: root/assets/ci.sh
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2021-06-30 03:03:48 +0200
committercbdev <cb@cbcdn.com>2021-06-30 03:03:48 +0200
commitbc3d80e9e6c038c87a64432586670c663a23e53d (patch)
tree5a28b0004a7f3492455316f34bb2c783e670f944 /assets/ci.sh
parent8a0a413f1dd5593189dd6b651babcff9b2495451 (diff)
parentf16f7db86662fcdbf45b6373257c90c824b0b4b0 (diff)
downloadmidimonster-bc3d80e9e6c038c87a64432586670c663a23e53d.tar.gz
midimonster-bc3d80e9e6c038c87a64432586670c663a23e53d.tar.bz2
midimonster-bc3d80e9e6c038c87a64432586670c663a23e53d.zip
Merge branch 'master' into debian/master
Diffstat (limited to 'assets/ci.sh')
-rwxr-xr-xassets/ci.sh313
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