changemaker.lite/scripts/upgrade-check.sh
bunker-admin da3e43fcf7 Add browser-based system upgrade UI with file-based IPC
API container writes trigger files to a shared volume (data/upgrade/),
and a systemd path watcher on the host detects them and runs the
upgrade scripts. This avoids giving the container Docker socket access.

- Add upgrade-check.sh (git fetch + compare + write status.json)
- Add upgrade-watcher.sh (systemd bridge, dispatches check/upgrade)
- Add systemd path/service units with placeholder substitution
- Modify upgrade.sh with --api-mode flag (progress.json + result.json)
- Add API upgrade module (service + routes, SUPER_ADMIN only)
- Add System tab to Settings page with version info, changelog,
  progress steps, and upgrade confirmation modal
- Add upgrade watcher installation to config.sh wizard
- Add data/upgrade/ shared volume to api service in docker-compose

Bunker Admin
2026-03-03 18:00:15 -07:00

106 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================================
# Changemaker Lite V2 — Upgrade Check Script
# Checks for available updates and writes status to data/upgrade/status.json.
# Safe to run via cron or on-demand via file trigger.
# Usage: ./scripts/upgrade-check.sh [--branch BRANCH]
# =============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
UPGRADE_DIR="${PROJECT_DIR}/data/upgrade"
STATUS_FILE="${UPGRADE_DIR}/status.json"
BRANCH=""
# --- Parse Arguments ---
while [[ $# -gt 0 ]]; do
case "$1" in
--branch) BRANCH="$2"; shift 2 ;;
*) shift ;;
esac
done
cd "$PROJECT_DIR"
mkdir -p "$UPGRADE_DIR"
# Determine branch
if [[ -z "$BRANCH" ]]; then
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
fi
# Write an error status and exit
write_error() {
local msg="$1"
cat > "$STATUS_FILE" <<EOF
{
"branch": "${BRANCH}",
"currentCommit": "$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")",
"currentCommitFull": "$(git rev-parse HEAD 2>/dev/null || echo "unknown")",
"currentMessage": "$(git log -1 --format='%s' HEAD 2>/dev/null | sed 's/"/\\"/g' || echo "")",
"currentDate": "$(git log -1 --format='%aI' HEAD 2>/dev/null || echo "")",
"remoteCommit": null,
"commitsBehind": 0,
"changelog": [],
"checkedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"error": "${msg}"
}
EOF
exit 1
}
# Fetch latest from remote
if ! timeout 30 git fetch origin "$BRANCH" 2>/dev/null; then
write_error "Failed to reach git remote"
fi
# Gather info
CURRENT_COMMIT="$(git rev-parse HEAD)"
CURRENT_SHORT="$(git rev-parse --short HEAD)"
CURRENT_MSG="$(git log -1 --format='%s' HEAD | sed 's/"/\\"/g')"
CURRENT_DATE="$(git log -1 --format='%aI' HEAD)"
REMOTE_COMMIT="$(git rev-parse "origin/${BRANCH}" 2>/dev/null || echo "")"
REMOTE_SHORT="$(git rev-parse --short "origin/${BRANCH}" 2>/dev/null || echo "")"
if [[ -z "$REMOTE_COMMIT" ]]; then
write_error "Remote branch origin/${BRANCH} not found"
fi
# Count commits behind
COMMITS_BEHIND=0
if [[ "$CURRENT_COMMIT" != "$REMOTE_COMMIT" ]]; then
COMMITS_BEHIND="$(git rev-list --count HEAD..origin/"${BRANCH}" 2>/dev/null || echo "0")"
fi
# Build changelog (last 30 commits we're behind)
CHANGELOG="[]"
if [[ "$COMMITS_BEHIND" -gt 0 ]]; then
CHANGELOG="$(git log --oneline --format='{"hash":"%h","message":"%s","date":"%aI","author":"%an"}' HEAD..origin/"${BRANCH}" 2>/dev/null | head -30 | while IFS= read -r line; do
# Escape any double quotes in the message that aren't already escaped
echo "$line"
done | paste -sd ',' | sed 's/^/[/' | sed 's/$/]/')"
# Fallback if jq-less approach fails
if [[ -z "$CHANGELOG" ]] || [[ "$CHANGELOG" == "[]" ]]; then
CHANGELOG="[]"
fi
fi
# Write status
cat > "$STATUS_FILE" <<EOF
{
"branch": "${BRANCH}",
"currentCommit": "${CURRENT_SHORT}",
"currentCommitFull": "${CURRENT_COMMIT}",
"currentMessage": "${CURRENT_MSG}",
"currentDate": "${CURRENT_DATE}",
"remoteCommit": "${REMOTE_SHORT}",
"remoteCommitFull": "${REMOTE_COMMIT}",
"commitsBehind": ${COMMITS_BEHIND},
"changelog": ${CHANGELOG},
"checkedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"error": null
}
EOF
echo "Update check complete: ${COMMITS_BEHIND} commit(s) behind on ${BRANCH}"