From 8c5b176d26162eea286fd54bf6430e43020a3184 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Fri, 11 Aug 2023 19:43:45 +0200 Subject: [PATCH 01/31] Add beginnings of install script --- install.sh | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100755 install.sh diff --git a/install.sh b/install.sh new file mode 100755 index 000000000..05091d4c5 --- /dev/null +++ b/install.sh @@ -0,0 +1,275 @@ +#!/bin/bash + +# ------------------------------------------------------------------------------------------------- +# Error codes +# 10 - No valid ruby present, user chose not to install ruby with this script +# 11 - No valid ruby present, installing rbenv failed +# 12 - No valid ruby present, rbenv ruby-build plugin not present or no ruby 3 version selectable +# 13 - No valid ruby present, rbenv installation of ruby 3 failed +# 16 - No valid ruby present, unable to set ruby version using rbenv +# 15 - No valid ruby present, rvm installation of ruby 3 failed +# 16 - No valid ruby present, unable to set ruby version using rvm + +# ------------------------------------------------------------------------------------------------- +# Helper functions + +log() { printf "%b\n" "$*"; } +warn() { log "WARN: $*" >&2 ; } +fail() { fail_with_code 1 "$*" ; } +fail_with_code() { code="$1" ; shift ; log "\nERROR ($code): $*\n" >&2 ; exit "$code" ; } + +# Ask the user a yes/no question +ask() +{ + while true; do + read -p "$* [y/n] " -r yn + case "$yn" in + y|Y ) return 0;; + n|N ) return 1;; + * ) log "Invalid choice";; + esac + done +} + +# Parses a YAML file using awk and sed +# Copied from StackOverflow: https://stackoverflow.com/a/21189044/14170691 +function parse_yaml { + local prefix=$2 + local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') + sed -ne "s|^\($s\):|\1|" \ + -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | + awk -F$fs '{ + indent = length($1)/2; + vname[indent] = $2; + for (i in vname) {if (i > indent) {delete vname[i]}} + if (length($3) > 0) { + vn=""; for (i=0; i /dev/null; then + # Check whether ruby 3 + rbversion="$(ruby --version)" + regex="(ruby 3\.[0-9]+\.[0-9]+).*" + if [[ $rbversion =~ $regex ]]; then + rbversion="${BASH_REMATCH[1]}" + log "✅ Ruby: found $rbversion" + + return 0 + else + log "❌ Ruby: unrecognized/unsupported ruby version:" + log " $rbversion" + log "" + if builtin command -v rbenv > /dev/null; then + log "🔶 Ruby: detected rbenv" + install_ruby_with_rbenv + elif builtin command -v rvm > /dev/null; then + log "🔶 Ruby: detected RVM" + install_ruby_with_rvm + else + log "❌ Ruby: not found" + install_rbenv + fi + + return 101 + fi + else + log "❌ Ruby: not found" + if builtin command -v rbenv > /dev/null; then + log "🔶 Ruby: detected rbenv" + install_ruby_with_rbenv + elif builtin command -v rvm > /dev/null; then + log "🔶 Ruby: detected RVM" + install_ruby_with_rvm + else + install_rbenv + fi + + return 101 + fi +} + +check_nodejs() +{ + if builtin command -v node > /dev/null; then + log "✅ NodeJS: found $(node --version)" + else + log "❌ NodeJS: not found" + log "" + log " Please install NodeJS for your distribution" + log "" + log " - For Debian-based / Ubuntu:" + log "" + log " sudo apt install nodejs" + log "" + log " - For Mac with homebrew:" + log "" + log " brew install nodejs" + exit 1 + fi +} + +check_mysql() +{ + # TODO: Do stuff with mysql database settings + if builtin command -v mysql > /dev/null; then + log "✅ MySQL client: found $(mysql --version)" + else + log '🔶 MySQL client: not found' + fi +} + +check_redis() +{ + if command -v redis-cli > /dev/null; then + log "✅ Redis: found $(redis-cli --version)" + else + log "🔶 Redis: no local installation found, checking via port..." + if lsof -i:6379 -sTCP:LISTEN > /dev/null; then + log "✅ Redis: seems to be accepting connections" + else + log "❌ Redis: Can't find a redis server on the default port." + log " You can set up redis by running it as a service, or by running it inside docker." + log "TODO" + fi + + log "TODO ask whether to continue" + + fi +} + +# ------------------------------------------------------------------------------------------------- +# Actual commands + +# Check ruby if previous check reports failure (installed using this command) +while ! check_ruby; do + log "🔶 Ruby: Checking again" +done + +check_nodejs +check_mysql +check_redis From e1b6ef5014466ca24c5c833af63c5cef6c8cac67 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Fri, 11 Aug 2023 19:44:01 +0200 Subject: [PATCH 02/31] Ignore rbenv ruby version selection --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 004c052c2..409070b05 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ qpixel-import.tar.gz *.swp dump.rdb + +# rbenv +.ruby-version From ad4127b3435508b4582a1dea78f1001861a6d504 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 18:53:56 +0200 Subject: [PATCH 03/31] Expand install script greatly - Add package installation for apt, homebrew, pacman, dnf - Add mysql2 ruby gem installation - Add bundle install - Add bundler ruby gem installation --- install.sh | 788 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 619 insertions(+), 169 deletions(-) diff --git a/install.sh b/install.sh index 05091d4c5..59ec7dc97 100755 --- a/install.sh +++ b/install.sh @@ -6,7 +6,7 @@ # 11 - No valid ruby present, installing rbenv failed # 12 - No valid ruby present, rbenv ruby-build plugin not present or no ruby 3 version selectable # 13 - No valid ruby present, rbenv installation of ruby 3 failed -# 16 - No valid ruby present, unable to set ruby version using rbenv +# 14 - No valid ruby present, unable to set ruby version using rbenv # 15 - No valid ruby present, rvm installation of ruby 3 failed # 16 - No valid ruby present, unable to set ruby version using rvm @@ -21,85 +21,451 @@ fail_with_code() { code="$1" ; shift ; log "\nERROR ($code): $*\n" >&2 ; exit "$ # Ask the user a yes/no question ask() { - while true; do - read -p "$* [y/n] " -r yn - case "$yn" in - y|Y ) return 0;; - n|N ) return 1;; - * ) log "Invalid choice";; - esac - done + while true; do + read -p "$* [Y/n] " -r yn + case "$yn" in + ("") return 0;; + y|Y ) return 0;; + n|N ) return 1;; + * ) log "Invalid choice";; + esac + done } # Parses a YAML file using awk and sed # Copied from StackOverflow: https://stackoverflow.com/a/21189044/14170691 function parse_yaml { - local prefix=$2 - local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') - sed -ne "s|^\($s\):|\1|" \ - -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ - -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | - awk -F$fs '{ - indent = length($1)/2; - vname[indent] = $2; - for (i in vname) {if (i > indent) {delete vname[i]}} + local prefix=$2 + local s='[[:space:]]*' w='[a-zA-Z0-9_]*' + local fs=$(echo @|tr @ '\034') + sed -ne "s|^\($s\):|\1|" \ + -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | + awk -F$fs '{ + indent = length($1)/2; + vname[indent] = $2; + for (i in vname) {if (i > indent) {delete vname[i]}} if (length($3) > 0) { - vn=""; for (i=0; i /dev/null; then + log "✅ NodeJS: found $(node --version)" + return 1 + else + log "❌ NodeJS: not found" + return 1 + fi +} -install_rbenv() +# Detects the package manager(s) present on the system and asks the user to install dependencies +# with all of them. +# In case of rejection for all, we fail. +install_packages() { - log "We recommend installing ruby using rbenv" - if ! ask "Do you want to install rbenv?"; then - fail_with_code 10 "❌ Not installing rbenv. Please install ruby 3.x" + if ! ask " Packages: Do you want to install required system packages?"; then + log "🔶 Packages: Skipping installation of system packages." + return 0 + fi + + any_matched=1 + + if builtin command -v apt-get > /dev/null; then + log "Detected apt-get (debian-based)" + if ask "Do you want to install required packages with apt-get?"; then + install_packages_apt + return $? + else + any_matched=0 + log "Not installing with apt-get" + fi + fi + + if builtin command -v pacman > /dev/null; then + log "Detected pacman (arch-based)" + if ask "Do you want to install required packages with pacman?"; then + install_packages_pacman + return $? + else + any_matched=0 + log "Not installing with pacman" fi + fi + + if builtin command -v dnf > /dev/null; then + log "Detected dnf (fedora-based)" + if ask "Do you want to install required packages with dnf?"; then + install_packages_dnf + return $? + else + any_matched=0 + log "Not installing with dnf" + fi + fi + + if builtin command -v yum > /dev/null; then + log "Detected yum (fedora-based)" + if ask "Do you want to install required packages with dnf?"; then + install_packages_yum + return $? + else + any_matched=0 + log "Not installing with yum" + fi + fi + + # Homebrew is intentionally placed at the bottom, as it is possible to use homebrew on linux + # In that case, the user may prefer using their system package manager. + if builtin command -v brew > /dev/null; then + log "Detected homebrew" + if ask "Do you want to install required packages with homebrew?"; then + install_packages_homebrew + return $? + else + any_matched=0 + log "Not installing with homebrew" + fi + fi + + # If we found any package manager, but did not confirm install with any of them, fail. + if [ $any_matched == 0 ]; then + fail "❌ No supported package manager was selected. Please install the required packages using the instructions." + fi +} + +install_packages_apt() +{ + log "" + log " --- UPDATING PACKAGE DATABASE USING APT-GET ---" + log "" + if ! sudo apt-get update; then + fail "❌ Unable to update package database using apt-get!" + fi + log "" + log " -------------------------------------------------" + log "" + + # Base packages + log "" + log " --- INSTALLING BASE PACKAGES USING APT-GET ---" + log "" + if ! sudo apt-get install gcc make pkg-config autoconf bison build-essential libssl-dev libyaml-dev libreadline-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev libmysqlclient-dev; then + fail "❌ Unable to install base packages. Please refer to the error above." + fi + log "" + log " ----------------------------------------------" + log "" + log "✅ Packages: installed base packages" + + if ! check_nodejs && ask "Do you want to install nodejs?"; then + log "" + log " --- INSTALLING NODEJS USING APT-GET ---" + log "" + if ! sudo apt-get install nodejs; then + fail "❌ Unable to install nodejs. Please refer to the error above." + fi + log "" + log " ---------------------------------------" + log "" + log "✅ Packages: installed nodejs" + fi + + log "To run QPixel, you need a database, either MySQL or MariaDB. It is also possible to run these in Docker or another server if you wish (but you will have to set that up yourself)." + if ask "Do you want to install MySQL?"; then + log "" + log " --- INSTALLING MYSQL-SERVER USING APT-GET ---" + log "" + if ! sudo apt-get install mysql-server; then + fail "❌ Unable to install mysql. Please refer to the error above." + fi + log "" + log " --------------------------------------" + log "" + log "✅ Packages: installed mysql" + elif ask "Do you want to install MariaDB?"; then + log "" + log " --- INSTALLING MARIADB-SERVER USING APT-GET ---" + log "" + if ! sudo apt-get install mariadb-server; then + fail "❌ Unable to install mariadb. Please refer to the error above." + fi + log "" + log " ---------------------------------------" + log "" + log "✅ Packages: installed mariadb" + fi +} + +install_packages_pacman() +{ + # Update database + log "" + log " --- UPDATING PACKAGE DATABASE USING PACMAN ---" + log "" + if ! sudo pacman -Syyu; then + fail "❌ Unable to update package database using pacman!" + fi + log "" + log " -------------------------------------------------" + log "" + + # Base packages + log "" + log " --- INSTALLING BASE PACKAGES USING PACMAN ---" + log "" + if ! sudo pacman -S gcc make autoconf bison base-devel unixodbc openssl; then + fail "❌ Unable to install base packages. Please refer to the error above." + fi + log "" + log " ---------------------------------------------" + log "" + log "✅ Packages: installed base packages" + # NodeJS + if ! check_nodejs && ask "Do you want to install nodejs?"; then log "" - log " --- INSTALLING RBENV ---" + log " --- INSTALLING NODEJS USING PACMAN ---" log "" + if ! sudo pacman -S nodejs; then + fail "❌ Unable to install nodejs. Please refer to the error above." + fi + log "" + log " --------------------------------------" + log "" + log "✅ Packages: installed nodejs" + fi - if ! \curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash; then - fail_with_code 11 "❌ Something went wrong with the installation. Please refer to output above." + # MySQL / MariaDB + log "To run QPixel, you need a database, either MySQL or MariaDB." + log "You can install either locally (with this install script), run either in docker or use either on another server (you will have to do that yourself)." + if ask "Do you want to install MySQL?"; then + log "" + log " --- INSTALLING MYSQL USING PACMAN ---" + log "" + if ! sudo pacman -S mysql; then + fail "❌ Unable to install mysql. Please refer to the error above." fi + log "" + log " --------------------------------------" + log "" + log "✅ Packages: installed mysql" + elif ask "Do you want to install MariaDB?"; then + log "" + log " --- INSTALLING MARIADB USING PACMAN ---" + log "" + if ! sudo pacman -S mariadb; then + fail "❌ Unable to install mariadb. Please refer to the error above." + fi + log "" + log " ---------------------------------------" + log "" + log "✅ Packages: installed mariadb" + fi + + # MySQL-client-headers Arch users should know what they are doing + log "" + log "You will need the mysql/mariadb client library files to install the ruby mysql2 gem." + log "These are present in mariadb-libs and in libmysqlclient" + if ask "Install mariadb-libs?"; then log "" - log " ------------------------" + log " --- INSTALLING MARIADB-LIBS USING PACMAN ---" + log "" + if ! sudo pacman -S mariadb-libs; then + fail "❌ Unable to install mariadb-libs. This error may be due to a conflict with MySQL. If you have MySQL installed, you may not need to install this package. In that case, rerun this install script but skip installing packages." + fi + log "" + log " --------------------------------------" + log "" + log "✅ Packages: installed mariadb-libs" + elif ask "Install libmysqlclient?"; then + log "" + log " --- INSTALLING LIBMYSQLCLIENT USING PACMAN ---" + log "" + if ! sudo pacman -S libmysqlclient; then + fail "❌ Unable to install libmysqlclient. This error may be due to a conflict with MariaDB. If you have MariaDB installed, you may not need to install this package. In that case, rerun this install script but skip installing packages." + fi + log "" + log " --------------------------------------" + log "" + log "✅ Packages: installed libmysqlclient" + fi +} - log "✅ Ruby - rbenv: installed rbenv" +install_packages_dnf() +{ + # TODO: Untested + # Base packages + log "" + log " --- INSTALLING BASE PACKAGES USING DNF ---" + log "" + log "$ sudo dnf group install \"C Development Tools and Libraries\"" + if ! sudo dnf group install "C Development Tools and Libraries"; then + fail "❌ Unable to install group C Development Tools and Libraries. Please refer to the error above." + fi + log "$ sudo dnf install ruby-devel zlib-devel" + if ! sudo dnf install ruby-devel zlib-devel; then + fail "❌ Unable to install C Development Tools and Libraries. Please refer to the error above." + fi + log "" + log " ----------------------------------------------" + log "" + log "✅ Packages: installed base packages" + if ! check_nodejs && ask "Do you want to install nodejs?"; then log "" - log "🔶 To finish the setup of rbenv, run the following command and follow its instructions:" + log " --- INSTALLING NODEJS USING DNF ---" log "" - log " rbenv init" + if ! sudo dnf install nodejs; then + fail "❌ Unable to install nodejs. Please refer to the error above." + fi + log "" + log " ---------------------------------------" log "" - log "After doing so, please close your terminal and open a new one, then rerun this install command." - exit 0 + log "✅ Packages: installed nodejs" + fi + + # TODO Finish +} + +install_packages_homebrew() +{ + # Check XCode CLI Tools on Mac + case "$OSTYPE" in + darwin*) + if ! xcode-select -p > /dev/null; then + log "Detected Mac OS. On Mac, QPixel needs the XCode Command Line Tools." + if ask "Do you want to install XCode Command Line Tools?"; then + log "" + log " --- INSTALLING XCODE CLI TOOLS ---" + log "" + log "Please confirm the installation using the GUI prompt." + log "" + if ! xcode-select --install; then + fail "❌ xcode-select --install failed" + fi + log "" + log " ----------------------------------" + log "" + fi + fi + ;; + *) ;; + esac + + # Base packages + log "" + log " --- INSTALLING PACKAGES USING HOMEBREW ---" + log "" + if ! brew install bison openssl mysql-client; then + fail_with_code 30 "❌ Error while installing packages with brew. Please refer to the error above." + fi + log "" + log " ------------------------------------------" + log "" + log "✅ Packages: installed base packages" + + if ! check_nodejs && ask "Do you want to install nodejs?"; then + log "" + log " --- INSTALLING NODEJS USING HOMEBREW ---" + log "" + if ! brew install node; then + fail "❌ Unable to install nodejs. Please refer to the error above." + fi + log "" + log " ----------------------------------------" + log "" + log "✅ Packages: installed nodejs" + fi + + log "To run QPixel, you need a database, either MySQL or MariaDB." + log "You can install either locally (with this install script), run either in docker or use either on another server (you will have to do that yourself)." + if ask "Do you want to install MySQL locally?"; then + log "" + log " --- INSTALLING MYSQL USING HOMEBREW ---" + log "" + if ! brew install mysql; then + fail "❌ Unable to install mysql. Please refer to the error above." + fi + log "" + log " ---------------------------------------" + log "" + log "✅ Packages: installed mysql" + elif ask "Do you want to install MariaDB locally?"; then + log "" + log " --- INSTALLING MARIADB USING HOMEBREW ---" + log "" + if ! brew install mariadb; then + fail "❌ Unable to install mariadb. Please refer to the error above." + fi + log "" + log " ---------------------------------------" + log "" + log "✅ Packages: installed mariadb" + fi +} + +# ------------------------------------------------------------------------------------------------- +# Ruby + +## Asks to install RVM, and if user agrees continues with the installation +#install_rvm() +#{ +# log "We recommend installing Ruby using RVM" +# if ! ask "Do you want to install RVM now?"; then +# log "Not installing RVM" +# return 1 +# fi +# +# log " --- Installing RVM ---" +# log "\curl -sSL https://get.rvm.io | bash -s stable --ruby" +# +# return $? +#} + +install_rbenv() +{ + log "We recommend installing ruby using rbenv" + if ! ask "Do you want to install rbenv?"; then + fail_with_code 10 "❌ Not installing rbenv. Please install ruby 3.x" + fi + + log "" + log " --- INSTALLING RBENV ---" + log "" + + if ! \curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash; then + fail_with_code 11 "❌ Something went wrong with the installation. Please refer to output above." + fi + + log "" + log " ------------------------" + + log "✅ Ruby - rbenv: installed rbenv" + + log "" + log "🔶 To finish the setup of rbenv, run the following command and follow its instructions:" + log "" + log " rbenv init" + log "" + log "After doing so, please close your terminal and open a new one, then rerun this install command." + exit 0 } install_ruby_with_rbenv() { - if ! latest_3=$(rbenv install -l | grep "^3\.\d\d*\.\d\d*$" | tail -n1); then - fail_with_code 12 " + if ! latest_3=$(rbenv install -l | grep "^3\.\d\d*\.\d\d*$" | tail -n1); then + fail_with_code 12 " It looks like your rbenv does not have the install option or does not know about any ruby 3 versions. This may be because you are missing the ruby-build plugin for rbenv. Another potential cause is that your version of rbenv is too old. @@ -107,169 +473,253 @@ This may be because you are missing the ruby-build plugin for rbenv. Another pot Please refer to the documentation of rbenv at https://github.com/rbenv/rbenv to debug this issue. You can also consider removing rbenv. This install script can re-install it for you." - fi + fi - if ! ask "Do you want to install the latest ruby 3.x version using rbenv now?"; then - fail_with_code 10 "❌ Not installing ruby using rbenv. Please install ruby 3.x" - fi + if ! ask "Do you want to install the latest ruby 3.x version using rbenv now?"; then + fail_with_code 10 "❌ Not installing ruby using rbenv. Please install ruby 3.x" + fi - log "" - log " --- INSTALLING RUBY $latest_3 USING RBENV ---" - log "" + log "" + log " --- INSTALLING RUBY $latest_3 USING RBENV ---" + log "" - if ! rbenv install "$latest_3"; then - fail_with_code 13 "Something went wrong with the installation. Please refer to the rbenv output above." - fi + if ! rbenv install "$latest_3"; then + fail_with_code 13 "Something went wrong with the installation. Please refer to the rbenv output above." + fi - log "" - log " -----------------------------------------" - log "" + log "" + log " -----------------------------------------" + log "" - log "✅ Ruby - rbenv: installed ruby $latest_3" + log "✅ Ruby - rbenv: installed ruby $latest_3" - if rbenv local "$latest_3"; then - log "✅ Ruby - rbenv: set ruby $latest_3 as default for QPixel" - log "🔶 Ruby - rbenv: use \`rbenv global $latest_3\` to set your global ruby version." - else - log "❌ Ruby - rbenv: unable to set ruby $latest_3 as default for QPixel" - fail_with_code 14 "Use \`rbenv local $latest_3\` or \`rbenv global $latest_3\` to set your current ruby version." - fi + if rbenv local "$latest_3"; then + log "✅ Ruby - rbenv: set ruby $latest_3 as default for QPixel" + log "🔶 Ruby - rbenv: use \`rbenv global $latest_3\` to set your global ruby version." + else + log "❌ Ruby - rbenv: unable to set ruby $latest_3 as default for QPixel" + fail_with_code 14 "Use \`rbenv local $latest_3\` or \`rbenv global $latest_3\` to set your current ruby version." + fi - return 0 + return 0 } install_ruby_with_rvm() { - if ! ask "Do you want to install ruby using RVM now?"; then - fail_with_code 10 "❌ Not installing ruby using RVM. Please install ruby 3.x" - fi + if ! ask "Do you want to install ruby using RVM now?"; then + fail_with_code 10 "❌ Not installing ruby using RVM. Please install ruby 3.x" + fi - log "" - log " --- INSTALLING RUBY USING RVM ---" - log "" + log "" + log " --- INSTALLING RUBY USING RVM ---" + log "" - if ! rvm install ruby --latest; then - fail_with_code 15 "Something went wrong with the installation. Please refer to the rvm output above." - fi + if ! rvm install ruby --latest; then + fail_with_code 15 "Something went wrong with the installation. Please refer to the rvm output above." + fi - log "" - log " ----------------------------------" - log "" - log "✅ Ruby - rvm: installed ruby" + log "" + log " ----------------------------------" + log "" + log "✅ Ruby - rvm: installed ruby" - if rvm --default use ruby --latest; then - log "✅ Ruby - rvm: set installed ruby as default for QPixel" + if rvm --default use ruby --latest; then + log "✅ Ruby - rvm: set installed ruby as default for QPixel" + else + log "❌ Ruby - rbenv: unable to set ruby $latest_3 as default for QPixel" + fail_with_code 16 "Use \`rbenv local $latest_3\` or \`rbenv global $latest_3\` to set your current ruby version." + fi + + return 0 +} + +# Checks whether ruby is installed +# If it is not installed (or the installed version is not supported), will ask user to install it +# using rbenv/rvm or install rbenv to do so. +# @return 0 if ruby found, 101 if ruby should be rechecked. +check_install_ruby() +{ + if builtin command -v ruby > /dev/null; then + # Check whether ruby 3 + rbversion="$(ruby --version)" + regex="(ruby 3\.[0-9]+\.[0-9]+).*" + if [[ $rbversion =~ $regex ]]; then + rbversion="${BASH_REMATCH[1]}" + log "✅ Ruby: found $rbversion" + + return 0 else - log "❌ Ruby - rbenv: unable to set ruby $latest_3 as default for QPixel" - fail_with_code 16 "Use \`rbenv local $latest_3\` or \`rbenv global $latest_3\` to set your current ruby version." + log "❌ Ruby: unrecognized/unsupported ruby version:" + log " $rbversion" + log "" + if builtin command -v rbenv > /dev/null; then + log "🔶 Ruby: detected rbenv" + install_ruby_with_rbenv + elif builtin command -v rvm > /dev/null; then + log "🔶 Ruby: detected RVM" + install_ruby_with_rvm + else + install_rbenv + fi + + return 101 + fi + else + log "❌ Ruby: not found" + if builtin command -v rbenv > /dev/null; then + log "🔶 Ruby: detected rbenv" + install_ruby_with_rbenv + elif builtin command -v rvm > /dev/null; then + log "🔶 Ruby: detected RVM" + install_ruby_with_rvm + else + install_rbenv fi + return 101 + fi +} + +# ------------------------------------------------------------------------------------------------- +# Bundler and gems + +check_install_gem_bundler() +{ + if gem info -i bundler > /dev/null; then + log "✅ Ruby gems - bundler: found" return 0 + fi + + log "❌ Ruby gems - bundler: not found, installing..." + if ! gem install bundler; then + fail "❌ Unable to install bundler (ruby package manager). Please refer to the error above." + fi + # TODO } -# Checks whether ruby is installed -# If it is not installed (or the installed version is not -check_ruby() +check_install_gem_mysql() { - if builtin command -v ruby > /dev/null; then - # Check whether ruby 3 - rbversion="$(ruby --version)" - regex="(ruby 3\.[0-9]+\.[0-9]+).*" - if [[ $rbversion =~ $regex ]]; then - rbversion="${BASH_REMATCH[1]}" - log "✅ Ruby: found $rbversion" - - return 0 - else - log "❌ Ruby: unrecognized/unsupported ruby version:" - log " $rbversion" - log "" - if builtin command -v rbenv > /dev/null; then - log "🔶 Ruby: detected rbenv" - install_ruby_with_rbenv - elif builtin command -v rvm > /dev/null; then - log "🔶 Ruby: detected RVM" - install_ruby_with_rvm - else - log "❌ Ruby: not found" - install_rbenv - fi - - return 101 - fi - else - log "❌ Ruby: not found" - if builtin command -v rbenv > /dev/null; then - log "🔶 Ruby: detected rbenv" - install_ruby_with_rbenv - elif builtin command -v rvm > /dev/null; then - log "🔶 Ruby: detected RVM" - install_ruby_with_rvm - else - install_rbenv - fi + # Check Gemfile + if [[ ! -f "Gemfile" ]]; then + fail "❌ Unable to find Gemfile! Please ensure you cd to the directory of the project and run this script as ./install.sh" + fi + + # Check whether bundler reports the gem as installed + if bundle info mysql2 1> /dev/null 2> /dev/null; then + log "✅ Ruby gems - mysql2: found compatible version" + return 0 + fi - return 101 + # Check homebrew, as it needs a different mysql configuration + if builtin command -v brew > /dev/null && brew info openssl 1> /dev/null 2> /dev/null; then + log " Ruby gems - MySQL2: detected homebrew, configuring bundler for mysql2 installation..." + + if ! bundle config --global build.mysql2 --with-opt-dir="$(brew --prefix openssl)"; then + fail "❌ Error while configuring bundler. Please refer to the error above." fi + + log "✅ Ruby gems - mysql2: configured bundler for mysql2 installation through homebrew" + fi + + # Determine the version(s) of mysql2 that are acceptable and install them (this is a best effort). + mysql_version=$(cat Gemfile | grep mysql2) + regex=", '([~><=\ 0-9\.]+)'" + if [[ $mysql_version =~ $regex ]]; then + mysql_version="${BASH_REMATCH[1]}" + else + fail "❌ Unable to find version of MySQL2 required by the application. Please report this issue on https://github.com/codidact/qpixel" + fi + + log "" + log " --- INSTALLING GEM MYSQL2 $mysql_version ---" + log "" + if ! gem install mysql2 -v "$mysql_version"; then + fail "❌ Failed to install MySQL2 gem. Please refer to the error above. If you skipped installing system packages, you may need to install libmysqlclient-dev, mysql-devel or a similar package." + fi + log "" + log " --------------------------------------" + log "" + log "✅ Ruby gems - mysql2: installed" } -check_nodejs() +bundle_install() { - if builtin command -v node > /dev/null; then - log "✅ NodeJS: found $(node --version)" - else - log "❌ NodeJS: not found" - log "" - log " Please install NodeJS for your distribution" - log "" - log " - For Debian-based / Ubuntu:" - log "" - log " sudo apt install nodejs" - log "" - log " - For Mac with homebrew:" - log "" - log " brew install nodejs" - exit 1 + log "" + log " --- INSTALLING RUBY DEPENDENCIES USING BUNDLER ---" + log "" + if ! bundle install; then + fail "❌ Failed to install dependencies using bundler. Please refer to the error above." fi + log "" + log " --------------------------------------" + log "" + log "✅ Ruby gems - other: installed" } check_mysql() { - # TODO: Do stuff with mysql database settings - if builtin command -v mysql > /dev/null; then - log "✅ MySQL client: found $(mysql --version)" - else - log '🔶 MySQL client: not found' - fi + # TODO: Do stuff with mysql database settings + if builtin command -v mysql > /dev/null; then + log "✅ MySQL client: found $(mysql --version)" + else + log "🔶 MySQL client: not found" + fi } check_redis() { - if command -v redis-cli > /dev/null; then - log "✅ Redis: found $(redis-cli --version)" + if command -v redis-cli > /dev/null; then + log "✅ Redis: found $(redis-cli --version)" + else + log "🔶 Redis: no local installation found, checking via port..." + if lsof -i:6379 -sTCP:LISTEN > /dev/null; then + log "✅ Redis: seems to be accepting connections" else - log "🔶 Redis: no local installation found, checking via port..." - if lsof -i:6379 -sTCP:LISTEN > /dev/null; then - log "✅ Redis: seems to be accepting connections" - else - log "❌ Redis: Can't find a redis server on the default port." - log " You can set up redis by running it as a service, or by running it inside docker." - log "TODO" - fi + log "❌ Redis: Can't find a redis server on the default port." + log " You can set up redis by running it as a service, or by running it inside docker." + log "TODO" + fi - log "TODO ask whether to continue" + log "TODO ask whether to continue" - fi + fi } +set_up_db() +{ + log " Setup - Database: QPixel supports MySQL and MariaDB." + log " Setup - Database: However, if you use MariaDB, we need to update some of the collations used." + + if ask "Are you using MariaDB/will you use MariaDB for QPixel?"; then + log " Setup - Database: Setting collations to be compatible with MariaDB" + if ! sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' "db/schema.rb"; then + fail "❌ Unable to update collations." + fi + else + log " Setup - Database: Setting collations to be compatible with MySQL" + if ! sed -i 's/utf8mb4_unicode_ci/utf8mb4_0900_ai_ci/g' "db/schema.rb"; then + fail "❌ Unable to update collations." + fi + fi + + log "✅ Setup - Database: set correct collations" +} # ------------------------------------------------------------------------------------------------- # Actual commands +install_packages # Check ruby if previous check reports failure (installed using this command) -while ! check_ruby; do - log "🔶 Ruby: Checking again" +while ! check_install_ruby; do + log "🔶 Ruby: Checking again" done +# Check nodejs check_nodejs -check_mysql -check_redis + +# Ruby gems +check_install_gem_bundler +check_install_gem_mysql +bundle_install + +#check_mysql +#check_redis From 810d055056f7c8df450bd8ad27eab8df1232372c Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 21:52:01 +0200 Subject: [PATCH 04/31] Add convenience functions for header, footer and running commands The _run function will output the command being run for better debugging --- install.sh | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/install.sh b/install.sh index 59ec7dc97..b26318389 100755 --- a/install.sh +++ b/install.sh @@ -32,6 +32,39 @@ ask() done } +# runs the command, outputting it to the console and +_run() +{ + cmd="$*" + log "$ $cmd" + $cmd +} + +# Print nicely formatted header to a section +# "Leaks" the $_header_text variable for use in the footer. +# @param 1 - The text to display in the header +# @param 2 - The character to use (default -) +_header() +{ + _header_text="$1" + _header_char="${2:--}" + log "" + log " $_header_char$_header_char$_header_char $_header_text $_header_char$_header_char$_header_char" + log "" +} + +# Print nicely formatted footer to a section +# Uses the leaked $_header_text variable to determine length. +_footer() +{ + local sequence + # shellcheck disable=SC2183 + sequence="$(printf '%*s' "$((${#_header_text} + 8))" | tr ' ' "$_header_char")" + log "" + log " $sequence" + log "" +} + # Parses a YAML file using awk and sed # Copied from StackOverflow: https://stackoverflow.com/a/21189044/14170691 function parse_yaml { From 8fdda141b8a6c5d902f7c5ae3e4df54637d03df1 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 21:52:35 +0200 Subject: [PATCH 05/31] Fix debug test --- install.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/install.sh b/install.sh index b26318389..52528b39e 100755 --- a/install.sh +++ b/install.sh @@ -94,7 +94,6 @@ check_nodejs() { if builtin command -v node > /dev/null; then log "✅ NodeJS: found $(node --version)" - return 1 else log "❌ NodeJS: not found" return 1 From b3f37a47aec6940cfd168bc4d670b1b1a0ffc6cb Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 21:53:28 +0200 Subject: [PATCH 06/31] Use _header _footer and _run everywhere --- install.sh | 246 +++++++++++++++++------------------------------------ 1 file changed, 79 insertions(+), 167 deletions(-) diff --git a/install.sh b/install.sh index 52528b39e..00910078f 100755 --- a/install.sh +++ b/install.sh @@ -177,103 +177,73 @@ install_packages() install_packages_apt() { - log "" - log " --- UPDATING PACKAGE DATABASE USING APT-GET ---" - log "" - if ! sudo apt-get update; then + _header "UPDATING PACKAGE DATABASE USING APT-GET" + if ! _run 'sudo apt-get update'; then fail "❌ Unable to update package database using apt-get!" fi - log "" - log " -------------------------------------------------" - log "" + _footer # Base packages - log "" - log " --- INSTALLING BASE PACKAGES USING APT-GET ---" - log "" - if ! sudo apt-get install gcc make pkg-config autoconf bison build-essential libssl-dev libyaml-dev libreadline-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev libmysqlclient-dev; then + _header "INSTALLING BASE PACKAGES USING APT-GET" + if ! _run 'sudo apt-get install gcc make pkg-config autoconf bison build-essential libssl-dev libyaml-dev libreadline-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev libmysqlclient-dev'; then fail "❌ Unable to install base packages. Please refer to the error above." fi - log "" - log " ----------------------------------------------" - log "" + _footer log "✅ Packages: installed base packages" if ! check_nodejs && ask "Do you want to install nodejs?"; then - log "" - log " --- INSTALLING NODEJS USING APT-GET ---" - log "" - if ! sudo apt-get install nodejs; then + _header "INSTALLING NODEJS USING APT-GET" + if ! _run 'sudo apt-get install nodejs'; then fail "❌ Unable to install nodejs. Please refer to the error above." fi - log "" - log " ---------------------------------------" - log "" + _footer log "✅ Packages: installed nodejs" fi log "To run QPixel, you need a database, either MySQL or MariaDB. It is also possible to run these in Docker or another server if you wish (but you will have to set that up yourself)." if ask "Do you want to install MySQL?"; then - log "" - log " --- INSTALLING MYSQL-SERVER USING APT-GET ---" - log "" - if ! sudo apt-get install mysql-server; then + _header "INSTALLING MYSQL-SERVER USING APT-GET" + if ! _run 'sudo apt-get install mysql-server'; then fail "❌ Unable to install mysql. Please refer to the error above." fi - log "" - log " --------------------------------------" - log "" + _footer log "✅ Packages: installed mysql" elif ask "Do you want to install MariaDB?"; then - log "" - log " --- INSTALLING MARIADB-SERVER USING APT-GET ---" - log "" - if ! sudo apt-get install mariadb-server; then + _header "INSTALLING MARIADB-SERVER USING APT-GET" + if ! _run 'sudo apt-get install mariadb-server'; then fail "❌ Unable to install mariadb. Please refer to the error above." fi - log "" - log " ---------------------------------------" - log "" + _footer log "✅ Packages: installed mariadb" + else + log "🔶 Packages: skipped installing database software" fi } install_packages_pacman() { # Update database - log "" - log " --- UPDATING PACKAGE DATABASE USING PACMAN ---" - log "" + _header "UPDATING PACKAGE DATABASE USING PACMAN" if ! sudo pacman -Syyu; then fail "❌ Unable to update package database using pacman!" fi - log "" - log " -------------------------------------------------" - log "" + _footer # Base packages - log "" - log " --- INSTALLING BASE PACKAGES USING PACMAN ---" - log "" + _header "INSTALLING BASE PACKAGES USING PACMAN" if ! sudo pacman -S gcc make autoconf bison base-devel unixodbc openssl; then fail "❌ Unable to install base packages. Please refer to the error above." fi - log "" - log " ---------------------------------------------" - log "" + _footer log "✅ Packages: installed base packages" # NodeJS if ! check_nodejs && ask "Do you want to install nodejs?"; then - log "" - log " --- INSTALLING NODEJS USING PACMAN ---" - log "" + _header "INSTALLING NODEJS USING PACMAN" if ! sudo pacman -S nodejs; then fail "❌ Unable to install nodejs. Please refer to the error above." fi - log "" - log " --------------------------------------" - log "" + _footer log "✅ Packages: installed nodejs" fi @@ -281,26 +251,18 @@ install_packages_pacman() log "To run QPixel, you need a database, either MySQL or MariaDB." log "You can install either locally (with this install script), run either in docker or use either on another server (you will have to do that yourself)." if ask "Do you want to install MySQL?"; then - log "" - log " --- INSTALLING MYSQL USING PACMAN ---" - log "" + _header "INSTALLING MYSQL USING PACMAN" if ! sudo pacman -S mysql; then fail "❌ Unable to install mysql. Please refer to the error above." fi - log "" - log " --------------------------------------" - log "" + _footer log "✅ Packages: installed mysql" elif ask "Do you want to install MariaDB?"; then - log "" - log " --- INSTALLING MARIADB USING PACMAN ---" - log "" + _header "INSTALLING MARIADB USING PACMAN" if ! sudo pacman -S mariadb; then fail "❌ Unable to install mariadb. Please refer to the error above." fi - log "" - log " ---------------------------------------" - log "" + _footer log "✅ Packages: installed mariadb" fi @@ -310,26 +272,18 @@ install_packages_pacman() log "These are present in mariadb-libs and in libmysqlclient" if ask "Install mariadb-libs?"; then - log "" - log " --- INSTALLING MARIADB-LIBS USING PACMAN ---" - log "" + _header "INSTALLING MARIADB-LIBS USING PACMAN" if ! sudo pacman -S mariadb-libs; then fail "❌ Unable to install mariadb-libs. This error may be due to a conflict with MySQL. If you have MySQL installed, you may not need to install this package. In that case, rerun this install script but skip installing packages." fi - log "" - log " --------------------------------------" - log "" + _footer log "✅ Packages: installed mariadb-libs" elif ask "Install libmysqlclient?"; then - log "" - log " --- INSTALLING LIBMYSQLCLIENT USING PACMAN ---" - log "" + _header "INSTALLING LIBMYSQLCLIENT USING PACMAN" if ! sudo pacman -S libmysqlclient; then fail "❌ Unable to install libmysqlclient. This error may be due to a conflict with MariaDB. If you have MariaDB installed, you may not need to install this package. In that case, rerun this install script but skip installing packages." fi - log "" - log " --------------------------------------" - log "" + _footer log "✅ Packages: installed libmysqlclient" fi } @@ -338,32 +292,23 @@ install_packages_dnf() { # TODO: Untested # Base packages - log "" - log " --- INSTALLING BASE PACKAGES USING DNF ---" - log "" - log "$ sudo dnf group install \"C Development Tools and Libraries\"" - if ! sudo dnf group install "C Development Tools and Libraries"; then + _header "INSTALLING BASE PACKAGES USING DNF" + if ! _run 'sudo dnf group install "C Development Tools and Libraries"'; then fail "❌ Unable to install group C Development Tools and Libraries. Please refer to the error above." fi log "$ sudo dnf install ruby-devel zlib-devel" - if ! sudo dnf install ruby-devel zlib-devel; then + if ! _run 'sudo dnf install ruby-devel zlib-devel'; then fail "❌ Unable to install C Development Tools and Libraries. Please refer to the error above." fi - log "" - log " ----------------------------------------------" - log "" + _footer log "✅ Packages: installed base packages" if ! check_nodejs && ask "Do you want to install nodejs?"; then - log "" - log " --- INSTALLING NODEJS USING DNF ---" - log "" - if ! sudo dnf install nodejs; then + _header "INSTALLING NODEJS USING DNF" + if ! _run 'sudo dnf install nodejs'; then fail "❌ Unable to install nodejs. Please refer to the error above." fi - log "" - log " ---------------------------------------" - log "" + _footer log "✅ Packages: installed nodejs" fi @@ -378,17 +323,13 @@ install_packages_homebrew() if ! xcode-select -p > /dev/null; then log "Detected Mac OS. On Mac, QPixel needs the XCode Command Line Tools." if ask "Do you want to install XCode Command Line Tools?"; then - log "" - log " --- INSTALLING XCODE CLI TOOLS ---" - log "" + _header "INSTALLING XCODE CLI TOOLS" log "Please confirm the installation using the GUI prompt." log "" - if ! xcode-select --install; then + if ! _run 'xcode-select --install'; then fail "❌ xcode-select --install failed" fi - log "" - log " ----------------------------------" - log "" + _footer fi fi ;; @@ -396,53 +337,37 @@ install_packages_homebrew() esac # Base packages - log "" - log " --- INSTALLING PACKAGES USING HOMEBREW ---" - log "" - if ! brew install bison openssl mysql-client; then + _header "INSTALLING PACKAGES USING HOMEBREW" + if ! _run 'brew install bison openssl mysql-client'; then fail_with_code 30 "❌ Error while installing packages with brew. Please refer to the error above." fi - log "" - log " ------------------------------------------" - log "" + _footer log "✅ Packages: installed base packages" if ! check_nodejs && ask "Do you want to install nodejs?"; then - log "" - log " --- INSTALLING NODEJS USING HOMEBREW ---" - log "" - if ! brew install node; then + _header "INSTALLING NODEJS USING HOMEBREW" + if ! _run 'brew install node'; then fail "❌ Unable to install nodejs. Please refer to the error above." fi - log "" - log " ----------------------------------------" - log "" + _footer log "✅ Packages: installed nodejs" fi log "To run QPixel, you need a database, either MySQL or MariaDB." log "You can install either locally (with this install script), run either in docker or use either on another server (you will have to do that yourself)." if ask "Do you want to install MySQL locally?"; then - log "" - log " --- INSTALLING MYSQL USING HOMEBREW ---" - log "" - if ! brew install mysql; then + _header "INSTALLING MYSQL USING HOMEBREW" + if ! _run 'brew install mysql'; then fail "❌ Unable to install mysql. Please refer to the error above." fi - log "" - log " ---------------------------------------" - log "" + _footer log "✅ Packages: installed mysql" elif ask "Do you want to install MariaDB locally?"; then - log "" - log " --- INSTALLING MARIADB USING HOMEBREW ---" - log "" - if ! brew install mariadb; then + _header "INSTALLING MARIADB USING HOMEBREW" + if ! _run 'brew install mariadb'; then fail "❌ Unable to install mariadb. Please refer to the error above." fi - log "" - log " ---------------------------------------" - log "" + _footer log "✅ Packages: installed mariadb" fi } @@ -472,11 +397,9 @@ install_rbenv() fail_with_code 10 "❌ Not installing rbenv. Please install ruby 3.x" fi - log "" - log " --- INSTALLING RBENV ---" - log "" + _header "INSTALLING RBENV" - if ! \curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash; then + if ! _run '\curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash'; then fail_with_code 11 "❌ Something went wrong with the installation. Please refer to output above." fi @@ -511,21 +434,17 @@ You can also consider removing rbenv. This install script can re-install it for fail_with_code 10 "❌ Not installing ruby using rbenv. Please install ruby 3.x" fi - log "" - log " --- INSTALLING RUBY $latest_3 USING RBENV ---" - log "" + _header "INSTALLING RUBY $latest_3 USING RBENV" - if ! rbenv install "$latest_3"; then + if ! _run "rbenv install \"$latest_3\""; then fail_with_code 13 "Something went wrong with the installation. Please refer to the rbenv output above." fi - log "" - log " -----------------------------------------" - log "" + _footer log "✅ Ruby - rbenv: installed ruby $latest_3" - if rbenv local "$latest_3"; then + if _run "rbenv local \"$latest_3\""; then log "✅ Ruby - rbenv: set ruby $latest_3 as default for QPixel" log "🔶 Ruby - rbenv: use \`rbenv global $latest_3\` to set your global ruby version." else @@ -542,24 +461,20 @@ install_ruby_with_rvm() fail_with_code 10 "❌ Not installing ruby using RVM. Please install ruby 3.x" fi - log "" - log " --- INSTALLING RUBY USING RVM ---" - log "" + _header "INSTALLING RUBY USING RVM" - if ! rvm install ruby --latest; then + if ! _run 'rvm install ruby --latest'; then fail_with_code 15 "Something went wrong with the installation. Please refer to the rvm output above." fi - log "" - log " ----------------------------------" - log "" + _footer log "✅ Ruby - rvm: installed ruby" - if rvm --default use ruby --latest; then + if _run 'rvm --default use ruby --latest'; then log "✅ Ruby - rvm: set installed ruby as default for QPixel" else - log "❌ Ruby - rbenv: unable to set ruby $latest_3 as default for QPixel" - fail_with_code 16 "Use \`rbenv local $latest_3\` or \`rbenv global $latest_3\` to set your current ruby version." + log "❌ Ruby - rvm: unable to set installed ruby as default for QPixel" + fail_with_code 16 "Use \`rvm use ruby --latest\` or \`rvm --default use ruby --latest\` to set your current ruby version." fi return 0 @@ -623,7 +538,7 @@ check_install_gem_bundler() fi log "❌ Ruby gems - bundler: not found, installing..." - if ! gem install bundler; then + if ! _run 'gem install bundler'; then fail "❌ Unable to install bundler (ruby package manager). Please refer to the error above." fi # TODO @@ -644,9 +559,14 @@ check_install_gem_mysql() # Check homebrew, as it needs a different mysql configuration if builtin command -v brew > /dev/null && brew info openssl 1> /dev/null 2> /dev/null; then - log " Ruby gems - MySQL2: detected homebrew, configuring bundler for mysql2 installation..." + log " Ruby gems - mysql2: detected homebrew, configuring bundler for mysql2 installation..." + + local _openssl_dir + if ! _openssl_dir="$(_run brew --prefix openssl)"; then + fail "❌ Unable to determine homebrew openssl install location. Please refer to the error above." + fi - if ! bundle config --global build.mysql2 --with-opt-dir="$(brew --prefix openssl)"; then + if ! _run "bundle config --global build.mysql2 --with-opt-dir=\"$_openssl_dir\""; then fail "❌ Error while configuring bundler. Please refer to the error above." fi @@ -662,29 +582,21 @@ check_install_gem_mysql() fail "❌ Unable to find version of MySQL2 required by the application. Please report this issue on https://github.com/codidact/qpixel" fi - log "" - log " --- INSTALLING GEM MYSQL2 $mysql_version ---" - log "" - if ! gem install mysql2 -v "$mysql_version"; then + _header "INSTALLING GEM MYSQL2 $mysql_version" + if ! _run "gem install mysql2 -v \"$mysql_version\""; then fail "❌ Failed to install MySQL2 gem. Please refer to the error above. If you skipped installing system packages, you may need to install libmysqlclient-dev, mysql-devel or a similar package." fi - log "" - log " --------------------------------------" - log "" + _footer log "✅ Ruby gems - mysql2: installed" } bundle_install() { - log "" - log " --- INSTALLING RUBY DEPENDENCIES USING BUNDLER ---" - log "" - if ! bundle install; then + _header "INSTALLING RUBY DEPENDENCIES USING BUNDLER" + if ! _run 'bundle install'; then fail "❌ Failed to install dependencies using bundler. Please refer to the error above." fi - log "" - log " --------------------------------------" - log "" + _footer log "✅ Ruby gems - other: installed" } From 49c308696814b361e4e082cf8ba7c6ee41eae46a Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 21:53:48 +0200 Subject: [PATCH 07/31] Improve code with shellcheck suggestion --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 00910078f..581c6c637 100755 --- a/install.sh +++ b/install.sh @@ -574,7 +574,7 @@ check_install_gem_mysql() fi # Determine the version(s) of mysql2 that are acceptable and install them (this is a best effort). - mysql_version=$(cat Gemfile | grep mysql2) + mysql_version=$(grep mysql2 < Gemfile) regex=", '([~><=\ 0-9\.]+)'" if [[ $mysql_version =~ $regex ]]; then mysql_version="${BASH_REMATCH[1]}" From b99f2cf599a04e226fed57d7fa76a2d2d5cc7886 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 21:57:26 +0200 Subject: [PATCH 08/31] Fix small inconsistencies --- install.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/install.sh b/install.sh index 581c6c637..e232b9ebd 100755 --- a/install.sh +++ b/install.sh @@ -105,7 +105,7 @@ check_nodejs() # In case of rejection for all, we fail. install_packages() { - if ! ask " Packages: Do you want to install required system packages?"; then + if ! ask "Do you want to install required system packages?"; then log "🔶 Packages: Skipping installation of system packages." return 0 fi @@ -224,14 +224,14 @@ install_packages_pacman() { # Update database _header "UPDATING PACKAGE DATABASE USING PACMAN" - if ! sudo pacman -Syyu; then + if ! _run 'sudo pacman -Syyu'; then fail "❌ Unable to update package database using pacman!" fi _footer # Base packages _header "INSTALLING BASE PACKAGES USING PACMAN" - if ! sudo pacman -S gcc make autoconf bison base-devel unixodbc openssl; then + if ! _run 'sudo pacman -S gcc make autoconf bison base-devel unixodbc openssl'; then fail "❌ Unable to install base packages. Please refer to the error above." fi _footer @@ -240,7 +240,7 @@ install_packages_pacman() # NodeJS if ! check_nodejs && ask "Do you want to install nodejs?"; then _header "INSTALLING NODEJS USING PACMAN" - if ! sudo pacman -S nodejs; then + if ! _run 'sudo pacman -S nodejs'; then fail "❌ Unable to install nodejs. Please refer to the error above." fi _footer @@ -252,14 +252,14 @@ install_packages_pacman() log "You can install either locally (with this install script), run either in docker or use either on another server (you will have to do that yourself)." if ask "Do you want to install MySQL?"; then _header "INSTALLING MYSQL USING PACMAN" - if ! sudo pacman -S mysql; then + if ! _run 'sudo pacman -S mysql'; then fail "❌ Unable to install mysql. Please refer to the error above." fi _footer log "✅ Packages: installed mysql" elif ask "Do you want to install MariaDB?"; then _header "INSTALLING MARIADB USING PACMAN" - if ! sudo pacman -S mariadb; then + if ! _run 'sudo pacman -S mariadb'; then fail "❌ Unable to install mariadb. Please refer to the error above." fi _footer @@ -273,14 +273,14 @@ install_packages_pacman() if ask "Install mariadb-libs?"; then _header "INSTALLING MARIADB-LIBS USING PACMAN" - if ! sudo pacman -S mariadb-libs; then + if ! _run 'sudo pacman -S mariadb-libs'; then fail "❌ Unable to install mariadb-libs. This error may be due to a conflict with MySQL. If you have MySQL installed, you may not need to install this package. In that case, rerun this install script but skip installing packages." fi _footer log "✅ Packages: installed mariadb-libs" elif ask "Install libmysqlclient?"; then _header "INSTALLING LIBMYSQLCLIENT USING PACMAN" - if ! sudo pacman -S libmysqlclient; then + if ! _run 'sudo pacman -S libmysqlclient'; then fail "❌ Unable to install libmysqlclient. This error may be due to a conflict with MariaDB. If you have MariaDB installed, you may not need to install this package. In that case, rerun this install script but skip installing packages." fi _footer @@ -298,7 +298,7 @@ install_packages_dnf() fi log "$ sudo dnf install ruby-devel zlib-devel" if ! _run 'sudo dnf install ruby-devel zlib-devel'; then - fail "❌ Unable to install C Development Tools and Libraries. Please refer to the error above." + fail "❌ Unable to install ruby-devel and zlib-devel. Please refer to the error above." fi _footer log "✅ Packages: installed base packages" @@ -597,7 +597,7 @@ bundle_install() fail "❌ Failed to install dependencies using bundler. Please refer to the error above." fi _footer - log "✅ Ruby gems - other: installed" + log "✅ Ruby gems: installed all dependencies" } check_mysql() From 9111b2832dc57d9dd95bc9ec1761640c284f189d Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 22:59:37 +0200 Subject: [PATCH 09/31] Add check for development/prod --- install.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/install.sh b/install.sh index e232b9ebd..6117779c1 100755 --- a/install.sh +++ b/install.sh @@ -85,6 +85,26 @@ function parse_yaml { }' } +# ------------------------------------------------------------------------------------------------- +# General + +# Asks whether this setup is for production +check_production() +{ + if ask "Are you setting up QPixel for development?"; then + production=0 + development=1 + else + production=1 + development=0 + fi +} + +# Convenience getters which turn the production / development variables into return values. +# Note that return values (0 = good, 1 = bad) are inverted from boolean values (0 = false, 1 = true) +is_prod() { return $((1 - production)); } +is_dev() { return $((1 - development)); } + # ------------------------------------------------------------------------------------------------- # System packages From 632f9120e5241e7bbc9a09f459adcc3b54e5e656 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 23:00:17 +0200 Subject: [PATCH 10/31] Add secure_mysql beginnings --- install.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 6117779c1..0a0853278 100755 --- a/install.sh +++ b/install.sh @@ -120,6 +120,15 @@ check_nodejs() fi } +# Secures a MySQL installation by having the user set a password and go through the security setup. +secure_mysql() +{ + temp_passwd="$(sudo grep 'temporary password' /var/log/mysqld.log)" + log "🔶 Packages: Your mysql root password is $temp_passwd" + + # TODO +} + # Detects the package manager(s) present on the system and asks the user to install dependencies # with all of them. # In case of rejection for all, we fail. @@ -220,7 +229,8 @@ install_packages_apt() log "✅ Packages: installed nodejs" fi - log "To run QPixel, you need a database, either MySQL or MariaDB. It is also possible to run these in Docker or another server if you wish (but you will have to set that up yourself)." + log "To run QPixel, you need a database, either MySQL or MariaDB." + log "You can install either locally (with this install script), run in docker or use a database on another server (you will have to do that yourself)." if ask "Do you want to install MySQL?"; then _header "INSTALLING MYSQL-SERVER USING APT-GET" if ! _run 'sudo apt-get install mysql-server'; then @@ -228,6 +238,7 @@ install_packages_apt() fi _footer log "✅ Packages: installed mysql" + secure_mysql elif ask "Do you want to install MariaDB?"; then _header "INSTALLING MARIADB-SERVER USING APT-GET" if ! _run 'sudo apt-get install mariadb-server'; then @@ -269,7 +280,7 @@ install_packages_pacman() # MySQL / MariaDB log "To run QPixel, you need a database, either MySQL or MariaDB." - log "You can install either locally (with this install script), run either in docker or use either on another server (you will have to do that yourself)." + log "You can install either locally (with this install script), run in docker or use a database on another server (you will have to do that yourself)." if ask "Do you want to install MySQL?"; then _header "INSTALLING MYSQL USING PACMAN" if ! _run 'sudo pacman -S mysql'; then @@ -382,6 +393,7 @@ install_packages_homebrew() fi _footer log "✅ Packages: installed mysql" + secure_mysql elif ask "Do you want to install MariaDB locally?"; then _header "INSTALLING MARIADB USING HOMEBREW" if ! _run 'brew install mariadb'; then From ec5ddd86ae95109e1859d5d8f0be0210dcf9b9e4 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 23:00:40 +0200 Subject: [PATCH 11/31] Make DNF installation more robust --- install.sh | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/install.sh b/install.sh index 0a0853278..324c26314 100755 --- a/install.sh +++ b/install.sh @@ -321,14 +321,20 @@ install_packages_pacman() install_packages_dnf() { - # TODO: Untested + # Update database + _header "UPDATING PACKAGE DATABASE USING DNF" + if ! _run 'sudo dnf update'; then + fail "❌ Unable to update package database using pacman!" + fi + _footer + # Base packages _header "INSTALLING BASE PACKAGES USING DNF" - if ! _run 'sudo dnf group install "C Development Tools and Libraries"'; then + if ! _run 'sudo dnf group install "C Development Tools and Libraries" -y'; then fail "❌ Unable to install group C Development Tools and Libraries. Please refer to the error above." fi log "$ sudo dnf install ruby-devel zlib-devel" - if ! _run 'sudo dnf install ruby-devel zlib-devel'; then + if ! _run 'sudo dnf install ruby-devel zlib-devel -y'; then fail "❌ Unable to install ruby-devel and zlib-devel. Please refer to the error above." fi _footer @@ -336,14 +342,33 @@ install_packages_dnf() if ! check_nodejs && ask "Do you want to install nodejs?"; then _header "INSTALLING NODEJS USING DNF" - if ! _run 'sudo dnf install nodejs'; then + if ! _run 'sudo dnf install nodejs -y'; then fail "❌ Unable to install nodejs. Please refer to the error above." fi _footer log "✅ Packages: installed nodejs" fi - # TODO Finish + log "To run QPixel, you need a database, either MySQL or MariaDB." + log "You can install either locally (with this install script), run in docker or use a database on another server (you will have to do that yourself)." + if ask "Do you want to install MySQL?"; then + _header "INSTALLING MYSQL USING DNF" + if ! _run 'sudo dnf install community-mysql-server community-mysql-libs -y' && ! _run 'sudo dnf install mysql-server mysql-libs -y'; then + fail "❌ Unable to install mysql. Please refer to the error above." + fi + _footer + log "✅ Packages: installed mysql" + secure_mysql + elif ask "Do you want to install MariaDB?"; then + _header "INSTALLING MARIADB-SERVER USING DNF" + if ! _run 'sudo dnf install mariadb-server mariadb-connector-c-devel -y'; then + fail "❌ Unable to install mariadb. Please refer to the error above." + fi + _footer + log "✅ Packages: installed mariadb" + else + log "🔶 Packages: skipped installing database software" + fi } install_packages_homebrew() From 6dbb4861c254eb879b7e65f0fefc6835e37c5fa7 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sat, 12 Aug 2023 23:00:56 +0200 Subject: [PATCH 12/31] Check production --- install.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/install.sh b/install.sh index 324c26314..e1ce36009 100755 --- a/install.sh +++ b/install.sh @@ -708,7 +708,10 @@ set_up_db() # ------------------------------------------------------------------------------------------------- # Actual commands +check_production + install_packages + # Check ruby if previous check reports failure (installed using this command) while ! check_install_ruby; do log "🔶 Ruby: Checking again" From 81b1b5452f363e69fd84a308fe5f581aecba0b87 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 14:52:46 +0200 Subject: [PATCH 13/31] Add libvips and make package install more similar accross languages --- install.sh | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/install.sh b/install.sh index e1ce36009..ebd7d4f5f 100755 --- a/install.sh +++ b/install.sh @@ -214,15 +214,18 @@ install_packages_apt() # Base packages _header "INSTALLING BASE PACKAGES USING APT-GET" - if ! _run 'sudo apt-get install gcc make pkg-config autoconf bison build-essential libssl-dev libyaml-dev libreadline-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev libmysqlclient-dev'; then + if ! _run 'sudo apt-get -y install gcc make pkg-config autoconf bison build-essential libssl-dev libyaml-dev libreadline-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev libmysqlclient-dev'; then fail "❌ Unable to install base packages. Please refer to the error above." fi + if ! _run 'sudo apt-get -y install libvips'; then + fail "❌ Unable to install libvips. Please refer to the error above." + fi _footer log "✅ Packages: installed base packages" if ! check_nodejs && ask "Do you want to install nodejs?"; then _header "INSTALLING NODEJS USING APT-GET" - if ! _run 'sudo apt-get install nodejs'; then + if ! _run 'sudo apt-get -y install nodejs'; then fail "❌ Unable to install nodejs. Please refer to the error above." fi _footer @@ -233,7 +236,7 @@ install_packages_apt() log "You can install either locally (with this install script), run in docker or use a database on another server (you will have to do that yourself)." if ask "Do you want to install MySQL?"; then _header "INSTALLING MYSQL-SERVER USING APT-GET" - if ! _run 'sudo apt-get install mysql-server'; then + if ! _run 'sudo apt-get -y install mysql-server'; then fail "❌ Unable to install mysql. Please refer to the error above." fi _footer @@ -241,7 +244,7 @@ install_packages_apt() secure_mysql elif ask "Do you want to install MariaDB?"; then _header "INSTALLING MARIADB-SERVER USING APT-GET" - if ! _run 'sudo apt-get install mariadb-server'; then + if ! _run 'sudo apt-get -y install mariadb-server'; then fail "❌ Unable to install mariadb. Please refer to the error above." fi _footer @@ -265,6 +268,9 @@ install_packages_pacman() if ! _run 'sudo pacman -S gcc make autoconf bison base-devel unixodbc openssl'; then fail "❌ Unable to install base packages. Please refer to the error above." fi + if ! _run 'sudo pacman -S libvips'; then + fail "❌ Unable to install libvips. Please refer to the error above." + fi _footer log "✅ Packages: installed base packages" @@ -295,6 +301,8 @@ install_packages_pacman() fi _footer log "✅ Packages: installed mariadb" + else + log "🔶 Packages: skipped installing database software" fi # MySQL-client-headers Arch users should know what they are doing @@ -333,10 +341,12 @@ install_packages_dnf() if ! _run 'sudo dnf group install "C Development Tools and Libraries" -y'; then fail "❌ Unable to install group C Development Tools and Libraries. Please refer to the error above." fi - log "$ sudo dnf install ruby-devel zlib-devel" if ! _run 'sudo dnf install ruby-devel zlib-devel -y'; then fail "❌ Unable to install ruby-devel and zlib-devel. Please refer to the error above." fi + if ! _run 'sudo dnf install vips -y'; then + fail "❌ Unable to install vips. Please refer to the error above. Note that on CentOS, vips is not in the repositories and may need to be built from source." + fi _footer log "✅ Packages: installed base packages" @@ -395,7 +405,10 @@ install_packages_homebrew() # Base packages _header "INSTALLING PACKAGES USING HOMEBREW" if ! _run 'brew install bison openssl mysql-client'; then - fail_with_code 30 "❌ Error while installing packages with brew. Please refer to the error above." + fail "❌ Error while installing packages with brew. Please refer to the error above." + fi + if ! _run 'brew install vips'; then + fail "❌ Error while installing vips with brew. Please refer to the error above." fi _footer log "✅ Packages: installed base packages" @@ -426,6 +439,8 @@ install_packages_homebrew() fi _footer log "✅ Packages: installed mariadb" + else + log "🔶 Packages: skipped installing database software" fi } From e7e956724a24fe947a5361955332e95267f7cfd1 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 14:53:20 +0200 Subject: [PATCH 14/31] Drop yum --- install.sh | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/install.sh b/install.sh index ebd7d4f5f..a3778fbd2 100755 --- a/install.sh +++ b/install.sh @@ -173,17 +173,6 @@ install_packages() log "Not installing with dnf" fi fi - - if builtin command -v yum > /dev/null; then - log "Detected yum (fedora-based)" - if ask "Do you want to install required packages with dnf?"; then - install_packages_yum - return $? - else - any_matched=0 - log "Not installing with yum" - fi - fi # Homebrew is intentionally placed at the bottom, as it is possible to use homebrew on linux # In that case, the user may prefer using their system package manager. From 5754c2027121b54e89a5168f237460f005982a7e Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 17:02:46 +0200 Subject: [PATCH 15/31] Add imagemagick to package installs --- install.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index a3778fbd2..edc6cbd8a 100755 --- a/install.sh +++ b/install.sh @@ -209,6 +209,9 @@ install_packages_apt() if ! _run 'sudo apt-get -y install libvips'; then fail "❌ Unable to install libvips. Please refer to the error above." fi + if ! _run 'sudo apt-get -y install libmagickwand-dev'; then + fail "❌ Unable to install libmagickwand-dev (imagemagick). Please refer to the error above." + fi _footer log "✅ Packages: installed base packages" @@ -260,6 +263,9 @@ install_packages_pacman() if ! _run 'sudo pacman -S libvips'; then fail "❌ Unable to install libvips. Please refer to the error above." fi + if ! _run 'sudo pacman -S imagemagick'; then + fail "❌ Unable to install imagemagick. Please refer to the error above." + fi _footer log "✅ Packages: installed base packages" @@ -333,8 +339,12 @@ install_packages_dnf() if ! _run 'sudo dnf install ruby-devel zlib-devel -y'; then fail "❌ Unable to install ruby-devel and zlib-devel. Please refer to the error above." fi + # Order swapped here as vips is more tricky than imagemagick-libs. + if ! _run 'sudo dnf install imagemagick-libs -y'; then + fail "❌ Unable to install imagemagick-libs. Please refer to the error above." + fi if ! _run 'sudo dnf install vips -y'; then - fail "❌ Unable to install vips. Please refer to the error above. Note that on CentOS, vips is not in the repositories and may need to be built from source." + fail "❌ Unable to install vips. Please refer to the error above.\nNote that on CentOS, vips is not in the default repositories, but can be compiled from source or installed from other repositories (like Remi)." fi _footer log "✅ Packages: installed base packages" @@ -399,6 +409,9 @@ install_packages_homebrew() if ! _run 'brew install vips'; then fail "❌ Error while installing vips with brew. Please refer to the error above." fi + if ! _run 'brew install imagemagick'; then + fail "❌ Error while installing imagemagick with brew. Please refer to the error above." + fi _footer log "✅ Packages: installed base packages" From 19a2e1070edef5eaad5e1a72d391fa932277efb8 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 17:03:00 +0200 Subject: [PATCH 16/31] Apply shellcheck suggestions --- install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index edc6cbd8a..a8e0b7a90 100755 --- a/install.sh +++ b/install.sh @@ -70,7 +70,9 @@ _footer() function parse_yaml { local prefix=$2 local s='[[:space:]]*' w='[a-zA-Z0-9_]*' - local fs=$(echo @|tr @ '\034') + local fs + fs=$(echo @|tr @ '\034') + # shellcheck disable=SC2086 disable=SC1087 sed -ne "s|^\($s\):|\1|" \ -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | From d1142bd211632f9fa89cfdc3c3e661d657322020 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 17:03:59 +0200 Subject: [PATCH 17/31] Generalize gem install setup into helper functions Also add rmagick installation --- install.sh | 101 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 22 deletions(-) diff --git a/install.sh b/install.sh index a8e0b7a90..341184f34 100755 --- a/install.sh +++ b/install.sh @@ -606,6 +606,67 @@ check_install_ruby() # ------------------------------------------------------------------------------------------------- # Bundler and gems +# Checks whether a gem with the given name is installed from the bundle. +# @param 1 - name of the gem +# @return 0 if installed, 1 otherwise +# @fail - If the Gemfile.lock cannot be found +check_gem() +{ + local name + name="$1" + + # Check Gemfile.lock existence (failsafe) + if [[ ! -f "Gemfile.lock" ]]; then + fail "❌ Unable to find Gemfile.lock! Please ensure you cd to the directory of the project and run this script as ./install.sh" + fi + + # Check whether bundler reports the gem as installed + if bundle info "$name" 1> /dev/null 2> /dev/null; then + return 0 + fi + + return 1 +} + +# Extracts the version string for the given gem from the Gemfile. +# The version is made available in the $version variable +# +# @param 1 - The name of the gem +# @return 0 if successful, the $version variable will contain the version. 1 otherwise. +extract_gem_version() +{ + local regex + regex=" $1 \(([0-9\.]+)\)" + version="$(grep \"$1\" < Gemfile.lock)" + if [[ $version =~ $regex ]]; then + version="${BASH_REMATCH[1]}" + else + return 1 + fi +} + +# Attempts to install a gem with the given name +# @param 1 - The name of the gem to install +# @param 2 - Extra information to report to the user in case of gem install failure +# @fail - If gem version cannot be found or the installation fails. +install_gem() +{ + local name + name="$1" + + # Determine the version(s) of gem from the lockfile + if ! extract_gem_version "$name"; then + fail "❌ Unable to find version of $name required by the application. Please report this issue on https://github.com/codidact/qpixel" + fi + + _header "INSTALLING GEM ${name^^} $version" + if ! _run "gem install $name -v \"$version\""; then + fail "❌ Failed to install $name gem. Please refer to the error above. $2" + fi + _footer + log "✅ Ruby gems - $name: installed" +} + check_install_gem_bundler() { if gem info -i bundler > /dev/null; then @@ -614,21 +675,27 @@ check_install_gem_bundler() fi log "❌ Ruby gems - bundler: not found, installing..." + _header 'INSTALLING BUNDLER' if ! _run 'gem install bundler'; then fail "❌ Unable to install bundler (ruby package manager). Please refer to the error above." fi - # TODO + _footer + log "✅ Ruby gems - bundler: installed" } -check_install_gem_mysql() +check_install_gem_rmagick() { - # Check Gemfile - if [[ ! -f "Gemfile" ]]; then - fail "❌ Unable to find Gemfile! Please ensure you cd to the directory of the project and run this script as ./install.sh" + if check_gem 'rmagick'; then + log "✅ Ruby gems - rmagick: found compatible version" + return 0 fi - # Check whether bundler reports the gem as installed - if bundle info mysql2 1> /dev/null 2> /dev/null; then + install_gem 'rmagick' "If you skipped installing system packages, you may need to install libmagicwand-dev, imagemagick or a similar package." +} + +check_install_gem_mysql() +{ + if check_gem 'mysql2'; then log "✅ Ruby gems - mysql2: found compatible version" return 0 fi @@ -649,21 +716,7 @@ check_install_gem_mysql() log "✅ Ruby gems - mysql2: configured bundler for mysql2 installation through homebrew" fi - # Determine the version(s) of mysql2 that are acceptable and install them (this is a best effort). - mysql_version=$(grep mysql2 < Gemfile) - regex=", '([~><=\ 0-9\.]+)'" - if [[ $mysql_version =~ $regex ]]; then - mysql_version="${BASH_REMATCH[1]}" - else - fail "❌ Unable to find version of MySQL2 required by the application. Please report this issue on https://github.com/codidact/qpixel" - fi - - _header "INSTALLING GEM MYSQL2 $mysql_version" - if ! _run "gem install mysql2 -v \"$mysql_version\""; then - fail "❌ Failed to install MySQL2 gem. Please refer to the error above. If you skipped installing system packages, you may need to install libmysqlclient-dev, mysql-devel or a similar package." - fi - _footer - log "✅ Ruby gems - mysql2: installed" + install_gem 'mysql2' "If you skipped installing system packages, you may need to install libmysqlclient-dev, mysql-devel or a similar package." } bundle_install() @@ -676,6 +729,9 @@ bundle_install() log "✅ Ruby gems: installed all dependencies" } +# ------------------------------------------------------------------------------------------------- +# Setup + check_mysql() { # TODO: Do stuff with mysql database settings @@ -741,6 +797,7 @@ check_nodejs # Ruby gems check_install_gem_bundler +check_install_gem_rmagick check_install_gem_mysql bundle_install From 3bf88db91a7e780838ae6f3b23f42f9c28cf77b4 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 17:15:53 +0200 Subject: [PATCH 18/31] Fix gem version extraction quotes --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 341184f34..cdf435676 100755 --- a/install.sh +++ b/install.sh @@ -637,7 +637,7 @@ extract_gem_version() { local regex regex=" $1 \(([0-9\.]+)\)" - version="$(grep \"$1\" < Gemfile.lock)" + version="$(grep "$1" < Gemfile.lock)" if [[ $version =~ $regex ]]; then version="${BASH_REMATCH[1]}" else From d4787269a3abd4b32f8fd7e43da527b1338e3425 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 17:16:16 +0200 Subject: [PATCH 19/31] Fix gem installation --- install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index cdf435676..14caf1e1a 100755 --- a/install.sh +++ b/install.sh @@ -659,8 +659,8 @@ install_gem() fail "❌ Unable to find version of $name required by the application. Please report this issue on https://github.com/codidact/qpixel" fi - _header "INSTALLING GEM ${name^^} $version" - if ! _run "gem install $name -v \"$version\""; then + _header "INSTALLING GEM $(echo "$name" | tr '[:lower:]' '[:upper:]') $version" + if ! _run "gem install $name -v $version"; then fail "❌ Failed to install $name gem. Please refer to the error above. $2" fi _footer From de846e30472be77fc8f67b1b060ac25ccf20a769 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 17:16:27 +0200 Subject: [PATCH 20/31] Fix mysql path logging --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 14caf1e1a..645db3402 100755 --- a/install.sh +++ b/install.sh @@ -705,7 +705,7 @@ check_install_gem_mysql() log " Ruby gems - mysql2: detected homebrew, configuring bundler for mysql2 installation..." local _openssl_dir - if ! _openssl_dir="$(_run brew --prefix openssl)"; then + if ! _openssl_dir="$(brew --prefix openssl)"; then fail "❌ Unable to determine homebrew openssl install location. Please refer to the error above." fi From a271fcee8ca437aef9ea24fc13e12263c72aef0f Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 19:12:05 +0200 Subject: [PATCH 21/31] Add comments --- install.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/install.sh b/install.sh index 645db3402..d6f8095b9 100755 --- a/install.sh +++ b/install.sh @@ -683,6 +683,7 @@ check_install_gem_bundler() log "✅ Ruby gems - bundler: installed" } +# We specifically install rmagick as it requires the correct library to be installed. check_install_gem_rmagick() { if check_gem 'rmagick'; then @@ -693,6 +694,8 @@ check_install_gem_rmagick() install_gem 'rmagick' "If you skipped installing system packages, you may need to install libmagicwand-dev, imagemagick or a similar package." } +# We specifically install mysql as it requires the correct libraries to be installed. +# Additionally, it needs a special path on Mac OS with homebrew. check_install_gem_mysql() { if check_gem 'mysql2'; then From 98cb525207777cb146ecee2415393b38abddf387 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 19:12:16 +0200 Subject: [PATCH 22/31] Add ruby setup tasks --- install.sh | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/install.sh b/install.sh index d6f8095b9..544ea4ccf 100755 --- a/install.sh +++ b/install.sh @@ -783,6 +783,153 @@ set_up_db() log "✅ Setup - Database: set correct collations" } + +# ------------------------------------------------------------------------------------------------- +# In-rails setup + +setup_ruby_initialize() +{ + if bundle exec rails db:version 1> /dev/null 2> /dev/null; then + log "✅ Setup: database found" + else + if ! _run "bundle exec rails db:create"; then + warn "Unable to create database, it may already be created. Continuing.." + fi + fi + + # Check if we can query communities. If that fails, we will get an error and we will load the schema + if bundle exec rails r "Community.any?" 1> /dev/null 2> /dev/null; then + log "✅ Setup: schema already loaded" + else + if ask "Do you want to wipe the database and load the initial database schema?" && \ + ask "🔶 WARNING: If your QPixel database already contains data, this will wipe it. Are you sure?"; then + _header 'LOADING SCHEMA' + if ! _run "bundle exec rails db:schema:load"; then + fail "❌ Unable to create DB schema. Please check whether you set the correct database credentials in config/database.yml" + fi + _footer + log "✅ Setup: schema loaded" + fi + fi + + # TODO check whether schema exists? + _header 'CREATING TAG PATH VIEW' + if ! _run "bundle exec rails r db/scripts/create_tags_path_view.rb"; then + fail "❌ Unable to create database view for tag paths." + fi + _footer + log "✅ Setup: tag path view created" + + # Run database migrations + _header 'RUNNING DATABASE MIGRATIONS' + if ! _run "bundle exec rails db:migrate"; then + fail "❌ Unable to run database migrations." + fi + _footer + log "✅ Setup: ran database migrations" +} + +create_community() +{ + local name domain + while true; do + read -p "Please enter the fully qualified domain for which you want to create a community, without http(s) and without slashes (e.g. meta.codidact.com)" -r domain + read -p "Please enter the (user-facing) name for this community: " -r name + ask "You want to create '$name' @ '$domain'?" || continue + if bundle exec rails r "Community.create!(name: '$name', host: '$domain'); Rails.cache.clear" 2>&1 | head -n 2; then + log "✅ Setup - communities: created community '$name' @ '$domain'" + return 0 + else + warn "❌ Failed to create community '$name' @ '$domain'. Please refer to the error above" + return 1 + fi + done +} + +set_up_communities() +{ + if is_dev; then + # Check whether dev community already exists + if ! bundle exec rails r "exit(1) unless Community.where(host: 'localhost:3000').any?" 2> /dev/null; then + log "✅ Setup - communities: found development community @ 'localhost:3000'" + else + log " Setup: creating default community for development..." + if ! _run "bundle exec rails r \"Community.create(name: 'Dev Community', host: 'localhost:3000'); Rails.cache.clear\""; then + fail "❌ Unable to create development community. Please refer to the error above" + fi + log "✅ Setup - communities: created development community @ 'localhost:3000" + fi + else + log "QPixel is designed for a multi-community setup." + log "This means that a single instance of the software can host multiple, separate communities across different domains." + log "Accounts are the same for all communities of an instance, and users can see an overview of the communities being hosted on the instance." + log "The content, reputation and user privileges are completely separate per community." + log "" + log "The domain which you access in your browser is used to determine which community to serve, so it needs to be configured correctly in the application." + + local domain name + if bundle exec rails r "exit(1) unless Community.any?" 2> /dev/null; then + log "🔶 Setup - communities: detected existing communities:" + bundle exec rails r "Community.all.each { |c| puts \"'#{c.name}' @ '#{c.host}'\" }" 2> /dev/null + else + log "🔶 Setup - communities: no communities detected - setting up first community..." + if ! create_community; then + fail "❌ Failed to create community" + fi + fi + + while ask "Do you want to set up another community?"; do + create_community + done + + log "🔶 Setup - communities: if you ever want to create additional communities, you can run this script again." + fi +} + +# Ensures that all communities have correct tag sets +set_up_tag_sets() +{ + # This code needs to have no indentation to work correctly + local rails_code + # shellcheck disable=SC2140 + rails_code=""\ +"Community.all.each { |c| "\ +"RequestContext.community = c; "\ +"cat=Category.find_by(name: 'Meta'); "\ +"cat.update!(tag_set: TagSet.find_by(name: 'Meta')) unless cat&.tag_set_id; "\ +"cat=Category.find_by(name: 'Q&A'); "\ +"cat.update!(tag_set: TagSet.find_by(name: 'Main')) unless cat&.tag_set_id; "\ +"}" + + if ! _run "bundle exec rails r \"$rails_code\""; then + fail "❌ Unable to set tag sets for communities. Please refer to the error above." + fi + log "✅ Setup - database: ensured base categories have tag sets" +} + +set_up_seeds() +{ + # TODO: Ask user to seed to prevent recreation of Q&A category? (Or perhaps that is a bug that needs fixing?) + _header "SEEDING DATABASE" + if ! bundle exec rails r "exit(1) unless Post.unscoped.where(post_type: PostType.where(name: ['HelpDoc', 'PolicyDoc'])).any?"; then + # No help posts detected, seed those too + if ! _run "UPDATE_POSTS=true bundle exec rails db:seed"; then + fail "❌ Failed to seed database (with initial posts). Please refer to the error above." + fi + elif ! _run "bundle exec rails db:seed"; then + fail "❌ Failed to seed database. Please refer to the error above." + fi + _footer + log "✅ Setup - database: seeded database" +} + +set_up_admin_user() +{ + if ! _run "bundle exec rails r \"User.last.update(confirmed_at: DateTime.now, is_global_admin: true)\""; then + fail "❌ Unable to create default user" + fi +} + # ------------------------------------------------------------------------------------------------- # Actual commands @@ -804,5 +951,12 @@ check_install_gem_rmagick check_install_gem_mysql bundle_install +# TODO Settings of DB/Redis +# TODO Start DB/Redis services #check_mysql #check_redis + +setup_ruby_initialize +set_up_communities +set_up_tag_sets +set_up_seeds From a1a68d949dad424f648459e7e60bef9fc7d9ec59 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 20:07:51 +0200 Subject: [PATCH 23/31] Fix run command for spaced arguments --- install.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 544ea4ccf..a51ed4fa4 100755 --- a/install.sh +++ b/install.sh @@ -32,12 +32,14 @@ ask() done } -# runs the command, outputting it to the console and +# runs the command, outputting it to stdout and returning its result +# @param * - The full command to run +# @return the result of running the given command _run() { cmd="$*" - log "$ $cmd" - $cmd + log "$ $*" + eval "$cmd" } # Print nicely formatted header to a section From 3d9cc9010e636f7cb1a87f087a145e99ec8d01f3 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 20:08:24 +0200 Subject: [PATCH 24/31] Do not create tag_paths if already exists --- install.sh | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/install.sh b/install.sh index a51ed4fa4..ce2ae4948 100755 --- a/install.sh +++ b/install.sh @@ -814,13 +814,18 @@ setup_ruby_initialize() fi fi - # TODO check whether schema exists? - _header 'CREATING TAG PATH VIEW' - if ! _run "bundle exec rails r db/scripts/create_tags_path_view.rb"; then - fail "❌ Unable to create database view for tag paths." + # Tag paths view + # MySQL throws an error if we run this again, so we instead check with rails whether there exists a view with its name. + if bundle exec rails r "exit(1) unless ActiveRecord::Base.connection.execute('SHOW FULL TABLES WHERE TABLE_TYPE LIKE \"%VIEW%\";')&.map(&:first)&.include?('tags_paths')" 1> /dev/null 2> /dev/null; then + log "✅ Setup: tag paths view already present" + else + _header 'CREATING TAG_PATHS VIEW' + if ! _run "bundle exec rails r db/scripts/create_tags_path_view.rb"; then + fail "❌ Unable to create database view for tag paths." + fi + _footer + log "✅ Setup: tag_paths view created" fi - _footer - log "✅ Setup: tag path view created" # Run database migrations _header 'RUNNING DATABASE MIGRATIONS' From a0d692aee35e7d9e4f5debeb50a8b06c12d15a9a Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 20:08:47 +0200 Subject: [PATCH 25/31] Fix community creation --- install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index ce2ae4948..b31ed7dd8 100755 --- a/install.sh +++ b/install.sh @@ -857,12 +857,12 @@ set_up_communities() { if is_dev; then # Check whether dev community already exists - if ! bundle exec rails r "exit(1) unless Community.where(host: 'localhost:3000').any?" 2> /dev/null; then + if bundle exec rails r "exit(1) unless Community.where(host: 'localhost:3000').any?" 2> /dev/null; then log "✅ Setup - communities: found development community @ 'localhost:3000'" else log " Setup: creating default community for development..." - if ! _run "bundle exec rails r \"Community.create(name: 'Dev Community', host: 'localhost:3000'); Rails.cache.clear\""; then - fail "❌ Unable to create development community. Please refer to the error above" + if ! _run "bundle exec rails r \"Community.create!(name: 'Dev Community', host: 'localhost:3000'); Rails.cache.clear\""; then + fail "❌ Unable to create development community. Please refer to the error above." fi log "✅ Setup - communities: created development community @ 'localhost:3000" fi From 97d5b6198047d1e946bd212fd944f4d369e4ffd6 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 20:09:07 +0200 Subject: [PATCH 26/31] Do not output for check --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index b31ed7dd8..a1eee0791 100755 --- a/install.sh +++ b/install.sh @@ -918,7 +918,7 @@ set_up_seeds() { # TODO: Ask user to seed to prevent recreation of Q&A category? (Or perhaps that is a bug that needs fixing?) _header "SEEDING DATABASE" - if ! bundle exec rails r "exit(1) unless Post.unscoped.where(post_type: PostType.where(name: ['HelpDoc', 'PolicyDoc'])).any?"; then + if ! bundle exec rails r "exit(1) unless Post.unscoped.where(post_type: PostType.where(name: ['HelpDoc', 'PolicyDoc'])).any?" 2> /dev/null; then # No help posts detected, seed those too if ! _run "UPDATE_POSTS=true bundle exec rails db:seed"; then fail "❌ Failed to seed database (with initial posts). Please refer to the error above." From 3a5ed9f7153b94d5afe8231656124390ff03bd4e Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 20:28:47 +0200 Subject: [PATCH 27/31] Add headers to install sections + improve header display --- install.sh | 52 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index a1eee0791..5337c6224 100755 --- a/install.sh +++ b/install.sh @@ -42,8 +42,15 @@ _run() eval "$cmd" } -# Print nicely formatted header to a section -# "Leaks" the $_header_text variable for use in the footer. +# Print nicely formatted header to a section as follows: +# +# --- INPUT TEXT --- +# +# ... +# +# ------------------ +# +# "Leaks" the $_header_text and $_header_char variables for use in the footer. # @param 1 - The text to display in the header # @param 2 - The character to use (default -) _header() @@ -51,7 +58,7 @@ _header() _header_text="$1" _header_char="${2:--}" log "" - log " $_header_char$_header_char$_header_char $_header_text $_header_char$_header_char$_header_char" + log "$_header_char$_header_char$_header_char $_header_text $_header_char$_header_char$_header_char" log "" } @@ -63,7 +70,30 @@ _footer() # shellcheck disable=SC2183 sequence="$(printf '%*s' "$((${#_header_text} + 8))" | tr ' ' "$_header_char")" log "" - log " $sequence" + log "$sequence" + log "" +} + + +# Print nicely formatted header to a section as follows: +# +# =============================================================================== +# INPUT TEXT +# =============================================================================== +# +# @param 1 - The text to display in the header +# @param 2 - The character to use (default =) +_header2() +{ + local _header_text _header_char sequence + _header_text="$1" + _header_char="${2:-=}" + # shellcheck disable=SC2183 + sequence="$(printf '%*s' "80" | tr ' ' "$_header_char")" + log "" + log "$sequence" + log "$_header_text" + log "$sequence" log "" } @@ -908,9 +938,11 @@ set_up_tag_sets() "cat.update!(tag_set: TagSet.find_by(name: 'Main')) unless cat&.tag_set_id; "\ "}" + _header 'SETTING UP CATEGORY TAG SETS' if ! _run "bundle exec rails r \"$rails_code\""; then fail "❌ Unable to set tag sets for communities. Please refer to the error above." fi + _footer log "✅ Setup - database: ensured base categories have tag sets" } @@ -942,28 +974,32 @@ set_up_admin_user() check_production +_header2 'PACKAGES' '=' install_packages +check_nodejs # Check ruby if previous check reports failure (installed using this command) +_header2 'RUBY' while ! check_install_ruby; do log "🔶 Ruby: Checking again" done -# Check nodejs -check_nodejs - # Ruby gems +_header2 'RUBY DEPENDENCIES' check_install_gem_bundler check_install_gem_rmagick check_install_gem_mysql bundle_install +_header2 'DATABASE SETTINGS' # TODO Settings of DB/Redis # TODO Start DB/Redis services #check_mysql #check_redis +_header2 'QPIXEL SETUP' setup_ruby_initialize set_up_communities -set_up_tag_sets set_up_seeds +set_up_tag_sets + From 8c877e2e5ca7c694e214c699a691e48df71a2a23 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 21:00:08 +0200 Subject: [PATCH 28/31] Make a few minor improvements --- install.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index 5337c6224..32b14f8c3 100755 --- a/install.sh +++ b/install.sh @@ -830,7 +830,7 @@ setup_ruby_initialize() fi # Check if we can query communities. If that fails, we will get an error and we will load the schema - if bundle exec rails r "Community.any?" 1> /dev/null 2> /dev/null; then + if bundle exec rails r "Community.any? || Vote.any?" 1> /dev/null 2> /dev/null; then log "✅ Setup: schema already loaded" else if ask "Do you want to wipe the database and load the initial database schema?" && \ @@ -851,7 +851,7 @@ setup_ruby_initialize() else _header 'CREATING TAG_PATHS VIEW' if ! _run "bundle exec rails r db/scripts/create_tags_path_view.rb"; then - fail "❌ Unable to create database view for tag paths." + fail "❌ Unable to create database view for tag paths. Please refer to the error above." fi _footer log "✅ Setup: tag_paths view created" @@ -860,7 +860,7 @@ setup_ruby_initialize() # Run database migrations _header 'RUNNING DATABASE MIGRATIONS' if ! _run "bundle exec rails db:migrate"; then - fail "❌ Unable to run database migrations." + fail "❌ Unable to run database migrations. Please refer to the error above." fi _footer log "✅ Setup: ran database migrations" @@ -870,14 +870,14 @@ create_community() { local name domain while true; do - read -p "Please enter the fully qualified domain for which you want to create a community, without http(s) and without slashes (e.g. meta.codidact.com)" -r domain - read -p "Please enter the (user-facing) name for this community: " -r name + read -p "Please enter the fully qualified domain for which you want to create a community, without http(s) and without slashes (e.g. meta.codidact.com): " -r domain + read -p "Please enter the (user-facing) name for this community (do not use quotes in the name): " -r name ask "You want to create '$name' @ '$domain'?" || continue - if bundle exec rails r "Community.create!(name: '$name', host: '$domain'); Rails.cache.clear" 2>&1 | head -n 2; then + if bundle exec rails r "Community.create!(name: '$name', host: '$domain'); Rails.cache.clear" 2>&1 | head -n 2; then log "✅ Setup - communities: created community '$name' @ '$domain'" return 0 else - warn "❌ Failed to create community '$name' @ '$domain'. Please refer to the error above" + warn "❌ Failed to create community '$name' @ '$domain'. Please refer to the error above." return 1 fi done @@ -897,7 +897,8 @@ set_up_communities() log "✅ Setup - communities: created development community @ 'localhost:3000" fi else - log "QPixel is designed for a multi-community setup." + log "" + log "NOTE: QPixel is designed for a multi-community setup." log "This means that a single instance of the software can host multiple, separate communities across different domains." log "Accounts are the same for all communities of an instance, and users can see an overview of the communities being hosted on the instance." log "The content, reputation and user privileges are completely separate per community." From ec95f57a003142eca465a9f059a2adc290e0ca96 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Sun, 13 Aug 2023 22:00:28 +0200 Subject: [PATCH 29/31] Fix bugs after testing on arch --- install.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index 32b14f8c3..8210f64f4 100755 --- a/install.sh +++ b/install.sh @@ -280,18 +280,21 @@ install_packages_apt() fi } +# Install packages using pacman (default on Arch linux) +# Since we are dealing with an arch user here, we will not pass a "auto-confirm" flag to the installation. +# The user gets the chance to accept or reject the installation. install_packages_pacman() { # Update database _header "UPDATING PACKAGE DATABASE USING PACMAN" - if ! _run 'sudo pacman -Syyu'; then + if ! _run 'sudo pacman -Syy'; then fail "❌ Unable to update package database using pacman!" fi _footer # Base packages _header "INSTALLING BASE PACKAGES USING PACMAN" - if ! _run 'sudo pacman -S gcc make autoconf bison base-devel unixodbc openssl'; then + if ! _run 'sudo pacman -S gcc make autoconf bison base-devel unixodbc openssl libyaml'; then fail "❌ Unable to install base packages. Please refer to the error above." fi if ! _run 'sudo pacman -S libvips'; then @@ -306,7 +309,7 @@ install_packages_pacman() # NodeJS if ! check_nodejs && ask "Do you want to install nodejs?"; then _header "INSTALLING NODEJS USING PACMAN" - if ! _run 'sudo pacman -S nodejs'; then + if ! _run 'sudo pacman -S nodejs npm'; then fail "❌ Unable to install nodejs. Please refer to the error above." fi _footer @@ -323,6 +326,7 @@ install_packages_pacman() fi _footer log "✅ Packages: installed mysql" + secure_mysql elif ask "Do you want to install MariaDB?"; then _header "INSTALLING MARIADB USING PACMAN" if ! _run 'sudo pacman -S mariadb'; then @@ -517,17 +521,14 @@ install_rbenv() log "✅ Ruby - rbenv: installed rbenv" log "" - log "🔶 To finish the setup of rbenv, run the following command and follow its instructions:" - log "" - log " rbenv init" - log "" + log "🔶 To finish the setup of rbenv, run the init command as suggested above (rbenv init) and follow its instructions." log "After doing so, please close your terminal and open a new one, then rerun this install command." exit 0 } install_ruby_with_rbenv() { - if ! latest_3=$(rbenv install -l | grep "^3\.\d\d*\.\d\d*$" | tail -n1); then + if ! latest_3=$(rbenv install -l | grep '^3\.[0-9][0-9]*\.[0-9][0-9]*$' | tail -n1); then fail_with_code 12 " It looks like your rbenv does not have the install option or does not know about any ruby 3 versions. From 4820625781ecb636091143e85347d06935ea9375 Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Tue, 15 Aug 2023 17:27:20 +0200 Subject: [PATCH 30/31] Add storage/db setup --- install.sh | 62 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index 8210f64f4..8d2f03930 100755 --- a/install.sh +++ b/install.sh @@ -326,7 +326,6 @@ install_packages_pacman() fi _footer log "✅ Packages: installed mysql" - secure_mysql elif ask "Do you want to install MariaDB?"; then _header "INSTALLING MARIADB USING PACMAN" if ! _run 'sudo pacman -S mariadb'; then @@ -799,22 +798,66 @@ check_redis() set_up_db() { - log " Setup - Database: QPixel supports MySQL and MariaDB." - log " Setup - Database: However, if you use MariaDB, we need to update some of the collations used." + log " Setup - database: QPixel supports MySQL and MariaDB." + log " Setup - database: However, if you use MariaDB, we need to update some of the collations used." if ask "Are you using MariaDB/will you use MariaDB for QPixel?"; then - log " Setup - Database: Setting collations to be compatible with MariaDB" + log " Setup - database: Setting collations to be compatible with MariaDB" if ! sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' "db/schema.rb"; then fail "❌ Unable to update collations." fi else - log " Setup - Database: Setting collations to be compatible with MySQL" + log " Setup - database: Setting collations to be compatible with MySQL" if ! sed -i 's/utf8mb4_unicode_ci/utf8mb4_0900_ai_ci/g' "db/schema.rb"; then fail "❌ Unable to update collations." fi fi - log "✅ Setup - Database: set correct collations" + log "✅ Setup - database: set correct collations" + + if ask "Do you want to create a database user?"; then + local _username _password _database + read -p "Please enter the base name to use for the database (DB NAME) [qpixel]: " -r _database + read -p "Please enter a name for the database user to create (USER NAME) [qpixel]: " -r _username + read -sp "Please enter a password for the database user to create (don't use quotes) (USER PASS): " -r _password + + sudo mysql -u root -e "CREATE USER $_username@localhost IDENTIFIED BY '$_password'" + sudo mysql -u root -e "GRANT ALL ON ${_database}.* TO $_username@localhost" + + if is_dev; then + sudo mysql -u root -e "GRANT ALL ON ${_database}_dev.* TO $_username@localhost" + sudo mysql -u root -e "GRANT ALL ON ${_database}_test.* TO $_username@localhost" + fi + + # TODO Write to database yml file + log "TODO: Actually write database settings to file" + fi + +} + +set_up_storage() +{ + if [[ ! -f config/storage.yml ]]; then + cp config/storage.sample.yml config/storage.yml + log "✅ Setup - storage: set up default storage profile" + + if is_prod; then + log '🔶 Setup - storage: Files are saved by default to ./storage in the project root.'\ +'You may want to change this for your production setup to go to a bulk drive, or to external storage like S3. You can change this in config/storage.yml' + read -p "Press any key to continue." -r -n1 _nothing + fi + else + log "✅ Setup - storage: configuration already present" + fi +} + +set_up_irb() +{ + # TODO Log output? + if [[ ! -f .irbrc ]]; then + _run 'cp .sample.irbrc .irbrc > /dev/null' + log "✅ Setup - console: added rails console enhancements" + fi } # ------------------------------------------------------------------------------------------------- @@ -993,13 +1036,16 @@ check_install_gem_rmagick check_install_gem_mysql bundle_install -_header2 'DATABASE SETTINGS' +_header2 'QPIXEL SETTINGS' # TODO Settings of DB/Redis # TODO Start DB/Redis services #check_mysql #check_redis +set_up_storage +set_up_db +set_up_irb -_header2 'QPIXEL SETUP' +_header2 'QPIXEL INITIALIZATION' setup_ruby_initialize set_up_communities set_up_seeds From acb81c813cf6cd76f436bf920ff2ad2732a31f9a Mon Sep 17 00:00:00 2001 From: Taico Aerts Date: Thu, 17 Aug 2023 21:30:48 +0200 Subject: [PATCH 31/31] Add crontab scheduling --- install.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/install.sh b/install.sh index 8d2f03930..7ce5378fd 100755 --- a/install.sh +++ b/install.sh @@ -1014,6 +1014,15 @@ set_up_admin_user() fi } +set_up_whenever() +{ + if _run "bundle exec whenever --update-crontab"; then + log "✅ Setup - crontab: updated scheduled tasks" + else + warn "❌ Unable to schedule tasks with crontab" + fi +} + # ------------------------------------------------------------------------------------------------- # Actual commands @@ -1051,3 +1060,6 @@ set_up_communities set_up_seeds set_up_tag_sets +set_up_whenever + +} \ No newline at end of file