- df -kP: POSIX mode prevents LVM line-wrap false WARNs (all tier scripts) - 11_wiki: glow from @testing on x86_64; CE repo path kept for ARM - 12_access: ly from @testing on x86_64+aarch64; MANUAL stub for armhf; post-install: rc-update add ly default + comment tty2 getty in inittab - 05_fonts: nerd-fonts-all from v3.23 stable community (no @edge tag) - ce-common: add ohiod_address() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
204 lines
6.9 KiB
Bash
204 lines
6.9 KiB
Bash
#!/usr/bin/env bash
|
|
# Created by John A. Hoeven with the ethical assistance of Claude AI
|
|
# ---------------------------------------------------------------------------
|
|
# ce-common.sh
|
|
# ~/projects/ceos/alpine-installer/lib/ce-common.sh
|
|
# Version: v0.0.1 | Status: DEVELOPMENT
|
|
# Target: Alpine Linux x86-64 (tinkerpad / ThinkPad T480)
|
|
# ---------------------------------------------------------------------------
|
|
# Shared library: logging, run_test, package helpers, common guards.
|
|
# Source this file; do not execute directly.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# Guard against double-sourcing
|
|
[[ -n "${CE_COMMON_LOADED:-}" ]] && return 0
|
|
CE_COMMON_LOADED=1
|
|
|
|
# ohiod_address — address the Organic Humanoid I/O Device by unit ID
|
|
ohiod_address() {
|
|
local unit_id="${SUDO_USER:-${USER}}"
|
|
echo "Organic Humanoid I/O Device unit ID ${unit_id}"
|
|
}
|
|
|
|
# Architecture detection
|
|
ARCH="$(uname -m)"
|
|
|
|
# Logging setup — SCRIPT_NAME must be set before sourcing
|
|
LOG_DIR="${HOME}/.local/logs/ceos_installer"
|
|
SCRIPT_NAME="${SCRIPT_NAME:-ce-common}"
|
|
LOG_FILE="${LOG_DIR}/${SCRIPT_NAME}-$(date +%Y-%m-%d).log"
|
|
|
|
# Failed packages tracker — shared across all sourced subscripts
|
|
FAILED_PKGS=()
|
|
|
|
# Packages requiring manual follow-up (distinct from simple failures)
|
|
MANUAL_PKGS=()
|
|
|
|
mkdir -p "${LOG_DIR}"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Logging
|
|
# ---------------------------------------------------------------------------
|
|
|
|
_log() {
|
|
local level="${1}" msg="${2}" ts
|
|
ts="$(date '+%Y-%m-%d %H:%M:%S')"
|
|
printf '[%s] [%s] %s\n' "${ts}" "${level}" "${msg}" | tee -a "${LOG_FILE}"
|
|
}
|
|
|
|
log_info() { _log "INFO " "${1}"; }
|
|
log_warn() { _log "WARN " "${1}" >&2; }
|
|
log_error() { _log "ERROR" "${1}" >&2; }
|
|
log_debug() { [[ "${CE_DEBUG:-0}" == "1" ]] && _log "DEBUG" "${1}"; }
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# run_test <description> <test_expression> <fail|warn>
|
|
# ---------------------------------------------------------------------------
|
|
|
|
run_test() {
|
|
local desc="${1}" cmd="${2}" mode="${3:-fail}"
|
|
|
|
if eval "${cmd}" >/dev/null 2>&1; then
|
|
log_info " PASS: ${desc}"
|
|
return 0
|
|
fi
|
|
|
|
if [[ "${mode}" == "fail" ]]; then
|
|
log_error " FAIL: ${desc}"
|
|
exit 1
|
|
else
|
|
log_warn " WARN: ${desc}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Package helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# install_pkg <package> — one package, logs result
|
|
install_pkg() {
|
|
local pkg="${1}"
|
|
if doas apk add "${pkg}" >> "${LOG_FILE}" 2>&1; then
|
|
log_info "Installed: ${pkg}"
|
|
return 0
|
|
else
|
|
log_warn "FAILED: ${pkg} — logged, continuing"
|
|
FAILED_PKGS+=("${pkg}")
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# install_pkg_edge <package> — install with @edge tag, warn on fail
|
|
install_pkg_edge() {
|
|
local pkg="${1}"
|
|
if doas apk add "${pkg}@edge" >> "${LOG_FILE}" 2>&1; then
|
|
log_info "Installed: ${pkg} (@edge)"
|
|
return 0
|
|
else
|
|
log_warn "FAILED: ${pkg}@edge — manual verification required"
|
|
FAILED_PKGS+=("${pkg} (edge, manual verification required)")
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ensure_edge_repo — add @edge community tag if not present
|
|
ensure_edge_repo() {
|
|
if ! grep -q "^@edge" /etc/apk/repositories 2>/dev/null; then
|
|
log_info "Adding @edge community tag to /etc/apk/repositories"
|
|
printf '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community\n' \
|
|
| doas tee -a /etc/apk/repositories > /dev/null 2>&1 \
|
|
|| log_warn "Could not add @edge tag — edge installs may fail"
|
|
fi
|
|
}
|
|
|
|
# ensure_testing_repo — add @testing tag if not present
|
|
ensure_testing_repo() {
|
|
if ! grep -q "^@testing" /etc/apk/repositories 2>/dev/null; then
|
|
log_info "Adding @testing edge/testing tag to /etc/apk/repositories"
|
|
printf '@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing\n' \
|
|
| doas tee -a /etc/apk/repositories > /dev/null 2>&1 \
|
|
|| log_warn "Could not add @testing tag — testing installs may fail"
|
|
fi
|
|
}
|
|
|
|
# install_pkg_testing <package> — install with @testing tag, warn on fail
|
|
install_pkg_testing() {
|
|
local pkg="${1}"
|
|
if doas apk add "${pkg}@testing" >> "${LOG_FILE}" 2>&1; then
|
|
log_info "Installed: ${pkg} (@testing)"
|
|
else
|
|
log_warn "FAILED: ${pkg}@testing — manual verification required"
|
|
FAILED_PKGS+=("${pkg} (testing, manual verification required)")
|
|
fi
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Guards and prompts
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# check_not_root — exit if accidentally run as root
|
|
check_not_root() {
|
|
if [[ "${EUID}" -eq 0 ]]; then
|
|
echo "ERROR: Do not run as root. Run as a standard user with doas configured." >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# confirm_proceed — single prompt; bypassed when CE_INSTALL_NO_CONFIRM=1
|
|
confirm_proceed() {
|
|
[[ "${CE_INSTALL_NO_CONFIRM:-0}" == "1" ]] && return 0
|
|
echo ""
|
|
read -r -p "Proceed with installation? [y/N] " confirm
|
|
[[ "${confirm,,}" == "y" ]] || { log_info "Aborted by user."; exit 0; }
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Summary
|
|
# ---------------------------------------------------------------------------
|
|
|
|
print_summary() {
|
|
log_info "=== INSTALLATION SUMMARY ==="
|
|
if [[ ${#FAILED_PKGS[@]} -eq 0 && ${#MANUAL_PKGS[@]} -eq 0 ]]; then
|
|
log_info "All packages installed successfully."
|
|
return 0
|
|
fi
|
|
if [[ ${#FAILED_PKGS[@]} -gt 0 ]]; then
|
|
log_warn "Failed or skipped packages:"
|
|
for pkg in "${FAILED_PKGS[@]}"; do
|
|
log_warn " - ${pkg}"
|
|
done
|
|
fi
|
|
if [[ ${#MANUAL_PKGS[@]} -gt 0 ]]; then
|
|
log_warn "Requires manual follow-up:"
|
|
for item in "${MANUAL_PKGS[@]}"; do
|
|
log_warn " - ${item}"
|
|
done
|
|
fi
|
|
}
|
|
|
|
# review_pause <label> [log_file]
|
|
# Greps the tier log for WARN/ERROR lines and displays them.
|
|
# If issues found: blocks until OHIOD confirms reviewed.
|
|
# If clean: logs OK and continues without prompting.
|
|
# Not bypassed by CE_INSTALL_NO_CONFIRM — this is an OHIOD safety gate.
|
|
review_pause() {
|
|
local label="${1:-this step}"
|
|
local log="${2:-${LOG_FILE}}"
|
|
local issues
|
|
|
|
issues="$(grep -E '\[(WARN |ERROR)\]' "${log}" 2>/dev/null || true)"
|
|
|
|
echo ""
|
|
if [[ -n "${issues}" ]]; then
|
|
log_warn "=== REVIEW REQUIRED — ${label} ==="
|
|
echo ""
|
|
echo "${issues}"
|
|
echo ""
|
|
read -r -p "Address any issues above. Ready to proceed? [y/N] " confirm
|
|
[[ "${confirm,,}" == "y" ]] \
|
|
|| { log_info "Stopped at ${label} — address issues and re-run from this tier."; exit 0; }
|
|
else
|
|
log_info "${label} — no issues found, continuing."
|
|
fi
|
|
}
|