Files
mc-webui/scripts/update.sh
T
MarekWoandClaude Opus 5 60faa44d37 feat(updater): one-click updates for Docker Hub installations
The version check already worked for an installation running the published
image - CI freezes the version before building, so version_frozen.py ships
inside it - but "Update now" never appeared, because the webhook behind it
was installed from scripts/, a folder such an installation does not have.
And update.sh could not have served it anyway: it does git pull + rebuild.

- both installers accept being piped through bash (curl | sudo bash). They
  then download what they need into /opt/mc-webui-{updater,watchdog} and
  find the instance by looking for docker-compose.yml. A checkout install
  keeps running its scripts from the checkout, unchanged
- updater.py picks the update path per request: git checkout -> update.sh,
  bare docker-compose.yml -> the new update-image.sh (pull + recreate).
  Resolved per request, so cloning the repo later flips it without a restart
- both update scripts end with MC_UPDATE_RESULT=updated|no_change, which
  the webhook parses and /api/updater/status passes on. The UI used to
  watch only for the version to change and then claim it timed out after
  two minutes - the normal outcome right after a push, while the image for
  that commit is still building. It now says so as soon as the run ends,
  in a neutral state rather than a red cross
- the marker prints only when stdout is not a terminal, so mcupdate output
  stays as it was

Also corrects the claim, in the README and in updater.py's own docstring,
that the webhook listens on localhost. It binds 0.0.0.0 - the container
reaches it over the Docker bridge - and sends no token, so port 5050 is
worth keeping off untrusted networks.

Verified: update-image.sh reports updated then no_change against a real
docker compose project; the standalone installer installs, runs and
uninstalls cleanly under systemd (WSL), with the app reaching it through
host.docker.internal and a triggered run coming back changed=false; the
resulting modal checked in a browser in both en and pl.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 18:53:35 +02:00

116 lines
3.4 KiB
Bash
Executable File

#!/bin/bash
#
# mc-webui update script
# Updates the application from Git and rebuilds Docker containers
#
# Usage:
# ./scripts/update.sh # Run from mc-webui directory
# mcupdate # If alias is configured (see README)
#
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Print colored status messages
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
# Determine mc-webui directory
if [ -f "docker-compose.yml" ] && [ -d "app" ]; then
MCWEBUI_DIR="$(pwd)"
elif [ -n "$MCWEBUI_DIR" ] && [ -d "$MCWEBUI_DIR" ]; then
cd "$MCWEBUI_DIR"
elif [ -d "$HOME/mc-webui" ]; then
MCWEBUI_DIR="$HOME/mc-webui"
cd "$MCWEBUI_DIR"
else
error "Cannot find mc-webui directory. Run from mc-webui folder or set MCWEBUI_DIR environment variable."
fi
info "Updating mc-webui in: $MCWEBUI_DIR"
echo ""
# Step 1: Git pull
info "Pulling latest changes from Git..."
BEFORE_HEAD="$(git rev-parse HEAD 2>/dev/null || echo unknown)"
# Force HTTP/1.1 for the pull. GitHub's HTTP/2 edge rejects the anonymous
# git-upload-pack POST sent by older git/libcurl (e.g. Debian bookworm's
# git 2.39 + libcurl 7.88) with a 401, which git reports as a credential
# prompt - "Username for 'https://github.com'" - even on this public repo.
# GIT_TERMINAL_PROMPT=0 turns any auth failure into an error instead of
# leaving the script waiting on stdin forever.
if GIT_TERMINAL_PROMPT=0 git -c http.version=HTTP/1.1 pull; then
success "Git pull completed"
else
error "Git pull failed"
fi
AFTER_HEAD="$(git rev-parse HEAD 2>/dev/null || echo unknown)"
if [ "$BEFORE_HEAD" == "$AFTER_HEAD" ]; then
CHANGED=false
warn "Already on the newest commit - rebuilding anyway to be sure."
else
CHANGED=true
fi
echo ""
# Step 2: Freeze version
info "Freezing version..."
if python3 -m app.version freeze; then
success "Version frozen"
else
warn "Version freeze failed (non-critical, continuing...)"
fi
echo ""
# Step 3: Rebuild and restart containers
info "Rebuilding and restarting Docker containers..."
if docker compose up -d --build; then
success "Containers rebuilt and started"
else
error "Docker compose failed"
fi
echo ""
# Step 4: Show status
info "Container status:"
docker compose ps
echo ""
# Step 5: Show version
if command -v curl &> /dev/null; then
sleep 2 # Wait for container to start
VERSION=$(curl -s http://localhost:5000/api/version 2>/dev/null | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
if [ -n "$VERSION" ]; then
success "mc-webui updated to version: $VERSION"
else
warn "Could not fetch version (container may still be starting)"
fi
fi
echo ""
if [ "$CHANGED" == "true" ]; then
echo -e "${GREEN}Update complete!${NC}"
else
echo -e "${YELLOW}Nothing new was pulled - already on the newest commit.${NC}"
fi
# Machine-readable result for the updater webhook - keep this the last line.
# Only when stdout is not a terminal: the webhook captures output through a
# pipe, while a human running this by hand has already read the same thing in
# plain words just above and does not need the marker in their terminal.
if [ ! -t 1 ]; then
if [ "$CHANGED" == "true" ]; then
echo "MC_UPDATE_RESULT=updated"
else
echo "MC_UPDATE_RESULT=no_change"
fi
fi