|
@@ -1,36 +1,50 @@
|
|
#!/bin/bash
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
+set -e
|
|
|
|
+
|
|
export PATH=/usr/local/bin:/usr/bin:/bin
|
|
export PATH=/usr/local/bin:/usr/bin:/bin
|
|
|
|
|
|
|
|
+# Color variables
|
|
CYAN='\033[33;36m';
|
|
CYAN='\033[33;36m';
|
|
RED='\033[0;31m'
|
|
RED='\033[0;31m'
|
|
YELLOW='\033[0;93m'
|
|
YELLOW='\033[0;93m'
|
|
GREEN='\033[0;32m'
|
|
GREEN='\033[0;32m'
|
|
NC='\033[0m'
|
|
NC='\033[0m'
|
|
|
|
|
|
|
|
+# Print provided formatted error and exit with code (default 1)
|
|
|
|
+throw()
|
|
|
|
+{
|
|
|
|
+ echo -e "${RED}${1}${NC}"
|
|
|
|
+ exit "${2:-1}"
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Navigate to repository
|
|
scriptLocation=$(dirname -- "$(readlink -fn -- "$0"; echo x)")
|
|
scriptLocation=$(dirname -- "$(readlink -fn -- "$0"; echo x)")
|
|
-cd "${scriptLocation%x}" || exit 1
|
|
|
|
-
|
|
|
|
-if [[ -f .env ]]; then
|
|
|
|
- # shellcheck disable=SC1091
|
|
|
|
- source .env
|
|
|
|
-else
|
|
|
|
- echo -e "${RED}Error: .env does not exist${NC}"
|
|
|
|
- exit 2
|
|
|
|
|
|
+cd "${scriptLocation%x}"
|
|
|
|
+
|
|
|
|
+# Import environment variables
|
|
|
|
+if [[ ! -f .env ]]; then
|
|
|
|
+ throw "Error: .env does not exist" 2
|
|
fi
|
|
fi
|
|
|
|
+# shellcheck disable=SC1091
|
|
|
|
+source .env
|
|
|
|
|
|
-if [[ -z ${DOCKER_COMMAND} ]]; then
|
|
|
|
- DOCKER_COMMAND="docker"
|
|
|
|
-elif [[ ${DOCKER_COMMAND} != "docker" && ${DOCKER_COMMAND} != "podman" ]]; then
|
|
|
|
- echo -e "${RED}Error: Invalid DOCKER_COMMAND${NC}"
|
|
|
|
- exit 1
|
|
|
|
|
|
+# Define docker command
|
|
|
|
+docker="${DOCKER_COMMAND:-docker}"
|
|
|
|
+if [[ ${docker} != "docker" && ${docker} != "podman" ]]; then
|
|
|
|
+ throw "Error: Invalid DOCKER_COMMAND"
|
|
fi
|
|
fi
|
|
|
|
|
|
-docker="${DOCKER_COMMAND}"
|
|
|
|
|
|
+set +e
|
|
|
|
+
|
|
|
|
+# Check if docker is installed
|
|
${docker} --version > /dev/null 2>&1
|
|
${docker} --version > /dev/null 2>&1
|
|
dockerInstalled=$?
|
|
dockerInstalled=$?
|
|
|
|
|
|
|
|
+# Define docker compose command
|
|
dockerCompose="${docker} compose"
|
|
dockerCompose="${docker} compose"
|
|
|
|
+
|
|
|
|
+# Check if docker compose is installed
|
|
${dockerCompose} version > /dev/null 2>&1
|
|
${dockerCompose} version > /dev/null 2>&1
|
|
composeInstalled=$?
|
|
composeInstalled=$?
|
|
if [[ ${composeInstalled} -gt 0 ]]; then
|
|
if [[ ${composeInstalled} -gt 0 ]]; then
|
|
@@ -39,15 +53,19 @@ if [[ ${composeInstalled} -gt 0 ]]; then
|
|
composeInstalled=$?
|
|
composeInstalled=$?
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
+set -e
|
|
|
|
+
|
|
|
|
+# Exit if docker and/or docker compose is not installed
|
|
if [[ ${dockerInstalled} -gt 0 || ${composeInstalled} -gt 0 ]]; then
|
|
if [[ ${dockerInstalled} -gt 0 || ${composeInstalled} -gt 0 ]]; then
|
|
if [[ ${dockerInstalled} -eq 0 && ${composeInstalled} -gt 0 ]]; then
|
|
if [[ ${dockerInstalled} -eq 0 && ${composeInstalled} -gt 0 ]]; then
|
|
- echo -e "${RED}Error: ${dockerCompose} not installed.${NC}"
|
|
|
|
- elif [[ ${dockerInstalled} -gt 0 && ${composeInstalled} -eq 0 ]]; then
|
|
|
|
- echo -e "${RED}Error: ${docker} not installed.${NC}"
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}Error: ${docker} and ${dockerCompose} not installed.${NC}"
|
|
|
|
|
|
+ throw "Error: ${dockerCompose} not installed."
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ ${dockerInstalled} -gt 0 && ${composeInstalled} -eq 0 ]]; then
|
|
|
|
+ throw "Error: ${docker} not installed."
|
|
fi
|
|
fi
|
|
- exit 1
|
|
|
|
|
|
+
|
|
|
|
+ throw "Error: ${docker} and ${dockerCompose} not installed."
|
|
fi
|
|
fi
|
|
|
|
|
|
# Add docker compose file arguments to command
|
|
# Add docker compose file arguments to command
|
|
@@ -65,11 +83,14 @@ elif [[ -f docker-compose.override.yml ]]; then
|
|
fi
|
|
fi
|
|
dockerCompose="${dockerCompose} ${composeFiles}"
|
|
dockerCompose="${dockerCompose} ${composeFiles}"
|
|
|
|
|
|
|
|
+# Parse services from arguments string
|
|
handleServices()
|
|
handleServices()
|
|
{
|
|
{
|
|
|
|
+ # shellcheck disable=SC2206
|
|
validServices=($1)
|
|
validServices=($1)
|
|
servicesArray=()
|
|
servicesArray=()
|
|
invalidServices=false
|
|
invalidServices=false
|
|
|
|
+
|
|
for x in "${@:2}"; do
|
|
for x in "${@:2}"; do
|
|
if [[ ${validServices[*]} =~ (^|[[:space:]])"$x"($|[[:space:]]) ]]; then
|
|
if [[ ${validServices[*]} =~ (^|[[:space:]])"$x"($|[[:space:]]) ]]; then
|
|
if ! [[ ${servicesArray[*]} =~ (^|[[:space:]])"$x"($|[[:space:]]) ]]; then
|
|
if ! [[ ${servicesArray[*]} =~ (^|[[:space:]])"$x"($|[[:space:]]) ]]; then
|
|
@@ -83,6 +104,7 @@ handleServices()
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
done
|
|
done
|
|
|
|
+
|
|
if [[ $invalidServices == false && ${#servicesArray[@]} -gt 0 ]]; then
|
|
if [[ $invalidServices == false && ${#servicesArray[@]} -gt 0 ]]; then
|
|
echo "1|${servicesArray[*]}"
|
|
echo "1|${servicesArray[*]}"
|
|
elif [[ $invalidServices == false ]]; then
|
|
elif [[ $invalidServices == false ]]; then
|
|
@@ -92,81 +114,438 @@ handleServices()
|
|
fi
|
|
fi
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+# Execute a docker command
|
|
runDockerCommand()
|
|
runDockerCommand()
|
|
{
|
|
{
|
|
validCommands=(start stop restart pull build ps logs)
|
|
validCommands=(start stop restart pull build ps logs)
|
|
- if [[ ${validCommands[*]} =~ (^|[[:space:]])"$2"($|[[:space:]]) ]]; then
|
|
|
|
- servicesString=$(handleServices "backend frontend mongo redis" "${@:3}")
|
|
|
|
- if [[ ${servicesString:0:1} == 1 ]]; then
|
|
|
|
- if [[ ${servicesString:2:4} == "all" ]]; then
|
|
|
|
- servicesString=""
|
|
|
|
- pullServices="mongo redis"
|
|
|
|
- buildServices="backend frontend"
|
|
|
|
|
|
+ if ! [[ ${validCommands[*]} =~ (^|[[:space:]])"$2"($|[[:space:]]) ]]; then
|
|
|
|
+ throw "Error: Invalid runDockerCommand input"
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ servicesString=$(handleServices "backend frontend mongo redis" "${@:3}")
|
|
|
|
+ if [[ ${servicesString:0:1} != 1 ]]; then
|
|
|
|
+ throw "${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend, mongo, redis]"
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" ]]; then
|
|
|
|
+ servicesString=""
|
|
|
|
+ pullServices="mongo redis"
|
|
|
|
+ buildServices="backend frontend"
|
|
|
|
+ else
|
|
|
|
+ servicesString=${servicesString:2}
|
|
|
|
+ pullArray=()
|
|
|
|
+ buildArray=()
|
|
|
|
+
|
|
|
|
+ if [[ "${servicesString}" == *mongo* ]]; then
|
|
|
|
+ pullArray+=("mongo")
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ "${servicesString}" == *redis* ]]; then
|
|
|
|
+ pullArray+=("redis")
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ "${servicesString}" == *backend* ]]; then
|
|
|
|
+ buildArray+=("backend")
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ "${servicesString}" == *frontend* ]]; then
|
|
|
|
+ buildArray+=("frontend")
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ pullServices="${pullArray[*]}"
|
|
|
|
+ buildServices="${buildArray[*]}"
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ ${2} == "stop" || ${2} == "restart" ]]; then
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} stop ${servicesString}
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ ${2} == "start" || ${2} == "restart" ]]; then
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} up -d ${servicesString}
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ ${2} == "pull" && ${pullServices} != "" ]]; then
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} pull ${pullServices}
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ ${2} == "build" && ${buildServices} != "" ]]; then
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} build ${buildServices}
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ ${2} == "ps" || ${2} == "logs" ]]; then
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} "${2}" ${servicesString}
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Get docker container id
|
|
|
|
+getContainerId()
|
|
|
|
+{
|
|
|
|
+ if [[ $docker == "docker" ]]; then
|
|
|
|
+ containerId=$(${dockerCompose} ps -q "${1}")
|
|
|
|
+ else
|
|
|
|
+ containerId=$(${dockerCompose} ps \
|
|
|
|
+ | sed '0,/CONTAINER/d' \
|
|
|
|
+ | awk "/${1}/ {print \$1;exit}")
|
|
|
|
+ fi
|
|
|
|
+ echo "${containerId}"
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Reset services
|
|
|
|
+handleReset()
|
|
|
|
+{
|
|
|
|
+ servicesString=$(handleServices "backend frontend mongo redis" "${@:2}")
|
|
|
|
+ if [[ ${servicesString:0:1} != 1 ]]; then
|
|
|
|
+ throw "${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend, mongo, redis]"
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ confirmMessage="${GREEN}Are you sure you want to reset all data"
|
|
|
|
+ if [[ ${servicesString:2:4} != "all" ]]; then
|
|
|
|
+ confirmMessage="${confirmMessage} for $(echo "${servicesString:2}" | tr ' ' ',')"
|
|
|
|
+ fi
|
|
|
|
+ echo -e "${confirmMessage}? ${YELLOW}[y,n]: ${NC}"
|
|
|
|
+
|
|
|
|
+ read -r confirm
|
|
|
|
+ if [[ "${confirm}" != y* ]]; then
|
|
|
|
+ throw "Cancelled reset"
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" ]]; then
|
|
|
|
+ runDockerCommand "$(basename "$0") $1" stop
|
|
|
|
+ ${dockerCompose} rm -v --force
|
|
|
|
+ else
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ runDockerCommand "$(basename "$0") $1" stop ${servicesString:2}
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} rm -v --force ${servicesString:2}
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Attach to service in docker container
|
|
|
|
+attachContainer()
|
|
|
|
+{
|
|
|
|
+ containerId=$(getContainerId "${2}")
|
|
|
|
+ if [[ -z $containerId ]]; then
|
|
|
|
+ throw "Error: ${2} offline, please start to attach."
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ case $2 in
|
|
|
|
+ backend)
|
|
|
|
+ echo -e "${YELLOW}Detach with CTRL+P+Q${NC}"
|
|
|
|
+ ${docker} attach "$containerId"
|
|
|
|
+ ;;
|
|
|
|
+
|
|
|
|
+ mongo)
|
|
|
|
+ MONGO_VERSION_INT=${MONGO_VERSION:0:1}
|
|
|
|
+ echo -e "${YELLOW}Detach with CTRL+D${NC}"
|
|
|
|
+ if [[ $MONGO_VERSION_INT -ge 5 ]]; then
|
|
|
|
+ ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry()" --shell
|
|
else
|
|
else
|
|
- servicesString=${servicesString:2}
|
|
|
|
- pullArray=()
|
|
|
|
- buildArray=()
|
|
|
|
- if [[ "${servicesString}" == *mongo* ]]; then
|
|
|
|
- pullArray+=("mongo")
|
|
|
|
- fi
|
|
|
|
- if [[ "${servicesString}" == *redis* ]]; then
|
|
|
|
- pullArray+=("redis")
|
|
|
|
- fi
|
|
|
|
- if [[ "${servicesString}" == *backend* ]]; then
|
|
|
|
- buildArray+=("backend")
|
|
|
|
- fi
|
|
|
|
- if [[ "${servicesString}" == *frontend* ]]; then
|
|
|
|
- buildArray+=("frontend")
|
|
|
|
- fi
|
|
|
|
- pullServices="${pullArray[*]}"
|
|
|
|
- buildServices="${buildArray[*]}"
|
|
|
|
|
|
+ ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}"
|
|
fi
|
|
fi
|
|
|
|
+ ;;
|
|
|
|
|
|
- if [[ ${2} == "stop" || ${2} == "restart" ]]; then
|
|
|
|
- # shellcheck disable=SC2086
|
|
|
|
- ${dockerCompose} stop ${servicesString}
|
|
|
|
- fi
|
|
|
|
- if [[ ${2} == "start" || ${2} == "restart" ]]; then
|
|
|
|
- # shellcheck disable=SC2086
|
|
|
|
- ${dockerCompose} up -d ${servicesString}
|
|
|
|
- fi
|
|
|
|
- if [[ ${2} == "pull" && ${pullServices} != "" ]]; then
|
|
|
|
- # shellcheck disable=SC2086
|
|
|
|
- ${dockerCompose} "${2}" ${pullServices}
|
|
|
|
- fi
|
|
|
|
- if [[ ${2} == "build" && ${buildServices} != "" ]]; then
|
|
|
|
- # shellcheck disable=SC2086
|
|
|
|
- ${dockerCompose} "${2}" ${buildServices}
|
|
|
|
- fi
|
|
|
|
- if [[ ${2} == "ps" || ${2} == "logs" ]]; then
|
|
|
|
- # shellcheck disable=SC2086
|
|
|
|
- ${dockerCompose} "${2}" ${servicesString}
|
|
|
|
- fi
|
|
|
|
|
|
+ redis)
|
|
|
|
+ echo -e "${YELLOW}Detach with CTRL+C${NC}"
|
|
|
|
+ ${dockerCompose} exec redis redis-cli -a "${REDIS_PASSWORD}"
|
|
|
|
+ ;;
|
|
|
|
+
|
|
|
|
+ *)
|
|
|
|
+ throw "Invalid service ${2}\n${YELLOW}Usage: ${1} [backend, mongo, redis]"
|
|
|
|
+ ;;
|
|
|
|
+ esac
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Lint codebase, docs, scripts, etc
|
|
|
|
+handleLinting()
|
|
|
|
+{
|
|
|
|
+ set +e
|
|
|
|
+ # shellcheck disable=SC2001
|
|
|
|
+ services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}fix//g;t;q1" <<< "${@:2}")
|
|
|
|
+ fixFound=$?
|
|
|
|
+ if [[ $fixFound -eq 0 ]]; then
|
|
|
|
+ fix="--fix"
|
|
|
|
+ echo -e "${GREEN}Auto-fix enabled${NC}"
|
|
|
|
+ fi
|
|
|
|
+ # shellcheck disable=SC2001
|
|
|
|
+ services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}no-cache//g;t;q1" <<< "${services}")
|
|
|
|
+ noCacheFound=$?
|
|
|
|
+ cache="--cache"
|
|
|
|
+ if [[ $noCacheFound -eq 0 ]]; then
|
|
|
|
+ cache=""
|
|
|
|
+ echo -e "${YELLOW}ESlint cache disabled${NC}"
|
|
|
|
+ fi
|
|
|
|
+ set -e
|
|
|
|
+
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ servicesString=$(handleServices "backend frontend docs" ${services[@]})
|
|
|
|
+ if [[ ${servicesString:0:1} != 1 ]]; then
|
|
|
|
+ throw "${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend, docs] [fix]"
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ set +e
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
|
|
|
|
+ echo -e "${CYAN}Running frontend lint...${NC}"
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} exec -T frontend npm run lint -- ${cache} ${fix}
|
|
|
|
+ frontendExitValue=$?
|
|
|
|
+ fi
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *backend* ]]; then
|
|
|
|
+ echo -e "${CYAN}Running backend lint...${NC}"
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} exec -T backend npm run lint -- ${cache} ${fix}
|
|
|
|
+ backendExitValue=$?
|
|
|
|
+ fi
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *docs* ]]; then
|
|
|
|
+ echo -e "${CYAN}Running docs lint...${NC}"
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${docker} run --rm -v "${scriptLocation}":/workdir ghcr.io/igorshubovych/markdownlint-cli:latest ".wiki" "*.md" ${fix}
|
|
|
|
+ docsExitValue=$?
|
|
|
|
+ fi
|
|
|
|
+ set -e
|
|
|
|
+ if [[ ${frontendExitValue} -gt 0 || ${backendExitValue} -gt 0 || ${docsExitValue} -gt 0 || ${shellExitValue} -gt 0 ]]; then
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Validate typescript in services
|
|
|
|
+handleTypescript()
|
|
|
|
+{
|
|
|
|
+ set +e
|
|
|
|
+ # shellcheck disable=SC2001
|
|
|
|
+ services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}strict//g;t;q1" <<< "${@:2}")
|
|
|
|
+ strictFound=$?
|
|
|
|
+ if [[ $strictFound -eq 0 ]]; then
|
|
|
|
+ strict="--strict"
|
|
|
|
+ echo -e "${GREEN}Strict mode enabled${NC}"
|
|
|
|
+ fi
|
|
|
|
+ set -e
|
|
|
|
+
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ servicesString=$(handleServices "backend frontend" ${services[@]})
|
|
|
|
+ if [[ ${servicesString:0:1} != 1 ]]; then
|
|
|
|
+ throw "${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend] [strict]"
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ set +e
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
|
|
|
|
+ echo -e "${CYAN}Running frontend typescript check...${NC}"
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} exec -T frontend npm run typescript -- ${strict}
|
|
|
|
+ frontendExitValue=$?
|
|
|
|
+ fi
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *backend* ]]; then
|
|
|
|
+ echo -e "${CYAN}Running backend typescript check...${NC}"
|
|
|
|
+ # shellcheck disable=SC2086
|
|
|
|
+ ${dockerCompose} exec -T backend npm run typescript -- ${strict}
|
|
|
|
+ backendExitValue=$?
|
|
|
|
+ fi
|
|
|
|
+ set -e
|
|
|
|
+ if [[ ${frontendExitValue} -gt 0 || ${backendExitValue} -gt 0 ]]; then
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Execute automated tests in services
|
|
|
|
+handleTests()
|
|
|
|
+{
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ servicesString=$(handleServices "frontend" ${services[@]})
|
|
|
|
+ if [[ ${servicesString:0:1} != 1 ]]; then
|
|
|
|
+ throw "${servicesString:2}\n${YELLOW}Usage: ${1} [frontend]"
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ set +e
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
|
|
|
|
+ echo -e "${CYAN}Running frontend tests...${NC}"
|
|
|
|
+ ${dockerCompose} exec -T frontend npm run test -- --run
|
|
|
|
+ frontendExitValue=$?
|
|
|
|
+ fi
|
|
|
|
+ set -e
|
|
|
|
+ if [[ ${frontendExitValue} -gt 0 ]]; then
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Execute test coverage in services
|
|
|
|
+handleTestCoverage()
|
|
|
|
+{
|
|
|
|
+ servicesString=$(handleServices "frontend" "${@:2}")
|
|
|
|
+ if [[ ${servicesString:0:1} != 1 ]]; then
|
|
|
|
+ throw "${servicesString:2}\n${YELLOW}Usage: ${1} [frontend]"
|
|
|
|
+ fi
|
|
|
|
|
|
- exitValue=$?
|
|
|
|
- if [[ ${exitValue} -gt 0 ]]; then
|
|
|
|
- exit ${exitValue}
|
|
|
|
|
|
+ set +e
|
|
|
|
+ if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
|
|
|
|
+ echo -e "${CYAN}Running frontend test coverage report...${NC}"
|
|
|
|
+ ${dockerCompose} exec -T frontend npm run coverage
|
|
|
|
+ frontendExitValue=$?
|
|
|
|
+ fi
|
|
|
|
+ set -e
|
|
|
|
+ if [[ ${frontendExitValue} -gt 0 ]]; then
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Update Musare
|
|
|
|
+handleUpdate()
|
|
|
|
+{
|
|
|
|
+ musareshModified=$(git diff HEAD -- musare.sh)
|
|
|
|
+
|
|
|
|
+ git fetch
|
|
|
|
+
|
|
|
|
+ updated=$(git log --name-only --oneline HEAD..@\{u\})
|
|
|
|
+ if [[ ${updated} == "" ]]; then
|
|
|
|
+ echo -e "${GREEN}Already up to date${NC}"
|
|
|
|
+ exit 0
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ breakingConfigChange=$(git rev-list "$(git rev-parse HEAD)" | grep d8b73be1de231821db34c677110b7b97e413451f)
|
|
|
|
+ if [[ -f backend/config/default.json && -z $breakingConfigChange ]]; then
|
|
|
|
+ throw "Configuration has breaking changes. Please rename or remove 'backend/config/default.json' and run the update command again to continue."
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ musareshChange=$(echo "${updated}" | grep "musare.sh")
|
|
|
|
+ dbChange=$(echo "${updated}" | grep "backend/logic/db/schemas")
|
|
|
|
+ bcChange=$(echo "${updated}" | grep "backend/config/default.json")
|
|
|
|
+ if [[ ( $2 == "auto" && -z $dbChange && -z $bcChange && -z $musareshChange ) || -z $2 ]]; then
|
|
|
|
+ if [[ -n $musareshChange && $(git diff @\{u\} -- musare.sh) != "" ]]; then
|
|
|
|
+ if [[ $musareshModified != "" ]]; then
|
|
|
|
+ throw "musare.sh has been modified, please reset these changes and run the update command again to continue."
|
|
|
|
+ else
|
|
|
|
+ git checkout @\{u\} -- musare.sh
|
|
|
|
+ throw "${YELLOW}musare.sh has been updated, please run the update command again to continue."
|
|
fi
|
|
fi
|
|
else
|
|
else
|
|
- echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend, mongo, redis]${NC}"
|
|
|
|
- exit 1
|
|
|
|
|
|
+ git pull
|
|
|
|
+ echo -e "${CYAN}Updating...${NC}"
|
|
|
|
+ runDockerCommand "$(basename "$0") $1" pull
|
|
|
|
+ runDockerCommand "$(basename "$0") $1" build
|
|
|
|
+ runDockerCommand "$(basename "$0") $1" restart
|
|
|
|
+ echo -e "${GREEN}Updated!${NC}"
|
|
|
|
+ if [[ -n $dbChange ]]; then
|
|
|
|
+ echo -e "${RED}Database schema has changed, please run migration!${NC}"
|
|
|
|
+ fi
|
|
|
|
+ if [[ -n $bcChange ]]; then
|
|
|
|
+ echo -e "${RED}Backend config has changed, please update!${NC}"
|
|
|
|
+ fi
|
|
fi
|
|
fi
|
|
|
|
+ elif [[ $2 == "auto" ]]; then
|
|
|
|
+ throw "Auto Update Failed! musare.sh, database and/or config has changed!"
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Backup the database
|
|
|
|
+handleBackup()
|
|
|
|
+{
|
|
|
|
+ if [[ -z "${BACKUP_LOCATION}" ]]; then
|
|
|
|
+ backupLocation="${scriptLocation%x}/backups"
|
|
else
|
|
else
|
|
- echo -e "${RED}Error: Invalid runDockerCommand input${NC}"
|
|
|
|
- exit 1
|
|
|
|
|
|
+ backupLocation="${BACKUP_LOCATION%/}"
|
|
|
|
+ fi
|
|
|
|
+ if [[ ! -d "${backupLocation}" ]]; then
|
|
|
|
+ echo -e "${YELLOW}Creating backup directory at ${backupLocation}${NC}"
|
|
|
|
+ mkdir "${backupLocation}"
|
|
|
|
+ fi
|
|
|
|
+ if [[ -z "${BACKUP_NAME}" ]]; then
|
|
|
|
+ backupLocation="${backupLocation}/musare-$(date +"%Y-%m-%d-%s").dump"
|
|
|
|
+ else
|
|
|
|
+ backupLocation="${backupLocation}/${BACKUP_NAME}"
|
|
fi
|
|
fi
|
|
|
|
+ echo -e "${YELLOW}Creating backup at ${backupLocation}${NC}"
|
|
|
|
+ ${dockerCompose} exec -T mongo sh -c "mongodump --authenticationDatabase musare -u ${MONGO_USER_USERNAME} -p ${MONGO_USER_PASSWORD} -d musare --archive" > "${backupLocation}"
|
|
}
|
|
}
|
|
|
|
|
|
-getContainerId()
|
|
|
|
|
|
+# Restore database from dump
|
|
|
|
+handleRestore()
|
|
{
|
|
{
|
|
- if [[ ${DOCKER_COMMAND} == "docker" ]]; then
|
|
|
|
- containerId=$(${dockerCompose} ps -q "${1}")
|
|
|
|
|
|
+ if [[ -z $2 ]]; then
|
|
|
|
+ echo -e "${GREEN}Please enter the full path of the dump you wish to restore: ${NC}"
|
|
|
|
+ read -r restoreFile
|
|
else
|
|
else
|
|
- containerId=$(${dockerCompose} ps | sed '0,/CONTAINER/d' | awk "/${1}/ {print \$1;exit}")
|
|
|
|
|
|
+ restoreFile=$2
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ -z ${restoreFile} ]]; then
|
|
|
|
+ throw "Error: no restore path given, cancelled restoration."
|
|
|
|
+ elif [[ -d ${restoreFile} ]]; then
|
|
|
|
+ throw "Error: restore path given is a directory, cancelled restoration."
|
|
|
|
+ elif [[ ! -f ${restoreFile} ]]; then
|
|
|
|
+ throw "Error: no file at restore path given, cancelled restoration."
|
|
|
|
+ else
|
|
|
|
+ ${dockerCompose} exec -T mongo sh -c "mongorestore --authenticationDatabase musare -u ${MONGO_USER_USERNAME} -p ${MONGO_USER_PASSWORD} --archive" < "${restoreFile}"
|
|
fi
|
|
fi
|
|
- echo "${containerId}"
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+# Toggle user admin role
|
|
|
|
+handleAdmin()
|
|
|
|
+{
|
|
|
|
+ MONGO_VERSION_INT=${MONGO_VERSION:0:1}
|
|
|
|
+
|
|
|
|
+ case $2 in
|
|
|
|
+ add)
|
|
|
|
+ if [[ -z $3 ]]; then
|
|
|
|
+ echo -e "${GREEN}Please enter the username of the user you wish to make an admin: ${NC}"
|
|
|
|
+ read -r adminUser
|
|
|
|
+ else
|
|
|
|
+ adminUser=$3
|
|
|
|
+ fi
|
|
|
|
+ if [[ -z $adminUser ]]; then
|
|
|
|
+ throw "Error: Username for new admin not provided."
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ $MONGO_VERSION_INT -ge 5 ]]; then
|
|
|
|
+ ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry(); db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'admin'}})"
|
|
|
|
+ else
|
|
|
|
+ ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'admin'}})"
|
|
|
|
+ fi
|
|
|
|
+ ;;
|
|
|
|
+ remove)
|
|
|
|
+ if [[ -z $3 ]]; then
|
|
|
|
+ echo -e "${GREEN}Please enter the username of the user you wish to remove as admin: ${NC}"
|
|
|
|
+ read -r adminUser
|
|
|
|
+ else
|
|
|
|
+ adminUser=$3
|
|
|
|
+ fi
|
|
|
|
+ if [[ -z $adminUser ]]; then
|
|
|
|
+ throw "Error: Username for new admin not provided."
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if [[ $MONGO_VERSION_INT -ge 5 ]]; then
|
|
|
|
+ ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry(); db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'default'}})"
|
|
|
|
+ else
|
|
|
|
+ ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'default'}})"
|
|
|
|
+ fi
|
|
|
|
+ ;;
|
|
|
|
+ *)
|
|
|
|
+ throw "Invalid command $2\n${YELLOW}Usage: ${1} [add,remove] username"
|
|
|
|
+ ;;
|
|
|
|
+ esac
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+availableCommands=$(cat << COMMANDS
|
|
|
|
+start - Start services
|
|
|
|
+stop - Stop services
|
|
|
|
+restart - Restart services
|
|
|
|
+status - Service status
|
|
|
|
+logs - View logs for services
|
|
|
|
+update - Update Musare
|
|
|
|
+attach [backend,mongo,redis] - Attach to backend service, mongo or redis shell
|
|
|
|
+build - Build services
|
|
|
|
+lint - Run lint on frontend, backend, and/or docs
|
|
|
|
+backup - Backup database data to file
|
|
|
|
+restore - Restore database data from backup file
|
|
|
|
+reset - Reset service data
|
|
|
|
+admin [add,remove] - Assign/unassign admin role to/from a user
|
|
|
|
+typescript - Run typescript checks on frontend and/or backend
|
|
|
|
+COMMANDS
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+# Handle command
|
|
case $1 in
|
|
case $1 in
|
|
start)
|
|
start)
|
|
echo -e "${CYAN}Musare | Start Services${NC}"
|
|
echo -e "${CYAN}Musare | Start Services${NC}"
|
|
@@ -202,252 +581,43 @@ case $1 in
|
|
|
|
|
|
reset)
|
|
reset)
|
|
echo -e "${CYAN}Musare | Reset Services${NC}"
|
|
echo -e "${CYAN}Musare | Reset Services${NC}"
|
|
- servicesString=$(handleServices "backend frontend mongo redis" "${@:2}")
|
|
|
|
- if [[ ${servicesString:0:1} == 1 && ${servicesString:2:4} == "all" ]]; then
|
|
|
|
- echo -e "${GREEN}Are you sure you want to reset all data? ${YELLOW}[y,n]: ${NC}"
|
|
|
|
- read -r confirm
|
|
|
|
- if [[ "${confirm}" == y* ]]; then
|
|
|
|
- runDockerCommand "$(basename "$0") $1" stop
|
|
|
|
- ${dockerCompose} rm -v --force
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}Cancelled reset${NC}"
|
|
|
|
- fi
|
|
|
|
- elif [[ ${servicesString:0:1} == 1 ]]; then
|
|
|
|
- echo -e "${GREEN}Are you sure you want to reset all data for $(echo "${servicesString:2}" | tr ' ' ',')? ${YELLOW}[y,n]: ${NC}"
|
|
|
|
- read -r confirm
|
|
|
|
- if [[ "${confirm}" == y* ]]; then
|
|
|
|
- # shellcheck disable=SC2086
|
|
|
|
- runDockerCommand "$(basename "$0") $1" stop ${servicesString:2}
|
|
|
|
- # shellcheck disable=SC2086
|
|
|
|
- ${dockerCompose} rm -v --force ${servicesString}
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}Cancelled reset${NC}"
|
|
|
|
- fi
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") build [backend, frontend, mongo, redis]${NC}"
|
|
|
|
- exit 1
|
|
|
|
- fi
|
|
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ handleReset "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
attach)
|
|
attach)
|
|
echo -e "${CYAN}Musare | Attach${NC}"
|
|
echo -e "${CYAN}Musare | Attach${NC}"
|
|
- if [[ $2 == "backend" ]]; then
|
|
|
|
- containerId=$(getContainerId backend)
|
|
|
|
- if [[ -z $containerId ]]; then
|
|
|
|
- echo -e "${RED}Error: Backend offline, please start to attach.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- else
|
|
|
|
- echo -e "${YELLOW}Detach with CTRL+P+Q${NC}"
|
|
|
|
- ${docker} attach "$containerId"
|
|
|
|
- fi
|
|
|
|
- elif [[ $2 == "mongo" ]]; then
|
|
|
|
- MONGO_VERSION_INT=${MONGO_VERSION:0:1}
|
|
|
|
- if [[ -z $(getContainerId mongo) ]]; then
|
|
|
|
- echo -e "${RED}Error: Mongo offline, please start to attach.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- else
|
|
|
|
- echo -e "${YELLOW}Detach with CTRL+D${NC}"
|
|
|
|
- if [[ $MONGO_VERSION_INT -ge 5 ]]; then
|
|
|
|
- ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry()" --shell
|
|
|
|
- else
|
|
|
|
- ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}"
|
|
|
|
- fi
|
|
|
|
- fi
|
|
|
|
- elif [[ $2 == "redis" ]]; then
|
|
|
|
- if [[ -z $(getContainerId redis) ]]; then
|
|
|
|
- echo -e "${RED}Error: Redis offline, please start to attach.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- else
|
|
|
|
- echo -e "${YELLOW}Detach with CTRL+C${NC}"
|
|
|
|
- ${dockerCompose} exec redis redis-cli -a "${REDIS_PASSWORD}"
|
|
|
|
- fi
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}Invalid service $2\n${YELLOW}Usage: $(basename "$0") attach [backend,mongo,redis]${NC}"
|
|
|
|
- exit 1
|
|
|
|
- fi
|
|
|
|
|
|
+ attachContainer "$(basename "$0") $1" "$2"
|
|
;;
|
|
;;
|
|
|
|
|
|
lint|eslint)
|
|
lint|eslint)
|
|
echo -e "${CYAN}Musare | Lint${NC}"
|
|
echo -e "${CYAN}Musare | Lint${NC}"
|
|
- services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}fix//g;t;q1" <<< "${@:2}")
|
|
|
|
- fixFound=$?
|
|
|
|
- if [[ $fixFound -eq 0 ]]; then
|
|
|
|
- fix="--fix"
|
|
|
|
- echo -e "${GREEN}Auto-fix enabled${NC}"
|
|
|
|
- fi
|
|
|
|
- services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}no-cache//g;t;q1" <<< "${services}")
|
|
|
|
- noCacheFound=$?
|
|
|
|
- cache="--cache"
|
|
|
|
- if [[ $noCacheFound -eq 0 ]]; then
|
|
|
|
- cache=""
|
|
|
|
- echo -e "${YELLOW}ESlint cache disabled${NC}"
|
|
|
|
- fi
|
|
|
|
# shellcheck disable=SC2068
|
|
# shellcheck disable=SC2068
|
|
- servicesString=$(handleServices "backend frontend docs" ${services[@]})
|
|
|
|
- if [[ ${servicesString:0:1} == 1 ]]; then
|
|
|
|
- if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
|
|
|
|
- echo -e "${CYAN}Running frontend lint...${NC}"
|
|
|
|
- ${dockerCompose} exec -T frontend npm run lint -- $cache $fix
|
|
|
|
- frontendExitValue=$?
|
|
|
|
- fi
|
|
|
|
- if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *backend* ]]; then
|
|
|
|
- echo -e "${CYAN}Running backend lint...${NC}"
|
|
|
|
- ${dockerCompose} exec -T backend npm run lint -- $cache $fix
|
|
|
|
- backendExitValue=$?
|
|
|
|
- fi
|
|
|
|
- if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *docs* ]]; then
|
|
|
|
- echo -e "${CYAN}Running docs lint...${NC}"
|
|
|
|
- ${docker} run --rm -v "${scriptLocation}":/workdir ghcr.io/igorshubovych/markdownlint-cli:latest ".wiki" "*.md" $fix
|
|
|
|
- docsExitValue=$?
|
|
|
|
- fi
|
|
|
|
- if [[ ${frontendExitValue} -gt 0 || ${backendExitValue} -gt 0 || ${docsExitValue} -gt 0 ]]; then
|
|
|
|
- exitValue=1
|
|
|
|
- else
|
|
|
|
- exitValue=0
|
|
|
|
- fi
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") lint [backend, frontend, docs] [fix]${NC}"
|
|
|
|
- exitValue=1
|
|
|
|
- fi
|
|
|
|
- if [[ ${exitValue} -gt 0 ]]; then
|
|
|
|
- exit ${exitValue}
|
|
|
|
- fi
|
|
|
|
|
|
+ handleLinting "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
-
|
|
|
|
typescript|ts)
|
|
typescript|ts)
|
|
echo -e "${CYAN}Musare | TypeScript Check${NC}"
|
|
echo -e "${CYAN}Musare | TypeScript Check${NC}"
|
|
- services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}strict//g;t;q1" <<< "${@:2}")
|
|
|
|
- strictFound=$?
|
|
|
|
- if [[ $strictFound -eq 0 ]]; then
|
|
|
|
- strict="--strict"
|
|
|
|
- echo -e "${GREEN}Strict mode enabled${NC}"
|
|
|
|
- fi
|
|
|
|
# shellcheck disable=SC2068
|
|
# shellcheck disable=SC2068
|
|
- servicesString=$(handleServices "backend frontend" ${services[@]})
|
|
|
|
- if [[ ${servicesString:0:1} == 1 ]]; then
|
|
|
|
- if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
|
|
|
|
- echo -e "${CYAN}Running frontend typescript check...${NC}"
|
|
|
|
- ${dockerCompose} exec -T frontend npm run typescript -- $strict
|
|
|
|
- frontendExitValue=$?
|
|
|
|
- fi
|
|
|
|
- if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *backend* ]]; then
|
|
|
|
- echo -e "${CYAN}Running backend typescript check...${NC}"
|
|
|
|
- ${dockerCompose} exec -T backend npm run typescript -- $strict
|
|
|
|
- backendExitValue=$?
|
|
|
|
- fi
|
|
|
|
- if [[ ${frontendExitValue} -gt 0 || ${backendExitValue} -gt 0 ]]; then
|
|
|
|
- exitValue=1
|
|
|
|
- else
|
|
|
|
- exitValue=0
|
|
|
|
- fi
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") typescript [backend, frontend] [strict]${NC}"
|
|
|
|
- exitValue=1
|
|
|
|
- fi
|
|
|
|
- if [[ ${exitValue} -gt 0 ]]; then
|
|
|
|
- exit ${exitValue}
|
|
|
|
- fi
|
|
|
|
|
|
+ handleTypescript "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
test)
|
|
test)
|
|
echo -e "${CYAN}Musare | Test${NC}"
|
|
echo -e "${CYAN}Musare | Test${NC}"
|
|
- servicesString=$(handleServices "frontend" "${@:2}")
|
|
|
|
- if [[ ${servicesString:0:1} == 1 ]]; then
|
|
|
|
- if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
|
|
|
|
- echo -e "${CYAN}Running frontend tests...${NC}"
|
|
|
|
- ${dockerCompose} exec -T frontend npm run test -- --run
|
|
|
|
- frontendExitValue=$?
|
|
|
|
- fi
|
|
|
|
- if [[ ${frontendExitValue} -gt 0 ]]; then
|
|
|
|
- exitValue=1
|
|
|
|
- else
|
|
|
|
- exitValue=0
|
|
|
|
- fi
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") test [frontend]${NC}"
|
|
|
|
- exitValue=1
|
|
|
|
- fi
|
|
|
|
- if [[ ${exitValue} -gt 0 ]]; then
|
|
|
|
- exit ${exitValue}
|
|
|
|
- fi
|
|
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ handleTests "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
test:coverage)
|
|
test:coverage)
|
|
echo -e "${CYAN}Musare | Test Coverage${NC}"
|
|
echo -e "${CYAN}Musare | Test Coverage${NC}"
|
|
- servicesString=$(handleServices "frontend" "${@:2}")
|
|
|
|
- if [[ ${servicesString:0:1} == 1 ]]; then
|
|
|
|
- if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
|
|
|
|
- echo -e "${CYAN}Running frontend test coverage report...${NC}"
|
|
|
|
- ${dockerCompose} exec -T frontend npm run coverage
|
|
|
|
- frontendExitValue=$?
|
|
|
|
- fi
|
|
|
|
- if [[ ${frontendExitValue} -gt 0 ]]; then
|
|
|
|
- exitValue=1
|
|
|
|
- else
|
|
|
|
- exitValue=0
|
|
|
|
- fi
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") test:coverage [frontend]${NC}"
|
|
|
|
- exitValue=1
|
|
|
|
- fi
|
|
|
|
- if [[ ${exitValue} -gt 0 ]]; then
|
|
|
|
- exit ${exitValue}
|
|
|
|
- fi
|
|
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ handleTestCoverage "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
update)
|
|
update)
|
|
echo -e "${CYAN}Musare | Update${NC}"
|
|
echo -e "${CYAN}Musare | Update${NC}"
|
|
- musareshModified=$(git diff HEAD -- musare.sh)
|
|
|
|
- git fetch
|
|
|
|
- exitValue=$?
|
|
|
|
- if [[ ${exitValue} -gt 0 ]]; then
|
|
|
|
- exit ${exitValue}
|
|
|
|
- fi
|
|
|
|
- updated=$(git log --name-only --oneline HEAD..@\{u\})
|
|
|
|
- if [[ ${updated} == "" ]]; then
|
|
|
|
- echo -e "${GREEN}Already up to date${NC}"
|
|
|
|
- exit ${exitValue}
|
|
|
|
- fi
|
|
|
|
- breakingConfigChange=$(git rev-list "$(git rev-parse HEAD)" | grep d8b73be1de231821db34c677110b7b97e413451f)
|
|
|
|
- if [[ -f backend/config/default.json && -z $breakingConfigChange ]]; then
|
|
|
|
- echo -e "${RED}Configuration has breaking changes. Please rename or remove 'backend/config/default.json' and run the update command again to continue.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- fi
|
|
|
|
- musareshChange=$(echo "${updated}" | grep "musare.sh")
|
|
|
|
- dbChange=$(echo "${updated}" | grep "backend/logic/db/schemas")
|
|
|
|
- bcChange=$(echo "${updated}" | grep "backend/config/default.json")
|
|
|
|
- if [[ ( $2 == "auto" && -z $dbChange && -z $bcChange && -z $musareshChange ) || -z $2 ]]; then
|
|
|
|
- if [[ -n $musareshChange && $(git diff @\{u\} -- musare.sh) != "" ]]; then
|
|
|
|
- if [[ $musareshModified != "" ]]; then
|
|
|
|
- echo -e "${RED}musare.sh has been modified, please reset these changes and run the update command again to continue.${NC}"
|
|
|
|
- else
|
|
|
|
- git checkout @\{u\} -- musare.sh
|
|
|
|
- echo -e "${YELLOW}musare.sh has been updated, please run the update command again to continue.${NC}"
|
|
|
|
- fi
|
|
|
|
- exit 1
|
|
|
|
- else
|
|
|
|
- git pull
|
|
|
|
- exitValue=$?
|
|
|
|
- if [[ ${exitValue} -gt 0 ]]; then
|
|
|
|
- exit ${exitValue}
|
|
|
|
- fi
|
|
|
|
- echo -e "${CYAN}Updating...${NC}"
|
|
|
|
- runDockerCommand "$(basename "$0") $1" pull
|
|
|
|
- runDockerCommand "$(basename "$0") $1" build
|
|
|
|
- runDockerCommand "$(basename "$0") $1" restart
|
|
|
|
- echo -e "${GREEN}Updated!${NC}"
|
|
|
|
- if [[ -n $dbChange ]]; then
|
|
|
|
- echo -e "${RED}Database schema has changed, please run migration!${NC}"
|
|
|
|
- fi
|
|
|
|
- if [[ -n $bcChange ]]; then
|
|
|
|
- echo -e "${RED}Backend config has changed, please update!${NC}"
|
|
|
|
- fi
|
|
|
|
- fi
|
|
|
|
- elif [[ $2 == "auto" ]]; then
|
|
|
|
- echo -e "${RED}Auto Update Failed! musare.sh, database and/or config has changed!${NC}"
|
|
|
|
- exit 1
|
|
|
|
- fi
|
|
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ handleUpdate "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
logs)
|
|
logs)
|
|
@@ -458,125 +628,32 @@ case $1 in
|
|
|
|
|
|
backup)
|
|
backup)
|
|
echo -e "${CYAN}Musare | Backup${NC}"
|
|
echo -e "${CYAN}Musare | Backup${NC}"
|
|
- if [[ -z "${BACKUP_LOCATION}" ]]; then
|
|
|
|
- backupLocation="${scriptLocation%x}/backups"
|
|
|
|
- else
|
|
|
|
- backupLocation="${BACKUP_LOCATION%/}"
|
|
|
|
- fi
|
|
|
|
- if [[ ! -d "${backupLocation}" ]]; then
|
|
|
|
- echo -e "${YELLOW}Creating backup directory at ${backupLocation}${NC}"
|
|
|
|
- mkdir "${backupLocation}"
|
|
|
|
- fi
|
|
|
|
- if [[ -z "${BACKUP_NAME}" ]]; then
|
|
|
|
- backupLocation="${backupLocation}/musare-$(date +"%Y-%m-%d-%s").dump"
|
|
|
|
- else
|
|
|
|
- backupLocation="${backupLocation}/${BACKUP_NAME}"
|
|
|
|
- fi
|
|
|
|
- echo -e "${YELLOW}Creating backup at ${backupLocation}${NC}"
|
|
|
|
- ${dockerCompose} exec -T mongo sh -c "mongodump --authenticationDatabase musare -u ${MONGO_USER_USERNAME} -p ${MONGO_USER_PASSWORD} -d musare --archive" > "${backupLocation}"
|
|
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ handleBackup "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
restore)
|
|
restore)
|
|
echo -e "${CYAN}Musare | Restore${NC}"
|
|
echo -e "${CYAN}Musare | Restore${NC}"
|
|
- if [[ -z $2 ]]; then
|
|
|
|
- echo -e "${GREEN}Please enter the full path of the dump you wish to restore: ${NC}"
|
|
|
|
- read -r restoreFile
|
|
|
|
- else
|
|
|
|
- restoreFile=$2
|
|
|
|
- fi
|
|
|
|
- if [[ -z ${restoreFile} ]]; then
|
|
|
|
- echo -e "${RED}Error: no restore path given, cancelled restoration.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- elif [[ -d ${restoreFile} ]]; then
|
|
|
|
- echo -e "${RED}Error: restore path given is a directory, cancelled restoration.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- elif [[ ! -f ${restoreFile} ]]; then
|
|
|
|
- echo -e "${RED}Error: no file at restore path given, cancelled restoration.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- else
|
|
|
|
- ${dockerCompose} exec -T mongo sh -c "mongorestore --authenticationDatabase musare -u ${MONGO_USER_USERNAME} -p ${MONGO_USER_PASSWORD} --archive" < "${restoreFile}"
|
|
|
|
- fi
|
|
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ handleRestore "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
admin)
|
|
admin)
|
|
echo -e "${CYAN}Musare | Add Admin${NC}"
|
|
echo -e "${CYAN}Musare | Add Admin${NC}"
|
|
- MONGO_VERSION_INT=${MONGO_VERSION:0:1}
|
|
|
|
- if [[ $2 == "add" ]]; then
|
|
|
|
- if [[ -z $3 ]]; then
|
|
|
|
- echo -e "${GREEN}Please enter the username of the user you wish to make an admin: ${NC}"
|
|
|
|
- read -r adminUser
|
|
|
|
- else
|
|
|
|
- adminUser=$3
|
|
|
|
- fi
|
|
|
|
- if [[ -z $adminUser ]]; then
|
|
|
|
- echo -e "${RED}Error: Username for new admin not provided.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- else
|
|
|
|
- if [[ $MONGO_VERSION_INT -ge 5 ]]; then
|
|
|
|
- ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry(); db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'admin'}})"
|
|
|
|
- else
|
|
|
|
- ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'admin'}})"
|
|
|
|
- fi
|
|
|
|
- fi
|
|
|
|
- elif [[ $2 == "remove" ]]; then
|
|
|
|
- if [[ -z $3 ]]; then
|
|
|
|
- echo -e "${GREEN}Please enter the username of the user you wish to remove as admin: ${NC}"
|
|
|
|
- read -r adminUser
|
|
|
|
- else
|
|
|
|
- adminUser=$3
|
|
|
|
- fi
|
|
|
|
- if [[ -z $adminUser ]]; then
|
|
|
|
- echo -e "${RED}Error: Username for new admin not provided.${NC}"
|
|
|
|
- exit 1
|
|
|
|
- else
|
|
|
|
- if [[ $MONGO_VERSION_INT -ge 5 ]]; then
|
|
|
|
- ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry(); db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'default'}})"
|
|
|
|
- else
|
|
|
|
- ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'default'}})"
|
|
|
|
- fi
|
|
|
|
- fi
|
|
|
|
- else
|
|
|
|
- echo -e "${RED}Invalid command $2\n${YELLOW}Usage: $(basename "$0") admin [add,remove] username${NC}"
|
|
|
|
- exit 1
|
|
|
|
- fi
|
|
|
|
|
|
+ # shellcheck disable=SC2068
|
|
|
|
+ handleAdmin "$(basename "$0") $1" ${@:2}
|
|
;;
|
|
;;
|
|
|
|
|
|
"")
|
|
"")
|
|
echo -e "${CYAN}Musare | Available Commands${NC}"
|
|
echo -e "${CYAN}Musare | Available Commands${NC}"
|
|
- echo -e "${YELLOW}start - Start services${NC}"
|
|
|
|
- echo -e "${YELLOW}stop - Stop services${NC}"
|
|
|
|
- echo -e "${YELLOW}restart - Restart services${NC}"
|
|
|
|
- echo -e "${YELLOW}status - Service status${NC}"
|
|
|
|
- echo -e "${YELLOW}logs - View logs for services${NC}"
|
|
|
|
- echo -e "${YELLOW}update - Update Musare${NC}"
|
|
|
|
- echo -e "${YELLOW}attach [backend,mongo,redis] - Attach to backend service, mongo or redis shell${NC}"
|
|
|
|
- echo -e "${YELLOW}build - Build services${NC}"
|
|
|
|
- echo -e "${YELLOW}lint - Run lint on frontend, backend and/or docs${NC}"
|
|
|
|
- echo -e "${YELLOW}backup - Backup database data to file${NC}"
|
|
|
|
- echo -e "${YELLOW}restore - Restore database data from backup file${NC}"
|
|
|
|
- echo -e "${YELLOW}reset - Reset service data${NC}"
|
|
|
|
- echo -e "${YELLOW}admin [add,remove] - Assign/unassign admin role to/from a user${NC}"
|
|
|
|
- echo -e "${YELLOW}typescript - Run typescript checks on frontend and/or backend${NC}"
|
|
|
|
|
|
+ echo -e "${YELLOW}${availableCommands}${NC}"
|
|
;;
|
|
;;
|
|
|
|
|
|
*)
|
|
*)
|
|
echo -e "${CYAN}Musare${NC}"
|
|
echo -e "${CYAN}Musare${NC}"
|
|
echo -e "${RED}Error: Invalid Command $1${NC}"
|
|
echo -e "${RED}Error: Invalid Command $1${NC}"
|
|
echo -e "${CYAN}Available Commands:${NC}"
|
|
echo -e "${CYAN}Available Commands:${NC}"
|
|
- echo -e "${YELLOW}start - Start services${NC}"
|
|
|
|
- echo -e "${YELLOW}stop - Stop services${NC}"
|
|
|
|
- echo -e "${YELLOW}restart - Restart services${NC}"
|
|
|
|
- echo -e "${YELLOW}status - Service status${NC}"
|
|
|
|
- echo -e "${YELLOW}logs - View logs for services${NC}"
|
|
|
|
- echo -e "${YELLOW}update - Update Musare${NC}"
|
|
|
|
- echo -e "${YELLOW}attach [backend,mongo,redis] - Attach to backend service, mongo or redis shell${NC}"
|
|
|
|
- echo -e "${YELLOW}build - Build services${NC}"
|
|
|
|
- echo -e "${YELLOW}lint - Run lint on frontend, backend and/or docs${NC}"
|
|
|
|
- echo -e "${YELLOW}backup - Backup database data to file${NC}"
|
|
|
|
- echo -e "${YELLOW}restore - Restore database data from backup file${NC}"
|
|
|
|
- echo -e "${YELLOW}reset - Reset service data${NC}"
|
|
|
|
- echo -e "${YELLOW}admin [add,remove] - Assign/unassign admin role to/from a user${NC}"
|
|
|
|
- echo -e "${YELLOW}typescript - Run typescript checks on frontend and/or backend${NC}"
|
|
|
|
|
|
+ echo -e "${YELLOW}${availableCommands}${NC}"
|
|
exit 1
|
|
exit 1
|
|
;;
|
|
;;
|
|
esac
|
|
esac
|