Add CI/CD pipelines, NSIS installer, ES module bundling, and ruff linting
Lint & Test / test (push) Failing after 9s
Release / create-release (push) Successful in 1s
Release / build-windows (push) Successful in 59s

- Add Gitea Actions workflows: test.yml (lint + test on push/PR) and
  release.yml (build + NSIS installer + upload on v* tags)
- Add NSIS installer with optional desktop shortcut and auto-start
- Add esbuild bundler: ES module migration with IIFE bundle output
- Add build-dist-windows.sh for cross-building Windows distribution
- Fix all ruff lint errors (import sorting, unused imports, line length)
- Remove redundant scripts (start-server.bat, stop-server.bat,
  start-server-background.vbs)
- Update CLAUDE.md with CI/CD and release documentation
This commit is contained in:
2026-03-23 02:01:28 +03:00
parent be48318212
commit 5439af1955
41 changed files with 1702 additions and 310 deletions
+10 -1
View File
@@ -9,4 +9,13 @@ from .links import router as links_router
from .media import router as media_router
from .scripts import router as scripts_router
__all__ = ["audio_router", "browser_router", "callbacks_router", "display_router", "health_router", "links_router", "media_router", "scripts_router"]
__all__ = [
"audio_router",
"browser_router",
"callbacks_router",
"display_router",
"health_router",
"links_router",
"media_router",
"scripts_router",
]
+3 -4
View File
@@ -4,20 +4,19 @@ import asyncio
import logging
import tempfile
from pathlib import Path
from typing import Optional
from urllib.parse import unquote
from fastapi import APIRouter, Depends, HTTPException, Query, Response
from fastapi.responses import FileResponse, StreamingResponse
from fastapi.responses import FileResponse
from pydantic import BaseModel, Field
from ..auth import verify_token, verify_token_or_query
from ..config import MediaFolderConfig, settings
from ..config_manager import config_manager
from ..services import get_media_controller
from ..services.browser_service import BrowserService
from ..services.metadata_service import MetadataService
from ..services.thumbnail_service import ThumbnailService
from ..services import get_media_controller
from ..services.websocket_manager import ws_manager
logger = logging.getLogger(__name__)
@@ -281,7 +280,7 @@ async def browse(
logger.warning(f"Folder temporarily unavailable: {e}")
raise HTTPException(
status_code=503,
detail=f"Folder is temporarily unavailable. It may be a network share that is not accessible at the moment."
detail="Folder is temporarily unavailable. It may be a network share that is not accessible at the moment."
)
except Exception as e:
logger.error(f"Error browsing directory (type: {type(e).__name__}): {e}")
+8 -3
View File
@@ -2,7 +2,6 @@
import asyncio
import logging
import re
import subprocess
import time
from concurrent.futures import ThreadPoolExecutor
@@ -238,7 +237,10 @@ async def create_callback(
if callback_name in settings.callbacks:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Callback '{callback_name}' already exists. Use PUT /api/callbacks/update/{callback_name} to update it.",
detail=(
f"Callback '{callback_name}' already exists."
f" Use PUT /api/callbacks/update/{callback_name} to update it."
),
)
# Create callback config
@@ -283,7 +285,10 @@ async def update_callback(
if callback_name not in settings.callbacks:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Callback '{callback_name}' not found. Use POST /api/callbacks/create/{callback_name} to create it.",
detail=(
f"Callback '{callback_name}' not found."
f" Use POST /api/callbacks/create/{callback_name} to create it."
),
)
# Create updated callback config
-1
View File
@@ -7,7 +7,6 @@ from pydantic import BaseModel, Field
from ..auth import verify_token
from ..services.display_service import (
get_brightness,
list_monitors,
set_brightness,
set_power,
+3 -4
View File
@@ -3,14 +3,13 @@
import asyncio
import logging
from fastapi import APIRouter, Depends, HTTPException, Query, WebSocket, WebSocketDisconnect
from fastapi import status
from fastapi import APIRouter, Depends, HTTPException, Query, WebSocket, WebSocketDisconnect, status
from fastapi.responses import Response
from ..auth import verify_token, verify_token_or_query
from ..config import settings
from ..models import MediaStatus, VolumeRequest, SeekRequest
from ..services import get_media_controller, get_current_album_art
from ..models import MediaStatus, SeekRequest, VolumeRequest
from ..services import get_current_album_art, get_media_controller
from ..services.websocket_manager import ws_manager
logger = logging.getLogger(__name__)