diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 05f51c8f2..661a9a19b 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - master paths-ignore: - '*.md' - 'docs/**' @@ -30,6 +31,9 @@ env: UI_DIRECTORY: ./frontend jobs: + # ========================================================================== + # Build Scraper Image (separate job with its own cache) + # ========================================================================== build-scraper: runs-on: ubuntu-latest permissions: @@ -80,23 +84,21 @@ jobs: cache-from: type=gha,scope=scraper cache-to: type=gha,mode=max,scope=scraper + # ========================================================================== + # Build Frontend (cached via GitHub Actions cache) + # ========================================================================== build-frontend: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v5 - - name: Cache node_modules - uses: actions/cache@v4 - with: - path: "${{ env.UI_DIRECTORY }}/node_modules" - key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }} - restore-keys: ${{ runner.os }}-modules- - - name: Setup NodeJS uses: actions/setup-node@v4 with: node-version-file: "${{ env.UI_DIRECTORY }}/.nvmrc" + cache: 'npm' + cache-dependency-path: "${{ env.UI_DIRECTORY }}/package-lock.json" - name: Install Dependencies run: npm ci @@ -113,6 +115,9 @@ jobs: path: ${{ env.UI_DIRECTORY }}/build retention-days: 1 + # ========================================================================== + # Build and Push Bazarr Image + # ========================================================================== build-and-push: needs: [build-frontend, build-scraper] runs-on: ubuntu-latest @@ -183,7 +188,7 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - # Latest tag on main branch + # Latest tag on main/master branch type=raw,value=latest,enable={{is_default_branch}} # Version tag (e.g., v1.5.3-lavx.20241214) type=raw,value=${{ steps.version.outputs.fork_version }} @@ -207,8 +212,11 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + # Use GHA cache with separate scopes for different layers + cache-from: | + type=gha,scope=bazarr-deps + type=gha,scope=bazarr-main + cache-to: type=gha,mode=max,scope=bazarr-main build-args: | BAZARR_VERSION=${{ steps.version.outputs.fork_version }} BUILD_DATE=${{ github.event.repository.updated_at }} @@ -223,28 +231,27 @@ jobs: - name: Create Release Summary run: | - echo "## 🐳 Docker Image Published" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "### Pull Commands" >> $GITHUB_STEP_SUMMARY + echo "## 🐳 Docker Images Published" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY + echo "### Bazarr (LavX Fork)" >> $GITHUB_STEP_SUMMARY echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY - echo "# Latest" >> $GITHUB_STEP_SUMMARY echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "# Specific Version" >> $GITHUB_STEP_SUMMARY echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.fork_version }}" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY + echo "### OpenSubtitles Scraper" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY + echo "docker pull ${{ env.REGISTRY }}/${{ env.SCRAPER_IMAGE_NAME }}:latest" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY echo "### Image Details" >> $GITHUB_STEP_SUMMARY echo "- **Digest:** \`${{ steps.push.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY echo "- **Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "### 🔌 OpenSubtitles Scraper" >> $GITHUB_STEP_SUMMARY - echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY - echo "docker pull ${{ env.REGISTRY }}/${{ env.SCRAPER_IMAGE_NAME }}:latest" >> $GITHUB_STEP_SUMMARY - echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "- **Cache Status:** GHA cache enabled" >> $GITHUB_STEP_SUMMARY - # Optional: Create GitHub Release for tagged versions + # ========================================================================== + # Create GitHub Release for tagged versions + # ========================================================================== create-release: needs: build-and-push runs-on: ubuntu-latest @@ -260,15 +267,20 @@ jobs: with: generate_release_notes: true body: | - ## 🐳 Docker Image + ## 🐳 Docker Images ```bash + # Bazarr (LavX Fork) docker pull ghcr.io/${{ github.repository }}:${{ github.ref_name }} + + # OpenSubtitles Scraper + docker pull ghcr.io/${{ github.repository_owner }}/opensubtitles-scraper:latest ``` ## 📝 Changes This release is based on upstream Bazarr with the following custom modifications: - - OpenSubtitles.org web scraper provider + - OpenSubtitles.org web scraper provider (no VIP API needed) + - Auto-sync with upstream daily at 4 AM UTC See the auto-generated release notes below for detailed changes. \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 7229cbd33..9ba7c27a5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # ============================================================================= # Bazarr LavX Fork - Production Docker Image # ============================================================================= -# Multi-stage build for optimized image size +# Multi-stage build optimized for layer caching # Based on Debian Slim for better compatibility (unrar, etc.) # ============================================================================= @@ -10,22 +10,7 @@ ARG BUILD_DATE ARG VCS_REF # ============================================================================= -# Stage 1: Build Frontend -# ============================================================================= -FROM node:20-slim AS frontend-builder - -WORKDIR /app - -# Install dependencies first for better caching -COPY frontend/package*.json ./frontend/ -RUN cd frontend && npm ci - -# Copy frontend source and build -COPY frontend ./frontend/ -RUN cd frontend && npm run build - -# ============================================================================= -# Stage 2: Install Python Dependencies +# Stage 1: Install Python Dependencies (cached heavily) # ============================================================================= FROM python:3.12-slim-bookworm AS python-builder @@ -40,12 +25,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ WORKDIR /app -# Copy requirements and install Python packages +# Copy ONLY requirements first for maximum caching +# This layer will only rebuild when requirements.txt changes COPY requirements.txt ./ -RUN pip install --no-cache-dir --prefix=/install -r requirements.txt + +# Use pip cache mount to avoid re-downloading packages across builds +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install --prefix=/install -r requirements.txt # ============================================================================= -# Stage 3: Production Image +# Stage 2: Production Image # ============================================================================= FROM python:3.12-slim-bookworm AS production @@ -64,7 +53,10 @@ LABEL org.opencontainers.image.title="Bazarr (LavX Fork)" \ org.opencontainers.image.licenses="GPL-3.0" # Enable non-free repository for unrar and install runtime dependencies -RUN sed -i 's/Components: main/Components: main non-free non-free-firmware/' /etc/apt/sources.list.d/debian.sources && \ +# Use apt cache mount to speed up repeated builds +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + sed -i 's/Components: main/Components: main non-free non-free-firmware/' /etc/apt/sources.list.d/debian.sources && \ apt-get update && apt-get install -y --no-install-recommends \ ffmpeg \ libxml2 \ @@ -76,31 +68,35 @@ RUN sed -i 's/Components: main/Components: main non-free non-free-firmware/' /et bash \ gosu \ curl \ - && rm -rf /var/lib/apt/lists/* \ && mkdir -p /app/bazarr/bin /config /defaults \ && groupadd -g 1000 bazarr \ && useradd -u 1000 -g bazarr -d /config -s /bin/bash bazarr -# Copy Python packages from builder +# Copy Python packages from builder (changes rarely) COPY --from=python-builder /install /usr/local -# Copy application code +# Copy entrypoint script (changes rarely) +COPY docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +# Set work directory WORKDIR /app/bazarr -COPY bazarr.py ./ + +# Copy libs directories (change less frequently than main app code) COPY libs ./libs COPY custom_libs ./custom_libs -COPY bazarr ./bazarr COPY migrations ./migrations +# Copy main application code (changes most frequently - keep at end) +COPY bazarr.py ./ +COPY bazarr ./bazarr + # Copy fork identification file (shows "LavX Fork" in System Status) COPY package_info /app/bazarr/package_info -# Copy frontend build -COPY --from=frontend-builder /app/frontend/build ./frontend/build - -# Copy entrypoint script -COPY docker/entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh +# Copy pre-built frontend (built in GitHub Actions workflow for caching) +# This layer only rebuilds when frontend/build changes +COPY frontend/build ./frontend/build # Set environment variables ENV HOME="/config" \