From 70e25b7f118db4b044515433c2ce70d88322a061 Mon Sep 17 00:00:00 2001
From: hiento09 <136591877+hiento09@users.noreply.github.com>
Date: Tue, 19 Nov 2024 09:53:41 +0700
Subject: [PATCH] feat: linux install script (#1701)

Co-authored-by: Hien To <tominhhien97@gmail.com>
---
 engine/templates/linux/install.sh | 281 ++++++++++++++++++++++++++++++
 1 file changed, 281 insertions(+)
 create mode 100644 engine/templates/linux/install.sh

diff --git a/engine/templates/linux/install.sh b/engine/templates/linux/install.sh
new file mode 100644
index 000000000..e907150a8
--- /dev/null
+++ b/engine/templates/linux/install.sh
@@ -0,0 +1,281 @@
+#!/bin/bash -e
+
+# Check for root privileges
+if [ "$(id -u)" != "0" ]; then
+    echo "This script must be run as root. Please run again with sudo."
+    exit 1
+fi
+
+# Determine the home directory based on the user
+USER_TO_RUN_AS=${SUDO_USER:-$(whoami)}
+if [ "$USER_TO_RUN_AS" = "root" ]; then
+    USER_HOME="/root"
+else
+    USER_HOME="/home/$USER_TO_RUN_AS"
+fi
+
+# Check and suggest installing jq and tar if not present
+check_install_jq_tar() {
+    RED='\033[0;31m'
+    GREEN='\033[0;32m'
+    NC='\033[0m' # No Color
+
+    if ! command -v jq &> /dev/null; then
+        echo -e "${RED}jq could not be found ...${NC}"
+        echo -e "${GREEN}Please install jq then rerun this script${NC}"
+        exit 1
+    fi
+
+    if ! command -v tar &> /dev/null; then
+        echo -e "${RED}tar could not be found ...${NC}"
+        echo -e "${GREEN}Please install tar then rerun this script${NC}"
+        exit 1
+    fi
+}
+
+# Function to fetch the latest version based on channel
+get_latest_version() {
+  local channel=$1
+  local tag_name
+  case $channel in
+    stable)
+      tag_name=$(curl -s "https://api.github.com/repos/janhq/cortex.cpp/releases/latest" | grep -oP '"tag_name": "\K(.*)(?=")')
+      ;;
+    beta)
+      tag_name=$(curl -s "https://api.github.com/repos/janhq/cortex.cpp/releases" | jq -r '.[] | select(.prerelease) | .tag_name' | head -n 1)
+      ;;
+    nightly)
+      tag_name=$(curl -s "https://delta.jan.ai/cortex/latest/version.json" | jq -r '.tag_name')
+      ;;
+    *)
+      echo "Invalid channel specified."
+      exit 1
+      ;;
+  esac
+  echo "${tag_name#v}"
+}
+
+# Default values
+CHANNEL="stable"
+VERSION=""
+IS_UPDATE="false"
+DEB_LOCAL="false"
+
+# Function to parse command-line arguments
+parse_args() {
+  while [[ "$#" -gt 0 ]]; do
+    case $1 in
+      --channel)
+        CHANNEL="$2"
+        shift 2
+        ;;
+      --version)
+        VERSION="$2"
+        shift 2
+        ;;
+      --deb_local)
+        DEB_LOCAL="true"
+        shift 1
+        ;;
+      --is_update)
+        IS_UPDATE="true"
+        shift 1
+        ;;
+      *)
+        echo "Unknown option: $1"
+        exit 1
+        ;;
+    esac
+  done
+}
+
+# Call parse_args function to handle options
+parse_args "$@"
+
+# Check if VERSION is empty and fetch latest if necessary
+if [ -z "$VERSION" ]; then
+    VERSION=$(get_latest_version $CHANNEL)
+fi
+
+# Set paths based on channel
+case $CHANNEL in
+  stable)
+    CLI_BINARY_NAME="cortex"
+    SERVER_BINARY_NAME="cortex-server"
+    DATA_DIR="$USER_HOME/cortexcpp"
+    UNINSTALL_SCRIPT="/usr/bin/cortex-uninstall.sh"
+    CONFIGURATION_FILE="$USER_HOME/.cortexrc"
+    DEB_APP_NAME="cortexcpp"
+    ;;
+  beta)
+    CLI_BINARY_NAME="cortex-beta"
+    SERVER_BINARY_NAME="cortex-server-beta"
+    DATA_DIR="$USER_HOME/cortexcpp-beta"
+    UNINSTALL_SCRIPT="/usr/bin/cortex-beta-uninstall.sh"
+    CONFIGURATION_FILE="$USER_HOME/.cortexrc-beta"
+    DEB_APP_NAME="cortexcpp-beta"
+    ;;
+  nightly)
+    CLI_BINARY_NAME="cortex-nightly"
+    SERVER_BINARY_NAME="cortex-server-nightly"
+    DATA_DIR="$USER_HOME/cortexcpp-nightly"
+    UNINSTALL_SCRIPT="/usr/bin/cortex-nightly-uninstall.sh"
+    CONFIGURATION_FILE="$USER_HOME/.cortexrc-nightly"
+    DEB_APP_NAME="cortexcpp-nightly"
+    ;;
+  *)
+    echo "Invalid channel specified."
+    exit 1
+    ;;
+esac
+
+INSTALL_DIR="/usr/bin"
+
+# Function to download and extract cortex
+install_cortex() {
+  local channel=$1
+  local version=$2
+  local is_deb=$3
+  local url_binary=""
+  local url_deb_local=""
+  local url_deb_network=""
+
+  case $channel in
+    stable)
+      url_binary="https://github.com/janhq/cortex.cpp/releases/download/v${version}/cortex-${version}-linux-amd64.tar.gz"
+      url_deb_local="https://github.com/janhq/cortex.cpp/releases/download/v${version}/cortex-${version}-linux-amd64-local-installer.deb"
+      url_deb_network="https://github.com/janhq/cortex.cpp/releases/download/v${version}/cortex-${version}-linux-amd64-network-installer.deb"
+      ;;
+    beta)
+      url_binary="https://github.com/janhq/cortex.cpp/releases/download/v${version}/cortex-${version}-linux-amd64.tar.gz"
+      url_deb_local="https://github.com/janhq/cortex.cpp/releases/download/v${version}/cortex-${version}-linux-amd64-local-installer.deb"
+      url_deb_network="https://github.com/janhq/cortex.cpp/releases/download/v${version}/cortex-${version}-linux-amd64-network-installer.deb"
+      ;;
+    nightly)
+      url_binary="https://delta.jan.ai/cortex/v${version}/linux-amd64/cortex-nightly.tar.gz"
+      url_deb_local="https://delta.jan.ai/cortex/v${version}/linux-amd64/cortex-${version}-linux-amd64-local-installer.deb"
+      url_deb_network="https://delta.jan.ai/cortex/v${version}/linux-amd64/cortex-${version}-linux-amd64-network-installer.deb"
+      ;;
+  esac
+
+  if [ "$is_deb" = "true" ]; then
+    # Download the deb package
+    if [ "$DEB_LOCAL" = "true" ]; then
+      echo "Downloading cortex $channel version $version from $url_deb_local"
+      curl -L $url_deb_local -o /tmp/cortex.deb
+    else
+      echo "Downloading cortex $channel version $version from $url_deb_network"
+      curl -L $url_deb_network -o /tmp/cortex.deb
+    fi
+
+    # Install the deb package
+    if [ "$IS_UPDATE" = "false" ]; then
+      apt-get install -y /tmp/cortex.deb
+    else
+      echo -e "n\n" | SKIP_POSTINSTALL=true apt-get install -y --allow-downgrades /tmp/cortex.deb
+    fi
+    rm -f /tmp/cortex.deb
+  else
+    echo "Downloading cortex $channel version $version from $url_binary"
+    curl -L $url_binary -o /tmp/cortex.tar.gz
+    tar -xzvf /tmp/cortex.tar.gz -C /tmp
+    chmod +x /tmp/cortex/*
+    cp /tmp/cortex/* /usr/bin/
+    # Check is update or not
+    if [ "$IS_UPDATE" = "false" ]; then
+      su -c "$INSTALL_DIR/$CLI_BINARY_NAME engines install llama-cpp" $USER_TO_RUN_AS
+      su -c "$INSTALL_DIR/$CLI_BINARY_NAME stop > /dev/null 2>&1" $USER_TO_RUN_AS
+    fi
+    rm -rf /tmp/cortex
+    rm -f /tmp/cortex.tar.gz
+  fi
+}
+
+# Function to create uninstall script
+create_uninstall_script() {
+  local is_deb=$1
+  if [ "$is_deb" = "false" ]; then
+    cat << EOF > $UNINSTALL_SCRIPT
+#!/bin/bash
+# Check for root privileges
+if [ "\$(id -u)" != "0" ]; then
+    echo "This script must be run as root. Please run again with sudo."
+    exit 1
+fi
+
+echo "Stopping cortex..."
+su -c "$INSTALL_DIR/$CLI_BINARY_NAME stop > /dev/null 2>&1" $USER_TO_RUN_AS
+rm -f $INSTALL_DIR/$CLI_BINARY_NAME
+rm -f $INSTALL_DIR/$SERVER_BINARY_NAME
+rm -f $UNINSTALL_SCRIPT
+
+echo "Do you want to delete the $DATA_DIR data folder and file $CONFIGURATION_FILE? (yes/no) [default: no]"
+read -r answer
+while true; do
+    case "\$answer" in
+        [yY][eE][sS]|[yY])
+            echo "Deleting cortex data folders..."
+            if [ -d "$DATA_DIR" ]; then
+                echo "Removing $DATA_DIR"
+                rm -rf "$DATA_DIR" > /dev/null 2>&1
+            fi
+            if [ -f "$CONFIGURATION_FILE" ]; then
+                echo "Removing $CONFIGURATION_FILE"
+                rm -f "$CONFIGURATION_FILE" > /dev/null 2>&1
+            fi
+            break
+            ;;
+        [nN][oO]|[nN]|"")
+            echo "Keeping the 'cortex' data folders."
+            break
+            ;;
+        *)
+            echo "Invalid response. Please type 'yes', 'no', 'y', or 'n' (case-insensitive)."
+            read -r answer
+            ;;
+    esac
+done
+
+EOF
+
+  else
+    cat << EOF > $UNINSTALL_SCRIPT
+#!/bin/bash
+# Check for root privileges
+if [ "\$(id -u)" != "0" ]; then
+    echo "This script must be run as root. Please run again with sudo."
+    exit 1
+fi
+
+apt-get remove -y $DEB_APP_NAME
+rm -f $UNINSTALL_SCRIPT
+EOF
+  fi
+
+  chmod +x $UNINSTALL_SCRIPT
+  echo "Uninstall script created at $UNINSTALL_SCRIPT"
+}
+
+# Run installation
+check_install_jq_tar
+
+IS_DEB="false"
+
+# Check if apt-get command is available
+if command -v apt-get &> /dev/null; then
+  if [ "$IS_UPDATE" = "true" ]; then
+    # check if cortexcpp deb package is installed
+    if dpkg -l | grep -q $DEB_APP_NAME; then
+      IS_DEB="true"
+    else
+      IS_DEB="false"
+    fi
+  else
+    IS_DEB="true"
+  fi
+fi
+
+install_cortex $CHANNEL $VERSION $IS_DEB
+create_uninstall_script $IS_DEB
+
+echo "Installation complete. Run cortex-uninstall.sh to uninstall."
\ No newline at end of file