#!/usr/bin/env bash set -euo pipefail # Build Linux distribution (self-contained venv + tarball) # Usage: ./build-dist-linux.sh [VERSION] # --- Version detection --- VERSION="${1:-}" if [ -z "$VERSION" ]; then VERSION=$(git describe --tags --exact-match 2>/dev/null || true) fi if [ -z "$VERSION" ]; then VERSION="${GITEA_REF_NAME:-${GITHUB_REF_NAME:-}}" fi if [ -z "$VERSION" ]; then VERSION=$(grep -oP '__version__\s*=\s*"\K[^"]+' \ media_server/__init__.py 2>/dev/null || echo "0.0.0") fi VERSION_CLEAN="${VERSION#v}" echo "Building Media Server v${VERSION_CLEAN} for Linux" # --- Configuration --- DIST_DIR="dist/media-server" BUILD_OUTPUT="build/MediaServer-v${VERSION_CLEAN}-linux-x64" rm -rf dist build mkdir -p "${DIST_DIR}" build # --- Verify frontend bundle --- if [ ! -f "media_server/static/dist/app.bundle.js" ]; then echo "ERROR: Frontend bundle not found. Run 'npm ci && npm run build' first." exit 1 fi # --- Create self-contained virtualenv --- echo "Creating virtualenv..." python3 -m venv "${DIST_DIR}/venv" source "${DIST_DIR}/venv/bin/activate" pip install --quiet --upgrade pip pip install --quiet ".[visualizer]" # Remove the installed package (app source is on PYTHONPATH via launcher) rm -rf "${DIST_DIR}"/venv/lib/python*/site-packages/media_server* rm -rf "${DIST_DIR}"/venv/lib/python*/site-packages/media_server*.dist-info deactivate # --- Copy application --- echo "Copying application files..." mkdir -p "${DIST_DIR}/app" cp -r media_server "${DIST_DIR}/app/" # Remove source JS (bundle is in dist/) rm -rf "${DIST_DIR}/app/media_server/static/js" # Remove source maps from release rm -f "${DIST_DIR}/app/media_server/static/dist/"*.map # Copy config example cp config.example.yaml "${DIST_DIR}/" # --- Write version --- echo "$VERSION_CLEAN" > "${DIST_DIR}/VERSION" # --- Create launcher --- cat > "${DIST_DIR}/media-server.sh" << 'LAUNCHER' #!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" export PYTHONPATH="$SCRIPT_DIR/app" source "$SCRIPT_DIR/venv/bin/activate" exec python -m media_server.main "$@" LAUNCHER chmod +x "${DIST_DIR}/media-server.sh" # --- Create systemd service installer --- cat > "${DIST_DIR}/install-service.sh" << 'SERVICE' #!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SERVICE_NAME="media-server" SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" if [ "$EUID" -ne 0 ]; then echo "Please run with sudo: sudo ./install-service.sh" exit 1 fi REAL_USER="${SUDO_USER:-$USER}" cat > "$SERVICE_FILE" << EOF [Unit] Description=Media Server After=network.target sound.target [Service] Type=simple User=${REAL_USER} WorkingDirectory=${SCRIPT_DIR} ExecStart=${SCRIPT_DIR}/media-server.sh Restart=on-failure RestartSec=5 Environment=PYTHONUNBUFFERED=1 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable "${SERVICE_NAME}" systemctl start "${SERVICE_NAME}" echo "Service '${SERVICE_NAME}' installed and started." echo "Check status: systemctl status ${SERVICE_NAME}" SERVICE chmod +x "${DIST_DIR}/install-service.sh" # --- Package --- echo "Creating archive..." cp -r "${DIST_DIR}" "${BUILD_OUTPUT}" tar -czf "${BUILD_OUTPUT}.tar.gz" -C build "MediaServer-v${VERSION_CLEAN}-linux-x64" echo "Build complete: ${BUILD_OUTPUT}.tar.gz"