feat(system): implement one-shot upgrade mode and enhance upgrade handling

This commit is contained in:
jxxghp
2026-05-05 15:22:33 +08:00
parent 27436757a0
commit caf615f3bd
8 changed files with 280 additions and 109 deletions

View File

@@ -310,7 +310,7 @@ All endpoints are under the base URL `{MP_HOST}`. Path parameters are shown as `
| POST | `/api/v1/workflow/fork` | Fork shared workflow. Body: WorkflowShare JSON |
| GET | `/api/v1/workflow/shares` | List shared workflows. Params: `name`, `page`, `count` |
### System (20 endpoints)
### System (21 endpoints)
| Method | Path | Description |
|--------|------|-------------|
@@ -321,6 +321,7 @@ All endpoints are under the base URL `{MP_HOST}`. Path parameters are shown as `
| GET | `/api/v1/system/global` | Non-sensitive settings. Params: `token` (required) |
| GET | `/api/v1/system/global/user` | User-related settings |
| GET | `/api/v1/system/restart` | Restart system |
| POST | `/api/v1/system/upgrade` | Upgrade and restart system. Body: `"release"` or `"dev"` |
| GET | `/api/v1/system/runscheduler` | Run scheduled service. Params: `jobid` (required) |
| GET | `/api/v1/system/runscheduler2` | Run scheduler (API_TOKEN, use `--token-param`). Params: `jobid` |
| GET | `/api/v1/system/modulelist` | List loaded modules |

View File

@@ -1,144 +1,74 @@
---
name: moviepilot-update
version: 1
description: Use this skill when you need to restart or upgrade MoviePilot. This skill covers system restart, version check, and manual upgrade procedures.
version: 2
description: Use this skill when you need to check MoviePilot versions, restart MoviePilot, or trigger a MoviePilot upgrade. Prefer the built-in system APIs instead of docker commands or manual file replacement. If auto-update on restart is already enabled, just restart. If it is disabled, call the upgrade API so MoviePilot performs a one-shot upgrade and restart.
---
# MoviePilot System Update & Restart
# MoviePilot Update
> All script paths are relative to this skill file.
This skill provides capabilities to restart MoviePilot service, check for updates, and perform manual upgrades.
Use this skill for MoviePilot restart and upgrade operations.
## Restart MoviePilot
## Setup
### Method 1: Using REST API (Recommended)
This skill reuses the `moviepilot-api` client configuration.
Call the restart endpoint with admin authentication:
Configure host and API key once:
```bash
# Using moviepilot-api skill
python scripts/mp-api.py GET /api/v1/system/restart
python ../moviepilot-api/scripts/mp-api.py configure --host http://localhost:3000 --apikey <API_TOKEN>
```
Or with curl:
```bash
curl -X GET "http://localhost:3000/api/v1/system/restart" \
-H "X-API-KEY: <YOUR_API_TOKEN>"
```
## Preferred Commands
**Note:** This API will restart the Docker container internally. The service will be briefly unavailable during restart.
### Method 2: Using execute_command tool
If you have admin privileges, you can execute the restart command directly:
### Check versions
```bash
docker restart moviepilot
python scripts/mp-update.py versions
```
## Check for Updates
This calls `GET /api/v1/system/versions`.
### Method 1: Using REST API
### Restart MoviePilot
```bash
python scripts/mp-api.py GET /api/v1/system/versions
python scripts/mp-update.py restart
```
This returns all available GitHub releases.
This calls `GET /api/v1/system/restart`.
### Method 2: Check current version
### Upgrade and restart MoviePilot
Release mode:
```bash
# Check current version
cat /app/version.py
python scripts/mp-update.py upgrade
```
## Upgrade MoviePilot
Dev mode:
### Option 1: Automatic Update (Recommended)
```bash
python scripts/mp-update.py upgrade dev
```
Set the environment variable `MOVIEPILOT_AUTO_UPDATE` and restart:
This calls `POST /api/v1/system/upgrade`.
1. **For Docker Compose users:**
```bash
# Edit docker-compose.yml, add environment variable:
environment:
- MOVIEPILOT_AUTO_UPDATE=release # or "dev" for dev版本
# Then restart
docker-compose down && docker-compose up -d
```
Behavior:
2. **For Docker run users:**
```bash
docker stop moviepilot
docker rm moviepilot
docker run -d ... -e MOVIEPILOT_AUTO_UPDATE=release jxxghp/moviepilot
```
- If `MOVIEPILOT_AUTO_UPDATE` is already enabled (`release` or `dev`), MoviePilot only triggers a restart and lets the normal startup flow perform the upgrade.
- If `MOVIEPILOT_AUTO_UPDATE` is disabled, MoviePilot writes a one-shot upgrade flag, restarts itself, performs that single upgrade during startup, and then continues running without changing the persisted auto-update setting.
The update script (`/usr/local/bin/mp_update.sh` or `/app/docker/update.sh`) will automatically:
- Check GitHub for latest release
- Download new backend code
- Update dependencies if changed
- Download new frontend
- Update site resources
- Restart the service
## Direct API Examples
### Option 2: Manual Upgrade
```bash
python ../moviepilot-api/scripts/mp-api.py GET /api/v1/system/restart
python ../moviepilot-api/scripts/mp-api.py POST /api/v1/system/upgrade --json '"release"'
python ../moviepilot-api/scripts/mp-api.py POST /api/v1/system/upgrade --json '"dev"'
```
If you need to manually download and apply updates:
## Notes
1. **Get latest release version:**
```bash
curl -s https://api.github.com/repos/jxxghp/MoviePilot/releases | grep '"tag_name"' | grep "v2" | head -1
```
2. **Download and extract backend:**
```bash
# Replace v2.x.x with actual version
curl -L -o /tmp/backend.zip https://github.com/jxxghp/MoviePilot/archive/refs/tags/v2.x.x.zip
unzip -d /tmp/backend /tmp/backend.zip
```
3. **Backup and replace:**
```bash
# Backup current installation
cp -r /app /app_backup
# Replace files (exclude config and plugins)
cp -r /tmp/backend/MoviePilot-*/* /app/
```
4. **Restart MoviePilot:**
```bash
# Use API or docker restart
python scripts/mp-api.py GET /api/v1/system/restart
```
### Important Notes
- **Backup first:** Before upgrading, backup your configuration and database
- **Dependencies:** Check if requirements.in has changes; if so, update virtual environment
- **Plugins:** The update script automatically backs up and restores plugins
- **Non-Docker:** For non-Docker installations, use `git pull` or `pip install -U moviepilot`
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Restart fails | Check if Docker daemon is running; verify container has restart policy |
| Update fails | Check network connectivity to GitHub; ensure sufficient disk space |
| Version unchanged | Verify `MOVIEPILOT_AUTO_UPDATE` environment variable is set correctly |
| Dependency errors | May need to rebuild virtual environment: `pip-compile requirements.in && pip install -r requirements.txt` |
## Environment Variables for Auto-Update
| Variable | Value | Description |
|----------|-------|-------------|
| `MOVIEPILOT_AUTO_UPDATE` | `release` | Auto-update to latest stable release |
| `MOVIEPILOT_AUTO_UPDATE` | `dev` | Auto-update to latest dev version |
| `MOVIEPILOT_AUTO_UPDATE` | `false` | Disable auto-update (default) |
| `GITHUB_TOKEN` | (token) | GitHub token for higher rate limits |
| `GITHUB_PROXY` | (url) | GitHub proxy URL for China users |
| `PROXY_HOST` | (url) | Global proxy host |
- These operations require administrator authentication.
- Restart or upgrade will interrupt the current agent session. Do not rely on post-restart follow-up steps in the same run.
- Prefer the API flow above. Only fall back to manual container commands when the API is unavailable.

