From b47f91b1ab0729412735048010352428a37ec892 Mon Sep 17 00:00:00 2001 From: Anton Afanasyev Date: Wed, 24 Jun 2026 22:53:38 +0200 Subject: [PATCH] Cluster deploy: ac/* only, hub assets, auth routes at project root. Remove monolith clone path; add hub deploy, legacy purge, composed-backend login/logout nginx locations, and full hub asset rsync validation. Co-authored-by: Cursor --- sim/cluster0/cluster.env | 12 +- sim/cluster0/nginx/apps-port80.conf | 14 +- sim/cluster0/populate_lab_setup.sh | 3 +- sim/cluster0/scripts/compose-lab-backend.sh | 11 +- sim/cluster0/scripts/deploy-ac-hub.sh | 45 +++++++ sim/cluster0/scripts/deploy-ac-workspace.sh | 10 +- sim/cluster0/scripts/deploy-app.sh | 121 ++---------------- .../scripts/journal-backfill-cluster0.sh | 2 +- sim/cluster0/scripts/purge-legacy-monolith.sh | 30 +++++ sim/cluster0/scripts/validate-ac-repos.sh | 46 ++++++- 10 files changed, 156 insertions(+), 138 deletions(-) create mode 100755 sim/cluster0/scripts/deploy-ac-hub.sh create mode 100755 sim/cluster0/scripts/purge-legacy-monolith.sh diff --git a/sim/cluster0/cluster.env b/sim/cluster0/cluster.env index 1bba49f..665172c 100644 --- a/sim/cluster0/cluster.env +++ b/sim/cluster0/cluster.env @@ -23,17 +23,16 @@ ARTC0_IP=10.7.16.128 SSH_USER=ai -GIT_ORIGIN=git://f0xx.org/android_cast -GIT_BRANCH=next -# git | bundle — bundle uses SHARED_MOUNT/cluster/release/current/ -APP_SOURCE=git - -# ac/* org (SPEC migration — git server SoT; Gitea browse only, not required for deploy) +# ── Source of truth: git://f0xx.org/ac/* ONLY ───────────────────────────── +# Do NOT clone git://f0xx.org/android_cast on cluster nodes (frozen monolith). AC_GIT_BASE=git://f0xx.org/ac AC_WORKSPACE_ORIGIN=git://f0xx.org/ac/ac-workspace AC_WORKSPACE_ROOT=/var/www/ac/workspace AC_GIT_BRANCH=next +# Minimal submodules for first workspace init (fast path) AC_SUBMODULES_CORE="ac-platform-db ac-platform-php ac-platform-web ac-platform-edge ac-deploy ac-docs ac-scripts ac-ms-url-shortener ac-be-hub ac-ms-identity" +# Full set required by compose-lab-backend.sh (init after workspace clone) +AC_SUBMODULES_COMPOSE="ac-platform-php ac-platform-web ac-ms-identity ac-ms-rbac ac-ms-devices ac-ms-issues ac-ms-tickets ac-ms-graphs ac-ms-remote-access ac-be-auth ac-be-issues ac-be-tickets ac-be-graphs ac-be-remote-access ac-be-access ac-be-builder ac-ms-build" URL_SHORTENER_ORIGIN=git://f0xx.org/ac/ac-ms-url-shortener URL_SHORTENER_ROOT=/var/www/url-shortener @@ -44,7 +43,6 @@ APP_HUB_PATH=/app/androidcast_project COMPOSE_BACKEND=/var/www/ac/composed/backend AC_PLATFORM_ROOT=/var/www/ac/platform COMPOSE_RUNTIME=1 -COMPOSE_SKIP_MONOLITH=1 POSTGRES_SEMI_ENABLE=1 # Gitea browse UI on cast01 (primary); mirrors added later diff --git a/sim/cluster0/nginx/apps-port80.conf b/sim/cluster0/nginx/apps-port80.conf index 2748c7f..a33354c 100644 --- a/sim/cluster0/nginx/apps-port80.conf +++ b/sim/cluster0/nginx/apps-port80.conf @@ -28,6 +28,16 @@ server { rewrite ^ /app/androidcast_project/index.php last; } + # Shared session auth at project root (not under /issues/) — composed ac/* backend + location ~ ^/app/androidcast_project/(login|logout|register|two-factor|verify-email)(/|$) { + include fastcgi_params; + fastcgi_pass 127.0.0.1:9000; + fastcgi_param SCRIPT_FILENAME /var/www/ac/composed/backend/public/index.php; + fastcgi_param SCRIPT_NAME /app/androidcast_project/issues/index.php; + fastcgi_param REQUEST_URI $request_uri; + client_max_body_size 4m; + } + location /app/androidcast_project/ { alias /var/www/localhost/htdocs/apps/app/androidcast_project/; index index.php index.html; @@ -117,13 +127,13 @@ server { } location ^~ /app/androidcast_project/build/assets/ { - alias /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/build_console/backend/public/assets/; + alias /var/www/ac/workspace/ac-be-builder/public/assets/; } location ^~ /app/androidcast_project/build/ { include fastcgi_params; fastcgi_pass 127.0.0.1:9000; - fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/build_console/backend/public/index.php; + fastcgi_param SCRIPT_FILENAME /var/www/ac/workspace/ac-be-builder/public/index.php; fastcgi_param SCRIPT_NAME /app/androidcast_project/build/index.php; fastcgi_param REQUEST_URI $request_uri; client_max_body_size 512m; diff --git a/sim/cluster0/populate_lab_setup.sh b/sim/cluster0/populate_lab_setup.sh index c4ac86b..7ed3934 100644 --- a/sim/cluster0/populate_lab_setup.sh +++ b/sim/cluster0/populate_lab_setup.sh @@ -68,11 +68,12 @@ run_phase_app() { if is_replica_node; then wait_for_primary_db fi - run_script "$ROOT/scripts/deploy-app.sh" run_script "$ROOT/scripts/deploy-ac-workspace.sh" + run_script "$ROOT/scripts/purge-legacy-monolith.sh" run_script "$ROOT/scripts/deploy-ac-url-shortener.sh" if [ "${COMPOSE_RUNTIME:-0}" = "1" ]; then run_script "$ROOT/scripts/compose-lab-backend.sh" + run_script "$ROOT/scripts/deploy-ac-hub.sh" if is_primary_node; then run_script "$ROOT/scripts/ensure-auth-email-bearer.sh" || journal_warn auth_bearer "mint failed" run_script "$ROOT/scripts/compose-lab-backend.sh" diff --git a/sim/cluster0/scripts/compose-lab-backend.sh b/sim/cluster0/scripts/compose-lab-backend.sh index e0a5544..fb6e38c 100755 --- a/sim/cluster0/scripts/compose-lab-backend.sh +++ b/sim/cluster0/scripts/compose-lab-backend.sh @@ -8,14 +8,7 @@ load_cluster_env WS="${AC_WORKSPACE_ROOT:-/var/www/ac/workspace}" LAB_SEED="${ROOT}/lab-seeds/backend" -MONOLITH_BACKEND="${APP_ROOT}/android_cast/examples/crash_reporter/backend" -if [ -d "${LAB_SEED}/public" ]; then - LEGACY="$LAB_SEED" -elif [ "${COMPOSE_SKIP_MONOLITH:-0}" = "1" ]; then - die "lab-seeds missing at ${LAB_SEED} and COMPOSE_SKIP_MONOLITH=1" -else - LEGACY="$MONOLITH_BACKEND" -fi +LEGACY="$LAB_SEED" COMPOSED="${COMPOSE_BACKEND:-/var/www/ac/composed/backend}" PLATFORM_ROOT="${AC_PLATFORM_ROOT:-/var/www/ac/platform}" APP_PASS="$(read_cred mariadb_app password)" @@ -53,7 +46,7 @@ overlay_views() { } if [ ! -f "${COMPOSED}/public/index.php" ] || [ "${FORCE_COMPOSE_SEED:-0}" = "1" ]; then - [ -d "$LEGACY/public" ] || die "backend seed missing at $LEGACY (lab-seeds or deploy-app.sh monolith)" + [ -d "$LEGACY/public" ] || die "backend seed missing at $LEGACY (sync ac-deploy lab-seeds to NFS /shared/cluster)" log "seed composed backend from ${LEGACY}" mkdir -p "$(dirname "$COMPOSED")" rm -rf "$COMPOSED" diff --git a/sim/cluster0/scripts/deploy-ac-hub.sh b/sim/cluster0/scripts/deploy-ac-hub.sh new file mode 100755 index 0000000..8f422df --- /dev/null +++ b/sim/cluster0/scripts/deploy-ac-hub.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# Deploy ac-be-hub landing to APP_ROOT (hub index.php + full assets tree). +set -eu +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +# shellcheck source=/dev/null +. "$ROOT/scripts/lib/common.sh" +load_cluster_env + +WS="${AC_WORKSPACE_ROOT:-/var/www/ac/workspace}" +HUB="${WS}/ac-be-hub" +DEST="${APP_ROOT:-/var/www/localhost/htdocs/apps/app/androidcast_project}" + +[ -d "$HUB" ] || die "missing ac-be-hub at $HUB (run deploy-ac-workspace.sh first)" + +mkdir -p "$DEST/partials" +for f in index.php index.html hub.css hub-logo-layers.css hub-landing.css landing-pages.inc.php; do + install -m 0644 "$HUB/$f" "$DEST/$f" +done +install -D -m 0644 "$HUB/partials/cookie_consent.php" "$DEST/partials/cookie_consent.php" + +# Hub clock/globe/logo layers need the full assets/ tree (SVG alphabets, fragments, optional fonts/). +log "rsync hub assets/" +rsync -a --delete \ + --exclude='*.py' \ + --exclude='analytics.config.example.js' \ + "$HUB/assets/" "$DEST/assets/" + +# Hub footer expects platform under android_cast/examples/platform OR ../platform +PLATFORM_SRC="${WS}/ac-platform-php/platform" +PLATFORM_DEST="${DEST}/android_cast/examples/platform" +if [ -d "$PLATFORM_SRC" ]; then + mkdir -p "$(dirname "$PLATFORM_DEST")" + rsync -a --delete "$PLATFORM_SRC/" "$PLATFORM_DEST/" +fi + +for _req in \ + assets/hub-logo-transparent.svg \ + assets/hub-logo-fragment-globe.svg \ + assets/overtime-01-alphabet.svg \ + assets/quartz-alphabet.svg; do + [ -f "$DEST/$_req" ] || die "hub deploy incomplete: missing $_req" +done + +chown -R nginx:nginx "$DEST" 2>/dev/null || true +log "deploy-ac-hub_ok $(host_short)" diff --git a/sim/cluster0/scripts/deploy-ac-workspace.sh b/sim/cluster0/scripts/deploy-ac-workspace.sh index b37d6d4..5395165 100755 --- a/sim/cluster0/scripts/deploy-ac-workspace.sh +++ b/sim/cluster0/scripts/deploy-ac-workspace.sh @@ -9,7 +9,8 @@ load_cluster_env AC_ROOT="${AC_WORKSPACE_ROOT:-/var/www/ac/workspace}" ORIGIN="${AC_WORKSPACE_ORIGIN:-git://f0xx.org/ac/ac-workspace}" BRANCH="${AC_GIT_BRANCH:-next}" -SUBS="${AC_SUBMODULES_CORE:-ac-platform-db ac-platform-php ac-platform-web ac-platform-edge ac-deploy ac-docs ac-scripts ac-ms-url-shortener ac-be-hub ac-ms-identity}" +SUBS_CORE="${AC_SUBMODULES_CORE:-ac-platform-db ac-platform-php ac-platform-web ac-platform-edge ac-deploy ac-docs ac-scripts ac-ms-url-shortener ac-be-hub ac-ms-identity}" +SUBS_COMPOSE="${AC_SUBMODULES_COMPOSE:-ac-platform-php ac-platform-web ac-ms-identity ac-ms-rbac ac-ms-devices ac-ms-issues ac-ms-tickets ac-ms-graphs ac-ms-remote-access ac-be-auth ac-be-issues ac-be-tickets ac-be-graphs ac-be-remote-access ac-be-access ac-be-builder ac-ms-build}" mkdir -p "$(dirname "$AC_ROOT")" git config --global --add safe.directory "$AC_ROOT" 2>/dev/null || true @@ -27,10 +28,13 @@ else fi cd "$AC_ROOT" -log "submodule sync + init: ${SUBS}" +log "submodule sync + init core: ${SUBS_CORE}" git submodule sync --recursive 2>/dev/null || true # shellcheck disable=SC2086 -git submodule update --init --depth 1 $SUBS +git submodule update --init --depth 1 $SUBS_CORE +log "submodule init compose: ${SUBS_COMPOSE}" +# shellcheck disable=SC2086 +git submodule update --init --depth 1 $SUBS_COMPOSE chown -R nginx:nginx "$(dirname "$AC_ROOT")" 2>/dev/null || true log "deploy-ac-workspace_ok $(host_short) $(git -C "$AC_ROOT" rev-parse --short HEAD)" diff --git a/sim/cluster0/scripts/deploy-app.sh b/sim/cluster0/scripts/deploy-app.sh index ef2ddc1..7011d20 100644 --- a/sim/cluster0/scripts/deploy-app.sh +++ b/sim/cluster0/scripts/deploy-app.sh @@ -1,116 +1,21 @@ #!/bin/sh -# Deploy androidcast project tree + lab config.php (local disk, not NFS). +# DEPRECATED — cluster uses ac/* only (ac-workspace + compose-lab-backend.sh). +# This script refuses to clone git://f0xx.org/android_cast. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd)" # shellcheck source=/dev/null . "$ROOT/scripts/lib/common.sh" -ensure_shared_mounted +load_cluster_env -if [ "${COMPOSE_SKIP_MONOLITH:-0}" = "1" ]; then - log "COMPOSE_SKIP_MONOLITH=1 — skip monolith git pull (use lab-seeds + compose-lab-backend.sh)" - exit 0 +LEGACY="${APP_ROOT}/android_cast" +if [ -d "${LEGACY}/.git" ]; then + _url="$(git -C "$LEGACY" config --get remote.origin.url 2>/dev/null || true)" + case "$_url" in + *android_cast*) + die "legacy monolith still present at $LEGACY ($_url). Run: sudo sh $ROOT/scripts/purge-legacy-monolith.sh" + ;; + esac fi -APP_PASS="$(read_cred mariadb_app password)" -DB_HOST="$PRIMARY_DB_HOST" -if is_primary_node; then - DB_HOST=127.0.0.1 -fi - -mkdir -p "$(dirname "$APP_ROOT")" -GIT_ROOT="${APP_ROOT}/android_cast" -BACKEND="${GIT_ROOT}/examples/crash_reporter/backend" -CONFIG="${BACKEND}/config/config.php" - -case "$APP_SOURCE" in - git) - if [ -d "${GIT_ROOT}/.git" ]; then - log "git pull ${GIT_BRANCH} in ${GIT_ROOT}" - git config --global --add safe.directory "$GIT_ROOT" 2>/dev/null || true - # Lab config.php is generated below — never block monolith pull on it. - git -C "$GIT_ROOT" checkout -- examples/crash_reporter/backend/config/config.php 2>/dev/null || true - git -C "$GIT_ROOT" fetch origin - git -C "$GIT_ROOT" checkout "$GIT_BRANCH" - git -C "$GIT_ROOT" pull --ff-only origin "$GIT_BRANCH" || git -C "$GIT_ROOT" reset --hard "origin/${GIT_BRANCH}" - else - log "git clone ${GIT_ORIGIN} → ${GIT_ROOT}" - rm -rf "$GIT_ROOT" - git clone --branch "$GIT_BRANCH" --depth 1 "$GIT_ORIGIN" "$GIT_ROOT" - git config --global --add safe.directory "$GIT_ROOT" 2>/dev/null || true - fi - ;; - bundle) - BUNDLE="${ROOT}/release/current" - [ -d "$BUNDLE" ] || die "missing bundle dir $BUNDLE (APP_SOURCE=bundle)" - log "rsync bundle $BUNDLE → ${APP_ROOT}" - mkdir -p "$APP_ROOT" - rsync -a --delete "$BUNDLE/" "$APP_ROOT/" - ;; - *) - die "unknown APP_SOURCE=$APP_SOURCE" - ;; -esac - -mkdir -p "${BACKEND}/config" "${BACKEND}/data" "${BACKEND}/storage" -chown -R nginx:nginx "$APP_ROOT" 2>/dev/null || true - -if [ ! -f "$CONFIG" ] || [ "${FORCE_CONFIG:-1}" = "1" ]; then - log "writing lab config.php" - cat > "$CONFIG" < 'Android Cast Issues', - 'base_path' => '${APP_BASE_PATH}', - 'db' => [ - 'driver' => 'mariadb', - 'sqlite_path' => __DIR__ . '/../data/crashes.sqlite', - 'mysql' => [ - 'host' => '${DB_HOST}', - 'port' => ${PRIMARY_DB_PORT}, - 'socket' => '', - 'database' => 'androidcast_crashes', - 'username' => 'androidcast', - 'password' => '${APP_PASS}', - 'charset' => 'utf8mb4', - ], - ], - 'session_name' => 'ac_crash_sess', - 'session_cookie_path' => '${APP_HUB_PATH}', - 'debug' => true, - 'rbac' => [ - 'default_company_slug' => 'default', - 'default_company_id' => 1, - ], - 'analytics' => ['enabled' => false, 'measurement_id' => '', 'debug' => false], - 'remote_access' => [ - 'wg_endpoint' => '', - 'wg_server_public_key' => '', - 'provision_peers' => false, - 'require_wg_tools' => false, - ], - 'auth' => [ - 'encryption_key' => 'lab-cluster-dev-32-char-min-secret!!', - 'max_attempts' => 8, - 'lockout_window_minutes' => 15, - ], - 'url_shortener' => [ - 'enabled' => true, - 'public_base' => '${SHORT_LINKS_PUBLIC_BASE}', - 'db' => [ - 'mysql' => [ - 'host' => '${DB_HOST}', - 'port' => ${PRIMARY_DB_PORT}, - 'socket' => '', - 'database' => 'url_shortener', - 'username' => 'androidcast', - 'password' => '${APP_PASS}', - 'charset' => 'utf8mb4', - ], - ], - ], -]; -PHP - chown nginx:nginx "$CONFIG" 2>/dev/null || true -fi - -log "deploy-app_ok $(host_short)" +log "deploy-app: skipped (ac/* compose path — see deploy-ac-workspace.sh + compose-lab-backend.sh)" +exit 0 diff --git a/sim/cluster0/scripts/journal-backfill-cluster0.sh b/sim/cluster0/scripts/journal-backfill-cluster0.sh index 6f6b67b..6617473 100644 --- a/sim/cluster0/scripts/journal-backfill-cluster0.sh +++ b/sim/cluster0/scripts/journal-backfill-cluster0.sh @@ -42,7 +42,7 @@ append cast03 db mariadb-replica OK "GTID replica IO+SQL running" # App + nginx for H in cast01 cast02 cast03; do - append "$H" app deploy-app OK "git next → android_cast/" + append "$H" app deploy-ac-workspace OK "git next → ac-workspace + ac/* submodules" append "$H" app configure-nginx OK "apps-port80.conf php83:9000" done diff --git a/sim/cluster0/scripts/purge-legacy-monolith.sh b/sim/cluster0/scripts/purge-legacy-monolith.sh new file mode 100755 index 0000000..e93e046 --- /dev/null +++ b/sim/cluster0/scripts/purge-legacy-monolith.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# Remove frozen git://f0xx.org/android_cast checkout from cluster nodes. +# Run once after switching to ac/* compose deploy (populate uses ac-workspace only). +set -eu +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +# shellcheck source=/dev/null +. "$ROOT/scripts/lib/common.sh" +load_cluster_env + +LEGACY="${APP_ROOT}/android_cast" +if [ ! -e "$LEGACY" ]; then + log "no legacy monolith at $LEGACY — nothing to purge" + exit 0 +fi + +if [ -d "${LEGACY}/.git" ]; then + _url="$(git -C "$LEGACY" config --get remote.origin.url 2>/dev/null || true)" + case "$_url" in + *android_cast*) + log "removing legacy monolith $_url at $LEGACY" + ;; + *) + warn "unexpected origin $_url — not removing (manual review)" + exit 1 + ;; + esac +fi + +rm -rf "$LEGACY" +log "purge-legacy-monolith_ok $(host_short)" diff --git a/sim/cluster0/scripts/validate-ac-repos.sh b/sim/cluster0/scripts/validate-ac-repos.sh index 8058585..b9bb71c 100755 --- a/sim/cluster0/scripts/validate-ac-repos.sh +++ b/sim/cluster0/scripts/validate-ac-repos.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Validate ac-workspace + legacy runtime on this cluster node. +# Validate ac-workspace + composed backend on this cluster node (ac/* only). set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd)" # shellcheck source=/dev/null @@ -31,6 +31,7 @@ check_file() { AC_ROOT="${AC_WORKSPACE_ROOT:-/var/www/ac/workspace}" LEGACY="${APP_ROOT}/android_cast" +HUB="${APP_ROOT}/index.php" log "validate-ac-repos on $(host_short)" check_dir "ac-workspace" "$AC_ROOT" @@ -39,15 +40,46 @@ check_dir "ac-platform-php" "${AC_ROOT}/ac-platform-php/src" check_dir "ac-platform-web" "${AC_ROOT}/ac-platform-web/assets/css" check_dir "composed-backend" "${COMPOSE_BACKEND:-/var/www/ac/composed/backend}" check_file "composed-index" "${COMPOSE_BACKEND:-/var/www/ac/composed/backend}/public/index.php" -check_file "legacy-backend" "${LEGACY}/examples/crash_reporter/backend/public/index.php" -check_dir "legacy-monolith" "$LEGACY" +check_file "hub-index" "$HUB" +check_file "hub-logo-svg" "${APP_ROOT}/assets/hub-logo-transparent.svg" +check_file "hub-globe-svg" "${APP_ROOT}/assets/hub-logo-fragment-globe.svg" check_dir "url-shortener" "${URL_SHORTENER_ROOT:-/var/www/url-shortener}/public" -if [ -d "${AC_ROOT}/.git" ]; then - log "ac-workspace_sha=$(git -C "$AC_ROOT" rev-parse --short HEAD 2>/dev/null || echo none)" -fi if [ -d "${LEGACY}/.git" ]; then - log "legacy_sha=$(git -C "$LEGACY" rev-parse --short HEAD 2>/dev/null || echo none)" + _url="$(git -C "$LEGACY" config --get remote.origin.url 2>/dev/null || true)" + log "FAIL legacy monolith present at $LEGACY ($_url) — run purge-legacy-monolith.sh" + FAIL=1 +elif [ -e "$LEGACY" ]; then + log "FAIL legacy path still exists at $LEGACY (not a git checkout)" + FAIL=1 +else + log "OK no legacy monolith at $LEGACY" +fi + +URL_ROOT="${URL_SHORTENER_ROOT:-/var/www/url-shortener}" +if [ -d "${URL_ROOT}/.git" ]; then + _url="$(git -C "$URL_ROOT" config --get remote.origin.url 2>/dev/null || true)" + case "$_url" in + git://f0xx.org/ac/*|git://f0xx.org/ac/ac-ms-url-shortener|git://10.7.0.10/ac/*|git://10.7.0.10/ac/ac-ms-url-shortener) + log "OK url-shortener origin $_url" + ;; + *) + log "FAIL url-shortener wrong origin $_url (expect git://f0xx.org/ac/ac-ms-url-shortener)" + FAIL=1 + ;; + esac +fi + +if [ -d "${AC_ROOT}/.git" ]; then + _ws="$(git -C "$AC_ROOT" config --get remote.origin.url 2>/dev/null || true)" + log "ac-workspace origin=${_ws} sha=$(git -C "$AC_ROOT" rev-parse --short HEAD 2>/dev/null || echo none)" + case "$_ws" in + git://f0xx.org/ac/ac-workspace|git://10.7.0.10/ac/ac-workspace) ;; + *) + log "FAIL ac-workspace wrong origin $_ws" + FAIL=1 + ;; + esac fi if [ "$FAIL" -eq 0 ]; then