2025-05-08 11:54:39 +02:00

343 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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'