mirror of
https://github.com/soulis-1256/assemblrr.git
synced 2026-08-29 17:41:40 +00:00
Quiet setup copies and install CLI early for abort/uninstall
Per-file copy noise goes to the setup log only. Bootstrap the install tree and operator CLI as soon as the path is known so users can run uninstall after mid-setup abort; improve CLI discovery and partial-tree uninstall resilience.
This commit is contained in:
parent
0858a5a629
commit
fd4e7f33e1
2 changed files with 71 additions and 33 deletions
25
bin/cli.sh
25
bin/cli.sh
|
|
@ -44,15 +44,28 @@ if [ -z "$INSTALL_DIR" ]; then
|
|||
log_error "Could not find ${APP_NAME:-assemblrr} installation. Run setup first."
|
||||
fi
|
||||
|
||||
# Source runtime config
|
||||
safe_source "$INSTALL_DIR/.assemblrr-config"
|
||||
# Source runtime config (may be partial during mid-setup abort)
|
||||
if [ -f "$INSTALL_DIR/.assemblrr-config" ]; then
|
||||
safe_source "$INSTALL_DIR/.assemblrr-config"
|
||||
elif [ -f "$INSTALL_DIR/.${APP_NAME:-assemblrr}-config" ]; then
|
||||
safe_source "$INSTALL_DIR/.${APP_NAME:-assemblrr}-config"
|
||||
fi
|
||||
VPN_ENABLED="${VPN_ENABLED:-n}"
|
||||
MEDIA_SERVICE="${MEDIA_SERVICE:-jellyfin}"
|
||||
MEDIA_DIRECTORY="${MEDIA_DIRECTORY:-${HOME}/assemblrr-media}"
|
||||
|
||||
# Source branding from install directory
|
||||
load_branding "$INSTALL_DIR"
|
||||
load_branding "$INSTALL_DIR" 2>/dev/null || true
|
||||
|
||||
# Build compose command dynamically (uses lib/compose.sh build_compose_args + adds profile)
|
||||
build_compose_args "$INSTALL_DIR" "${VPN_ENABLED:-n}"
|
||||
DC=(run_docker compose "${COMPOSE_ARGS[@]}" "--profile" "${MEDIA_SERVICE:-jellyfin}")
|
||||
if [ -f "$INSTALL_DIR/compose/base.yaml" ]; then
|
||||
build_compose_args "$INSTALL_DIR" "${VPN_ENABLED:-n}"
|
||||
DC=(run_docker compose "${COMPOSE_ARGS[@]}" "--profile" "${MEDIA_SERVICE:-jellyfin}")
|
||||
else
|
||||
# Mid-setup / incomplete tree — uninstall can still remove dirs and CLI
|
||||
DC=(run_docker compose)
|
||||
COMPOSE_ARGS=()
|
||||
fi
|
||||
readonly TIMEOUT_SECONDS=60
|
||||
readonly IP_ENDPOINTS=(
|
||||
"https://ipinfo.io/ip"
|
||||
|
|
@ -408,6 +421,8 @@ uninstall_app() {
|
|||
# Setup writes this cheat-sheet under $HOME (outside the install dir)
|
||||
# Legacy setup wrote ~/assemblrr_services.txt — remove if present
|
||||
rm -f "$HOME/assemblrr_services.txt" 2>/dev/null || true
|
||||
# Install discovery pointer (may live outside the install dir)
|
||||
rm -f "$HOME/.assemblrr-config" "$HOME/.${APP_NAME:-assemblrr}-config" 2>/dev/null || true
|
||||
|
||||
log_success "${APP_DISPLAY_NAME} has been uninstalled!"
|
||||
log_info "Docker images were left on disk — see docs/uninstall.md to remove them."
|
||||
|
|
|
|||
79
bin/setup.sh
79
bin/setup.sh
|
|
@ -265,6 +265,8 @@ copy_configuration_files() {
|
|||
["docs/seerr-delete-request.md"]="docs/seerr-delete-request.md"
|
||||
)
|
||||
|
||||
local copied=0
|
||||
log_debug "Copying install tree into $install_directory"
|
||||
for src in "${!files[@]}"; do
|
||||
local dest="$install_directory/${files[$src]}"
|
||||
local dest_dir
|
||||
|
|
@ -277,30 +279,31 @@ copy_configuration_files() {
|
|||
|
||||
if ! src_path=$(resolve_project_file "$src"); then
|
||||
if [ "$src" = "compose/examples/custom.yaml.example" ]; then
|
||||
log_warning "Optional example file not found: $src"
|
||||
log_debug "Optional example file not found: $src"
|
||||
continue
|
||||
fi
|
||||
log_error "Failed to locate source file: $src"
|
||||
fi
|
||||
|
||||
log_info "Copying $src to $dest..."
|
||||
log_debug " $src -> $dest"
|
||||
if cp "$src_path" "$dest"; then
|
||||
# Custom scripts mounted into *arr containers must be executable;
|
||||
# Radarr/Sonarr validate CustomScript paths by exec'ing them on save.
|
||||
case "$src" in
|
||||
scripts/*) chmod +x "$dest" ;;
|
||||
esac
|
||||
log_success "$src copied successfully"
|
||||
copied=$((copied + 1))
|
||||
else
|
||||
log_error "Failed to copy $src to $dest. Check permissions"
|
||||
fi
|
||||
done
|
||||
log_debug "Copied ${copied} file(s) into $install_directory"
|
||||
}
|
||||
|
||||
generate_env_file() {
|
||||
local env_file="$install_directory/.env"
|
||||
|
||||
log_info "Generating environment configuration..."
|
||||
log_debug "Generating environment configuration..."
|
||||
|
||||
# Set VPN-related variables for envsubst (credentials go to secrets/)
|
||||
if [ "${setup_vpn,,}" == "y" ]; then
|
||||
|
|
@ -348,7 +351,7 @@ generate_env_file() {
|
|||
|
||||
chmod 600 "$env_file"
|
||||
|
||||
log_success "Environment configuration generated"
|
||||
log_debug "Environment configuration generated ($env_file)"
|
||||
}
|
||||
|
||||
write_vpn_secrets() {
|
||||
|
|
@ -516,8 +519,7 @@ early_vpn_gate() {
|
|||
echo
|
||||
log_info "Testing VPN connection before the rest of setup..."
|
||||
set_provisional_vpn_test_defaults
|
||||
mkdir -p "$install_directory"
|
||||
copy_configuration_files
|
||||
bootstrap_operator
|
||||
generate_env_file
|
||||
write_vpn_secrets
|
||||
# Bind mounts must exist as the host user before Gluetun starts
|
||||
|
|
@ -542,18 +544,24 @@ SUBTITLE_LANGUAGE="${subtitle_language:-}"
|
|||
SETUP_MODE="${SETUP_MODE:-manual}"
|
||||
EOF
|
||||
chmod 600 "$config_file"
|
||||
log_success "Runtime config written to $config_file"
|
||||
# Pointer so CLI discovery works even for non-default install paths
|
||||
if [ "$config_file" != "$HOME/.${APP_NAME}-config" ]; then
|
||||
printf 'INSTALL_DIRECTORY="%s"\n' "$install_directory" > "$HOME/.${APP_NAME}-config"
|
||||
chmod 600 "$HOME/.${APP_NAME}-config"
|
||||
fi
|
||||
log_debug "Runtime config written to $config_file"
|
||||
}
|
||||
|
||||
# build_compose_args is defined in lib/compose.sh
|
||||
# Usage: build_compose_args "$install_directory" "${setup_vpn,,}"
|
||||
|
||||
install_cli() {
|
||||
echo
|
||||
log_info "Installing ${APP_DISPLAY_NAME} CLI..."
|
||||
|
||||
# Copy from install directory (persistent), not SCRIPT_DIR (may be /tmp)
|
||||
local cli_source="$install_directory/cli.sh"
|
||||
if [ ! -f "$cli_source" ]; then
|
||||
log_warning "CLI source missing at $cli_source — skip install"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mkdir -p "$HOME/.local/bin/lib"
|
||||
# Copy lib modules (CLI sources them from lib/ subdirectory)
|
||||
|
|
@ -563,25 +571,43 @@ install_cli() {
|
|||
fi
|
||||
done
|
||||
cp "$cli_source" "$HOME/.local/bin/$APP_CLI_NAME" && chmod +x "$HOME/.local/bin/$APP_CLI_NAME"
|
||||
# Always on PATH for this process (and future shells via profile/fish config)
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
if ! grep -q '.local/bin' "$HOME/.profile" 2>/dev/null; then
|
||||
log_info "Adding $HOME/.local/bin to your PATH (in ~/.profile)..."
|
||||
log_debug "Adding $HOME/.local/bin to PATH in ~/.profile"
|
||||
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.profile"
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
fi
|
||||
# fish ignores ~/.profile, so register the path in its own config too
|
||||
if command -v fish &>/dev/null; then
|
||||
local fish_config="$HOME/.config/fish/config.fish"
|
||||
mkdir -p "$HOME/.config/fish"
|
||||
if ! grep -q '.local/bin' "$fish_config" 2>/dev/null; then
|
||||
log_info "Adding $HOME/.local/bin to your fish PATH (in $fish_config)..."
|
||||
log_debug "Adding $HOME/.local/bin to fish PATH in $fish_config"
|
||||
echo 'fish_add_path $HOME/.local/bin' >> "$fish_config"
|
||||
fi
|
||||
fi
|
||||
log_success "${APP_DISPLAY_NAME} CLI installed to $HOME/.local/bin/$APP_CLI_NAME"
|
||||
log_debug "CLI installed to $HOME/.local/bin/$APP_CLI_NAME"
|
||||
}
|
||||
|
||||
# Materialize install tree + operator CLI as soon as we know the install path.
|
||||
# Lets users run: assemblrr uninstall after aborting mid-setup.
|
||||
# Callers still generate .env / secrets when those steps are ready.
|
||||
bootstrap_operator() {
|
||||
local quiet="${1:-}"
|
||||
mkdir -p "$install_directory"
|
||||
copy_configuration_files
|
||||
write_runtime_config
|
||||
if install_cli; then
|
||||
if [ "$quiet" != "quiet" ]; then
|
||||
log_success "Operator CLI ready: $HOME/.local/bin/$APP_CLI_NAME"
|
||||
log_info "Abort anytime with: $APP_CLI_NAME uninstall"
|
||||
log_info "(If the shell says command not found: open a new terminal, or run the path above.)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
set_permissions() {
|
||||
log_info "Setting ownership for install and media directories..."
|
||||
log_debug "Setting ownership for install and media directories..."
|
||||
|
||||
# Install bind-mount tree (idempotent; also fixes root-owned leftovers)
|
||||
prepare_install_dirs "$install_directory" "$puid" "$pgid"
|
||||
|
|
@ -591,7 +617,7 @@ set_permissions() {
|
|||
fi
|
||||
ensure_owned "$media_directory" "$puid" "$pgid"
|
||||
|
||||
log_success "Ownership set for $install_directory and $media_directory"
|
||||
log_debug "Ownership set for $install_directory and $media_directory"
|
||||
}
|
||||
|
||||
main() {
|
||||
|
|
@ -607,12 +633,15 @@ log_info "Checking prerequisites..."
|
|||
check_dependencies
|
||||
|
||||
# 1) VPN questions, then immediately test the tunnel (fail fast).
|
||||
# VPN path bootstraps install tree + CLI early so uninstall works if you abort.
|
||||
configure_vpn
|
||||
early_vpn_gate
|
||||
|
||||
# 2) Only after VPN works (or is disabled): rest of the wizard
|
||||
get_user_info
|
||||
get_installation_paths
|
||||
# No-VPN (or path change after provisional VPN defaults): ensure tree + CLI exist
|
||||
bootstrap_operator quiet
|
||||
configure_media_service
|
||||
configure_seerr_profile
|
||||
configure_subtitle_language
|
||||
|
|
@ -640,7 +669,7 @@ echo " Subtitle language: ${subtitle_language:-en (Bazarr default)}"
|
|||
if [ "${opensubtitles_enabled:-n}" = "y" ]; then
|
||||
echo " OpenSubtitles.com: yes (username=${opensubtitles_username})"
|
||||
else
|
||||
echo " OpenSubtitles.com: no (pick providers at wire-up)"
|
||||
echo " OpenSubtitles.com: no"
|
||||
fi
|
||||
echo " Timezone: $tz"
|
||||
echo " Service login: $auth_username"
|
||||
|
|
@ -675,18 +704,18 @@ prepare_install_dirs "$install_directory" "$puid" "$pgid"
|
|||
if [ "${setup_vpn,,}" = "y" ] && [ "${VPN_ALREADY_VERIFIED:-}" != "1" ]; then
|
||||
ensure_vpn_connection
|
||||
elif [ "${setup_vpn,,}" = "y" ]; then
|
||||
log_info "VPN already verified earlier — not re-testing."
|
||||
log_debug "VPN already verified earlier — not re-testing."
|
||||
fi
|
||||
|
||||
write_auth_secrets
|
||||
write_opensubtitles_secrets
|
||||
write_qbittorrent_config
|
||||
write_runtime_config
|
||||
install_cli
|
||||
set_permissions
|
||||
|
||||
log_success "Install files ready — starting services..."
|
||||
|
||||
log_info "Starting ${APP_DISPLAY_NAME} services..."
|
||||
log_info "This may take a while..."
|
||||
log_info "Starting ${APP_DISPLAY_NAME} services (this may take a while)..."
|
||||
# Ensure mounts still exist/owned immediately before the full stack comes up
|
||||
prepare_install_dirs "$install_directory" "$puid" "$pgid"
|
||||
build_compose_args "$install_directory" "${setup_vpn,,}"
|
||||
|
|
@ -706,12 +735,6 @@ fi
|
|||
# Drop legacy name if an older install left it behind
|
||||
rm -f "$install_directory/configure.sh" 2>/dev/null || true
|
||||
|
||||
# Install CLI (needed for status/upgrade even if wiring failed)
|
||||
echo
|
||||
log_info "Installing CLI and configuring permissions..."
|
||||
install_cli
|
||||
set_permissions
|
||||
|
||||
echo
|
||||
# Live dashboard once (status exits non-zero when something is unhealthy —
|
||||
# that is still a successful print; do not fall back to a second URL list).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue