shepherd-launcher/scripts/lib/common.sh
2026-01-01 13:48:17 -05:00

193 lines
4.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# Common utilities for shepherd scripts
# Logging, error handling, and sudo helpers
set -euo pipefail
# Colors for terminal output (disabled if not a tty)
if [[ -t 1 ]]; then
RED='\033[0;31m'
YELLOW='\033[0;33m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
else
RED=''
YELLOW=''
GREEN=''
BLUE=''
NC=''
fi
# Logging functions
info() {
echo -e "${BLUE}[INFO]${NC} $*" >&2
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $*" >&2
}
error() {
echo -e "${RED}[ERROR]${NC} $*" >&2
}
success() {
echo -e "${GREEN}[OK]${NC} $*" >&2
}
die() {
error "$@"
exit 1
}
# Check if running as root
is_root() {
[[ $EUID -eq 0 ]]
}
# Require root or exit
require_root() {
if ! is_root; then
die "This command must be run as root (use sudo)"
fi
}
# Run a command with sudo if not already root
maybe_sudo() {
if is_root; then
"$@"
else
sudo "$@"
fi
}
# Check if a command exists
command_exists() {
command -v "$1" &>/dev/null
}
# Require a command or exit with helpful message
require_command() {
local cmd="$1"
local pkg="${2:-$1}"
if ! command_exists "$cmd"; then
die "Required command '$cmd' not found. Install it with: apt install $pkg"
fi
}
# Get the repository root directory
get_repo_root() {
local script_dir
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
(cd "$script_dir/../.." && pwd)
}
# Verify we're in the shepherd repository
verify_repo() {
local repo_root
repo_root="$(get_repo_root)"
if [[ ! -f "$repo_root/Cargo.toml" ]]; then
die "Not in shepherd repository (Cargo.toml not found at $repo_root)"
fi
# Check it's the right project
if ! grep -q 'shepherd-launcher-ui' "$repo_root/Cargo.toml" 2>/dev/null; then
die "This doesn't appear to be the shepherd-launcher repository"
fi
}
# Check Ubuntu version and warn if not supported
check_ubuntu_version() {
local min_version="${1:-25.10}"
if [[ ! -f /etc/os-release ]]; then
warn "Cannot determine OS version (not Linux or missing /etc/os-release)"
return 0
fi
# shellcheck source=/dev/null
source /etc/os-release
if [[ "${ID:-}" != "ubuntu" ]]; then
warn "This system is not Ubuntu (detected: ${ID:-unknown}). Some features may not work."
return 0
fi
local version="${VERSION_ID:-0}"
if [[ "$(printf '%s\n' "$min_version" "$version" | sort -V | head -n1)" != "$min_version" ]]; then
warn "Ubuntu version $version detected. Recommended: $min_version or higher."
fi
}
# Safe file backup - creates timestamped backup
backup_file() {
local file="$1"
local backup_dir="${2:-}"
if [[ ! -e "$file" ]]; then
return 0
fi
local timestamp
timestamp="$(date +%Y%m%d_%H%M%S)"
local backup_name
if [[ -n "$backup_dir" ]]; then
mkdir -p "$backup_dir"
backup_name="$backup_dir/$(basename "$file").$timestamp"
else
backup_name="$file.$timestamp.bak"
fi
cp -a "$file" "$backup_name"
echo "$backup_name"
}
# Create directory with proper permissions
ensure_dir() {
local dir="$1"
local mode="${2:-0755}"
local owner="${3:-}"
if [[ ! -d "$dir" ]]; then
mkdir -p "$dir"
chmod "$mode" "$dir"
if [[ -n "$owner" ]]; then
chown "$owner" "$dir"
fi
fi
}
# Validate username exists
validate_user() {
local user="$1"
if ! id "$user" &>/dev/null; then
die "User '$user' does not exist"
fi
}
# Get user's home directory
get_user_home() {
local user="$1"
getent passwd "$user" | cut -d: -f6
}
# Kill processes matching a pattern (silent if none found)
kill_matching() {
local pattern="$1"
pkill -f "$pattern" 2>/dev/null || true
}
# Wait for a file/socket to appear
wait_for_file() {
local file="$1"
local timeout="${2:-30}"
local elapsed=0
while [[ ! -e "$file" ]] && [[ $elapsed -lt $timeout ]]; do
sleep 0.5
elapsed=$((elapsed + 1))
done
[[ -e "$file" ]]
}