From 9397a21554434fb14dff261971d868294041bb67 Mon Sep 17 00:00:00 2001 From: Krishna Mohan Date: Mon, 5 Jan 2026 23:00:08 +0530 Subject: [PATCH 1/6] feat(one-liner): Added one liner with new latest installation production guide. Signed-off-by: Krishna Mohan --- install.sh | 519 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 519 insertions(+) create mode 100644 install.sh diff --git a/install.sh b/install.sh new file mode 100644 index 00000000..0f923905 --- /dev/null +++ b/install.sh @@ -0,0 +1,519 @@ +#!/usr/bin/env bash +# install.sh - One-liner installer for ShipSec Studio (Production/Docker mode) +# +# Usage: +# curl -fsSL https://raw.githubusercontent.com/ShipSecAI/studio/main/install.sh | bash +# +# This script installs ShipSec Studio using pre-built Docker images from GHCR. +# For development setup, see: https://github.com/ShipSecAI/studio#option-3-development-setup +# +# Supported platforms: macOS, Linux, Windows (Git Bash/MSYS2/WSL) + +set -u -o pipefail +IFS=$'\n\t' + +# ---------- Config ---------- +REPO_URL="https://github.com/ShipSecAI/studio" +REPO_DIR="studio" +WAIT_DOCKER_SEC=60 + +# ---------- Colors ---------- +setup_colors() { + if [[ -t 1 ]] && [[ -n "${TERM:-}" ]]; then + GREEN='\033[0;32m' + YELLOW='\033[1;33m' + RED='\033[0;31m' + CYAN='\033[0;36m' + BLUE='\033[0;34m' + BOLD='\033[1m' + NC='\033[0m' + else + GREEN='' + YELLOW='' + RED='' + CYAN='' + BLUE='' + BOLD='' + NC='' + fi +} +setup_colors + +# ---------- Logging ---------- +log() { printf "\n${GREEN}==>${NC} ${BOLD}%s${NC}\n" "$1"; } +info() { printf " %s\n" "$1"; } +warn() { printf " ${YELLOW}Warning:${NC} %s\n" "$1"; } +err() { printf " ${RED}Error:${NC} %s\n" "$1"; } + +# ---------- Traps ---------- +on_err() { + local rc=$? + printf "\n" + err "Installation failed (exit code: $rc)" + err "If you need help, please visit: https://github.com/ShipSecAI/studio/issues" + exit $rc +} +on_int() { + printf "\n" + warn "Installation cancelled by user." + exit 130 +} +trap 'on_err' ERR +trap 'on_int' INT + +# ---------- Utility ---------- +command_exists() { command -v "$1" >/dev/null 2>&1; } + +# Cross-platform user input +ask_yes_no() { + local prompt="$1" + local default="${2:-n}" + local yn_hint + + if [ "$default" = "y" ]; then + yn_hint="[Y/n]" + else + yn_hint="[y/N]" + fi + + # Non-interactive mode (piped input) + if [ ! -t 0 ]; then + case "$default" in + y|Y) return 0 ;; + *) return 1 ;; + esac + fi + + while true; do + printf " %s %s " "$prompt" "$yn_hint" + read -r ans || ans="" + ans="${ans:-$default}" + case "$ans" in + y|Y|yes|YES|Yes) return 0 ;; + n|N|no|NO|No) return 1 ;; + *) printf " Please enter 'y' for yes or 'n' for no.\n" ;; + esac + done +} + +# ---------- Platform Detection ---------- +detect_platform() { + local os_raw + os_raw="$(uname -s 2>/dev/null || echo Unknown)" + + case "$os_raw" in + Darwin) + PLATFORM="macos" + PLATFORM_NAME="macOS" + ;; + Linux) + if grep -qEi "(microsoft|wsl)" /proc/version 2>/dev/null; then + PLATFORM="wsl" + PLATFORM_NAME="Windows (WSL)" + else + PLATFORM="linux" + PLATFORM_NAME="Linux" + fi + ;; + MINGW*|MSYS*|CYGWIN*) + PLATFORM="windows" + PLATFORM_NAME="Windows (Git Bash)" + ;; + *) + PLATFORM="unknown" + PLATFORM_NAME="Unknown" + ;; + esac +} + +# ---------- Dependency Installation Instructions ---------- +show_install_instructions() { + local dep="$1" + + printf "\n" + printf " ${BOLD}How to install ${dep}:${NC}\n" + printf "\n" + + case "$dep" in + docker) + case "$PLATFORM" in + macos) + printf " ${CYAN}Option 1: Download Docker Desktop${NC}\n" + printf " https://www.docker.com/products/docker-desktop\n" + printf "\n" + printf " ${CYAN}Option 2: Install via Homebrew${NC}\n" + printf " brew install --cask docker\n" + ;; + linux) + printf " ${CYAN}Install Docker Engine:${NC}\n" + printf " curl -fsSL https://get.docker.com | sudo sh\n" + printf " sudo usermod -aG docker \$USER\n" + printf " # Log out and back in for group changes to take effect\n" + ;; + wsl) + printf " ${CYAN}Option 1: Use Docker Desktop for Windows${NC}\n" + printf " Install Docker Desktop and enable WSL2 integration in Settings\n" + printf " https://www.docker.com/products/docker-desktop\n" + printf "\n" + printf " ${CYAN}Option 2: Install Docker Engine in WSL${NC}\n" + printf " curl -fsSL https://get.docker.com | sudo sh\n" + printf " sudo usermod -aG docker \$USER\n" + ;; + windows) + printf " ${CYAN}Install Docker Desktop for Windows:${NC}\n" + printf " https://www.docker.com/products/docker-desktop\n" + printf "\n" + printf " ${CYAN}Or via winget:${NC}\n" + printf " winget install Docker.DockerDesktop\n" + ;; + esac + ;; + just) + case "$PLATFORM" in + macos) + printf " ${CYAN}Install via Homebrew:${NC}\n" + printf " brew install just\n" + ;; + linux|wsl) + printf " ${CYAN}Option 1: Install via script${NC}\n" + printf " curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin\n" + printf " # Add ~/.local/bin to your PATH if not already\n" + printf "\n" + printf " ${CYAN}Option 2: Install via package manager${NC}\n" + printf " # Debian/Ubuntu (if available)\n" + printf " sudo apt install just\n" + ;; + windows) + printf " ${CYAN}Option 1: Install via Scoop${NC}\n" + printf " scoop install just\n" + printf "\n" + printf " ${CYAN}Option 2: Install via Chocolatey${NC}\n" + printf " choco install just\n" + printf "\n" + printf " ${CYAN}Option 3: Download from GitHub${NC}\n" + printf " https://github.com/casey/just/releases\n" + ;; + esac + ;; + curl) + case "$PLATFORM" in + macos) + printf " curl is pre-installed on macOS.\n" + printf " If missing, install via: brew install curl\n" + ;; + linux|wsl) + printf " ${CYAN}Debian/Ubuntu:${NC}\n" + printf " sudo apt-get update && sudo apt-get install -y curl\n" + printf "\n" + printf " ${CYAN}RHEL/CentOS/Fedora:${NC}\n" + printf " sudo dnf install curl\n" + ;; + windows) + printf " curl is included in Windows 10+ and Git Bash.\n" + printf " If missing, install via: choco install curl\n" + ;; + esac + ;; + jq) + case "$PLATFORM" in + macos) + printf " ${CYAN}Install via Homebrew:${NC}\n" + printf " brew install jq\n" + ;; + linux|wsl) + printf " ${CYAN}Debian/Ubuntu:${NC}\n" + printf " sudo apt-get update && sudo apt-get install -y jq\n" + printf "\n" + printf " ${CYAN}RHEL/CentOS/Fedora:${NC}\n" + printf " sudo dnf install jq\n" + ;; + windows) + printf " ${CYAN}Option 1: Install via Scoop${NC}\n" + printf " scoop install jq\n" + printf "\n" + printf " ${CYAN}Option 2: Install via Chocolatey${NC}\n" + printf " choco install jq\n" + ;; + esac + ;; + git) + case "$PLATFORM" in + macos) + printf " ${CYAN}Install via Xcode Command Line Tools:${NC}\n" + printf " xcode-select --install\n" + printf "\n" + printf " ${CYAN}Or via Homebrew:${NC}\n" + printf " brew install git\n" + ;; + linux|wsl) + printf " ${CYAN}Debian/Ubuntu:${NC}\n" + printf " sudo apt-get update && sudo apt-get install -y git\n" + printf "\n" + printf " ${CYAN}RHEL/CentOS/Fedora:${NC}\n" + printf " sudo dnf install git\n" + ;; + windows) + printf " ${CYAN}Download Git for Windows:${NC}\n" + printf " https://git-scm.com/download/win\n" + printf "\n" + printf " ${CYAN}Or via winget:${NC}\n" + printf " winget install Git.Git\n" + ;; + esac + ;; + esac +} + +# ---------- Main Script ---------- + +detect_platform + +# Banner +printf "\n" +printf "${BLUE}┌─────────────────────────────────────────────────────────────────┐${NC}\n" +printf "${BLUE}│${NC} ${BLUE}│${NC}\n" +printf "${BLUE}│${NC} ${BOLD}ShipSec Studio Installer${NC} ${BLUE}│${NC}\n" +printf "${BLUE}│${NC} Self-Hosted Production Deployment ${BLUE}│${NC}\n" +printf "${BLUE}│${NC} ${BLUE}│${NC}\n" +printf "${BLUE}└─────────────────────────────────────────────────────────────────┘${NC}\n" +printf "\n" +info "Platform: ${BOLD}$PLATFORM_NAME${NC}" +info "Documentation: https://docs.shipsec.ai" +printf "\n" + +# ---------- Check Prerequisites ---------- +log "Checking prerequisites" +printf "\n" +info "ShipSec Studio requires the following tools:" +info " - docker (container runtime)" +info " - just (command runner)" +info " - curl (HTTP client)" +info " - jq (JSON processor)" +info " - git (version control)" +printf "\n" + +MISSING_DEPS="" +ALL_OK=true + +# Check each dependency +for dep in docker just curl jq git; do + if command_exists "$dep"; then + case "$dep" in + docker) ver=$(docker --version 2>/dev/null | sed 's/Docker version //' | cut -d',' -f1) ;; + just) ver=$(just --version 2>/dev/null | head -1) ;; + curl) ver=$(curl --version 2>/dev/null | head -1 | awk '{print $2}') ;; + jq) ver=$(jq --version 2>/dev/null) ;; + git) ver=$(git --version 2>/dev/null | sed 's/git version //') ;; + esac + printf " ${GREEN}✓${NC} %-10s %s\n" "$dep" "$ver" + else + printf " ${RED}✗${NC} %-10s ${RED}not found${NC}\n" "$dep" + MISSING_DEPS="$MISSING_DEPS $dep" + ALL_OK=false + fi +done + +# If dependencies are missing, show installation instructions +if [ "$ALL_OK" = false ]; then + MISSING_DEPS="${MISSING_DEPS# }" # trim leading space + + printf "\n" + err "Missing required dependencies: ${BOLD}$MISSING_DEPS${NC}" + + for dep in $MISSING_DEPS; do + show_install_instructions "$dep" + done + + printf "\n" + info "After installing the missing dependencies, run this script again:" + printf "\n" + printf " curl -fsSL https://raw.githubusercontent.com/ShipSecAI/studio/main/install.sh | bash\n" + printf "\n" + exit 1 +fi + +printf "\n" +info "${GREEN}All prerequisites are installed!${NC}" + +# ---------- Check Docker Daemon ---------- +log "Checking Docker daemon" + +if ! docker info >/dev/null 2>&1; then + printf "\n" + warn "Docker daemon is not running." + printf "\n" + + case "$PLATFORM" in + macos) + info "Please start Docker Desktop from your Applications folder." + printf "\n" + + if [ -d "/Applications/Docker.app" ]; then + if ask_yes_no "Would you like to start Docker Desktop now?" "y"; then + printf "\n" + info "Starting Docker Desktop..." + open -g "/Applications/Docker.app" + + printf " Waiting for Docker to be ready" + start=$(date +%s) + while ! docker info >/dev/null 2>&1; do + now=$(date +%s) + elapsed=$((now - start)) + if [ "$elapsed" -ge "$WAIT_DOCKER_SEC" ]; then + printf "\n\n" + err "Docker did not start within ${WAIT_DOCKER_SEC} seconds." + err "Please start Docker Desktop manually and run this script again." + exit 1 + fi + printf "." + sleep 2 + done + printf " ${GREEN}ready!${NC}\n" + else + printf "\n" + info "Please start Docker Desktop and run this script again." + exit 1 + fi + else + err "Docker Desktop not found at /Applications/Docker.app" + info "Please install Docker Desktop from: https://www.docker.com/products/docker-desktop" + exit 1 + fi + ;; + linux) + info "To start Docker, run:" + printf "\n" + printf " sudo systemctl start docker\n" + printf "\n" + info "Then run this script again." + exit 1 + ;; + wsl) + info "To use Docker in WSL, you have two options:" + printf "\n" + info " 1. Start Docker Desktop for Windows (with WSL2 integration enabled)" + info " 2. Start the Docker service in WSL: sudo service docker start" + printf "\n" + info "Then run this script again." + exit 1 + ;; + windows) + info "Please start Docker Desktop for Windows." + printf "\n" + info "Then run this script again." + exit 1 + ;; + esac +fi + +printf "\n" +info "${GREEN}Docker daemon is running!${NC}" + +# ---------- Repository Setup ---------- +log "Setting up repository" + +IN_REPO=false + +# Check if already in the repo +if [ -d .git ] && [ -f justfile ]; then + IN_REPO=true + info "Already in ShipSec Studio repository." +# Check if repo exists in current directory +elif [ -d "$REPO_DIR" ] && [ -d "$REPO_DIR/.git" ] && [ -f "$REPO_DIR/justfile" ]; then + info "Found existing repository in ./$REPO_DIR" + cd "$REPO_DIR" || { err "Failed to enter directory"; exit 1; } + IN_REPO=true +fi + +if [ "$IN_REPO" = false ]; then + if [ -d "$REPO_DIR" ]; then + printf "\n" + warn "Directory '$REPO_DIR' already exists." + + if ask_yes_no "Do you want to use the existing directory?" "y"; then + cd "$REPO_DIR" || { err "Failed to enter directory"; exit 1; } + else + info "Please remove or rename the '$REPO_DIR' directory and run this script again." + exit 1 + fi + else + printf "\n" + info "Cloning repository from GitHub..." + printf "\n" + + if ! git clone "$REPO_URL" "$REPO_DIR"; then + err "Failed to clone repository" + exit 1 + fi + + cd "$REPO_DIR" || { err "Failed to enter directory"; exit 1; } + fi +fi + +PROJECT_ROOT="$(pwd)" +printf "\n" +info "Project directory: ${BOLD}$PROJECT_ROOT${NC}" + +# ---------- Confirm Installation ---------- +log "Ready to install" + +printf "\n" +info "This will:" +info " 1. Fetch the latest release version from GitHub" +info " 2. Pull pre-built Docker images from GHCR" +info " 3. Start the full stack (frontend, backend, worker, infrastructure)" +printf "\n" +info "The following services will be available:" +info " - Frontend: http://localhost:8090" +info " - Backend: http://localhost:3211" +info " - Temporal UI: http://localhost:8081" +printf "\n" + +if ! ask_yes_no "Do you want to proceed with the installation?" "y"; then + printf "\n" + info "Installation cancelled." + printf "\n" + info "To install later, run:" + printf "\n" + printf " cd %s && just prod start-latest\n" "$PROJECT_ROOT" + printf "\n" + exit 0 +fi + +# ---------- Start Installation ---------- +log "Installing ShipSec Studio" + +printf "\n" +if ! just prod start-latest; then + printf "\n" + err "Installation failed." + err "Please check the error messages above." + printf "\n" + info "For troubleshooting, visit: https://github.com/ShipSecAI/studio/issues" + exit 1 +fi + +# ---------- Success ---------- +printf "\n" +printf "${GREEN}┌─────────────────────────────────────────────────────────────────┐${NC}\n" +printf "${GREEN}│${NC} ${GREEN}│${NC}\n" +printf "${GREEN}│${NC} ${BOLD}Installation Complete!${NC} ${GREEN}│${NC}\n" +printf "${GREEN}│${NC} ${GREEN}│${NC}\n" +printf "${GREEN}│${NC} Open ShipSec Studio in your browser: ${GREEN}│${NC}\n" +printf "${GREEN}│${NC} ${GREEN}│${NC}\n" +printf "${GREEN}│${NC} ${BOLD}http://localhost:8090${NC} ${GREEN}│${NC}\n" +printf "${GREEN}│${NC} ${GREEN}│${NC}\n" +printf "${GREEN}└─────────────────────────────────────────────────────────────────┘${NC}\n" +printf "\n" +info "Useful commands:" +printf "\n" +printf " just prod status - Check service status\n" +printf " just prod logs - View logs\n" +printf " just prod stop - Stop all services\n" +printf " just prod clean - Remove all data\n" +printf "\n" +info "Documentation: https://docs.shipsec.ai" +info "Need help? https://github.com/ShipSecAI/studio/issues" +printf "\n" + +exit 0 From ec1bff3f64ba299c656f641d9947b6d816fa233a Mon Sep 17 00:00:00 2001 From: Krishna Mohan Date: Thu, 8 Jan 2026 01:30:14 +0530 Subject: [PATCH 2/6] fix(one-liner): fixed and updated the one liner for linux and docker installation. Signed-off-by: Krishna Mohan --- install.sh | 1006 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 938 insertions(+), 68 deletions(-) diff --git a/install.sh b/install.sh index 0f923905..ebb9c3ed 100644 --- a/install.sh +++ b/install.sh @@ -126,7 +126,744 @@ detect_platform() { esac } -# ---------- Dependency Installation Instructions ---------- +# ---------- Dependency Installation ---------- + +# Check if we can use sudo +can_sudo() { + if command_exists sudo; then + # Check if user can sudo without password or is root + if [ "$(id -u)" = "0" ] || sudo -n true 2>/dev/null; then + return 0 + fi + # In interactive mode, try to get sudo access + if [ -t 0 ]; then + info "Some operations require administrator privileges." + if sudo -v 2>/dev/null; then + return 0 + fi + fi + fi + return 1 +} + +# Check if current user is in docker group (for Linux/WSL) +check_docker_group() { + # Skip on macOS and Windows - they don't use docker group + if [ "$PLATFORM" = "macos" ] || [ "$PLATFORM" = "windows" ]; then + return 0 + fi + + # Root doesn't need docker group + if [ "$(id -u)" = "0" ]; then + return 0 + fi + + # Check if docker group exists and user is a member + if command_exists docker && getent group docker >/dev/null 2>&1; then + if ! groups 2>/dev/null | grep -qw docker; then + return 1 # User not in docker group + fi + fi + + return 0 +} + +# Install Docker - always asks for permission +install_docker() { + log "Installing Docker" + + printf "\n" + warn "Docker installation requires your permission." + printf "\n" + + case "$PLATFORM" in + macos) + info "On macOS, you can install Docker in two ways:" + printf "\n" + info " ${BOLD}Option 1: Docker Desktop${NC} (GUI app, easiest)" + info " ${BOLD}Option 2: Colima${NC} (CLI-only, lightweight)" + printf "\n" + + if ! ask_yes_no "Would you like to install Docker now?" "y"; then + info "Docker installation skipped." + show_install_instructions "docker" + return 1 + fi + + if command_exists brew; then + printf "\n" + info "Which Docker runtime would you prefer?" + printf "\n" + info " 1) Docker Desktop (GUI application)" + info " 2) Colima (CLI-only, runs in terminal)" + printf "\n" + + local choice="" + if [ -t 0 ]; then + printf " Enter choice [1/2]: " + read -r choice || choice="1" + else + choice="1" + fi + + case "$choice" in + 2) + info "Installing Colima and Docker CLI via Homebrew..." + printf "\n" + if brew install colima docker docker-compose; then + printf "\n" + info "${GREEN}Colima and Docker CLI installed successfully!${NC}" + info "Starting Colima..." + if colima start; then + info "${GREEN}Colima is running! Docker daemon is ready.${NC}" + return 0 + else + warn "Colima installed but failed to start. Try: colima start" + return 0 + fi + else + err "Failed to install Colima" + return 1 + fi + ;; + *) + info "Installing Docker Desktop via Homebrew..." + printf "\n" + if brew install --cask docker; then + printf "\n" + info "${GREEN}Docker Desktop installed successfully!${NC}" + return 0 + else + err "Failed to install Docker via Homebrew" + return 1 + fi + ;; + esac + else + printf "\n" + warn "Homebrew is not installed." + info "Please install Docker Desktop manually from:" + printf "\n" + printf " https://www.docker.com/products/docker-desktop\n" + printf "\n" + info "Or install Homebrew first:" + printf "\n" + printf " /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n" + printf "\n" + return 1 + fi + ;; + linux) + if ! ask_yes_no "Would you like to install Docker Engine now?" "y"; then + info "Docker installation skipped." + show_install_instructions "docker" + return 1 + fi + + if can_sudo; then + info "Installing Docker Engine via official script..." + printf "\n" + if curl -fsSL https://get.docker.com | sudo sh; then + printf "\n" + info "Adding current user to docker group..." + sudo usermod -aG docker "$USER" 2>/dev/null || true + printf "\n" + printf "${GREEN}┌─────────────────────────────────────────────────────────────────┐${NC}\n" + printf "${GREEN}│${NC} ${BOLD}🚨 Docker installed but requires logout/login${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} Your user has been added to the 'docker' group, but this ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} change won't take effect until you log out and back in. ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${BOLD}➡️ Please log out, log back in, then run:${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} curl -fsSL https://raw.githubusercontent.com/ShipSecAI/ ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} studio/main/install.sh | bash ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${GREEN}│${NC}\n" + printf "${GREEN}└─────────────────────────────────────────────────────────────────┘${NC}\n" + printf "\n" + info "Exiting now to avoid permission issues." + exit 0 + else + err "Failed to install Docker" + return 1 + fi + else + printf "\n" + err "Cannot install Docker without sudo access." + info "Please install Docker manually:" + printf "\n" + printf " curl -fsSL https://get.docker.com | sudo sh\n" + printf " sudo usermod -aG docker \$USER\n" + printf "\n" + return 1 + fi + ;; + wsl) + printf "\n" + info "For WSL, you have two options:" + printf "\n" + info " ${BOLD}Option 1: Docker Desktop for Windows (Recommended)${NC}" + info " - Install Docker Desktop from: https://www.docker.com/products/docker-desktop" + info " - Enable WSL2 integration in Docker Desktop Settings > Resources > WSL Integration" + printf "\n" + info " ${BOLD}Option 2: Docker Engine in WSL${NC}" + + if ! ask_yes_no "Would you like to install Docker Engine directly in WSL?" "y"; then + info "Docker installation skipped." + info "Please install Docker Desktop for Windows and enable WSL2 integration." + return 1 + fi + + if can_sudo; then + info "Installing Docker Engine..." + printf "\n" + if curl -fsSL https://get.docker.com | sudo sh; then + printf "\n" + info "Adding current user to docker group..." + sudo usermod -aG docker "$USER" 2>/dev/null || true + printf "\n" + printf "${GREEN}┌─────────────────────────────────────────────────────────────────┐${NC}\n" + printf "${GREEN}│${NC} ${BOLD}🚨 Docker installed but requires logout/login${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} Your user has been added to the 'docker' group, but this ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} change won't take effect until you log out and back in. ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${BOLD}➡️ Please log out, log back in, then run:${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} curl -fsSL https://raw.githubusercontent.com/ShipSecAI/ ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} studio/main/install.sh | bash ${GREEN}│${NC}\n" + printf "${GREEN}│${NC} ${GREEN}│${NC}\n" + printf "${GREEN}└─────────────────────────────────────────────────────────────────┘${NC}\n" + printf "\n" + info "Exiting now to avoid permission issues." + exit 0 + else + err "Failed to install Docker" + return 1 + fi + else + err "Cannot install Docker without sudo access." + return 1 + fi + ;; + windows) + printf "\n" + info "Docker Desktop for Windows is required." + printf "\n" + + if ! ask_yes_no "Would you like to install Docker Desktop now?" "y"; then + info "Docker installation skipped." + show_install_instructions "docker" + return 1 + fi + + if command_exists winget; then + info "Installing Docker Desktop via winget..." + printf "\n" + if winget install Docker.DockerDesktop --accept-source-agreements --accept-package-agreements; then + printf "\n" + info "${GREEN}Docker Desktop installed successfully!${NC}" + info "Please restart your terminal and run this script again." + return 0 + else + err "Failed to install Docker Desktop" + return 1 + fi + fi + + info "Please install Docker Desktop manually from:" + printf "\n" + printf " https://www.docker.com/products/docker-desktop\n" + printf "\n" + return 1 + ;; + *) + err "Automatic Docker installation not supported on this platform." + info "Please install Docker manually." + return 1 + ;; + esac +} + +# Install just automatically +install_just() { + log "Installing just" + + case "$PLATFORM" in + macos) + if command_exists brew; then + info "Installing just via Homebrew..." + if brew install just; then + info "${GREEN}just installed successfully!${NC}" + return 0 + else + err "Failed to install just" + return 1 + fi + else + warn "Homebrew is not installed. Installing just via script..." + mkdir -p ~/.local/bin + if curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin; then + export PATH="$HOME/.local/bin:$PATH" + info "${GREEN}just installed to ~/.local/bin${NC}" + warn "Add ~/.local/bin to your PATH permanently by adding this to your shell profile:" + printf " export PATH=\"\$HOME/.local/bin:\$PATH\"\n" + return 0 + else + err "Failed to install just" + return 1 + fi + fi + ;; + linux|wsl) + info "Installing just via official script..." + mkdir -p ~/.local/bin + if curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin; then + export PATH="$HOME/.local/bin:$PATH" + info "${GREEN}just installed to ~/.local/bin${NC}" + # Check if ~/.local/bin is in PATH + if ! echo "$PATH" | grep -q "$HOME/.local/bin"; then + warn "Add ~/.local/bin to your PATH permanently by adding this to your shell profile:" + printf " export PATH=\"\$HOME/.local/bin:\$PATH\"\n" + fi + return 0 + else + err "Failed to install just" + return 1 + fi + ;; + windows) + if command_exists scoop; then + info "Installing just via Scoop..." + if scoop install just; then + info "${GREEN}just installed successfully!${NC}" + return 0 + fi + elif command_exists choco; then + info "Installing just via Chocolatey..." + if choco install just -y; then + info "${GREEN}just installed successfully!${NC}" + return 0 + fi + fi + + err "Could not install just automatically." + info "Please install just manually from: https://github.com/casey/just/releases" + return 1 + ;; + *) + err "Automatic just installation not supported on this platform." + return 1 + ;; + esac +} + +# Install jq automatically +install_jq() { + log "Installing jq" + + case "$PLATFORM" in + macos) + if command_exists brew; then + info "Installing jq via Homebrew..." + if brew install jq; then + info "${GREEN}jq installed successfully!${NC}" + return 0 + fi + fi + err "Failed to install jq" + return 1 + ;; + linux|wsl) + if can_sudo; then + # Detect package manager + if command_exists apt-get; then + info "Installing jq via apt..." + if sudo apt-get update -qq && sudo apt-get install -y jq; then + info "${GREEN}jq installed successfully!${NC}" + return 0 + fi + elif command_exists dnf; then + info "Installing jq via dnf..." + if sudo dnf install -y jq; then + info "${GREEN}jq installed successfully!${NC}" + return 0 + fi + elif command_exists yum; then + info "Installing jq via yum..." + if sudo yum install -y jq; then + info "${GREEN}jq installed successfully!${NC}" + return 0 + fi + elif command_exists pacman; then + info "Installing jq via pacman..." + if sudo pacman -S --noconfirm jq; then + info "${GREEN}jq installed successfully!${NC}" + return 0 + fi + fi + fi + err "Failed to install jq" + return 1 + ;; + windows) + if command_exists scoop; then + info "Installing jq via Scoop..." + if scoop install jq; then + info "${GREEN}jq installed successfully!${NC}" + return 0 + fi + elif command_exists choco; then + info "Installing jq via Chocolatey..." + if choco install jq -y; then + info "${GREEN}jq installed successfully!${NC}" + return 0 + fi + fi + err "Failed to install jq" + return 1 + ;; + *) + err "Automatic jq installation not supported on this platform." + return 1 + ;; + esac +} + +# Install git automatically +install_git() { + log "Installing git" + + case "$PLATFORM" in + macos) + info "Installing git via Xcode Command Line Tools..." + if xcode-select --install 2>/dev/null; then + info "Please complete the Xcode Command Line Tools installation and run this script again." + return 1 + elif command_exists brew; then + info "Installing git via Homebrew..." + if brew install git; then + info "${GREEN}git installed successfully!${NC}" + return 0 + fi + fi + err "Failed to install git" + return 1 + ;; + linux|wsl) + if can_sudo; then + if command_exists apt-get; then + info "Installing git via apt..." + if sudo apt-get update -qq && sudo apt-get install -y git; then + info "${GREEN}git installed successfully!${NC}" + return 0 + fi + elif command_exists dnf; then + info "Installing git via dnf..." + if sudo dnf install -y git; then + info "${GREEN}git installed successfully!${NC}" + return 0 + fi + elif command_exists yum; then + info "Installing git via yum..." + if sudo yum install -y git; then + info "${GREEN}git installed successfully!${NC}" + return 0 + fi + elif command_exists pacman; then + info "Installing git via pacman..." + if sudo pacman -S --noconfirm git; then + info "${GREEN}git installed successfully!${NC}" + return 0 + fi + fi + fi + err "Failed to install git" + return 1 + ;; + windows) + if command_exists winget; then + info "Installing git via winget..." + if winget install Git.Git --accept-source-agreements --accept-package-agreements; then + info "${GREEN}git installed successfully!${NC}" + info "Please restart your terminal for git to be available." + return 0 + fi + fi + err "Failed to install git" + info "Please install git from: https://git-scm.com/download/win" + return 1 + ;; + *) + err "Automatic git installation not supported on this platform." + return 1 + ;; + esac +} + +# Install curl automatically +install_curl() { + log "Installing curl" + + case "$PLATFORM" in + macos) + # curl is pre-installed on macOS + if command_exists brew; then + info "Installing curl via Homebrew..." + if brew install curl; then + info "${GREEN}curl installed successfully!${NC}" + return 0 + fi + fi + err "Failed to install curl" + return 1 + ;; + linux|wsl) + if can_sudo; then + if command_exists apt-get; then + info "Installing curl via apt..." + if sudo apt-get update -qq && sudo apt-get install -y curl; then + info "${GREEN}curl installed successfully!${NC}" + return 0 + fi + elif command_exists dnf; then + info "Installing curl via dnf..." + if sudo dnf install -y curl; then + info "${GREEN}curl installed successfully!${NC}" + return 0 + fi + elif command_exists yum; then + info "Installing curl via yum..." + if sudo yum install -y curl; then + info "${GREEN}curl installed successfully!${NC}" + return 0 + fi + fi + fi + err "Failed to install curl" + return 1 + ;; + windows) + # curl is included in Windows 10+ and Git Bash + if command_exists choco; then + info "Installing curl via Chocolatey..." + if choco install curl -y; then + info "${GREEN}curl installed successfully!${NC}" + return 0 + fi + fi + err "Failed to install curl" + return 1 + ;; + *) + err "Automatic curl installation not supported on this platform." + return 1 + ;; + esac +} + +# Try to install a missing dependency +try_install_dep() { + local dep="$1" + + case "$dep" in + docker) install_docker ;; + just) install_just ;; + jq) install_jq ;; + git) install_git ;; + curl) install_curl ;; + *) return 1 ;; + esac +} + +# Start Docker daemon +start_docker_daemon() { + log "Starting Docker daemon" + + case "$PLATFORM" in + macos) + # Check for Colima first (CLI-based, can start from terminal) + if command_exists colima; then + info "Found Colima - starting Docker runtime from terminal..." + printf "\n" + + # Check if Colima is already running + if colima status 2>/dev/null | grep -q "Running"; then + info "${GREEN}Colima is already running!${NC}" + return 0 + fi + + info "Starting Colima..." + if colima start 2>&1; then + printf "\n" + # Wait for Docker to be ready + printf " Waiting for Docker to be ready" + local start=$(date +%s) + while ! docker info >/dev/null 2>&1; do + local now=$(date +%s) + local elapsed=$((now - start)) + if [ "$elapsed" -ge "$WAIT_DOCKER_SEC" ]; then + printf "\n\n" + err "Docker did not become ready within ${WAIT_DOCKER_SEC} seconds." + return 1 + fi + printf "." + sleep 2 + done + printf " ${GREEN}ready!${NC}\n" + return 0 + else + warn "Failed to start Colima, trying Docker Desktop..." + fi + fi + + # Try Docker Desktop + if [ -d "/Applications/Docker.app" ]; then + info "Starting Docker Desktop..." + open -g "/Applications/Docker.app" + + printf " Waiting for Docker to be ready" + local start=$(date +%s) + while ! docker info >/dev/null 2>&1; do + local now=$(date +%s) + local elapsed=$((now - start)) + if [ "$elapsed" -ge "$WAIT_DOCKER_SEC" ]; then + printf "\n\n" + err "Docker did not start within ${WAIT_DOCKER_SEC} seconds." + return 1 + fi + printf "." + sleep 2 + done + printf " ${GREEN}ready!${NC}\n" + return 0 + fi + + # Neither Colima nor Docker Desktop found + err "No Docker runtime found." + info "Please install Docker using one of these methods:" + printf "\n" + info " ${BOLD}Option 1: Colima (CLI-only, recommended for terminal users)${NC}" + printf " brew install colima docker docker-compose\n" + printf " colima start\n" + printf "\n" + info " ${BOLD}Option 2: Docker Desktop${NC}" + printf " brew install --cask docker\n" + printf "\n" + return 1 + ;; + linux) + if can_sudo; then + # Try systemctl first (systemd) - preferred method + if command_exists systemctl; then + info "Starting Docker via systemctl..." + if sudo systemctl start docker 2>/dev/null; then + # Wait for Docker to be ready (use sudo for docker info if needed) + printf " Waiting for Docker to be ready" + local start=$(date +%s) + while ! sudo docker info >/dev/null 2>&1; do + local now=$(date +%s) + local elapsed=$((now - start)) + if [ "$elapsed" -ge "$WAIT_DOCKER_SEC" ]; then + printf "\n\n" + err "Docker did not start within ${WAIT_DOCKER_SEC} seconds." + return 1 + fi + printf "." + sleep 2 + done + printf " ${GREEN}ready!${NC}\n" + + # Enable Docker to start on boot + sudo systemctl enable docker 2>/dev/null || true + return 0 + fi + fi + + # Try service command (SysVinit) - fallback for non-systemd systems + if command_exists service; then + info "Starting Docker via service command..." + if sudo service docker start 2>/dev/null; then + sleep 3 + if sudo docker info >/dev/null 2>&1; then + info "${GREEN}Docker daemon started!${NC}" + return 0 + fi + fi + fi + fi + + # No backgrounding dockerd - it's dangerous and conflicts with init systems + err "Failed to start Docker daemon." + info "Please start Docker manually using your system's init system:" + printf "\n" + printf " # For systemd (most modern Linux):\n" + printf " sudo systemctl start docker\n" + printf "\n" + printf " # For SysVinit:\n" + printf " sudo service docker start\n" + return 1 + ;; + wsl) + # In WSL, try service command + if can_sudo; then + if command_exists service; then + info "Starting Docker via service command..." + if sudo service docker start 2>/dev/null; then + sleep 3 + if sudo docker info >/dev/null 2>&1; then + info "${GREEN}Docker daemon started!${NC}" + return 0 + fi + fi + fi + fi + + # No backgrounding dockerd - it's dangerous + printf "\n" + warn "Could not start Docker daemon automatically in WSL." + info "Please use one of these options:" + printf "\n" + info " 1. Start Docker Desktop for Windows (with WSL2 integration enabled)" + info " 2. Start the Docker service manually: sudo service docker start" + return 1 + ;; + windows) + # On Windows (Git Bash), try to start Docker Desktop via cmd.exe + # This is more robust than hardcoding paths (handles non-C drives, localized Windows, etc.) + info "Attempting to start Docker Desktop..." + + if cmd.exe /c start "" "Docker Desktop" 2>/dev/null; then + printf " Waiting for Docker to be ready" + local start=$(date +%s) + while ! docker info >/dev/null 2>&1; do + local now=$(date +%s) + local elapsed=$((now - start)) + if [ "$elapsed" -ge "$WAIT_DOCKER_SEC" ]; then + printf "\n\n" + warn "Docker did not become ready within ${WAIT_DOCKER_SEC} seconds." + info "Docker Desktop may still be starting. Please wait and try again." + return 1 + fi + printf "." + sleep 2 + done + printf " ${GREEN}ready!${NC}\n" + return 0 + else + warn "Could not start Docker Desktop automatically." + info "Please start Docker Desktop manually from the Start menu." + return 1 + fi + ;; + *) + err "Cannot start Docker daemon on this platform automatically." + return 1 + ;; + esac +} + +# ---------- Dependency Installation Instructions (fallback) ---------- show_install_instructions() { local dep="$1" @@ -281,6 +1018,23 @@ info "Platform: ${BOLD}$PLATFORM_NAME${NC}" info "Documentation: https://docs.shipsec.ai" printf "\n" +# ---------- Early Check: Non-interactive mode without sudo ---------- +# In CI / curl | bash scenarios, fail early if we can't get sudo and might need it +if [ ! -t 0 ]; then + # Non-interactive mode - check if we have sudo access + if [ "$PLATFORM" = "linux" ] || [ "$PLATFORM" = "wsl" ]; then + if [ "$(id -u)" != "0" ] && ! sudo -n true 2>/dev/null; then + warn "Running in non-interactive mode without sudo access." + info "If dependencies need to be installed, the script will fail." + info "For unattended installation, either:" + info " - Run as root" + info " - Configure passwordless sudo" + info " - Pre-install all dependencies (docker, just, curl, jq, git)" + printf "\n" + fi + fi +fi + # ---------- Check Prerequisites ---------- log "Checking prerequisites" printf "\n" @@ -313,27 +1067,110 @@ for dep in docker just curl jq git; do fi done -# If dependencies are missing, show installation instructions +# If dependencies are missing, offer to install them if [ "$ALL_OK" = false ]; then MISSING_DEPS="${MISSING_DEPS# }" # trim leading space printf "\n" - err "Missing required dependencies: ${BOLD}$MISSING_DEPS${NC}" - - for dep in $MISSING_DEPS; do - show_install_instructions "$dep" - done - - printf "\n" - info "After installing the missing dependencies, run this script again:" + warn "Missing required dependencies: ${BOLD}$MISSING_DEPS${NC}" printf "\n" - printf " curl -fsSL https://raw.githubusercontent.com/ShipSecAI/studio/main/install.sh | bash\n" + + # Check if we're in interactive mode + if [ -t 0 ]; then + if ask_yes_no "Would you like to install the missing dependencies automatically?" "y"; then + INSTALL_FAILED="" + + for dep in $MISSING_DEPS; do + printf "\n" + if try_install_dep "$dep"; then + # Re-check if the command is now available + if command_exists "$dep"; then + printf " ${GREEN}✓${NC} $dep is now available\n" + else + # Some installations require PATH update or terminal restart + warn "$dep was installed but may require a terminal restart to be available." + INSTALL_FAILED="$INSTALL_FAILED $dep" + fi + else + INSTALL_FAILED="$INSTALL_FAILED $dep" + fi + done + + # Check if any installations failed + if [ -n "$INSTALL_FAILED" ]; then + INSTALL_FAILED="${INSTALL_FAILED# }" # trim leading space + printf "\n" + err "Could not install: ${BOLD}$INSTALL_FAILED${NC}" + printf "\n" + info "Please install these dependencies manually:" + + for dep in $INSTALL_FAILED; do + show_install_instructions "$dep" + done + + printf "\n" + info "After installing, run this script again:" + printf "\n" + printf " curl -fsSL https://raw.githubusercontent.com/ShipSecAI/studio/main/install.sh | bash\n" + printf "\n" + exit 1 + fi + + printf "\n" + info "${GREEN}All dependencies installed successfully!${NC}" + else + # User declined automatic installation + printf "\n" + info "Manual installation instructions:" + + for dep in $MISSING_DEPS; do + show_install_instructions "$dep" + done + + printf "\n" + info "After installing the missing dependencies, run this script again:" + printf "\n" + printf " curl -fsSL https://raw.githubusercontent.com/ShipSecAI/studio/main/install.sh | bash\n" + printf "\n" + exit 1 + fi + else + # Non-interactive mode - show instructions and exit + err "Missing required dependencies: ${BOLD}$MISSING_DEPS${NC}" + + for dep in $MISSING_DEPS; do + show_install_instructions "$dep" + done + + printf "\n" + info "After installing the missing dependencies, run this script again:" + printf "\n" + printf " curl -fsSL https://raw.githubusercontent.com/ShipSecAI/studio/main/install.sh | bash\n" + printf "\n" + exit 1 + fi +else printf "\n" - exit 1 + info "${GREEN}All prerequisites are installed!${NC}" fi -printf "\n" -info "${GREEN}All prerequisites are installed!${NC}" +# ---------- Check Docker Group Membership (Linux/WSL only) ---------- +if [ "$PLATFORM" = "linux" ] || [ "$PLATFORM" = "wsl" ]; then + if ! check_docker_group; then + printf "\n" + warn "You are not in the 'docker' group." + info "Docker group membership is required to run Docker commands without sudo." + printf "\n" + info "To fix this, run:" + printf "\n" + printf " sudo usermod -aG docker \$USER\n" + printf "\n" + info "Then ${BOLD}log out and log back in${NC} for the change to take effect." + info "After logging back in, run this script again." + printf "\n" + exit 1 + fi +fi # ---------- Check Docker Daemon ---------- log "Checking Docker daemon" @@ -343,72 +1180,105 @@ if ! docker info >/dev/null 2>&1; then warn "Docker daemon is not running." printf "\n" - case "$PLATFORM" in - macos) - info "Please start Docker Desktop from your Applications folder." + # Check if we're in interactive mode + if [ -t 0 ]; then + if ask_yes_no "Would you like to start Docker automatically?" "y"; then printf "\n" - - if [ -d "/Applications/Docker.app" ]; then - if ask_yes_no "Would you like to start Docker Desktop now?" "y"; then - printf "\n" - info "Starting Docker Desktop..." - open -g "/Applications/Docker.app" - - printf " Waiting for Docker to be ready" - start=$(date +%s) - while ! docker info >/dev/null 2>&1; do - now=$(date +%s) - elapsed=$((now - start)) - if [ "$elapsed" -ge "$WAIT_DOCKER_SEC" ]; then - printf "\n\n" - err "Docker did not start within ${WAIT_DOCKER_SEC} seconds." - err "Please start Docker Desktop manually and run this script again." - exit 1 - fi - printf "." - sleep 2 - done - printf " ${GREEN}ready!${NC}\n" - else - printf "\n" - info "Please start Docker Desktop and run this script again." - exit 1 - fi + if start_docker_daemon; then + printf "\n" + info "${GREEN}Docker daemon is now running!${NC}" else - err "Docker Desktop not found at /Applications/Docker.app" - info "Please install Docker Desktop from: https://www.docker.com/products/docker-desktop" + printf "\n" + err "Failed to start Docker daemon automatically." + printf "\n" + + case "$PLATFORM" in + macos) + info "Please start Docker Desktop from your Applications folder and run this script again." + ;; + linux) + info "Please start Docker manually:" + printf " sudo systemctl start docker\n" + printf "\n" + info "Then run this script again." + ;; + wsl) + info "To use Docker in WSL, you have two options:" + printf "\n" + info " 1. Start Docker Desktop for Windows (with WSL2 integration enabled)" + info " 2. Start the Docker service in WSL: sudo service docker start" + printf "\n" + info "Then run this script again." + ;; + windows) + info "Please start Docker Desktop for Windows and run this script again." + ;; + esac exit 1 fi - ;; - linux) - info "To start Docker, run:" - printf "\n" - printf " sudo systemctl start docker\n" + else printf "\n" - info "Then run this script again." + case "$PLATFORM" in + macos) + info "Please start Docker Desktop from your Applications folder and run this script again." + ;; + linux) + info "To start Docker, run:" + printf "\n" + printf " sudo systemctl start docker\n" + printf "\n" + info "Then run this script again." + ;; + wsl) + info "To use Docker in WSL, you have two options:" + printf "\n" + info " 1. Start Docker Desktop for Windows (with WSL2 integration enabled)" + info " 2. Start the Docker service in WSL: sudo service docker start" + printf "\n" + info "Then run this script again." + ;; + windows) + info "Please start Docker Desktop for Windows and run this script again." + ;; + esac exit 1 - ;; - wsl) - info "To use Docker in WSL, you have two options:" + fi + else + # Non-interactive mode - try to start automatically + printf "\n" + info "Attempting to start Docker daemon automatically..." + printf "\n" + + if start_docker_daemon; then printf "\n" - info " 1. Start Docker Desktop for Windows (with WSL2 integration enabled)" - info " 2. Start the Docker service in WSL: sudo service docker start" + info "${GREEN}Docker daemon is now running!${NC}" + else printf "\n" - info "Then run this script again." - exit 1 - ;; - windows) - info "Please start Docker Desktop for Windows." + err "Failed to start Docker daemon." printf "\n" - info "Then run this script again." + + case "$PLATFORM" in + macos) + info "Please start Docker Desktop and run this script again." + ;; + linux) + info "Please start Docker manually: sudo systemctl start docker" + ;; + wsl) + info "Please start Docker Desktop for Windows or run: sudo service docker start" + ;; + windows) + info "Please start Docker Desktop for Windows." + ;; + esac exit 1 - ;; - esac + fi + fi +else + printf "\n" + info "${GREEN}Docker daemon is running!${NC}" fi -printf "\n" -info "${GREEN}Docker daemon is running!${NC}" - # ---------- Repository Setup ---------- log "Setting up repository" From 754333d24f96534231aab9ea20908c923dc0d38f Mon Sep 17 00:00:00 2001 From: Krishna Mohan Date: Thu, 8 Jan 2026 01:37:44 +0530 Subject: [PATCH 3/6] fix: added better production worthy script Signed-off-by: Krishna Mohan --- install.sh | 94 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/install.sh b/install.sh index ebb9c3ed..d0491769 100644 --- a/install.sh +++ b/install.sh @@ -180,8 +180,8 @@ install_docker() { macos) info "On macOS, you can install Docker in two ways:" printf "\n" - info " ${BOLD}Option 1: Docker Desktop${NC} (GUI app, easiest)" - info " ${BOLD}Option 2: Colima${NC} (CLI-only, lightweight)" + info " ${BOLD} Option 1: Docker Desktop${NC} (GUI app, easiest)" + info " ${BOLD} Option 2: Colima${NC} (CLI-only, lightweight)" printf "\n" if ! ask_yes_no "Would you like to install Docker now?" "y"; then @@ -302,11 +302,11 @@ install_docker() { printf "\n" info "For WSL, you have two options:" printf "\n" - info " ${BOLD}Option 1: Docker Desktop for Windows (Recommended)${NC}" + info " ${BOLD} Option 1: Docker Desktop for Windows (Recommended)${NC}" info " - Install Docker Desktop from: https://www.docker.com/products/docker-desktop" info " - Enable WSL2 integration in Docker Desktop Settings > Resources > WSL Integration" printf "\n" - info " ${BOLD}Option 2: Docker Engine in WSL${NC}" + info " ${BOLD} Option 2: Docker Engine in WSL${NC}" if ! ask_yes_no "Would you like to install Docker Engine directly in WSL?" "y"; then info "Docker installation skipped." @@ -717,10 +717,17 @@ start_docker_daemon() { fi fi - # Try Docker Desktop + # Try Docker Desktop - check multiple possible locations + local docker_app="" if [ -d "/Applications/Docker.app" ]; then + docker_app="/Applications/Docker.app" + elif [ -d "$HOME/Applications/Docker.app" ]; then + docker_app="$HOME/Applications/Docker.app" + fi + + if [ -n "$docker_app" ]; then info "Starting Docker Desktop..." - open -g "/Applications/Docker.app" + open -g "$docker_app" printf " Waiting for Docker to be ready" local start=$(date +%s) @@ -730,6 +737,9 @@ start_docker_daemon() { if [ "$elapsed" -ge "$WAIT_DOCKER_SEC" ]; then printf "\n\n" err "Docker did not start within ${WAIT_DOCKER_SEC} seconds." + info "Docker Desktop may need to complete first-time setup." + info "Please open Docker Desktop manually from Applications, complete the setup," + info "then run this script again." return 1 fi printf "." @@ -739,16 +749,36 @@ start_docker_daemon() { return 0 fi - # Neither Colima nor Docker Desktop found - err "No Docker runtime found." + # Docker CLI exists but no runtime - user probably installed just 'docker' via brew + if command_exists docker; then + printf "\n" + warn "Docker CLI is installed, but no Docker runtime is running." + info "The 'docker' command needs a runtime (Docker Desktop or Colima) to work." + printf "\n" + info "Please choose one of these options:" + printf "\n" + info " ${BOLD} Option 1: Install & start Colima (CLI-only, lightweight)${NC}" + printf " brew install colima docker-compose\n" + printf " colima start\n" + printf "\n" + info " ${BOLD} Option 2: Install & open Docker Desktop${NC}" + printf " brew install --cask docker\n" + printf " # Then open Docker Desktop from Applications\n" + printf "\n" + return 1 + fi + + # Neither Colima nor Docker Desktop found, and no docker CLI + err "No Docker installation found." info "Please install Docker using one of these methods:" printf "\n" - info " ${BOLD}Option 1: Colima (CLI-only, recommended for terminal users)${NC}" + info " ${BOLD} Option 1: Colima (CLI-only, recommended for terminal users)${NC}" printf " brew install colima docker docker-compose\n" printf " colima start\n" printf "\n" - info " ${BOLD}Option 2: Docker Desktop${NC}" + info " ${BOLD} Option 2: Docker Desktop${NC}" printf " brew install --cask docker\n" + printf " # Then open Docker Desktop from Applications\n" printf "\n" return 1 ;; @@ -875,24 +905,24 @@ show_install_instructions() { docker) case "$PLATFORM" in macos) - printf " ${CYAN}Option 1: Download Docker Desktop${NC}\n" + printf " ${CYAN} Option 1: Download Docker Desktop${NC}\n" printf " https://www.docker.com/products/docker-desktop\n" printf "\n" - printf " ${CYAN}Option 2: Install via Homebrew${NC}\n" + printf " ${CYAN} Option 2: Install via Homebrew${NC}\n" printf " brew install --cask docker\n" ;; linux) - printf " ${CYAN}Install Docker Engine:${NC}\n" + printf " ${CYAN} Install Docker Engine:${NC}\n" printf " curl -fsSL https://get.docker.com | sudo sh\n" printf " sudo usermod -aG docker \$USER\n" printf " # Log out and back in for group changes to take effect\n" ;; wsl) - printf " ${CYAN}Option 1: Use Docker Desktop for Windows${NC}\n" + printf " ${CYAN} Option 1: Use Docker Desktop for Windows${NC}\n" printf " Install Docker Desktop and enable WSL2 integration in Settings\n" printf " https://www.docker.com/products/docker-desktop\n" printf "\n" - printf " ${CYAN}Option 2: Install Docker Engine in WSL${NC}\n" + printf " ${CYAN} Option 2: Install Docker Engine in WSL${NC}\n" printf " curl -fsSL https://get.docker.com | sudo sh\n" printf " sudo usermod -aG docker \$USER\n" ;; @@ -908,26 +938,26 @@ show_install_instructions() { just) case "$PLATFORM" in macos) - printf " ${CYAN}Install via Homebrew:${NC}\n" + printf " ${CYAN} Install via Homebrew:${NC}\n" printf " brew install just\n" ;; linux|wsl) - printf " ${CYAN}Option 1: Install via script${NC}\n" + printf " ${CYAN} Option 1: Install via script${NC}\n" printf " curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin\n" printf " # Add ~/.local/bin to your PATH if not already\n" printf "\n" - printf " ${CYAN}Option 2: Install via package manager${NC}\n" + printf " ${CYAN} Option 2: Install via package manager${NC}\n" printf " # Debian/Ubuntu (if available)\n" printf " sudo apt install just\n" ;; windows) - printf " ${CYAN}Option 1: Install via Scoop${NC}\n" + printf " ${CYAN} Option 1: Install via Scoop${NC}\n" printf " scoop install just\n" printf "\n" - printf " ${CYAN}Option 2: Install via Chocolatey${NC}\n" + printf " ${CYAN} Option 2: Install via Chocolatey${NC}\n" printf " choco install just\n" printf "\n" - printf " ${CYAN}Option 3: Download from GitHub${NC}\n" + printf " ${CYAN} Option 3: Download from GitHub${NC}\n" printf " https://github.com/casey/just/releases\n" ;; esac @@ -954,21 +984,21 @@ show_install_instructions() { jq) case "$PLATFORM" in macos) - printf " ${CYAN}Install via Homebrew:${NC}\n" + printf " ${CYAN} Install via Homebrew:${NC}\n" printf " brew install jq\n" ;; linux|wsl) - printf " ${CYAN}Debian/Ubuntu:${NC}\n" + printf " ${CYAN} Debian/Ubuntu:${NC}\n" printf " sudo apt-get update && sudo apt-get install -y jq\n" printf "\n" - printf " ${CYAN}RHEL/CentOS/Fedora:${NC}\n" + printf " ${CYAN} RHEL/CentOS/Fedora:${NC}\n" printf " sudo dnf install jq\n" ;; windows) - printf " ${CYAN}Option 1: Install via Scoop${NC}\n" + printf " ${CYAN} Option 1: Install via Scoop${NC}\n" printf " scoop install jq\n" printf "\n" - printf " ${CYAN}Option 2: Install via Chocolatey${NC}\n" + printf " ${CYAN} Option 2: Install via Chocolatey${NC}\n" printf " choco install jq\n" ;; esac @@ -976,24 +1006,24 @@ show_install_instructions() { git) case "$PLATFORM" in macos) - printf " ${CYAN}Install via Xcode Command Line Tools:${NC}\n" + printf " ${CYAN} Install via Xcode Command Line Tools:${NC}\n" printf " xcode-select --install\n" printf "\n" - printf " ${CYAN}Or via Homebrew:${NC}\n" + printf " ${CYAN} Or via Homebrew:${NC}\n" printf " brew install git\n" ;; linux|wsl) - printf " ${CYAN}Debian/Ubuntu:${NC}\n" + printf " ${CYAN} Debian/Ubuntu:${NC}\n" printf " sudo apt-get update && sudo apt-get install -y git\n" printf "\n" - printf " ${CYAN}RHEL/CentOS/Fedora:${NC}\n" + printf " ${CYAN} RHEL/CentOS/Fedora:${NC}\n" printf " sudo dnf install git\n" ;; windows) - printf " ${CYAN}Download Git for Windows:${NC}\n" + printf " ${CYAN} Download Git for Windows:${NC}\n" printf " https://git-scm.com/download/win\n" printf "\n" - printf " ${CYAN}Or via winget:${NC}\n" + printf " ${CYAN} Or via winget:${NC}\n" printf " winget install Git.Git\n" ;; esac From b9fba1daccf7aad396e2b58d99c2ca3409063c28 Mon Sep 17 00:00:00 2001 From: Krishna Mohan Date: Fri, 9 Jan 2026 13:39:04 +0530 Subject: [PATCH 4/6] refactor: added details about one liner in readme Signed-off-by: Krishna Mohan --- README.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2f898a7a..3f4b260a 100644 --- a/README.md +++ b/README.md @@ -65,13 +65,30 @@ Get started with ShipSec Studio in minutes: The easiest way to run ShipSec Studio on your own infrastructure: -#### Prerequisites +#### One-Line Install + +```bash +curl -fsSL https://raw.githubusercontent.com/ShipSecAI/studio/main/install.sh | bash +``` + +This installer will: +- Check and install missing dependencies (docker, just, curl, jq, git) +- Start Docker if not running +- Clone the repository and start all services +- Guide you through any required setup steps + +Once complete, visit **http://localhost:8090** to access ShipSec Studio. + +#### Manual Installation + +If you prefer to install manually: +**Prerequisites:** - **[docker](https://www.docker.com/)** - For running the application and security components - **[just](https://github.com/casey/just)** - Command runner for simplified workflows - **curl** and **jq** - For fetching release information -#### Quick Start +**Steps:** ```bash # Clone the repository From e0e864e6f9efab84b068e73a55a6df35726c307b Mon Sep 17 00:00:00 2001 From: Krishna Mohan Date: Fri, 9 Jan 2026 15:33:25 +0530 Subject: [PATCH 5/6] fix: the linux version of one liner Signed-off-by: Krishna Mohan --- install.sh | 56 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/install.sh b/install.sh index d0491769..014a27ac 100644 --- a/install.sh +++ b/install.sh @@ -10,7 +10,8 @@ # Supported platforms: macOS, Linux, Windows (Git Bash/MSYS2/WSL) set -u -o pipefail -IFS=$'\n\t' +# Note: We intentionally keep the default IFS (space, tab, newline) +# because we use space-separated lists for MISSING_DEPS and INSTALL_FAILED # ---------- Config ---------- REPO_URL="https://github.com/ShipSecAI/studio" @@ -40,10 +41,11 @@ setup_colors() { setup_colors # ---------- Logging ---------- +# Note: Using %b to interpret escape sequences in the argument log() { printf "\n${GREEN}==>${NC} ${BOLD}%s${NC}\n" "$1"; } -info() { printf " %s\n" "$1"; } -warn() { printf " ${YELLOW}Warning:${NC} %s\n" "$1"; } -err() { printf " ${RED}Error:${NC} %s\n" "$1"; } +info() { printf " %b\n" "$1"; } +warn() { printf " ${YELLOW}Warning:${NC} %b\n" "$1"; } +err() { printf " ${RED}Error:${NC} %b\n" "$1"; } # ---------- Traps ---------- on_err() { @@ -64,7 +66,18 @@ trap 'on_int' INT # ---------- Utility ---------- command_exists() { command -v "$1" >/dev/null 2>&1; } +# Check if we can interact with user (even when piped via curl | bash) +is_interactive() { + # stdin is a terminal + [ -t 0 ] && return 0 + # stdin is piped but /dev/tty exists (curl | bash scenario) + [ -e /dev/tty ] && return 0 + # Truly non-interactive + return 1 +} + # Cross-platform user input +# Uses /dev/tty to allow prompts even when script is piped (curl | bash) ask_yes_no() { local prompt="$1" local default="${2:-n}" @@ -76,8 +89,15 @@ ask_yes_no() { yn_hint="[y/N]" fi - # Non-interactive mode (piped input) - if [ ! -t 0 ]; then + # Check if we can read from /dev/tty (works even when script is piped) + if [ -t 0 ]; then + # stdin is a terminal + : + elif [ -e /dev/tty ]; then + # stdin is piped but /dev/tty exists - we can still prompt + exec < /dev/tty + else + # Truly non-interactive (no terminal available) case "$default" in y|Y) return 0 ;; *) return 1 ;; @@ -135,10 +155,10 @@ can_sudo() { if [ "$(id -u)" = "0" ] || sudo -n true 2>/dev/null; then return 0 fi - # In interactive mode, try to get sudo access - if [ -t 0 ]; then + # In interactive mode, try to get sudo access (let user see password prompt) + if is_interactive; then info "Some operations require administrator privileges." - if sudo -v 2>/dev/null; then + if sudo -v; then return 0 fi fi @@ -199,7 +219,7 @@ install_docker() { printf "\n" local choice="" - if [ -t 0 ]; then + if is_interactive; then printf " Enter choice [1/2]: " read -r choice || choice="1" else @@ -1048,10 +1068,10 @@ info "Platform: ${BOLD}$PLATFORM_NAME${NC}" info "Documentation: https://docs.shipsec.ai" printf "\n" -# ---------- Early Check: Non-interactive mode without sudo ---------- -# In CI / curl | bash scenarios, fail early if we can't get sudo and might need it -if [ ! -t 0 ]; then - # Non-interactive mode - check if we have sudo access +# ---------- Early Check: Truly non-interactive mode without sudo ---------- +# Only warn if we truly can't interact (no /dev/tty available) +if ! is_interactive; then + # Truly non-interactive mode - check if we have sudo access if [ "$PLATFORM" = "linux" ] || [ "$PLATFORM" = "wsl" ]; then if [ "$(id -u)" != "0" ] && ! sudo -n true 2>/dev/null; then warn "Running in non-interactive mode without sudo access." @@ -1105,8 +1125,8 @@ if [ "$ALL_OK" = false ]; then warn "Missing required dependencies: ${BOLD}$MISSING_DEPS${NC}" printf "\n" - # Check if we're in interactive mode - if [ -t 0 ]; then + # Check if we can interact with user (works even with curl | bash) + if is_interactive; then if ask_yes_no "Would you like to install the missing dependencies automatically?" "y"; then INSTALL_FAILED="" @@ -1210,8 +1230,8 @@ if ! docker info >/dev/null 2>&1; then warn "Docker daemon is not running." printf "\n" - # Check if we're in interactive mode - if [ -t 0 ]; then + # Check if we can interact with user (works even with curl | bash) + if is_interactive; then if ask_yes_no "Would you like to start Docker automatically?" "y"; then printf "\n" if start_docker_daemon; then From 2763114e2c2c864457df76b9b7598599337a8416 Mon Sep 17 00:00:00 2001 From: Krishna Mohan Date: Fri, 9 Jan 2026 23:51:34 +0530 Subject: [PATCH 6/6] fix(install.sh): fixed the conflict and also made it more interactive and fixed few color and docker deamon issues in linux Signed-off-by: Krishna Mohan --- install.sh | 107 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 98 insertions(+), 9 deletions(-) diff --git a/install.sh b/install.sh index 014a27ac..af05357f 100644 --- a/install.sh +++ b/install.sh @@ -423,7 +423,8 @@ install_just() { else warn "Homebrew is not installed. Installing just via script..." mkdir -p ~/.local/bin - if curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin; then + # Use --force to overwrite if already exists + if curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin --force; then export PATH="$HOME/.local/bin:$PATH" info "${GREEN}just installed to ~/.local/bin${NC}" warn "Add ~/.local/bin to your PATH permanently by adding this to your shell profile:" @@ -438,11 +439,31 @@ install_just() { linux|wsl) info "Installing just via official script..." mkdir -p ~/.local/bin - if curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin; then + # Use --force to overwrite if already exists + if curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin --force; then + # Add to PATH for current session export PATH="$HOME/.local/bin:$PATH" info "${GREEN}just installed to ~/.local/bin${NC}" - # Check if ~/.local/bin is in PATH - if ! echo "$PATH" | grep -q "$HOME/.local/bin"; then + + # Check if ~/.local/bin is already in shell profile + local shell_profile="" + if [ -n "${BASH_VERSION:-}" ]; then + shell_profile="$HOME/.bashrc" + elif [ -n "${ZSH_VERSION:-}" ]; then + shell_profile="$HOME/.zshrc" + elif [ -f "$HOME/.bashrc" ]; then + shell_profile="$HOME/.bashrc" + elif [ -f "$HOME/.profile" ]; then + shell_profile="$HOME/.profile" + fi + + # Add to shell profile if not already there + if [ -n "$shell_profile" ] && [ -f "$shell_profile" ]; then + if ! grep -q '\.local/bin' "$shell_profile" 2>/dev/null; then + printf '\n# Added by ShipSec Studio installer\nexport PATH="$HOME/.local/bin:$PATH"\n' >> "$shell_profile" + info "Added ~/.local/bin to PATH in $shell_profile" + fi + else warn "Add ~/.local/bin to your PATH permanently by adding this to your shell profile:" printf " export PATH=\"\$HOME/.local/bin:\$PATH\"\n" fi @@ -775,13 +796,81 @@ start_docker_daemon() { warn "Docker CLI is installed, but no Docker runtime is running." info "The 'docker' command needs a runtime (Docker Desktop or Colima) to work." printf "\n" - info "Please choose one of these options:" + + if is_interactive && command_exists brew; then + info "Would you like to install a Docker runtime now?" + printf "\n" + info " 1) Colima (CLI-only, lightweight, recommended)" + info " 2) Docker Desktop (GUI application)" + info " 3) Skip (I'll install manually)" + printf "\n" + + printf " Enter choice [1/2/3]: " + local choice="" + read -r choice || choice="3" + + case "$choice" in + 1) + info "Installing Colima..." + printf "\n" + if brew install colima docker-compose; then + info "${GREEN}Colima installed!${NC}" + info "Starting Colima..." + if colima start; then + info "${GREEN}Colima is running! Docker daemon is ready.${NC}" + return 0 + else + err "Failed to start Colima. Try running: colima start" + return 1 + fi + else + err "Failed to install Colima" + return 1 + fi + ;; + 2) + info "Installing Docker Desktop..." + printf "\n" + if brew install --cask docker; then + info "${GREEN}Docker Desktop installed!${NC}" + info "Starting Docker Desktop..." + open -g "/Applications/Docker.app" + + printf " Waiting for Docker to be ready" + local start=$(date +%s) + while ! docker info >/dev/null 2>&1; do + local now=$(date +%s) + local elapsed=$((now - start)) + if [ "$elapsed" -ge "$WAIT_DOCKER_SEC" ]; then + printf "\n\n" + warn "Docker Desktop is taking a while to start." + info "Please wait for Docker Desktop to finish starting, then run this script again." + return 1 + fi + printf "." + sleep 2 + done + printf " ${GREEN}ready!${NC}\n" + return 0 + else + err "Failed to install Docker Desktop" + return 1 + fi + ;; + *) + info "Skipping Docker runtime installation." + ;; + esac + fi + + printf "\n" + info "Please install a Docker runtime manually:" printf "\n" - info " ${BOLD} Option 1: Install & start Colima (CLI-only, lightweight)${NC}" + info " ${BOLD}Option 1: Colima (CLI-only, lightweight)${NC}" printf " brew install colima docker-compose\n" printf " colima start\n" printf "\n" - info " ${BOLD} Option 2: Install & open Docker Desktop${NC}" + info " ${BOLD}Option 2: Docker Desktop${NC}" printf " brew install --cask docker\n" printf " # Then open Docker Desktop from Applications\n" printf "\n" @@ -1099,8 +1188,8 @@ printf "\n" MISSING_DEPS="" ALL_OK=true -# Check each dependency -for dep in docker just curl jq git; do +# Check each dependency (docker last since it may require logout/login on Linux) +for dep in just curl jq git docker; do if command_exists "$dep"; then case "$dep" in docker) ver=$(docker --version 2>/dev/null | sed 's/Docker version //' | cut -d',' -f1) ;;