From 583e1a5eead3cb61c7690dd10af57fae7b940d0e Mon Sep 17 00:00:00 2001 From: cclohmar Date: Sun, 14 Jun 2026 17:37:59 +0000 Subject: [PATCH] build: add update.sh for production updates, deploy to /opt/nextwks/ --- install.sh | 2 + update.sh | 252 ++++++++--------------------------------------------- 2 files changed, 38 insertions(+), 216 deletions(-) diff --git a/install.sh b/install.sh index 995a2f6..e29d2af 100755 --- a/install.sh +++ b/install.sh @@ -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/" diff --git a/update.sh b/update.sh index b358fc0..db403ca 100755 --- a/update.sh +++ b/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