build: add update.sh for production updates, deploy to /opt/nextwks/
This commit is contained in:
parent
461a9a7249
commit
583e1a5eea
2 changed files with 38 additions and 216 deletions
|
|
@ -207,6 +207,8 @@ header "── Installing ──"
|
|||
$SUDO mkdir -p "$BIN_DIR" "$DATA_DIR" "$STATIC_DIR"
|
||||
$SUDO cp "$REPO_DIR/app/core" "$BIN_DIR/core"
|
||||
$SUDO chmod 755 "$BIN_DIR/core"
|
||||
$SUDO cp "$REPO_DIR/update.sh" "$INSTALL_DIR/update.sh"
|
||||
$SUDO chmod +x "$INSTALL_DIR/update.sh"
|
||||
$SUDO chown -R "$SVC_USER:$SVC_USER" "$DATA_DIR" 2>/dev/null || true
|
||||
[ -d "$REPO_DIR/app/static" ] && $SUDO cp -r "$REPO_DIR/app/static"/* "$STATIC_DIR/"
|
||||
success "Copied files to $INSTALL_DIR/"
|
||||
|
|
|
|||
252
update.sh
252
update.sh
|
|
@ -1,231 +1,51 @@
|
|||
#!/bin/bash
|
||||
# ============================================================
|
||||
# Next Workspace — Update Script
|
||||
#
|
||||
# Checks for new versions of NextWks + Authelia,
|
||||
# shows changelog, asks approval, updates safely with rollback.
|
||||
#
|
||||
# Usage:
|
||||
# ./update.sh Check + interactive update
|
||||
# ./update.sh --check Check only, no update
|
||||
# ./update.sh --rollback Revert to previous backup
|
||||
# NextWks — Production Update Script
|
||||
# Pulls latest code, rebuilds, restarts services
|
||||
# Run: cd /opt/nextwks && sudo bash update.sh
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
|
||||
error() { echo -e "${RED}Error:${NC} $1" >&2; }
|
||||
success() { echo -e "${GREEN}$1${NC}"; }
|
||||
info() { echo -e "${BLUE}$1${NC}"; }
|
||||
warn() { echo -e "${YELLOW}$1${NC}"; }
|
||||
header() { echo -e "\n${BOLD}${CYAN}$1${NC}"; }
|
||||
GREEN='\033[0;32m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||||
info() { echo -e "${BLUE}$1${NC}"; }
|
||||
ok() { echo -e "${GREEN}$1${NC}"; }
|
||||
|
||||
REPO_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
NEXTWKS_BIN="/opt/nextwks/bin/core"
|
||||
AUTHELIA_BIN="/opt/authelia/authelia"
|
||||
BACKUP_DIR="/opt/nextwks/backups"
|
||||
REPO_URL="https://git.lohmar.co.uk/lexton-it/NextWks.git"
|
||||
REPO_DIR="/tmp/nextwks-update"
|
||||
INSTALL_DIR="/opt/nextwks"
|
||||
BIN_DIR="${INSTALL_DIR}/bin"
|
||||
|
||||
# ============================================================
|
||||
# HELPERS
|
||||
# ============================================================
|
||||
installed_version() {
|
||||
if [ -f "$NEXTWKS_BIN" ]; then
|
||||
curl -s --max-time 2 http://localhost:8080/api/version 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin).get('version','unknown'))" 2>/dev/null || echo "unknown"
|
||||
else
|
||||
echo "not-installed"
|
||||
fi
|
||||
}
|
||||
info "Updating NextWks..."
|
||||
|
||||
authelia_installed_version() {
|
||||
if [ -f "$AUTHELIA_BIN" ]; then
|
||||
"$AUTHELIA_BIN" version 2>/dev/null | head -1 | awk '{print $3}' | sed 's/v//' || echo "unknown"
|
||||
else
|
||||
echo "not-installed"
|
||||
fi
|
||||
}
|
||||
# Clone fresh copy
|
||||
rm -rf "$REPO_DIR" 2>/dev/null
|
||||
git clone --depth 1 "$REPO_URL" "$REPO_DIR" --quiet
|
||||
|
||||
backup() { mkdir -p "$BACKUP_DIR" && cp "$1" "$BACKUP_DIR/$(basename "$1").$(date +%s)" 2>/dev/null; }
|
||||
health_ok() { [ "$(curl -s --max-time 3 http://localhost:8080/api/health 2>/dev/null)" = '{"status":"ok"}' ]; }
|
||||
# Read new version
|
||||
VERSION=$(cat "$REPO_DIR/VERSION" 2>/dev/null || echo "dev")
|
||||
|
||||
# ============================================================
|
||||
# CHECK
|
||||
# ============================================================
|
||||
MODE="${1:-}"
|
||||
[ "$MODE" = "--rollback" ] && { header "Rollback"; ls -t "$BACKUP_DIR"/* 2>/dev/null | head -5; warn "Not implemented yet — restore manually"; exit 0; }
|
||||
# Build
|
||||
cd "$REPO_DIR/src"
|
||||
go build -ldflags="-s -w \
|
||||
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.Version=${VERSION} \
|
||||
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.BuildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
|
||||
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.CommitSHA=$(git rev-parse --short HEAD)" \
|
||||
-o /tmp/nextwks-core .
|
||||
|
||||
header "── Checking for Updates ──"
|
||||
# Replace
|
||||
systemctl stop nextwks
|
||||
cp /tmp/nextwks-core "$BIN_DIR/core"
|
||||
chmod 755 "$BIN_DIR/core"
|
||||
chown nextwks:nextwks "$BIN_DIR/core"
|
||||
systemctl start nextwks
|
||||
sleep 2
|
||||
|
||||
# --- NextWks ---
|
||||
CURRENT_NW=$(installed_version)
|
||||
info "NextWks: installed = ${CURRENT_NW}"
|
||||
|
||||
# Fetch latest tag from Forgejo
|
||||
LATEST_TAG=$(curl -s --max-time 5 "https://git.lohmar.co.uk/api/v1/repos/lexton-it/NextWks/releases?limit=1" 2>/dev/null | python3 -c "import sys,json; r=json.load(sys.stdin); print(r[0]['tag_name'].lstrip('v') if r else '0')" 2>/dev/null || echo "0")
|
||||
|
||||
# Also check git tag if repo is local
|
||||
if [ -d "$REPO_DIR/.git" ]; then
|
||||
cd "$REPO_DIR"
|
||||
git fetch --tags --quiet 2>/dev/null || true
|
||||
GIT_LATEST=$(git tag -l 'v*' --sort=-v:refname | head -1 | sed 's/^v//')
|
||||
[ -n "$GIT_LATEST" ] && LATEST_TAG="$GIT_LATEST"
|
||||
fi
|
||||
|
||||
info "NextWks: latest = ${LATEST_TAG:-unknown}"
|
||||
|
||||
NW_UPDATE=false
|
||||
[ "$CURRENT_NW" != "$LATEST_TAG" ] && [ -n "$LATEST_TAG" ] && [ "$LATEST_TAG" != "0" ] && NW_UPDATE=true
|
||||
|
||||
if $NW_UPDATE; then
|
||||
warn " ↳ Update available!"
|
||||
cd "$REPO_DIR"
|
||||
if [ -d "$REPO_DIR/.git" ]; then
|
||||
echo ""
|
||||
info "Recent commits since ${CURRENT_NW}:"
|
||||
git log "v${CURRENT_NW}..v${LATEST_TAG}" --oneline 2>/dev/null | head -10 || echo " (no local repo)"
|
||||
fi
|
||||
# Verify
|
||||
if curl -s --max-time 3 http://localhost:8080/api/health | grep -q ok; then
|
||||
ok "Updated to v${VERSION}"
|
||||
else
|
||||
success " ↳ Up to date"
|
||||
echo "Health check failed — check journalctl -u nextwks"
|
||||
fi
|
||||
|
||||
# --- Authelia ---
|
||||
CURRENT_AH=$(authelia_installed_version)
|
||||
info "Authelia: installed = ${CURRENT_AH}"
|
||||
|
||||
LATEST_AH=$(curl -s --max-time 5 "https://api.github.com/repos/authelia/authelia/releases/latest" 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin)['tag_name'].lstrip('v'))" 2>/dev/null || echo "unknown")
|
||||
|
||||
info "Authelia: latest = ${LATEST_AH:-unknown}"
|
||||
|
||||
AH_UPDATE=false
|
||||
[ "$CURRENT_AH" != "$LATEST_AH" ] && [ -n "$LATEST_AH" ] && [ "$LATEST_AH" != "unknown" ] && AH_UPDATE=true
|
||||
|
||||
if $AH_UPDATE; then
|
||||
warn " ↳ Update available!"
|
||||
else
|
||||
success " ↳ Up to date"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ "$MODE" = "--check" ]; then
|
||||
echo "Run without --check to install updates."; exit 0
|
||||
fi
|
||||
|
||||
if ! $NW_UPDATE && ! $AH_UPDATE; then
|
||||
success "Everything is up to date!"; exit 0
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# APPROVE
|
||||
# ============================================================
|
||||
header "── Approval ──"
|
||||
echo ""
|
||||
info "The following will be updated:"
|
||||
$NW_UPDATE && info " • NextWks: ${CURRENT_NW} → ${LATEST_TAG}"
|
||||
$AH_UPDATE && info " • Authelia: ${CURRENT_AH} → ${LATEST_AH}"
|
||||
echo ""
|
||||
read -p " Proceed with update? [y/N]: " CONFIRM
|
||||
[ "$CONFIRM" != "y" ] && [ "$CONFIRM" != "Y" ] && { echo "Aborted."; exit 0; }
|
||||
|
||||
# ============================================================
|
||||
# UPDATE NEXTWKS
|
||||
# ============================================================
|
||||
if $NW_UPDATE; then
|
||||
header "── Updating NextWks ──"
|
||||
|
||||
# Backup current binary
|
||||
if [ -f "$NEXTWKS_BIN" ]; then
|
||||
backup "$NEXTWKS_BIN"
|
||||
success "Backed up current binary"
|
||||
fi
|
||||
|
||||
# Pull latest source
|
||||
cd "$REPO_DIR"
|
||||
if [ -d "$REPO_DIR/.git" ]; then
|
||||
info "Pulling latest code..."
|
||||
git pull origin main --quiet 2>/dev/null || { error "git pull failed"; exit 1; }
|
||||
git checkout "v${LATEST_TAG}" --quiet 2>/dev/null || git checkout main --quiet 2>/dev/null
|
||||
fi
|
||||
|
||||
# Build
|
||||
cd "$REPO_DIR/src"
|
||||
info "Building..."
|
||||
BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
COMMIT_SHA=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||
|
||||
go build -ldflags="-s -w \
|
||||
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.Version=${LATEST_TAG} \
|
||||
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.BuildTime=${BUILD_TIME} \
|
||||
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.CommitSHA=${COMMIT_SHA}" \
|
||||
-o "$REPO_DIR/app/core" .
|
||||
success "Built ${LATEST_TAG}"
|
||||
|
||||
# Replace
|
||||
systemctl stop nextwks 2>/dev/null || true
|
||||
cp "$REPO_DIR/app/core" "$NEXTWKS_BIN"
|
||||
systemctl start nextwks
|
||||
sleep 3
|
||||
|
||||
if health_ok; then
|
||||
success "NextWks ${LATEST_TAG} — OK"
|
||||
else
|
||||
error "Health check failed — rolling back..."
|
||||
LATEST_BACKUP=$(ls -t "$BACKUP_DIR/core."* 2>/dev/null | head -1)
|
||||
if [ -n "$LATEST_BACKUP" ]; then
|
||||
systemctl stop nextwks 2>/dev/null || true
|
||||
cp "$LATEST_BACKUP" "$NEXTWKS_BIN"
|
||||
systemctl start nextwks
|
||||
sleep 2
|
||||
health_ok && success "Rollback successful" || error "Rollback also failed — manual intervention needed"
|
||||
else
|
||||
error "No backup found"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# UPDATE AUTHELIA
|
||||
# ============================================================
|
||||
if $AH_UPDATE; then
|
||||
header "── Updating Authelia ──"
|
||||
|
||||
if [ -f "$AUTHELIA_BIN" ]; then
|
||||
backup "$AUTHELIA_BIN"
|
||||
success "Backed up Authelia binary"
|
||||
fi
|
||||
|
||||
info "Downloading Authelia ${LATEST_AH}..."
|
||||
wget -q "https://github.com/authelia/authelia/releases/download/v${LATEST_AH}/authelia-v${LATEST_AH}-linux-amd64.tar.gz" -O /tmp/authelia-update.tar.gz
|
||||
tar -xzf /tmp/authelia-update.tar.gz -C /tmp/
|
||||
rm -f /tmp/authelia-update.tar.gz
|
||||
|
||||
systemctl stop authelia 2>/dev/null || true
|
||||
cp "/tmp/authelia-linux-amd64" "$AUTHELIA_BIN"
|
||||
chmod +x "$AUTHELIA_BIN"
|
||||
rm -f /tmp/authelia-linux-amd64
|
||||
systemctl start authelia
|
||||
sleep 3
|
||||
|
||||
if curl -s --max-time 3 http://127.0.0.1:9091/api/health 2>/dev/null | grep -q OK; then
|
||||
success "Authelia ${LATEST_AH} — OK"
|
||||
else
|
||||
error "Authelia health check failed — rolling back..."
|
||||
LATEST_BACKUP=$(ls -t "$BACKUP_DIR/authelia."* 2>/dev/null | head -1)
|
||||
if [ -n "$LATEST_BACKUP" ]; then
|
||||
systemctl stop authelia 2>/dev/null || true
|
||||
cp "$LATEST_BACKUP" "$AUTHELIA_BIN"
|
||||
systemctl start authelia
|
||||
sleep 2
|
||||
curl -s --max-time 3 http://127.0.0.1:9091/api/health | grep -q OK && success "Rollback OK" || error "Rollback failed"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# DONE
|
||||
# ============================================================
|
||||
echo ""
|
||||
success "════════════════════════════════════════"
|
||||
success " Update complete"
|
||||
success "════════════════════════════════════════"
|
||||
echo ""
|
||||
info " NextWks: $(installed_version)"
|
||||
info " Authelia: $(authelia_installed_version)"
|
||||
echo ""
|
||||
# Cleanup
|
||||
rm -rf "$REPO_DIR" /tmp/nextwks-core
|
||||
|
|
|
|||
Loading…
Reference in a new issue