View File

@@ -0,0 +1,62 @@
#!/usr/bin/env python3
from __future__ import annotations
import json
import sys
from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
API_SCRIPT = SCRIPT_DIR.parents[1] / "moviepilot-api" / "scripts" / "mp-api.py"
def run_api_call(args: list[str]) -> int:
command = [sys.executable, str(API_SCRIPT), *args]
return_code = __import__("subprocess").run(command, check=False).returncode
return return_code
def print_usage() -> None:
print(
"Usage:\n"
f" python {Path(sys.argv[0]).name} versions\n"
f" python {Path(sys.argv[0]).name} restart\n"
f" python {Path(sys.argv[0]).name} upgrade [release|dev]"
)
def main() -> int:
argv = sys.argv[1:]
if not argv or argv[0] in {"-h", "--help", "help"}:
print_usage()
return 0
command = argv[0].lower()
if command == "versions":
return run_api_call(["GET", "/api/v1/system/versions"])
if command == "restart":
return run_api_call(["GET", "/api/v1/system/restart"])
if command == "upgrade":
mode = (argv[1] if len(argv) > 1 else "release").strip().lower()
if mode == "true":
mode = "release"
if mode not in {"release", "dev"}:
print("Error: mode must be release or dev", file=sys.stderr)
return 1
return run_api_call([
"POST",
"/api/v1/system/upgrade",
"--json",
json.dumps(mode, ensure_ascii=False),
])
print(f"Error: unknown command: {command}", file=sys.stderr)
print_usage()
return 1
if __name__ == "__main__":
sys.exit(main())