#!/bin/bash BRANCH=master SCRIPT_DIR=$PWD PLANE_INSTALL_DIR=$PWD/plane-app export APP_RELEASE=$BRANCH export DOCKERHUB_USER=makeplane export PULL_POLICY=always USE_GLOBAL_IMAGES=1 RED='\033[0;31m' YELLOW='\033[1;33m' GREEN='\033[0;32m' NC='\033[0m' # No Color function print_header() { clear cat <<"EOF" --------------------------------------- ____ _ | _ \| | __ _ _ __ ___ | |_) | |/ _` | '_ \ / _ \ | __/| | (_| | | | | __/ |_| |_|\__,_|_| |_|\___| --------------------------------------- Project management tool from the future --------------------------------------- EOF } function buildLocalImage() { if [ "$1" == "--force-build" ]; then DO_BUILD="1" elif [ "$1" == "--skip-build" ]; then DO_BUILD="2" else printf "\n" >&2 printf "${YELLOW}You are on ${CPU_ARCH} cpu architecture. ${NC}\n" >&2 printf "${YELLOW}Since the prebuilt ${CPU_ARCH} compatible docker images are not available for, we will be running the docker build on this system. ${NC} \n" >&2 printf "${YELLOW}This might take ${YELLOW}5-30 min based on your system's hardware configuration. \n ${NC} \n" >&2 printf "\n" >&2 printf "${GREEN}Select an option to proceed: ${NC}\n" >&2 printf " 1) Build Fresh Images \n" >&2 printf " 2) Skip Building Images \n" >&2 printf " 3) Exit \n" >&2 printf "\n" >&2 read -p "Select Option [1]: " DO_BUILD until [[ -z "$DO_BUILD" || "$DO_BUILD" =~ ^[1-3]$ ]]; do echo "$DO_BUILD: invalid selection." >&2 read -p "Select Option [1]: " DO_BUILD done echo "" >&2 fi if [ "$DO_BUILD" == "1" ] || [ "$DO_BUILD" == "" ]; then REPO=https://github.com/makeplane/plane.git CURR_DIR=$PWD PLANE_TEMP_CODE_DIR=$(mktemp -d) git clone $REPO $PLANE_TEMP_CODE_DIR --branch $BRANCH --single-branch cp $PLANE_TEMP_CODE_DIR/deploy/selfhost/build.yml $PLANE_TEMP_CODE_DIR/build.yml cd $PLANE_TEMP_CODE_DIR if [ "$BRANCH" == "master" ]; then export APP_RELEASE=latest fi docker compose -f build.yml build --no-cache >&2 # cd $CURR_DIR # rm -rf $PLANE_TEMP_CODE_DIR echo "build_completed" elif [ "$DO_BUILD" == "2" ]; then printf "${YELLOW}Build action skipped by you in lieu of using existing images. ${NC} \n" >&2 echo "build_skipped" elif [ "$DO_BUILD" == "3" ]; then echo "build_exited" else printf "INVALID OPTION SUPPLIED" >&2 fi } function install() { echo "Installing Plane.........." download } function download() { cd $SCRIPT_DIR TS=$(date +%s) if [ -f "$PLANE_INSTALL_DIR/docker-compose.yaml" ] then mv $PLANE_INSTALL_DIR/docker-compose.yaml $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yaml fi curl -H 'Cache-Control: no-cache, no-store' -s -o $PLANE_INSTALL_DIR/docker-compose.yaml https://raw.githubusercontent.com/makeplane/plane/$BRANCH/deploy/selfhost/docker-compose.yml?$(date +%s) curl -H 'Cache-Control: no-cache, no-store' -s -o $PLANE_INSTALL_DIR/variables-upgrade.env https://raw.githubusercontent.com/makeplane/plane/$BRANCH/deploy/selfhost/variables.env?$(date +%s) if [ -f "$PLANE_INSTALL_DIR/.env" ]; then cp $PLANE_INSTALL_DIR/.env $PLANE_INSTALL_DIR/archive/$TS.env else mv $PLANE_INSTALL_DIR/variables-upgrade.env $PLANE_INSTALL_DIR/.env fi if [ "$BRANCH" != "master" ]; then cp $PLANE_INSTALL_DIR/docker-compose.yaml $PLANE_INSTALL_DIR/temp.yaml sed -e 's@${APP_RELEASE:-latest}@'"$BRANCH"'@g' \ $PLANE_INSTALL_DIR/temp.yaml > $PLANE_INSTALL_DIR/docker-compose.yaml rm $PLANE_INSTALL_DIR/temp.yaml fi if [ $USE_GLOBAL_IMAGES == 0 ]; then local res=$(buildLocalImage) # echo $res if [ "$res" == "build_exited" ]; then echo echo "Install action cancelled by you. Exiting now." echo exit 0 fi else docker compose -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH pull fi echo "" echo "Latest version is now available for you to use" echo "" echo "In case of Upgrade, your new setting file is availabe as 'variables-upgrade.env'. Please compare and set the required values in '.env 'file." echo "" } function startServices() { docker compose -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH up -d --quiet-pull local migrator_container_id=$(docker container ls -aq -f "name=plane-app-migrator") if [ -n "$migrator_container_id" ]; then local idx=0 while docker inspect --format='{{.State.Status}}' $migrator_container_id | grep -q "running"; do local message=">>> Waiting for Data Migration to finish" local dots=$(printf '%*s' $idx | tr ' ' '.') echo -ne "\r$message$dots" ((idx++)) sleep 1 done fi printf "\r\033[K" # if migrator exit status is not 0, show error message and exit if [ -n "$migrator_container_id" ]; then local migrator_exit_code=$(docker inspect --format='{{.State.ExitCode}}' $migrator_container_id) if [ $migrator_exit_code -ne 0 ]; then echo "Plane Server failed to start ❌" stopServices exit 1 fi fi local api_container_id=$(docker container ls -q -f "name=plane-app-api") local idx2=0 while ! docker logs $api_container_id 2>&1 | grep -m 1 -i "Application startup complete" | grep -q "."; do local message=">>> Waiting for API Service to Start" local dots=$(printf '%*s' $idx2 | tr ' ' '.') echo -ne "\r$message$dots" ((idx2++)) sleep 1 done printf "\r\033[K" } function stopServices() { docker compose -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH down } function restartServices() { docker compose -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH restart } function upgrade() { echo "***** STOPPING SERVICES ****" stopServices echo echo "***** DOWNLOADING LATEST VERSION ****" download echo "***** PLEASE VALIDATE AND START SERVICES ****" } function viewSpecificLogs(){ local SERVICE_NAME=$1 if docker-compose -f $DOCKER_FILE_PATH ps | grep -q "$SERVICE_NAME"; then echo "Service '$SERVICE_NAME' is running." else echo "Service '$SERVICE_NAME' is not running." fi docker compose -f $DOCKER_FILE_PATH logs -f $SERVICE_NAME } function viewLogs(){ ARG_SERVICE_NAME=$2 if [ -z "$ARG_SERVICE_NAME" ]; then echo echo "Select a Service you want to view the logs for:" echo " 1) Web" echo " 2) Space" echo " 3) API" echo " 4) Worker" echo " 5) Beat-Worker" echo " 6) Migrator" echo " 7) Proxy" echo " 8) Redis" echo " 9) Postgres" echo " 10) Minio" echo " 0) Back to Main Menu" echo read -p "Service: " DOCKER_SERVICE_NAME until (( DOCKER_SERVICE_NAME >= 0 && DOCKER_SERVICE_NAME <= 10 )); do echo "Invalid selection. Please enter a number between 1 and 11." read -p "Service: " DOCKER_SERVICE_NAME done if [ -z "$DOCKER_SERVICE_NAME" ]; then echo "INVALID SERVICE NAME SUPPLIED" else case $DOCKER_SERVICE_NAME in 1) viewSpecificLogs "web";; 2) viewSpecificLogs "space";; 3) viewSpecificLogs "api";; 4) viewSpecificLogs "worker";; 5) viewSpecificLogs "beat-worker";; 6) viewSpecificLogs "migrator";; 7) viewSpecificLogs "proxy";; 8) viewSpecificLogs "plane-redis";; 9) viewSpecificLogs "plane-db";; 10) viewSpecificLogs "plane-minio";; 0) askForAction;; *) echo "INVALID SERVICE NAME SUPPLIED";; esac fi elif [ -n "$ARG_SERVICE_NAME" ]; then ARG_SERVICE_NAME=$(echo "$ARG_SERVICE_NAME" | tr '[:upper:]' '[:lower:]') case $ARG_SERVICE_NAME in web) viewSpecificLogs "web";; space) viewSpecificLogs "space";; api) viewSpecificLogs "api";; worker) viewSpecificLogs "worker";; beat-worker) viewSpecificLogs "beat-worker";; migrator) viewSpecificLogs "migrator";; proxy) viewSpecificLogs "proxy";; redis) viewSpecificLogs "plane-redis";; postgres) viewSpecificLogs "plane-db";; minio) viewSpecificLogs "plane-minio";; *) echo "INVALID SERVICE NAME SUPPLIED";; esac else echo "INVALID SERVICE NAME SUPPLIED" fi } function askForAction() { local DEFAULT_ACTION=$1 if [ -z "$DEFAULT_ACTION" ]; then echo echo "Select a Action you want to perform:" echo " 1) Install (${CPU_ARCH})" echo " 2) Start" echo " 3) Stop" echo " 4) Restart" echo " 5) Upgrade" echo " 6) View Logs" echo " 7) Exit" echo read -p "Action [2]: " ACTION until [[ -z "$ACTION" || "$ACTION" =~ ^[1-7]$ ]]; do echo "$ACTION: invalid selection." read -p "Action [2]: " ACTION done if [ -z "$ACTION" ]; then ACTION=2 fi echo fi if [ "$ACTION" == "1" ] || [ "$DEFAULT_ACTION" == "install" ] then install askForAction elif [ "$ACTION" == "2" ] || [ "$DEFAULT_ACTION" == "start" ] then startServices askForAction elif [ "$ACTION" == "3" ] || [ "$DEFAULT_ACTION" == "stop" ] then stopServices askForAction elif [ "$ACTION" == "4" ] || [ "$DEFAULT_ACTION" == "restart" ] then restartServices askForAction elif [ "$ACTION" == "5" ] || [ "$DEFAULT_ACTION" == "upgrade" ] then upgrade askForAction elif [ "$ACTION" == "6" ] || [ "$DEFAULT_ACTION" == "logs" ] then viewLogs $@ askForAction elif [ "$ACTION" == "7" ] then exit 0 else echo "INVALID ACTION SUPPLIED" fi } # CPU ARCHITECHTURE BASED SETTINGS CPU_ARCH=$(uname -m) if [[ $CPU_ARCH == "amd64" || $CPU_ARCH == "x86_64" || ( $BRANCH == "master" && ( $CPU_ARCH == "arm64" || $CPU_ARCH == "aarch64" ) ) ]]; then USE_GLOBAL_IMAGES=1 DOCKERHUB_USER=makeplane PULL_POLICY=always else USE_GLOBAL_IMAGES=0 DOCKERHUB_USER=myplane PULL_POLICY=never fi if [ "$BRANCH" == "master" ]; then export APP_RELEASE=latest fi # REMOVE SPECIAL CHARACTERS FROM BRANCH NAME if [ "$BRANCH" != "master" ]; then PLANE_INSTALL_DIR=$PWD/plane-app-$(echo $BRANCH | sed -r 's@(\/|" "|\.)@-@g') fi mkdir -p $PLANE_INSTALL_DIR/archive DOCKER_FILE_PATH=$PLANE_INSTALL_DIR/docker-compose.yaml DOCKER_ENV_PATH=$PLANE_INSTALL_DIR/.env print_header askForAction $@