#!/bin/bash # Собирает публичные снапшоты Montana для скачивания. # Запускается systemd-таймером каждые 30 минут. # Стратегия: освобождаем место от старых архивов ПЕРЕД сборкой, # пишем новые напрямую в OUT с суффиксом .new, потом атомарный rename. set -euo pipefail REPO_DIR=/var/lib/gitea/data/gitea-repositories/efir369999/montana.git OUT=/var/www/montana_archive LOCK=/run/montana-archive.lock exec 9>"$LOCK" flock -n 9 || { echo "previous build still running, skip"; exit 0; } mkdir -p "$OUT" ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } log() { echo "[$(ts)] $*"; } log "=== Сборка архивов Montana ===" HEAD_SHA=$(GIT_DIR="$REPO_DIR" git rev-parse HEAD) SHORT_SHA="${HEAD_SHA:0:12}" log "HEAD = $HEAD_SHA" DISK_FREE_MB=$(df -m "$OUT" | awk 'NR==2{print $4}') log "свободно до сборки: ${DISK_FREE_MB}MB" # чистим старые .new если остались с упавшей предыдущей попытки rm -f "$OUT"/*.new # Освобождаем место — удаляем прошлые архивы. # Окно недоступности: ~3 минуты (пока строятся новые). За это окно # редиректы /archive/ будут отдавать 404 — это допустимо. rm -f "$OUT/montana-protocol-latest.tar.gz" \ "$OUT/montana-protocol-latest.zip" \ "$OUT/site-essentials.tar.gz" \ "$OUT/site-latest.tar.gz" \ "$OUT/montana-full.bundle" \ "$OUT/SHA256SUMS" log "очищено: $(df -m "$OUT" | awk 'NR==2{print $4}')MB свободно" export GIT_LFS_SKIP_SMUDGE=1 log "→ tar.gz (git archive, без LFS smudge)" GIT_DIR="$REPO_DIR" git -c filter.lfs.smudge= -c filter.lfs.required=false \ archive --format=tar HEAD \ | gzip -6 > "$OUT/montana-protocol-latest.tar.gz.new" log "→ zip (git archive)" GIT_DIR="$REPO_DIR" git -c filter.lfs.smudge= -c filter.lfs.required=false \ archive --format=zip -6 HEAD \ > "$OUT/montana-protocol-latest.zip.new" log "→ site-essentials (без бинарных ассетов)" tar -C /var/www -czf "$OUT/site-essentials.tar.gz.new" \ --exclude='*/node_modules' \ --exclude='*/__pycache__' \ --exclude='*.pyc' \ --exclude='*.log' \ --exclude='*.apk' \ --exclude='*.apk.bak*' \ --exclude='*.jpg' \ --exclude='*.jpeg' \ --exclude='*.png' \ --exclude='*.gif' \ --exclude='*.mp4' \ --exclude='*.webm' \ --exclude='*.zip' \ --exclude='*.tar.gz' \ --exclude='*/junona-app/dist' \ --exclude='*/messenger-backend' \ --exclude='montana_quest/vpn/city' \ montana_quest montana_hub_landing || echo "tar warn" log "→ sha256 + атомарный rename" ( cd "$OUT" && \ sha256sum montana-protocol-latest.tar.gz.new \ montana-protocol-latest.zip.new \ site-essentials.tar.gz.new \ | sed 's/\.new$//' > SHA256SUMS.new && \ mv -f montana-protocol-latest.tar.gz.new montana-protocol-latest.tar.gz && \ mv -f montana-protocol-latest.zip.new montana-protocol-latest.zip && \ mv -f site-essentials.tar.gz.new site-essentials.tar.gz && \ mv -f SHA256SUMS.new SHA256SUMS ) log "→ листинг index.html" SIZE_TGZ=$(numfmt --to=iec --suffix=B $(stat -c%s "$OUT/montana-protocol-latest.tar.gz")) SIZE_ZIP=$(numfmt --to=iec --suffix=B $(stat -c%s "$OUT/montana-protocol-latest.zip")) SIZE_SITE=$(numfmt --to=iec --suffix=B $(stat -c%s "$OUT/site-essentials.tar.gz")) BUILT="$(ts)" cat > "$OUT/index.html" <
$SHORT_SHA · сборка $BUILT