mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
343 lines
11 KiB
Bash
Executable File
343 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
||
# stop if something fails
|
||
set -euo pipefail
|
||
|
||
# check for some tools and install them, when missing
|
||
# bun https://bun.sh/install, faster packet-manager as yarn
|
||
if ! command -v bun &> /dev/null
|
||
then
|
||
if ! command -v unzip &> /dev/null
|
||
then
|
||
echo "'unzip' is missing, will be installed now!"
|
||
sudo apt-get install -y unzip
|
||
fi
|
||
echo "'bun' is missing, will be installed now!"
|
||
curl -fsSL https://bun.sh/install | BUN_INSTALL=/usr/local bash
|
||
export PATH="/root/.bun/bin:${PATH}"
|
||
fi
|
||
# turbo https://turborepo.com/docs/getting-started
|
||
if ! command -v turbo &> /dev/null
|
||
then
|
||
echo "'turbo' is missing, will be installed now!"
|
||
bun install --global turbo
|
||
fi
|
||
|
||
# check for parameter
|
||
FAST_MODE=false
|
||
POSITIONAL_ARGS=()
|
||
|
||
# loop through arguments
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
-f|--fast)
|
||
FAST_MODE=true
|
||
;;
|
||
*)
|
||
POSITIONAL_ARGS+=("$arg")
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# set $1, $2, ... only with position arguments
|
||
set -- "${POSITIONAL_ARGS[@]}"
|
||
|
||
# check for missing branch name
|
||
if [ -z "$1" ]; then
|
||
echo "Usage: $0 [--fast] <branchName>"
|
||
exit 1
|
||
fi
|
||
|
||
BRANCH_NAME="$1"
|
||
|
||
# Find current directory & configure paths
|
||
set -o allexport
|
||
SCRIPT_PATH=$(realpath $0)
|
||
SCRIPT_DIR=$(dirname $SCRIPT_PATH)
|
||
LOCK_FILE=$SCRIPT_DIR/update.lock
|
||
UPDATE_HTML=$SCRIPT_DIR/nginx/update-page/updating.html
|
||
PROJECT_ROOT=$SCRIPT_DIR/../..
|
||
NGINX_CONFIG_DIR=$SCRIPT_DIR/nginx/sites-available
|
||
set +o allexport
|
||
|
||
# Debug-Ausgabe
|
||
if [ -z "$1" ]; then
|
||
echo "Usage: Please provide a branch name as the first argument."
|
||
exit 1
|
||
fi
|
||
echo "Use branch: $BRANCH_NAME"
|
||
if [ "$FAST_MODE" = true ] ; then
|
||
echo "Use fast mode, keep packet manager, turbo and build cache"
|
||
fi
|
||
|
||
# enable nvm
|
||
export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||
nvm use
|
||
|
||
# NOTE: all config values will be in process.env when starting
|
||
# the services and will therefore take precedence over the .env
|
||
|
||
# We have to load the backend .env to get DB_USERNAME, DB_PASSWORD AND JWT_SECRET
|
||
# and the dht-node .env to get FEDERATION_DHT_SEED
|
||
export_var(){
|
||
export $1=$(grep -v '^#' $PROJECT_ROOT/backend/.env | grep -e "$1" | sed -e 's/.*=//')
|
||
export $1=$(grep -v '^#' $PROJECT_ROOT/dht-node/.env | grep -e "$1" | sed -e 's/.*=//')
|
||
}
|
||
|
||
if [ -f "$PROJECT_ROOT/backend/.env" ]; then
|
||
export_var 'DB_USER'
|
||
export_var 'DB_PASSWORD'
|
||
export_var 'JWT_SECRET'
|
||
fi
|
||
|
||
if [ -f "$PROJECT_ROOT/dht-node/.env" ]; then
|
||
export_var 'FEDERATION_DHT_SEED'
|
||
fi
|
||
|
||
# Load .env or .env.dist if not present
|
||
if [ -f "$SCRIPT_DIR/.env" ]; then
|
||
set -o allexport
|
||
source $SCRIPT_DIR/.env
|
||
set +o allexport
|
||
else
|
||
set -o allexport
|
||
source $SCRIPT_DIR/.env.dist
|
||
set +o allexport
|
||
fi
|
||
|
||
# set env variables dynamic if not already set in .env or .env.dist
|
||
: ${NGINX_SSL_CERTIFICATE:=/etc/letsencrypt/live/$COMMUNITY_HOST/fullchain.pem}
|
||
: ${NGINX_SSL_CERTIFICATE_KEY:=/etc/letsencrypt/live/$COMMUNITY_HOST/privkey.pem}
|
||
|
||
# export env variables
|
||
export NGINX_SSL_CERTIFICATE
|
||
export NGINX_SSL_CERTIFICATE_KEY
|
||
|
||
# lock start
|
||
if [ -f $LOCK_FILE ] ; then
|
||
echo "Already building!"
|
||
exit 1
|
||
fi
|
||
touch $LOCK_FILE
|
||
|
||
# called always on exit, regardless of error or success
|
||
cleanup() {
|
||
# release lock
|
||
rm $LOCK_FILE
|
||
}
|
||
trap cleanup EXIT
|
||
|
||
# find today string
|
||
TODAY=$(date +"%Y-%m-%d")
|
||
|
||
# Create a new updating.html from the template
|
||
\cp $SCRIPT_DIR/nginx/update-page/updating.html.template $UPDATE_HTML
|
||
|
||
# redirect all output of the script to the UPDATE_HTML and also have things on console
|
||
# TODO: this might pose a security risk
|
||
exec > >(tee -a $UPDATE_HTML) 2>&1
|
||
|
||
# configure nginx for the update-page
|
||
echo 'Configuring nginx to serve the update-page'
|
||
ln -sf $SCRIPT_DIR/nginx/sites-available/update-page.conf $SCRIPT_DIR/nginx/sites-enabled/default
|
||
sudo /etc/init.d/nginx restart
|
||
|
||
# helper functions
|
||
log_step() {
|
||
local message="$1"
|
||
echo -e "\e[34m$message\e[0m" > /dev/tty # blue in console
|
||
echo "<p style="color:blue">$message</p>" >> "$UPDATE_HTML" # blue in html
|
||
}
|
||
log_error() {
|
||
local message="$1"
|
||
echo -e "\e[31m$message\e[0m" > /dev/tty # red in console
|
||
echo "<p style="color:red">$message</p>" >> "$UPDATE_HTML" # red in html
|
||
}
|
||
log_success() {
|
||
local message="$1"
|
||
echo -e "\e[32m$message\e[0m" > /dev/tty # green in console
|
||
echo "<p style="color:green">$message</p>" >> "$UPDATE_HTML" # green in html
|
||
}
|
||
|
||
onError() {
|
||
local exit_code=$?
|
||
log_error ""
|
||
log_error " /> フ"
|
||
log_error " | _ _| Aaaaah!"
|
||
log_error " /\` ミ_xノ Command failed!"
|
||
log_error " / | Line: $LINENO"
|
||
log_error "/ ヽ ノ Exit Code: $exit_code"
|
||
log_error "| | | | Offending command: '$BASH_COMMAND'"
|
||
log_error "ノ_ノ。_ノ。_ノ。。。。。。。。。。。。"
|
||
log_error ""
|
||
cleanup
|
||
exit 1
|
||
}
|
||
trap onError ERR
|
||
|
||
|
||
# stop all services
|
||
log_step "Stop and delete all Gradido services"
|
||
pm2 delete all
|
||
pm2 save
|
||
|
||
# git
|
||
BRANCH=$1
|
||
log_step "Starting with git pull - branch:$BRANCH"
|
||
cd $PROJECT_ROOT
|
||
# TODO: this overfetches alot, but ensures we can use start.sh with tags
|
||
git fetch --all
|
||
git checkout $BRANCH
|
||
git pull
|
||
export BUILD_COMMIT="$(git rev-parse HEAD)"
|
||
|
||
# Generate gradido.conf from template
|
||
# *** 1st prepare for each apiversion the federation conf for nginx from federation-template
|
||
# *** set FEDERATION_PORT from FEDERATION_COMMUNITY_APIS and create gradido-federation.conf file
|
||
rm -f $NGINX_CONFIG_DIR/gradido.conf.tmp
|
||
rm -f $NGINX_CONFIG_DIR/gradido-federation.conf.locations
|
||
log_step "===================================================================================================="
|
||
IFS="," read -a API_ARRAY <<< $FEDERATION_COMMUNITY_APIS
|
||
for api in "${API_ARRAY[@]}"
|
||
do
|
||
export FEDERATION_APIVERSION=$api
|
||
# calculate port by remove '_' and add value of api to baseport
|
||
port=${api//_/}
|
||
FEDERATION_PORT=${FEDERATION_COMMUNITY_API_PORT:-5000}
|
||
FEDERATION_PORT=$(($FEDERATION_PORT + $port))
|
||
export FEDERATION_PORT
|
||
log_step "create ngingx config: location /api/$FEDERATION_APIVERSION to http://127.0.0.1:$FEDERATION_PORT"
|
||
envsubst '$FEDERATION_APIVERSION, $FEDERATION_PORT' < $NGINX_CONFIG_DIR/gradido-federation.conf.template >> $NGINX_CONFIG_DIR/gradido-federation.conf.locations
|
||
done
|
||
unset FEDERATION_APIVERSION
|
||
unset FEDERATION_PORT
|
||
log_step "===================================================================================================="
|
||
|
||
# *** 2nd read gradido-federation.conf file in env variable to be replaced in 3rd step
|
||
export FEDERATION_NGINX_CONF=$(< $NGINX_CONFIG_DIR/gradido-federation.conf.locations)
|
||
|
||
# *** 3rd generate gradido nginx config including federation modules per api-version
|
||
log_step 'Generate new gradido nginx config'
|
||
case "$URL_PROTOCOL" in
|
||
'https') TEMPLATE_FILE="gradido.conf.ssl.template" ;;
|
||
*) TEMPLATE_FILE="gradido.conf.template" ;;
|
||
esac
|
||
envsubst '$FEDERATION_NGINX_CONF' < $NGINX_CONFIG_DIR/$TEMPLATE_FILE > $NGINX_CONFIG_DIR/gradido.conf.tmp
|
||
unset FEDERATION_NGINX_CONF
|
||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $NGINX_CONFIG_DIR/gradido.conf.tmp > $NGINX_CONFIG_DIR/gradido.conf
|
||
rm $NGINX_CONFIG_DIR/gradido.conf.tmp
|
||
rm $NGINX_CONFIG_DIR/gradido-federation.conf.locations
|
||
|
||
# Generate update-page.conf from template
|
||
log_step 'Generate new update-page nginx config'
|
||
case "$URL_PROTOCOL" in
|
||
'https') TEMPLATE_FILE="update-page.conf.ssl.template" ;;
|
||
*) TEMPLATE_FILE="update-page.conf.template" ;;
|
||
esac
|
||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $NGINX_CONFIG_DIR/$TEMPLATE_FILE > $NGINX_CONFIG_DIR/update-page.conf
|
||
|
||
# Define all relevant subdirectories
|
||
MODULES=(
|
||
database
|
||
backend
|
||
frontend
|
||
admin
|
||
dht-node
|
||
federation
|
||
)
|
||
|
||
if [ "$FAST_MODE" = false ] ; then
|
||
log_step 'Clean tmp, bun and yarn cache'
|
||
# Clean tmp folder - remove yarn files
|
||
find /tmp -name "yarn--*" -exec rm -r {} \;
|
||
# Clean user cache folder
|
||
rm -Rf ~/.cache/yarn
|
||
# Clean bun cache
|
||
rm -Rf ~/.bun/install/cache
|
||
|
||
log_step 'Remove all node_modules, turbo cache and build folders'
|
||
|
||
EXTENDED_MODULES=("" config-schema "${MODULES[@]}")
|
||
# Remove node_modules, build and .turbo folders for all modules inclusive config-schema and project root
|
||
for dir in "${EXTENDED_MODULES[@]}"; do
|
||
base="$PROJECT_ROOT"
|
||
# if dir isn't empty add to base
|
||
[ -n "$dir" ] && base="$PROJECT_ROOT/$dir"
|
||
|
||
rm -rf $base/node_modules
|
||
rm -rf $base/build
|
||
rm -rf $base/.turbo
|
||
done
|
||
fi
|
||
|
||
# Regenerate .env files for all modules
|
||
log_step 'Regenerate .env files'
|
||
for dir in "${MODULES[@]}"; do
|
||
base="$PROJECT_ROOT/$dir"
|
||
cp -f $base/.env $base/.env.bak
|
||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $base/.env.template > $base/.env
|
||
done
|
||
|
||
# Install all node_modules
|
||
log_step 'Installing node_modules'
|
||
bun install
|
||
|
||
# build all modules
|
||
log_step 'build all modules'
|
||
turbo build --env-mode=loose
|
||
|
||
# database
|
||
log_step 'Updating database'
|
||
if [ "$DEPLOY_SEED_DATA" = "true" ]; then
|
||
log_step 'Clearing database'
|
||
turbo clear --env-mode=loose
|
||
turbo up --env-mode=loose
|
||
log_step 'Seeding database'
|
||
turbo seed --env-mode=loose
|
||
else
|
||
turbo up --env-mode=loose
|
||
fi
|
||
|
||
nvm use default
|
||
# start after building all to use up less ressources
|
||
pm2 start --name gradido-backend "turbo backend#start --env-mode=loose" -l $GRADIDO_LOG_PATH/pm2.backend.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
|
||
#pm2 start --name gradido-frontend "yarn --cwd $PROJECT_ROOT/frontend start" -l $GRADIDO_LOG_PATH/pm2.frontend.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
|
||
#pm2 start --name gradido-admin "yarn --cwd $PROJECT_ROOT/admin start" -l $GRADIDO_LOG_PATH/pm2.admin.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
|
||
pm2 save
|
||
if [ ! -z $FEDERATION_DHT_TOPIC ]; then
|
||
pm2 start --name gradido-dht-node "turbo dht-node#start --env-mode=loose" -l $GRADIDO_LOG_PATH/pm2.dht-node.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
|
||
pm2 save
|
||
else
|
||
log_step "====================================================================="
|
||
log_step "WARNING: FEDERATION_DHT_TOPIC not configured. DHT-Node not started..."
|
||
log_step "====================================================================="
|
||
fi
|
||
|
||
# set FEDERATION_PORT from FEDERATION_COMMUNITY_APIS
|
||
IFS="," read -a API_ARRAY <<< $FEDERATION_COMMUNITY_APIS
|
||
for api in "${API_ARRAY[@]}"
|
||
do
|
||
export FEDERATION_API=$api
|
||
log_step "FEDERATION_API=$FEDERATION_API"
|
||
export MODULENAME=gradido-federation-$api
|
||
log_step "MODULENAME=$MODULENAME"
|
||
# calculate port by remove '_' and add value of api to baseport
|
||
port=${api//_/}
|
||
FEDERATION_PORT=${FEDERATION_COMMUNITY_API_PORT:-5000}
|
||
FEDERATION_PORT=$(($FEDERATION_PORT + $port))
|
||
export FEDERATION_PORT
|
||
log_step "===================================================="
|
||
log_step " start $MODULENAME listening on port=$FEDERATION_PORT"
|
||
log_step "===================================================="
|
||
pm2 start --name $MODULENAME "turbo federation#start --env-mode=loose" -l $GRADIDO_LOG_PATH/pm2.$MODULENAME.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
|
||
pm2 save
|
||
done
|
||
|
||
# let nginx showing gradido
|
||
log_step 'Configuring nginx to serve gradido again'
|
||
ln -sf $SCRIPT_DIR/nginx/sites-available/gradido.conf $SCRIPT_DIR/nginx/sites-enabled/default
|
||
sudo /etc/init.d/nginx restart
|
||
|
||
# keep the update log
|
||
cat $UPDATE_HTML >> $GRADIDO_LOG_PATH/update.$TODAY.log
|
||
|
||
log_success 'Update finished' |