Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c65b5c8406 |
@@ -49,18 +49,23 @@ if ! git rev-parse --verify --quiet "refs/tags/$RELEASE_TAG" >/dev/null; then
|
|||||||
fi
|
fi
|
||||||
git checkout --detach "$RELEASE_TAG"
|
git checkout --detach "$RELEASE_TAG"
|
||||||
test "$(git describe --tags --exact-match HEAD)" = "$RELEASE_TAG"
|
test "$(git describe --tags --exact-match HEAD)" = "$RELEASE_TAG"
|
||||||
"$VENV/bin/pip" install --upgrade "$REPO_DIR"
|
"$VENV/bin/pip" install --upgrade --force-reinstall --no-cache-dir "$REPO_DIR"
|
||||||
install -m 0644 "$REPO_DIR/deploy/importarr.service" /etc/systemd/system/importarr.service
|
install -m 0644 "$REPO_DIR/deploy/importarr.service" /etc/systemd/system/importarr.service
|
||||||
install -m 0755 "$REPO_DIR/deploy/repo-upgrade.sh" "$PREFIX/repo-upgrade.sh"
|
install -m 0755 "$REPO_DIR/deploy/repo-upgrade.sh" "$PREFIX/repo-upgrade.sh"
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
GIT_SHA="$(git rev-parse --short=12 HEAD 2>/dev/null || printf development)"
|
GIT_SHA="$(git rev-parse --short=12 HEAD 2>/dev/null || printf development)"
|
||||||
BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
VERSION="$RELEASE_TAG"
|
VERSION="$RELEASE_TAG"
|
||||||
cat > "$PREFIX/build.env" <<EOF
|
BUILD_ENV_TMP="$PREFIX/build.env.tmp.$$"
|
||||||
|
trap 'rm -f "$BUILD_ENV_TMP"' EXIT HUP INT TERM
|
||||||
|
cat > "$BUILD_ENV_TMP" <<EOF
|
||||||
IMPORTARR_VERSION=$VERSION
|
IMPORTARR_VERSION=$VERSION
|
||||||
IMPORTARR_GIT_SHA=$GIT_SHA
|
IMPORTARR_GIT_SHA=$GIT_SHA
|
||||||
IMPORTARR_BUILD_DATE=$BUILD_DATE
|
IMPORTARR_BUILD_DATE=$BUILD_DATE
|
||||||
EOF
|
EOF
|
||||||
|
chmod 0644 "$BUILD_ENV_TMP"
|
||||||
|
mv -f "$BUILD_ENV_TMP" "$PREFIX/build.env"
|
||||||
|
trap - EXIT HUP INT TERM
|
||||||
systemctl restart "$SERVICE"
|
systemctl restart "$SERVICE"
|
||||||
systemctl restart manual-media-import.timer
|
systemctl restart manual-media-import.timer
|
||||||
systemctl --no-pager --full status "$SERVICE"
|
systemctl --no-pager --full status "$SERVICE"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ install -d -m 0755 /opt/importarr
|
|||||||
REPO_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
|
REPO_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
|
||||||
python3 -m venv /opt/importarr/venv
|
python3 -m venv /opt/importarr/venv
|
||||||
/opt/importarr/venv/bin/pip install --upgrade pip
|
/opt/importarr/venv/bin/pip install --upgrade pip
|
||||||
/opt/importarr/venv/bin/pip install --upgrade "$REPO_DIR"
|
/opt/importarr/venv/bin/pip install --upgrade --force-reinstall --no-cache-dir "$REPO_DIR"
|
||||||
if [ ! -f /etc/importarr/importarr.env ]; then
|
if [ ! -f /etc/importarr/importarr.env ]; then
|
||||||
install -m 0600 "$REPO_DIR/deploy/importarr.env.example" /etc/importarr/importarr.env
|
install -m 0600 "$REPO_DIR/deploy/importarr.env.example" /etc/importarr/importarr.env
|
||||||
echo "Created /etc/importarr/importarr.env; edit it before starting the service."
|
echo "Created /etc/importarr/importarr.env; edit it before starting the service."
|
||||||
@@ -31,11 +31,16 @@ fi
|
|||||||
GIT_SHA="$(git -C "$REPO_DIR" rev-parse --short=12 HEAD 2>/dev/null || printf development)"
|
GIT_SHA="$(git -C "$REPO_DIR" rev-parse --short=12 HEAD 2>/dev/null || printf development)"
|
||||||
BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
VERSION="$(git -C "$REPO_DIR" describe --tags --exact-match HEAD 2>/dev/null || /opt/importarr/venv/bin/python -c 'from importarr import __version__; print(__version__)')"
|
VERSION="$(git -C "$REPO_DIR" describe --tags --exact-match HEAD 2>/dev/null || /opt/importarr/venv/bin/python -c 'from importarr import __version__; print(__version__)')"
|
||||||
cat > /opt/importarr/build.env <<EOF
|
BUILD_ENV_TMP="/opt/importarr/build.env.tmp.$$"
|
||||||
|
trap 'rm -f "$BUILD_ENV_TMP"' EXIT HUP INT TERM
|
||||||
|
cat > "$BUILD_ENV_TMP" <<EOF
|
||||||
IMPORTARR_VERSION=$VERSION
|
IMPORTARR_VERSION=$VERSION
|
||||||
IMPORTARR_GIT_SHA=$GIT_SHA
|
IMPORTARR_GIT_SHA=$GIT_SHA
|
||||||
IMPORTARR_BUILD_DATE=$BUILD_DATE
|
IMPORTARR_BUILD_DATE=$BUILD_DATE
|
||||||
EOF
|
EOF
|
||||||
|
chmod 0644 "$BUILD_ENV_TMP"
|
||||||
|
mv -f "$BUILD_ENV_TMP" /opt/importarr/build.env
|
||||||
|
trap - EXIT HUP INT TERM
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable importarr.service
|
systemctl enable importarr.service
|
||||||
systemctl enable manual-media-import.timer
|
systemctl enable manual-media-import.timer
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "importarr-ui",
|
"name": "importarr-ui",
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "importarr-ui",
|
"name": "importarr-ui",
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-dialog": "^1.1.14",
|
"@radix-ui/react-dialog": "^1.1.14",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "importarr-ui",
|
"name": "importarr-ui",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "0.1.2"
|
__version__ = "0.1.3"
|
||||||
|
|||||||
+10
-6
@@ -402,13 +402,17 @@ def _schedule_update(command: list[str]) -> None:
|
|||||||
if not command:
|
if not command:
|
||||||
raise HTTPException(status_code=500, detail="update command is not configured")
|
raise HTTPException(status_code=500, detail="update command is not configured")
|
||||||
try:
|
try:
|
||||||
subprocess.Popen(
|
result = subprocess.run(
|
||||||
["/bin/sh", "-c", 'sleep 1; exec "$@"', "importarr-update", *command],
|
["systemd-run", "--unit=importarr-update", "--collect", "--no-block", "--on-active=2s", "--", *command],
|
||||||
stdin=subprocess.DEVNULL,
|
check=False,
|
||||||
stdout=subprocess.DEVNULL,
|
capture_output=True,
|
||||||
stderr=subprocess.DEVNULL,
|
text=True,
|
||||||
start_new_session=True,
|
timeout=10,
|
||||||
)
|
)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise HTTPException(status_code=500, detail=f"update command failed to schedule: {result.stderr[-1000:]}")
|
||||||
|
except subprocess.TimeoutExpired as exc:
|
||||||
|
raise HTTPException(status_code=504, detail="update command timed out while scheduling") from exc
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
raise HTTPException(status_code=500, detail=f"update command failed to start: {exc.__class__.__name__}") from exc
|
raise HTTPException(status_code=500, detail=f"update command failed to start: {exc.__class__.__name__}") from exc
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "importarr"
|
name = "importarr"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
description = "Arr-style manual SABnzbd import service"
|
description = "Arr-style manual SABnzbd import service"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
@@ -23,6 +23,9 @@ test = ["pytest>=8.2", "pytest-asyncio>=0.23"]
|
|||||||
importarr = "importarr.main:run"
|
importarr = "importarr.main:run"
|
||||||
manual-media-import = "importarr.worker:main"
|
manual-media-import = "importarr.worker:main"
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel]
|
||||||
|
packages = ["importarr"]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
testpaths = ["tests"]
|
testpaths = ["tests"]
|
||||||
pythonpath = ["."]
|
pythonpath = ["."]
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import fcntl
|
import fcntl
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import zipfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
@@ -30,3 +32,28 @@ def test_repo_upgrade_refuses_concurrent_run(tmp_path):
|
|||||||
|
|
||||||
assert result.returncode == 1
|
assert result.returncode == 1
|
||||||
assert "another Importarr upgrade is already running" in result.stderr
|
assert "another Importarr upgrade is already running" in result.stderr
|
||||||
|
|
||||||
|
|
||||||
|
def test_wheel_contains_built_frontend_assets(tmp_path):
|
||||||
|
root = Path(__file__).parents[1]
|
||||||
|
subprocess.run(
|
||||||
|
[sys.executable, "-m", "pip", "wheel", "--no-deps", "--wheel-dir", str(tmp_path), str(root)],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
wheel = next(tmp_path.glob("importarr-*.whl"))
|
||||||
|
with zipfile.ZipFile(wheel) as archive:
|
||||||
|
packaged = set(archive.namelist())
|
||||||
|
|
||||||
|
assert "importarr/static/index.html" in packaged
|
||||||
|
assert "importarr/static/assets/app.js" in packaged
|
||||||
|
assert "importarr/static/assets/app.css" in packaged
|
||||||
|
|
||||||
|
|
||||||
|
def test_repo_upgrade_forces_fresh_install_without_skipping_dependencies():
|
||||||
|
script = (Path(__file__).parents[1] / "deploy/repo-upgrade.sh").read_text()
|
||||||
|
|
||||||
|
assert "pip\" install --upgrade --force-reinstall --no-cache-dir" in script
|
||||||
|
assert "--no-deps" not in script
|
||||||
|
|||||||
@@ -194,6 +194,32 @@ def test_update_schedules_exact_latest_release_tag(tmp_path, monkeypatch):
|
|||||||
assert response["status"] == "update_scheduled"
|
assert response["status"] == "update_scheduled"
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_is_scheduled_outside_service_cgroup(tmp_path, monkeypatch):
|
||||||
|
monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db"))
|
||||||
|
import importarr.main as main
|
||||||
|
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
def fake_run(command, **kwargs):
|
||||||
|
calls.append((command, kwargs))
|
||||||
|
return main.subprocess.CompletedProcess(command, 0, stdout="Running as unit", stderr="")
|
||||||
|
|
||||||
|
monkeypatch.setattr(main.subprocess, "run", fake_run)
|
||||||
|
main._schedule_update(["/bin/sh", "/opt/importarr/repo-upgrade.sh", "v1.2.3"])
|
||||||
|
|
||||||
|
assert calls[0][0] == [
|
||||||
|
"systemd-run",
|
||||||
|
"--unit=importarr-update",
|
||||||
|
"--collect",
|
||||||
|
"--no-block",
|
||||||
|
"--on-active=2s",
|
||||||
|
"--",
|
||||||
|
"/bin/sh",
|
||||||
|
"/opt/importarr/repo-upgrade.sh",
|
||||||
|
"v1.2.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_update_endpoint_requires_expected_tag(tmp_path, monkeypatch):
|
def test_update_endpoint_requires_expected_tag(tmp_path, monkeypatch):
|
||||||
monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db"))
|
monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db"))
|
||||||
import importarr.main as main
|
import importarr.main as main
|
||||||
|
|||||||
Reference in New Issue
Block a user