301 lines
10 KiB
Bash
Executable File
301 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
#############################################################################
|
||
# Jellyfin Linux Package Build Automation Script
|
||
#
|
||
# Builds both Debian (.deb) and Red Hat (.rpm) packages from the current
|
||
# publishing parameters.
|
||
#
|
||
# Usage:
|
||
# ./build-linux-packages.sh # Build both packages
|
||
# ./build-linux-packages.sh --deb-only # Build Debian only
|
||
# ./build-linux-packages.sh --rpm-only # Build Red Hat only
|
||
# ./build-linux-packages.sh --version X.Y.Z # Specify version
|
||
#
|
||
#############################################################################
|
||
|
||
set -e
|
||
|
||
# Configuration
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
||
# Determine project root (script can be in root or in scripts/ subdirectory)
|
||
if [ -f "$SCRIPT_DIR/SharedVersion.cs" ]; then
|
||
PROJECT_ROOT="$SCRIPT_DIR"
|
||
elif [ -f "$(dirname "$SCRIPT_DIR")/SharedVersion.cs" ]; then
|
||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||
else
|
||
echo "Error: Could not locate project root (SharedVersion.cs not found)" >&2
|
||
exit 1
|
||
fi
|
||
|
||
# Parse arguments
|
||
BUILD_DEB=true
|
||
BUILD_RPM=true
|
||
CUSTOM_VERSION=""
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--deb-only)
|
||
BUILD_RPM=false
|
||
shift
|
||
;;
|
||
--rpm-only)
|
||
BUILD_DEB=false
|
||
shift
|
||
;;
|
||
--version)
|
||
CUSTOM_VERSION="$2"
|
||
shift 2
|
||
;;
|
||
*)
|
||
echo "Unknown option: $1"
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# Extract version from SharedVersion.cs (AssemblyVersion attribute)
|
||
if [ -z "$CUSTOM_VERSION" ]; then
|
||
VERSION=$(grep -oP 'AssemblyVersion\("\K[^"]+' "$PROJECT_ROOT/SharedVersion.cs" | head -1)
|
||
if [ -z "$VERSION" ]; then
|
||
echo "Error: Could not extract version from SharedVersion.cs" >&2
|
||
exit 1
|
||
fi
|
||
else
|
||
VERSION="$CUSTOM_VERSION"
|
||
fi
|
||
|
||
# Directory setup
|
||
PUBLISH_DIR="/tmp/jellyfin-publish-$$"
|
||
BUILD_OUTPUT_DIR="${PROJECT_ROOT}/build/packages"
|
||
TEMP_DIR="/tmp/jellyfin-build-$$"
|
||
mkdir -p "$TEMP_DIR"
|
||
|
||
# Log files
|
||
RESTORE_LOG="$TEMP_DIR/restore.log"
|
||
BUILD_LOG="$TEMP_DIR/build.log"
|
||
PUBLISH_LOG="$TEMP_DIR/publish.log"
|
||
|
||
# Color output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Helper functions
|
||
print_header() {
|
||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||
echo -e "${BLUE}║${NC} Jellyfin Linux Package Builder"
|
||
echo -e "${BLUE}║${NC} Version: $VERSION"
|
||
echo -e "${BLUE}║${NC} Building: $([ "$BUILD_DEB" = true ] && echo -n "Debian ") $([ "$BUILD_RPM" = true ] && echo -n "Red Hat")"
|
||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||
}
|
||
|
||
print_step() {
|
||
echo -e "\n${BLUE}[$(date +'%H:%M:%S')]${NC} $1"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✓${NC} $1"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}✗${NC} $1"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${YELLOW}ℹ${NC} $1"
|
||
}
|
||
|
||
cleanup() {
|
||
if [ -d "$PUBLISH_DIR" ]; then
|
||
rm -rf "$PUBLISH_DIR"
|
||
fi
|
||
if [ -d "$TEMP_DIR" ]; then
|
||
rm -rf "$TEMP_DIR"
|
||
fi
|
||
}
|
||
|
||
trap cleanup EXIT
|
||
|
||
# Main execution
|
||
print_header
|
||
|
||
# Step 1: Verify prerequisites
|
||
print_step "Checking prerequisites..."
|
||
|
||
if ! command -v dotnet &> /dev/null; then
|
||
print_error "dotnet CLI not found. Please install .NET SDK."
|
||
exit 1
|
||
fi
|
||
print_success ".NET SDK found"
|
||
|
||
if ! command -v fpm &> /dev/null; then
|
||
print_error "fpm not found. Installing..."
|
||
if command -v apt-get &> /dev/null; then
|
||
sudo apt-get update
|
||
sudo apt-get install -y ruby-dev
|
||
sudo gem install fpm
|
||
elif command -v dnf &> /dev/null; then
|
||
sudo dnf install -y ruby-devel
|
||
sudo gem install fpm
|
||
else
|
||
print_error "Could not install fpm. Please install manually."
|
||
exit 1
|
||
fi
|
||
fi
|
||
print_success "fpm found"
|
||
|
||
# Step 2: Publish the application
|
||
print_step "Publishing application for linux-x64..."
|
||
|
||
cd "$PROJECT_ROOT"
|
||
|
||
if ! dotnet restore Jellyfin.sln -r linux-x64 > "$RESTORE_LOG" 2>&1; then
|
||
print_error "dotnet restore failed"
|
||
if [ -s "$RESTORE_LOG" ]; then
|
||
print_error "Error output:"
|
||
tail -30 "$RESTORE_LOG"
|
||
fi
|
||
exit 1
|
||
fi
|
||
print_success "Dependencies restored"
|
||
|
||
if ! dotnet build Jellyfin.sln --configuration Release > "$BUILD_LOG" 2>&1; then
|
||
print_error "dotnet build failed"
|
||
if [ -s "$BUILD_LOG" ]; then
|
||
print_error "Error output (last 50 lines):"
|
||
tail -50 "$BUILD_LOG"
|
||
fi
|
||
exit 1
|
||
fi
|
||
print_success "Solution built in Release configuration"
|
||
|
||
if ! dotnet publish Jellyfin.Server/Jellyfin.Server.csproj \
|
||
--configuration Release \
|
||
--self-contained true \
|
||
--runtime linux-x64 \
|
||
--output "$PUBLISH_DIR" > "$PUBLISH_LOG" 2>&1; then
|
||
print_error "dotnet publish failed"
|
||
if [ -s "$PUBLISH_LOG" ]; then
|
||
print_error "Error output (last 50 lines):"
|
||
tail -50 "$PUBLISH_LOG"
|
||
fi
|
||
exit 1
|
||
fi
|
||
print_success "Published to $PUBLISH_DIR"
|
||
|
||
# Step 3: Create build output directory
|
||
mkdir -p "$BUILD_OUTPUT_DIR"
|
||
print_success "Output directory: $BUILD_OUTPUT_DIR"
|
||
|
||
# Step 4: Build Debian package
|
||
if [ "$BUILD_DEB" = true ]; then
|
||
print_step "Building Debian package..."
|
||
|
||
DEB_OUTPUT="$BUILD_OUTPUT_DIR/jellyfin-${VERSION}-amd64.deb"
|
||
DEB_LOG="$TEMP_DIR/deb.log"
|
||
|
||
if fpm \
|
||
-s dir \
|
||
-t deb \
|
||
-n jellyfin \
|
||
-v "$VERSION" \
|
||
--architecture x86_64 \
|
||
--description "Jellyfin Media Server" \
|
||
--url "https://jellyfin.org" \
|
||
--license "GPL-2.0" \
|
||
--maintainer "Jellyfin Team <jellyfin@jellyfin.org>" \
|
||
--depends "libssl3" \
|
||
--depends "libicu72" \
|
||
--depends "libfontconfig1" \
|
||
--after-install "${PROJECT_ROOT}/scripts/debian/postinst.sh" \
|
||
--before-remove "${PROJECT_ROOT}/scripts/debian/prerm.sh" \
|
||
--after-remove "${PROJECT_ROOT}/scripts/debian/postrm.sh" \
|
||
-C "$PUBLISH_DIR" \
|
||
-p "$DEB_OUTPUT" \
|
||
.=opt/jellyfin > "$DEB_LOG" 2>&1; then
|
||
print_success "Created: jellyfin-${VERSION}-amd64.deb"
|
||
DEB_SIZE=$(du -h "$DEB_OUTPUT" | cut -f1)
|
||
print_info "Size: $DEB_SIZE"
|
||
else
|
||
print_error "Failed to create Debian package"
|
||
if [ -s "$DEB_LOG" ]; then
|
||
print_error "Error output:"
|
||
tail -20 "$DEB_LOG"
|
||
fi
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Step 5: Build Red Hat package
|
||
if [ "$BUILD_RPM" = true ]; then
|
||
print_step "Building Red Hat package..."
|
||
|
||
RPM_OUTPUT="$BUILD_OUTPUT_DIR/jellyfin-${VERSION}-1.x86_64.rpm"
|
||
RPM_LOG="$TEMP_DIR/rpm.log"
|
||
|
||
if fpm \
|
||
-s dir \
|
||
-t rpm \
|
||
-n jellyfin \
|
||
-v "$VERSION" \
|
||
--architecture x86_64 \
|
||
--description "Jellyfin Media Server" \
|
||
--url "https://jellyfin.org" \
|
||
--license "GPL-2.0" \
|
||
--maintainer "Jellyfin Team <jellyfin@jellyfin.org>" \
|
||
--depends "openssl-libs" \
|
||
--depends "libicu" \
|
||
--depends "fontconfig" \
|
||
--after-install "${PROJECT_ROOT}/scripts/redhat/post.sh" \
|
||
--before-remove "${PROJECT_ROOT}/scripts/redhat/preun.sh" \
|
||
--after-remove "${PROJECT_ROOT}/scripts/redhat/postun.sh" \
|
||
-C "$PUBLISH_DIR" \
|
||
-p "$RPM_OUTPUT" \
|
||
.=opt/jellyfin > "$RPM_LOG" 2>&1; then
|
||
print_success "Created: jellyfin-${VERSION}-1.x86_64.rpm"
|
||
RPM_SIZE=$(du -h "$RPM_OUTPUT" | cut -f1)
|
||
print_info "Size: $RPM_SIZE"
|
||
else
|
||
print_error "Failed to create Red Hat package"
|
||
if [ -s "$RPM_LOG" ]; then
|
||
print_error "Error output:"
|
||
tail -20 "$RPM_LOG"
|
||
fi
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Summary
|
||
echo
|
||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||
echo -e "${BLUE}║${NC} Build Complete!"
|
||
echo -e "${BLUE}╠═══════════════════════════════════════════════════════════════╣${NC}"
|
||
echo -e "${BLUE}║${NC} Packages available in:"
|
||
echo -e "${BLUE}║${NC} ${GREEN}$BUILD_OUTPUT_DIR${NC}"
|
||
echo -e "${BLUE}╠═══════════════════════════════════════════════════════════════╣${NC}"
|
||
if [ "$BUILD_DEB" = true ]; then
|
||
echo -e "${BLUE}║${NC} ${GREEN}✓${NC} Debian: jellyfin-${VERSION}-amd64.deb"
|
||
fi
|
||
if [ "$BUILD_RPM" = true ]; then
|
||
echo -e "${BLUE}║${NC} ${GREEN}✓${NC} Red Hat: jellyfin-${VERSION}-1.x86_64.rpm"
|
||
fi
|
||
echo -e "${BLUE}╠═══════════════════════════════════════════════════════════════╣${NC}"
|
||
echo -e "${BLUE}║${NC} Next steps:"
|
||
echo -e "${BLUE}║${NC} Debian: sudo dpkg -i jellyfin-${VERSION}-amd64.deb"
|
||
echo -e "${BLUE}║${NC} Red Hat: sudo dnf install jellyfin-${VERSION}-1.x86_64.rpm"
|
||
echo -e "${BLUE}╠═══════════════════════════════════════════════════════════════╣${NC}"
|
||
echo -e "${BLUE}║${NC} Build logs (if errors occurred):"
|
||
echo -e "${BLUE}║${NC} $TEMP_DIR"
|
||
echo -e "${BLUE}║${NC}"
|
||
echo -e "${BLUE}║${NC} Log files:"
|
||
echo -e "${BLUE}║${NC} restore.log - dotnet restore output"
|
||
echo -e "${BLUE}║${NC} build.log - dotnet build output"
|
||
echo -e "${BLUE}║${NC} publish.log - dotnet publish output"
|
||
echo -e "${BLUE}║${NC} deb.log - Debian package creation output"
|
||
echo -e "${BLUE}║${NC} rpm.log - Red Hat package creation output"
|
||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|