3a63ced4d4
Adds a step_youtube wizard prompt (enable + cookies host folder), the @YOUTUBE_VOLUME@ token in templates/compose/backend.yml substituted in compose_gen, a YOUTUBE_ENABLED/cookies env block, ensure_youtube_dir in lifecycle, en/ru strings, and a README step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
146 lines
4.3 KiB
Bash
146 lines
4.3 KiB
Bash
# Lifecycle: pull, ordered start (deps → migrate → app), first admin, health,
|
|
# plus update/down/logs/status/clean. Wraps `docker compose` with the project's
|
|
# env file and generated compose file.
|
|
|
|
PROJECT="${MCMA_PROJECT:-mcma}"
|
|
|
|
dc() {
|
|
docker compose \
|
|
--project-name "$PROJECT" \
|
|
--project-directory "$BOOTSTRAP_DIR" \
|
|
--env-file "$ENV_FILE" \
|
|
-f "$COMPOSE_FILE" "$@"
|
|
}
|
|
|
|
# backing_services — the embedded dependencies present in the compose file that
|
|
# must be healthy/complete before migrations (subset of db redis minio*).
|
|
backing_services() {
|
|
local all want s out=""
|
|
all="$(dc config --services 2>/dev/null)"
|
|
for want in db redis minio minio-setup; do
|
|
while IFS= read -r s; do
|
|
[[ "$s" == "$want" ]] && out+="$want "
|
|
done <<<"$all"
|
|
done
|
|
printf '%s' "${out% }"
|
|
}
|
|
|
|
# app_services — everything that is not a one-shot/backing dependency wait.
|
|
ensure_media_dir() {
|
|
# MEDIA_HOST_PATH is read from the generated env file.
|
|
local p
|
|
p="$(grep -E '^MEDIA_HOST_PATH=' "$ENV_FILE" | cut -d= -f2-)"
|
|
[[ -n "$p" ]] || return 0
|
|
# Resolve relative paths against the project directory (compose does too).
|
|
[[ "$p" = /* ]] || p="${BOOTSTRAP_DIR}/${p#./}"
|
|
mkdir -p "$p"
|
|
}
|
|
|
|
ensure_youtube_dir() {
|
|
# YOUTUBE_COOKIES_HOST_PATH is only present when the YouTube source is
|
|
# enabled; create the folder so the bind mount has a real host directory
|
|
# (the user drops cookies.txt into it later).
|
|
local p
|
|
p="$(grep -E '^YOUTUBE_COOKIES_HOST_PATH=' "$ENV_FILE" | cut -d= -f2-)"
|
|
[[ -n "$p" ]] || return 0
|
|
[[ "$p" = /* ]] || p="${BOOTSTRAP_DIR}/${p#./}"
|
|
mkdir -p "$p"
|
|
}
|
|
|
|
lifecycle_pull() {
|
|
ui_info "$(t pull_images "$(grep -E '^MCMA_IMAGE_TAG=' "$ENV_FILE" | cut -d= -f2-)")"
|
|
ui_dim "$(t pull_hint)"
|
|
dc pull
|
|
}
|
|
|
|
# wait_api_healthy — poll the running API's liveness endpoint over the compose
|
|
# network (no host port / TLS assumptions). Returns non-zero on timeout.
|
|
wait_api_healthy() {
|
|
ui_info "$(t checking_health)"
|
|
dc run --rm --no-deps -T api python -c '
|
|
import urllib.request, time, sys
|
|
for _ in range(60):
|
|
try:
|
|
if urllib.request.urlopen("http://api:8000/health", timeout=2).status == 200:
|
|
sys.exit(0)
|
|
except Exception:
|
|
pass
|
|
time.sleep(2)
|
|
sys.exit(1)
|
|
'
|
|
}
|
|
|
|
# lifecycle_start CREATE_ADMIN(yes|no)
|
|
# Ordered, fail-loud startup. Never starts the backend over a broken DB.
|
|
lifecycle_start() {
|
|
local create_admin="${1:-no}"
|
|
ensure_media_dir
|
|
ensure_youtube_dir
|
|
lifecycle_pull
|
|
|
|
local deps; deps="$(backing_services)"
|
|
if [[ -n "$deps" ]]; then
|
|
ui_info "$(t starting_deps)"
|
|
# shellcheck disable=SC2086
|
|
dc up -d --wait $deps
|
|
fi
|
|
|
|
ui_info "$(t running_migrations)"
|
|
if ! dc run --rm --no-deps -T api alembic upgrade head; then
|
|
ui_err "$(t err_migrations_failed)"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$create_admin" == "yes" ]]; then
|
|
ui_info "$(t creating_admin)"
|
|
# Password passed via --password to avoid interactive prompts; not echoed.
|
|
dc run --rm --no-deps -T api mcma create-admin "$CFG_ADMIN_USER" --password "$CFG_ADMIN_PASS"
|
|
fi
|
|
|
|
ui_info "$(t starting_app)"
|
|
dc up -d
|
|
|
|
if ! wait_api_healthy; then
|
|
ui_err "$(t err_health_timeout)"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# -- management commands ---------------------------------------------------
|
|
lifecycle_update() {
|
|
lifecycle_pull
|
|
local deps; deps="$(backing_services)"
|
|
if [[ -n "$deps" ]]; then
|
|
# shellcheck disable=SC2086
|
|
dc up -d --wait $deps
|
|
fi
|
|
ui_info "$(t running_migrations)"
|
|
if ! dc run --rm --no-deps -T api alembic upgrade head; then
|
|
ui_err "$(t err_migrations_failed)"; exit 1
|
|
fi
|
|
dc up -d
|
|
wait_api_healthy || { ui_err "$(t err_health_timeout)"; exit 1; }
|
|
ui_ok "$(t done_title)"
|
|
}
|
|
|
|
lifecycle_up() { ensure_media_dir; ensure_youtube_dir; dc up -d; }
|
|
lifecycle_down() { dc down; }
|
|
lifecycle_logs() { dc logs -f --tail=100; }
|
|
|
|
lifecycle_status() {
|
|
dc ps
|
|
echo
|
|
if wait_api_healthy >/dev/null 2>&1; then ui_ok "API: ok"; else ui_warn "API: not ready"; fi
|
|
}
|
|
|
|
lifecycle_clean() {
|
|
dc down
|
|
if ui_yesno "$(t clean_volumes_confirm)" "no"; then
|
|
dc down -v
|
|
fi
|
|
if ui_yesno "$(t clean_confirm)" "yes"; then
|
|
rm -f "$COMPOSE_FILE" "$CADDYFILE" "$ENV_FILE"
|
|
ui_ok "$(t clean_done)"
|
|
fi
|
|
}
|