#!/bin/sh set -eu CONFIG_FILE=${DASHBOARD_UPDATE_CONFIG:-/etc/proxmox-dashboard/update.env} STATUS_FILE=${DASHBOARD_UPDATE_STATUS_PATH:-/var/lib/proxmox-dashboard/update-status.json} BINARY_PATH=${DASHBOARD_BINARY_PATH:-/usr/local/bin/proxmox-cpu-dashboard} REQUEST_FILE=${DASHBOARD_UPDATE_REQUEST_PATH:-/var/lib/proxmox-dashboard/update-request} if [ -f "$CONFIG_FILE" ]; then # shellcheck disable=SC1090 . "$CONFIG_FILE" fi GITEA_URL=${GITEA_URL:-https://git.myown.center} GITEA_REPOSITORY=${GITEA_REPOSITORY:-maxim/ProxmoxDash} GITEA_TOKEN=${GITEA_TOKEN:-} UPDATE_MODE=${UPDATE_MODE:-notify} ASSET_NAME=${ASSET_NAME:-proxmox-dashboard-linux-amd64} manual_request=false if [ -f "$REQUEST_FILE" ]; then manual_request=true rm -f "$REQUEST_FILE" fi mkdir -p "$(dirname "$STATUS_FILE")" tmp_dir=$(mktemp -d /tmp/proxmox-dashboard-update.XXXXXX) trap 'rm -rf "$tmp_dir"' EXIT INT TERM auth_header="" if [ -n "$GITEA_TOKEN" ]; then auth_header="Authorization: token $GITEA_TOKEN" fi api_get() { if [ -n "$auth_header" ]; then curl --fail --silent --show-error --location --header "$auth_header" "$1" else curl --fail --silent --show-error --location "$1" fi } write_status() { python3 - "$STATUS_FILE" "$1" "$2" "$3" "$4" "$5" "$6" <<'PY' import datetime, json, os, sys, tempfile path, current, available, state, mode, message, release_url = sys.argv[1:] payload = { "currentVersion": current, "availableVersion": available, "state": state, "mode": mode, "message": message, "releaseUrl": release_url, "checkedAt": datetime.datetime.now(datetime.timezone.utc).isoformat(), } fd, temporary = tempfile.mkstemp(dir=os.path.dirname(path), prefix=".update-status-") with os.fdopen(fd, "w") as stream: json.dump(payload, stream) os.chmod(temporary, 0o644) os.replace(temporary, path) PY } current_version=$($BINARY_PATH -version 2>/dev/null || printf 'dev') release_json=$(api_get "$GITEA_URL/api/v1/repos/$GITEA_REPOSITORY/releases/latest") printf '%s' "$release_json" > "$tmp_dir/release.json" release_data=$(python3 - "$tmp_dir/release.json" "$ASSET_NAME" <<'PY' import json, sys release = json.load(open(sys.argv[1])) asset_name = sys.argv[2] assets = {item.get("name"): item.get("browser_download_url") for item in release.get("assets", [])} binary = assets.get(asset_name, "") checksum = assets.get(asset_name + ".sha256", "") print(release.get("tag_name", "")) print(release.get("html_url", "")) print(binary) print(checksum) PY ) latest_version=$(printf '%s\n' "$release_data" | sed -n '1p') release_url=$(printf '%s\n' "$release_data" | sed -n '2p') binary_url=$(printf '%s\n' "$release_data" | sed -n '3p') checksum_url=$(printf '%s\n' "$release_data" | sed -n '4p') if [ -z "$latest_version" ] || [ -z "$binary_url" ]; then write_status "$current_version" "$latest_version" error "$UPDATE_MODE" "В свежем релизе не найден бинарник $ASSET_NAME." "$release_url" exit 1 fi newest=$(printf '%s\n%s\n' "$current_version" "$latest_version" | sort -V | tail -n 1) if [ "$current_version" = "$latest_version" ] || [ "$newest" = "$current_version" ]; then write_status "$current_version" "$latest_version" current "$UPDATE_MODE" "Установлена свежая версия." "$release_url" exit 0 fi if [ "$UPDATE_MODE" != "auto" ] && [ "$manual_request" != "true" ]; then write_status "$current_version" "$latest_version" available "$UPDATE_MODE" "Доступна новая версия $latest_version." "$release_url" exit 0 fi write_status "$current_version" "$latest_version" installing "$UPDATE_MODE" "Скачиваем и проверяем $latest_version." "$release_url" api_get "$binary_url" > "$tmp_dir/$ASSET_NAME" if [ -n "$checksum_url" ]; then api_get "$checksum_url" > "$tmp_dir/$ASSET_NAME.sha256" (cd "$tmp_dir" && sha256sum -c "$ASSET_NAME.sha256") fi chmod 0755 "$tmp_dir/$ASSET_NAME" file "$tmp_dir/$ASSET_NAME" | grep -q 'ELF 64-bit' cp -p "$BINARY_PATH" "$BINARY_PATH.previous" install -m 0755 "$tmp_dir/$ASSET_NAME" "$BINARY_PATH" write_status "$latest_version" "$latest_version" updated "$UPDATE_MODE" "Обновление $latest_version установлено." "$release_url" systemctl restart proxmox-cpu-dashboard.service