Fix media-api restart loop and add registry build scripts
- Fix @/utils/logger path alias (tsc doesn't transform @/ in output) - Add JWT_INVITE_SECRET to media-api compose environment block - Fix redis-exporter depends_on to use service name not container name - Fix upgrade.sh: restore tracked files deleted by restore_user_paths - Add scripts/build-and-push.sh for building + pushing production images - Add scripts/mirror-images.sh for mirroring third-party images Bunker Admin
This commit is contained in:
parent
e6e324262f
commit
be2fa5d80b
@ -1,7 +1,7 @@
|
|||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { logger } from '@/utils/logger';
|
import { logger } from '../../../utils/logger';
|
||||||
|
|
||||||
export interface ThumbnailOptions {
|
export interface ThumbnailOptions {
|
||||||
videoPath: string;
|
videoPath: string;
|
||||||
|
|||||||
@ -9,6 +9,7 @@ services:
|
|||||||
|
|
||||||
# Unified Express.js API
|
# Unified Express.js API
|
||||||
api:
|
api:
|
||||||
|
image: ${GITEA_REGISTRY:-gitea.bnkops.com/admin}/changemaker-api:${IMAGE_TAG:-local}
|
||||||
build:
|
build:
|
||||||
context: ./api
|
context: ./api
|
||||||
target: ${BUILD_TARGET:-development}
|
target: ${BUILD_TARGET:-development}
|
||||||
@ -97,6 +98,10 @@ services:
|
|||||||
- SMS_DEVICE_MONITOR_INTERVAL_MS=${SMS_DEVICE_MONITOR_INTERVAL_MS:-30000}
|
- SMS_DEVICE_MONITOR_INTERVAL_MS=${SMS_DEVICE_MONITOR_INTERVAL_MS:-30000}
|
||||||
# Docker container status via socket proxy (read-only, containers endpoint only)
|
# Docker container status via socket proxy (read-only, containers endpoint only)
|
||||||
- DOCKER_PROXY_URL=http://docker-socket-proxy:2375
|
- DOCKER_PROXY_URL=http://docker-socket-proxy:2375
|
||||||
|
# Container Registry
|
||||||
|
- GITEA_REGISTRY=${GITEA_REGISTRY:-gitea.bnkops.com/admin}
|
||||||
|
- GITEA_REGISTRY_USER=${GITEA_REGISTRY_USER:-}
|
||||||
|
- GITEA_REGISTRY_PASS=${GITEA_REGISTRY_PASS:-}
|
||||||
volumes:
|
volumes:
|
||||||
- ./api:/app
|
- ./api:/app
|
||||||
- /app/node_modules
|
- /app/node_modules
|
||||||
@ -123,6 +128,7 @@ services:
|
|||||||
|
|
||||||
# Fastify Media API (Microservice for Media Management)
|
# Fastify Media API (Microservice for Media Management)
|
||||||
media-api:
|
media-api:
|
||||||
|
image: ${GITEA_REGISTRY:-gitea.bnkops.com/admin}/changemaker-media-api:${IMAGE_TAG:-local}
|
||||||
build:
|
build:
|
||||||
context: ./api
|
context: ./api
|
||||||
dockerfile: Dockerfile.media
|
dockerfile: Dockerfile.media
|
||||||
@ -144,6 +150,7 @@ services:
|
|||||||
- REDIS_URL=redis://:${REDIS_PASSWORD}@redis-changemaker:6379
|
- REDIS_URL=redis://:${REDIS_PASSWORD}@redis-changemaker:6379
|
||||||
- JWT_ACCESS_SECRET=${JWT_ACCESS_SECRET}
|
- JWT_ACCESS_SECRET=${JWT_ACCESS_SECRET}
|
||||||
- JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
|
- JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
|
||||||
|
- JWT_INVITE_SECRET=${JWT_INVITE_SECRET}
|
||||||
- CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:3000,http://localhost:3100}
|
- CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:3000,http://localhost:3100}
|
||||||
- ENABLE_MEDIA_FEATURES=${ENABLE_MEDIA_FEATURES:-true}
|
- ENABLE_MEDIA_FEATURES=${ENABLE_MEDIA_FEATURES:-true}
|
||||||
- MEDIA_ROOT=/media/local
|
- MEDIA_ROOT=/media/local
|
||||||
@ -174,6 +181,7 @@ services:
|
|||||||
|
|
||||||
# React Admin GUI (Vite dev server)
|
# React Admin GUI (Vite dev server)
|
||||||
admin:
|
admin:
|
||||||
|
image: ${GITEA_REGISTRY:-gitea.bnkops.com/admin}/changemaker-admin:${IMAGE_TAG:-local}
|
||||||
build:
|
build:
|
||||||
context: ./admin
|
context: ./admin
|
||||||
target: ${BUILD_TARGET:-development}
|
target: ${BUILD_TARGET:-development}
|
||||||
@ -228,6 +236,7 @@ services:
|
|||||||
|
|
||||||
# Nginx reverse proxy
|
# Nginx reverse proxy
|
||||||
nginx:
|
nginx:
|
||||||
|
image: ${GITEA_REGISTRY:-gitea.bnkops.com/admin}/changemaker-nginx:${IMAGE_TAG:-local}
|
||||||
build:
|
build:
|
||||||
context: ./nginx
|
context: ./nginx
|
||||||
container_name: changemaker-v2-nginx
|
container_name: changemaker-v2-nginx
|
||||||
@ -478,6 +487,7 @@ services:
|
|||||||
|
|
||||||
# Code Server — Browser IDE
|
# Code Server — Browser IDE
|
||||||
code-server:
|
code-server:
|
||||||
|
image: ${GITEA_REGISTRY:-gitea.bnkops.com/admin}/changemaker-code-server:${IMAGE_TAG:-local}
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile.code-server
|
dockerfile: Dockerfile.code-server
|
||||||
@ -1196,7 +1206,7 @@ services:
|
|||||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis-changemaker
|
- redis
|
||||||
networks:
|
networks:
|
||||||
- changemaker-lite
|
- changemaker-lite
|
||||||
profiles:
|
profiles:
|
||||||
|
|||||||
171
scripts/build-and-push.sh
Executable file
171
scripts/build-and-push.sh
Executable file
@ -0,0 +1,171 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Changemaker Lite V2 — Build & Push to Gitea Registry
|
||||||
|
# Builds production Docker images, tags with commit SHA + latest, and pushes
|
||||||
|
# to the Gitea container registry at gitea.bnkops.com/admin.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/build-and-push.sh [OPTIONS]
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# --services a,b,c Comma-separated list of services to build
|
||||||
|
# (default: api admin media-api nginx)
|
||||||
|
# --include-code-server Also build and push code-server (~9GB, slow)
|
||||||
|
# --no-push Build only, skip push (verify builds work)
|
||||||
|
# --tag TAG Override commit SHA tag (default: git rev-parse --short HEAD)
|
||||||
|
# --registry URL Override registry (default: gitea.bnkops.com/admin)
|
||||||
|
# --dry-run Print commands without executing
|
||||||
|
# --help Show this help
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# docker login gitea.bnkops.com
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
# --- Defaults ---
|
||||||
|
REGISTRY="${GITEA_REGISTRY:-gitea.bnkops.com/admin}"
|
||||||
|
COMMIT_SHA="$(git -C "$PROJECT_DIR" rev-parse --short HEAD 2>/dev/null || echo "local")"
|
||||||
|
TAG="${COMMIT_SHA}"
|
||||||
|
SERVICES="api admin media-api nginx"
|
||||||
|
INCLUDE_CODE_SERVER=false
|
||||||
|
NO_PUSH=false
|
||||||
|
DRY_RUN=false
|
||||||
|
|
||||||
|
# --- Colors ---
|
||||||
|
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
|
||||||
|
RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m'
|
||||||
|
BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m'
|
||||||
|
else
|
||||||
|
RED='' GREEN='' YELLOW='' BLUE='' CYAN='' BOLD='' NC=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
||||||
|
success() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||||
|
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||||
|
run() { if [[ "$DRY_RUN" == "true" ]]; then echo -e "${CYAN}[DRY-RUN]${NC} $*"; else eval "$@"; fi; }
|
||||||
|
|
||||||
|
# --- Arg parser ---
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--services) SERVICES="${2//,/ }"; shift 2 ;;
|
||||||
|
--include-code-server) INCLUDE_CODE_SERVER=true; shift ;;
|
||||||
|
--no-push) NO_PUSH=true; shift ;;
|
||||||
|
--tag) TAG="$2"; shift 2 ;;
|
||||||
|
--registry) REGISTRY="$2"; shift 2 ;;
|
||||||
|
--dry-run) DRY_RUN=true; shift ;;
|
||||||
|
--help|-h)
|
||||||
|
sed -n '2,30p' "$0" | grep '^#' | sed 's/^# \?//'
|
||||||
|
exit 0 ;;
|
||||||
|
*) error "Unknown option: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Add code-server if requested
|
||||||
|
if [[ "$INCLUDE_CODE_SERVER" == "true" ]]; then
|
||||||
|
SERVICES="$SERVICES code-server"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BOLD}Changemaker Lite — Build & Push${NC}"
|
||||||
|
echo " Registry: $REGISTRY"
|
||||||
|
echo " Tag: $TAG"
|
||||||
|
echo " Services: $SERVICES"
|
||||||
|
echo " Push: $([[ "$NO_PUSH" == "true" ]] && echo "no" || echo "yes")"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# --- Build mapping: service → dockerfile + context ---
|
||||||
|
build_service() {
|
||||||
|
local svc="$1"
|
||||||
|
local image="$REGISTRY/changemaker-${svc}:${TAG}"
|
||||||
|
local image_latest="$REGISTRY/changemaker-${svc}:latest"
|
||||||
|
|
||||||
|
case "$svc" in
|
||||||
|
api)
|
||||||
|
info "Building api (Express + Prisma)..."
|
||||||
|
run docker buildx build \
|
||||||
|
--target production \
|
||||||
|
--tag "${image}" \
|
||||||
|
--tag "${image_latest}" \
|
||||||
|
--load \
|
||||||
|
"${PROJECT_DIR}/api"
|
||||||
|
;;
|
||||||
|
admin)
|
||||||
|
info "Building admin (React + Vite)..."
|
||||||
|
run docker buildx build \
|
||||||
|
--target production \
|
||||||
|
--tag "${image}" \
|
||||||
|
--tag "${image_latest}" \
|
||||||
|
--load \
|
||||||
|
"${PROJECT_DIR}/admin"
|
||||||
|
;;
|
||||||
|
media-api)
|
||||||
|
info "Building media-api (Fastify + FFmpeg)..."
|
||||||
|
run docker buildx build \
|
||||||
|
--target production \
|
||||||
|
--file "${PROJECT_DIR}/api/Dockerfile.media" \
|
||||||
|
--tag "${image}" \
|
||||||
|
--tag "${image_latest}" \
|
||||||
|
--load \
|
||||||
|
"${PROJECT_DIR}/api"
|
||||||
|
;;
|
||||||
|
nginx)
|
||||||
|
info "Building nginx (reverse proxy)..."
|
||||||
|
run docker buildx build \
|
||||||
|
--tag "${image}" \
|
||||||
|
--tag "${image_latest}" \
|
||||||
|
--load \
|
||||||
|
"${PROJECT_DIR}/nginx"
|
||||||
|
;;
|
||||||
|
code-server)
|
||||||
|
warn "Building code-server (~9GB) — this will take a while..."
|
||||||
|
run docker buildx build \
|
||||||
|
--file "${PROJECT_DIR}/Dockerfile.code-server" \
|
||||||
|
--tag "${image}" \
|
||||||
|
--tag "${image_latest}" \
|
||||||
|
--load \
|
||||||
|
"${PROJECT_DIR}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unknown service: $svc"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
success "Built ${svc} → ${image}"
|
||||||
|
|
||||||
|
if [[ "$NO_PUSH" == "false" ]]; then
|
||||||
|
info "Pushing ${svc}:${TAG}..."
|
||||||
|
run docker push "${image}"
|
||||||
|
run docker push "${image_latest}"
|
||||||
|
success "Pushed ${svc}:${TAG} + :latest"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Main ---
|
||||||
|
FAILED=()
|
||||||
|
for svc in $SERVICES; do
|
||||||
|
if ! build_service "$svc"; then
|
||||||
|
FAILED+=("$svc")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [[ ${#FAILED[@]} -eq 0 ]]; then
|
||||||
|
success "All services built${NO_PUSH:+ (not pushed)}."
|
||||||
|
echo ""
|
||||||
|
if [[ "$NO_PUSH" == "false" ]]; then
|
||||||
|
info "Images available in registry:"
|
||||||
|
for svc in $SERVICES; do
|
||||||
|
echo " ${REGISTRY}/changemaker-${svc}:${TAG}"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
info "To use these images: IMAGE_TAG=${TAG} docker compose pull ${SERVICES}"
|
||||||
|
info "Or set IMAGE_TAG=${TAG} in .env"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
error "Failed services: ${FAILED[*]}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
126
scripts/mirror-images.sh
Executable file
126
scripts/mirror-images.sh
Executable file
@ -0,0 +1,126 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Changemaker Lite V2 — Mirror Third-Party Images to Gitea Registry
|
||||||
|
# Pulls infrastructure images from Docker Hub and re-pushes to the Gitea
|
||||||
|
# container registry, protecting against Docker Hub rate limits.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/mirror-images.sh [OPTIONS]
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# --all Also mirror heavy optional images (Rocket.Chat, MongoDB, n8n,
|
||||||
|
# Gitea, Jitsi x4) in addition to core images
|
||||||
|
# --dry-run Print commands without executing
|
||||||
|
# --registry Override registry (default: gitea.bnkops.com/admin)
|
||||||
|
# --help Show this help
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# docker login gitea.bnkops.com
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
# --- Defaults ---
|
||||||
|
REGISTRY="${GITEA_REGISTRY:-gitea.bnkops.com/admin}"
|
||||||
|
INCLUDE_ALL=false
|
||||||
|
DRY_RUN=false
|
||||||
|
|
||||||
|
# --- Colors ---
|
||||||
|
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
|
||||||
|
RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m'
|
||||||
|
BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m'
|
||||||
|
else
|
||||||
|
RED='' GREEN='' YELLOW='' BLUE='' CYAN='' BOLD='' NC=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
||||||
|
success() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||||
|
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||||
|
run() { if [[ "$DRY_RUN" == "true" ]]; then echo -e "${CYAN}[DRY-RUN]${NC} $*"; else eval "$@"; fi; }
|
||||||
|
|
||||||
|
# --- Arg parser ---
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--all) INCLUDE_ALL=true; shift ;;
|
||||||
|
--dry-run) DRY_RUN=true; shift ;;
|
||||||
|
--registry) REGISTRY="$2"; shift 2 ;;
|
||||||
|
--help|-h)
|
||||||
|
sed -n '2,30p' "$0" | grep '^#' | sed 's/^# \?//'
|
||||||
|
exit 0 ;;
|
||||||
|
*) error "Unknown option: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- Core images (always mirrored) ---
|
||||||
|
CORE_IMAGES=(
|
||||||
|
"postgres:16-alpine"
|
||||||
|
"postgres:17-alpine"
|
||||||
|
"redis:7-alpine"
|
||||||
|
"nocodb/nocodb:0.301.3"
|
||||||
|
"listmonk/listmonk:v6.0.0"
|
||||||
|
"mailhog/mailhog:v1.0.1"
|
||||||
|
"prom/prometheus:v3.10.0"
|
||||||
|
"grafana/grafana:12.3.0"
|
||||||
|
"prom/alertmanager:v0.31.1"
|
||||||
|
"oliver006/redis_exporter:v1.81.0"
|
||||||
|
"gcr.io/cadvisor/cadvisor:v0.52.1"
|
||||||
|
"prom/node-exporter:v1.9.1"
|
||||||
|
"alpine:3"
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- Heavy optional images (--all flag) ---
|
||||||
|
OPTIONAL_IMAGES=(
|
||||||
|
"gitea/gitea:1.23"
|
||||||
|
"n8nio/n8n:1.83.2"
|
||||||
|
"rocket.chat:7.4.0"
|
||||||
|
"mongo:6.0"
|
||||||
|
"jitsi/web:stable-10168"
|
||||||
|
"jitsi/prosody:stable-10168"
|
||||||
|
"jitsi/jicofo:stable-10168"
|
||||||
|
"jitsi/jvb:stable-10168"
|
||||||
|
"gotify/server:2.6.1"
|
||||||
|
)
|
||||||
|
|
||||||
|
mirror_image() {
|
||||||
|
local source="$1"
|
||||||
|
# Get short name: last path segment + tag
|
||||||
|
local name_tag="${source##*/}"
|
||||||
|
local dest="${REGISTRY}/${name_tag}"
|
||||||
|
|
||||||
|
info "Mirroring ${source} → ${dest}..."
|
||||||
|
run docker pull "${source}"
|
||||||
|
run docker tag "${source}" "${dest}"
|
||||||
|
run docker push "${dest}"
|
||||||
|
success "Mirrored ${name_tag}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo -e "${BOLD}Changemaker Lite — Mirror Images${NC}"
|
||||||
|
echo " Registry: $REGISTRY"
|
||||||
|
echo " All: $INCLUDE_ALL"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
IMAGES=("${CORE_IMAGES[@]}")
|
||||||
|
if [[ "$INCLUDE_ALL" == "true" ]]; then
|
||||||
|
IMAGES+=("${OPTIONAL_IMAGES[@]}")
|
||||||
|
warn "Including heavy optional images — this will take a while"
|
||||||
|
fi
|
||||||
|
|
||||||
|
FAILED=()
|
||||||
|
for img in "${IMAGES[@]}"; do
|
||||||
|
if ! mirror_image "$img"; then
|
||||||
|
FAILED+=("$img")
|
||||||
|
warn "Failed to mirror: $img (continuing...)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [[ ${#FAILED[@]} -eq 0 ]]; then
|
||||||
|
success "All ${#IMAGES[@]} images mirrored to ${REGISTRY}"
|
||||||
|
else
|
||||||
|
warn "Mirrored $((${#IMAGES[@]} - ${#FAILED[@]}))/${#IMAGES[@]} images"
|
||||||
|
error "Failed: ${FAILED[*]}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@ -47,6 +47,7 @@ FORCE=false
|
|||||||
BRANCH=""
|
BRANCH=""
|
||||||
ROLLBACK=false
|
ROLLBACK=false
|
||||||
API_MODE=false
|
API_MODE=false
|
||||||
|
USE_REGISTRY=false
|
||||||
|
|
||||||
# --- Colors (respects NO_COLOR convention) ---
|
# --- Colors (respects NO_COLOR convention) ---
|
||||||
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
|
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
|
||||||
@ -145,7 +146,9 @@ restore_user_paths() {
|
|||||||
if [[ -e "$USER_SAVE_DIR/$p" ]]; then
|
if [[ -e "$USER_SAVE_DIR/$p" ]]; then
|
||||||
# Ensure parent directory exists (in case pull deleted it)
|
# Ensure parent directory exists (in case pull deleted it)
|
||||||
mkdir -p "$PROJECT_DIR/$(dirname "$p")"
|
mkdir -p "$PROJECT_DIR/$(dirname "$p")"
|
||||||
rm -rf "$PROJECT_DIR/$p"
|
# Use docker alpine to remove if regular rm fails (root-owned files from containers)
|
||||||
|
rm -rf "$PROJECT_DIR/$p" 2>/dev/null || \
|
||||||
|
docker run --rm -v "$PROJECT_DIR:/project" alpine rm -rf "/project/$p" 2>/dev/null || true
|
||||||
cp -a "$USER_SAVE_DIR/$p" "$PROJECT_DIR/$p"
|
cp -a "$USER_SAVE_DIR/$p" "$PROJECT_DIR/$p"
|
||||||
restored=$((restored + 1))
|
restored=$((restored + 1))
|
||||||
fi
|
fi
|
||||||
@ -279,6 +282,7 @@ Usage: ./scripts/upgrade.sh [OPTIONS]
|
|||||||
Options:
|
Options:
|
||||||
--skip-backup Skip backup phase (requires --force)
|
--skip-backup Skip backup phase (requires --force)
|
||||||
--pull-services Also pull new third-party Docker images
|
--pull-services Also pull new third-party Docker images
|
||||||
|
--use-registry Pull pre-built images from Gitea registry instead of rebuilding
|
||||||
--dry-run Show what would happen without executing
|
--dry-run Show what would happen without executing
|
||||||
--force Continue past non-critical warnings
|
--force Continue past non-critical warnings
|
||||||
--branch BRANCH Git branch to pull (default: current branch)
|
--branch BRANCH Git branch to pull (default: current branch)
|
||||||
@ -287,7 +291,8 @@ Options:
|
|||||||
--help Show this help message
|
--help Show this help message
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
./scripts/upgrade.sh # Standard upgrade
|
./scripts/upgrade.sh # Standard upgrade (build from source)
|
||||||
|
./scripts/upgrade.sh --use-registry # Fast upgrade using pre-built Gitea images
|
||||||
./scripts/upgrade.sh --dry-run # Preview changes
|
./scripts/upgrade.sh --dry-run # Preview changes
|
||||||
./scripts/upgrade.sh --pull-services # Also update PostgreSQL, Redis, etc.
|
./scripts/upgrade.sh --pull-services # Also update PostgreSQL, Redis, etc.
|
||||||
./scripts/upgrade.sh --rollback # Revert last upgrade
|
./scripts/upgrade.sh --rollback # Revert last upgrade
|
||||||
@ -304,6 +309,7 @@ while [[ $# -gt 0 ]]; do
|
|||||||
--branch) BRANCH="$2"; shift 2 ;;
|
--branch) BRANCH="$2"; shift 2 ;;
|
||||||
--rollback) ROLLBACK=true; shift ;;
|
--rollback) ROLLBACK=true; shift ;;
|
||||||
--api-mode) API_MODE=true; shift ;;
|
--api-mode) API_MODE=true; shift ;;
|
||||||
|
--use-registry) USE_REGISTRY=true; shift ;;
|
||||||
--help|-h) show_help ;;
|
--help|-h) show_help ;;
|
||||||
*) error "Unknown option: $1"; echo "Run with --help for usage."; exit 1 ;;
|
*) error "Unknown option: $1"; echo "Run with --help for usage."; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
@ -677,6 +683,15 @@ fi
|
|||||||
# Step 4b: Restore user-modifiable paths (unconditionally overwrites with saved copies)
|
# Step 4b: Restore user-modifiable paths (unconditionally overwrites with saved copies)
|
||||||
restore_user_paths
|
restore_user_paths
|
||||||
|
|
||||||
|
# Step 4c: Restore any tracked files accidentally deleted by restore_user_paths
|
||||||
|
# (can happen when save_user_paths can't read root-owned files in user paths)
|
||||||
|
DELETED_TRACKED="$(git ls-files --deleted 2>/dev/null || true)"
|
||||||
|
if [[ -n "$DELETED_TRACKED" ]]; then
|
||||||
|
info "Restoring $(echo "$DELETED_TRACKED" | wc -l | xargs) tracked file(s) deleted during restore..."
|
||||||
|
echo "$DELETED_TRACKED" | xargs git checkout HEAD -- 2>/dev/null || true
|
||||||
|
success "Tracked files restored from HEAD"
|
||||||
|
fi
|
||||||
|
|
||||||
# Step 5: Detect new env vars
|
# Step 5: Detect new env vars
|
||||||
info "Checking for new environment variables..."
|
info "Checking for new environment variables..."
|
||||||
if [[ -f "$PROJECT_DIR/.env.example" ]] && [[ -f "$PROJECT_DIR/.env" ]]; then
|
if [[ -f "$PROJECT_DIR/.env.example" ]] && [[ -f "$PROJECT_DIR/.env" ]]; then
|
||||||
@ -729,37 +744,89 @@ fi
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
phase "4" "Container Rebuild"
|
phase "4" "Container Rebuild"
|
||||||
write_progress 4 "Container Rebuild" 50 "Rebuilding containers..."
|
write_progress 4 "Container Rebuild" 50 "Preparing containers..."
|
||||||
|
|
||||||
# Always rebuild source-built containers
|
|
||||||
info "Rebuilding source containers: $SOURCE_CONTAINERS"
|
|
||||||
docker compose build $SOURCE_CONTAINERS
|
|
||||||
success "Source containers rebuilt"
|
|
||||||
|
|
||||||
# Conditionally rebuild containers whose Dockerfiles changed
|
|
||||||
CHANGED_FILES="$(git diff --name-only "$PRE_UPGRADE_COMMIT..HEAD" 2>/dev/null || true)"
|
CHANGED_FILES="$(git diff --name-only "$PRE_UPGRADE_COMMIT..HEAD" 2>/dev/null || true)"
|
||||||
for svc in $CONDITIONAL_CONTAINERS; do
|
|
||||||
case "$svc" in
|
if [[ "$USE_REGISTRY" == "true" ]]; then
|
||||||
nginx)
|
# --- Registry pull path: pull pre-built production images from Gitea ---
|
||||||
if echo "$CHANGED_FILES" | grep -q "^nginx/"; then
|
REGISTRY="${GITEA_REGISTRY:-gitea.bnkops.com/admin}"
|
||||||
info "Rebuilding nginx (config changed)..."
|
REGISTRY_TAG="$(git rev-parse --short HEAD 2>/dev/null || echo "latest")"
|
||||||
docker compose build nginx
|
export GITEA_REGISTRY="$REGISTRY"
|
||||||
success "nginx rebuilt"
|
export IMAGE_TAG="$REGISTRY_TAG"
|
||||||
else
|
export BUILD_TARGET=production
|
||||||
info "nginx unchanged, skipping rebuild"
|
|
||||||
|
info "Registry mode: ${REGISTRY} (tag: ${REGISTRY_TAG})"
|
||||||
|
write_progress 4 "Container Rebuild" 55 "Pulling images from registry..."
|
||||||
|
|
||||||
|
# Pull core app containers; fall back to source build if registry unavailable
|
||||||
|
if docker compose pull api admin media-api 2>/dev/null; then
|
||||||
|
success "Core images pulled from registry"
|
||||||
|
else
|
||||||
|
warn "Registry pull failed — falling back to source build"
|
||||||
|
docker compose build $SOURCE_CONTAINERS
|
||||||
|
success "Source containers rebuilt (registry fallback)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# nginx: pull if available, else rebuild only if config changed
|
||||||
|
if ! docker compose pull nginx 2>/dev/null; then
|
||||||
|
if echo "$CHANGED_FILES" | grep -q "^nginx/"; then
|
||||||
|
info "Rebuilding nginx (config changed, not in registry)..."
|
||||||
|
docker compose build nginx
|
||||||
|
success "nginx rebuilt"
|
||||||
|
else
|
||||||
|
info "nginx unchanged, skipping rebuild"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# code-server: pull from registry if Dockerfile changed; never build during upgrade
|
||||||
|
# (code-server is 9GB+ and takes 30+ min to build — run build-and-push.sh separately)
|
||||||
|
CS_IMAGE="${REGISTRY}/changemaker-code-server"
|
||||||
|
if docker image inspect "${CS_IMAGE}:${REGISTRY_TAG}" &>/dev/null 2>&1; then
|
||||||
|
info "code-server:${REGISTRY_TAG} already present, skipping"
|
||||||
|
elif docker compose pull code-server 2>/dev/null; then
|
||||||
|
success "code-server pulled from registry"
|
||||||
|
else
|
||||||
|
# Retag any existing local code-server image so compose up doesn't try to build it
|
||||||
|
for fallback_tag in local latest; do
|
||||||
|
if docker image inspect "${CS_IMAGE}:${fallback_tag}" &>/dev/null 2>&1; then
|
||||||
|
docker tag "${CS_IMAGE}:${fallback_tag}" "${CS_IMAGE}:${REGISTRY_TAG}" 2>/dev/null || true
|
||||||
|
info "Tagged code-server:${fallback_tag} → :${REGISTRY_TAG} (registry push pending)"
|
||||||
|
break
|
||||||
fi
|
fi
|
||||||
;;
|
done
|
||||||
code-server)
|
fi
|
||||||
if echo "$CHANGED_FILES" | grep -q "^Dockerfile.code-server"; then
|
|
||||||
info "Rebuilding code-server (Dockerfile changed)..."
|
else
|
||||||
docker compose build code-server
|
# --- Source build path (original behaviour) ---
|
||||||
success "code-server rebuilt"
|
info "Rebuilding source containers: $SOURCE_CONTAINERS"
|
||||||
else
|
docker compose build $SOURCE_CONTAINERS
|
||||||
info "code-server unchanged, skipping rebuild"
|
success "Source containers rebuilt"
|
||||||
fi
|
|
||||||
;;
|
# Conditionally rebuild containers whose Dockerfiles changed
|
||||||
esac
|
for svc in $CONDITIONAL_CONTAINERS; do
|
||||||
done
|
case "$svc" in
|
||||||
|
nginx)
|
||||||
|
if echo "$CHANGED_FILES" | grep -q "^nginx/"; then
|
||||||
|
info "Rebuilding nginx (config changed)..."
|
||||||
|
docker compose build nginx
|
||||||
|
success "nginx rebuilt"
|
||||||
|
else
|
||||||
|
info "nginx unchanged, skipping rebuild"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
code-server)
|
||||||
|
if echo "$CHANGED_FILES" | grep -q "^Dockerfile.code-server"; then
|
||||||
|
info "Rebuilding code-server (Dockerfile changed)..."
|
||||||
|
docker compose build code-server
|
||||||
|
success "code-server rebuilt"
|
||||||
|
else
|
||||||
|
info "code-server unchanged, skipping rebuild"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
# Optionally pull third-party images
|
# Optionally pull third-party images
|
||||||
if [[ "$PULL_SERVICES" == "true" ]]; then
|
if [[ "$PULL_SERVICES" == "true" ]]; then
|
||||||
@ -960,8 +1027,11 @@ fi
|
|||||||
# Restart monitoring if it was running before
|
# Restart monitoring if it was running before
|
||||||
if [[ "$MONITORING_WAS_RUNNING" == "true" ]]; then
|
if [[ "$MONITORING_WAS_RUNNING" == "true" ]]; then
|
||||||
info "Restarting monitoring stack..."
|
info "Restarting monitoring stack..."
|
||||||
docker compose --profile monitoring up -d
|
if docker compose --profile monitoring up -d 2>&1; then
|
||||||
success "Monitoring stack restarted"
|
success "Monitoring stack restarted"
|
||||||
|
else
|
||||||
|
warn "Monitoring stack restart had errors (non-fatal, services may already be running)"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user