feat: add Phase 1 — Gitea on Unraid
- phase1_gitea_unraid.sh: 9-step deploy (dirs, docker-compose, app.ini, container start, wait, admin user, API token, save to .env, create org). Every step has idempotency check — running twice changes nothing. - phase1_post_check.sh: 5 independent verification checks - phase1_teardown.sh: stop container + optionally remove data, with prompts Also adds inline comments to lib/common.sh and preflight.sh explaining WHY decisions were made (SSH flags, API tmpfile pattern, port checks, etc.) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,9 @@ _project_root() {
|
||||
cd "$(dirname "${BASH_SOURCE[1]:-${BASH_SOURCE[0]}}")/.." && pwd
|
||||
}
|
||||
|
||||
# Source .env and export all variables.
|
||||
# Uses set -a/+a to auto-export every variable defined in the file,
|
||||
# making them available to child processes (envsubst, ssh, etc.).
|
||||
load_env() {
|
||||
local env_file
|
||||
env_file="$(_project_root)/.env"
|
||||
@@ -77,10 +80,10 @@ load_env() {
|
||||
log_error "Copy .env.example to .env and populate values."
|
||||
return 1
|
||||
fi
|
||||
set -a
|
||||
set -a # auto-export all vars defined below
|
||||
# shellcheck source=/dev/null
|
||||
source "$env_file"
|
||||
set +a
|
||||
set +a # stop auto-exporting
|
||||
}
|
||||
|
||||
save_env_var() {
|
||||
@@ -124,10 +127,15 @@ require_vars() {
|
||||
# SSH
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Execute a command on a remote host via SSH.
|
||||
# Uses indirect variable expansion: ssh_exec "UNRAID" "ls" reads
|
||||
# UNRAID_IP, UNRAID_SSH_USER, UNRAID_SSH_PORT from the environment.
|
||||
# This pattern avoids passing connection details to every function call.
|
||||
ssh_exec() {
|
||||
local host_key="$1"; shift
|
||||
local cmd="$*"
|
||||
|
||||
# Indirect expansion: ${!ip_var} dereferences the variable named by $ip_var
|
||||
local ip_var="${host_key}_IP"
|
||||
local user_var="${host_key}_SSH_USER"
|
||||
local port_var="${host_key}_SSH_PORT"
|
||||
@@ -141,6 +149,9 @@ ssh_exec() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# ConnectTimeout: fail fast if host is unreachable (don't hang for 60s)
|
||||
# StrictHostKeyChecking=accept-new: auto-accept new hosts but reject changed keys
|
||||
# BatchMode=yes: never prompt for password (fail if key auth doesn't work)
|
||||
ssh -o ConnectTimeout=10 \
|
||||
-o StrictHostKeyChecking=accept-new \
|
||||
-o BatchMode=yes \
|
||||
@@ -181,6 +192,10 @@ scp_to() {
|
||||
# API wrappers — return JSON on stdout, logs go to stderr
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Internal API call helper. Writes response to a tmpfile so we can separate
|
||||
# the HTTP status code (via curl -w) from the response body. This ensures
|
||||
# JSON output goes to stdout and error messages go to stderr — callers can
|
||||
# pipe JSON through jq without log noise contaminating the output.
|
||||
_api_call() {
|
||||
local base_url="$1" token="$2" method="$3" path="$4" data="${5:-}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user