Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions .github/scripts/build_test.sh
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
#!/bin/bash
#!/usr/bin/env bash

python3 "${ROOT_DIRECTORY}"/bazarr.py --no-update &
set -euo pipefail

root_directory="${ROOT_DIRECTORY:-.}"
url="http://127.0.0.1:6767"

python3 "${root_directory}"/bazarr.py --no-update &
PID=$!

sleep 30
cleanup() {
echo "Stopping Bazarr..."
pkill -INT -P "${PID}" 2>/dev/null || true
kill -INT "${PID}" 2>/dev/null || true
wait "${PID}" 2>/dev/null || true
}
trap cleanup EXIT

deadline=$((SECONDS + 120))

if kill -s 0 $PID
then
echo "Bazarr is still running. We'll test if UI is working..."
else
exit 1
fi
until curl -fsS --max-time 5 "${url}" --output /dev/null; do
if ! kill -s 0 "${PID}" 2>/dev/null; then
echo "Bazarr stopped before the UI became responsive."
wait "${PID}" || true
exit 1
fi

exitcode=0
curl -fsSL --retry-all-errors --retry 60 --retry-max-time 120 --max-time 10 "http://127.0.0.1:6767" --output /dev/null || exitcode=$?
[[ ${exitcode} == 0 ]] && echo "UI is responsive, good news!" || echo "Oops, UI isn't reachable, bad news..."
if (( SECONDS >= deadline )); then
echo "Timed out waiting for Bazarr UI at ${url}."
exit 1
fi

echo "Let's stop Bazarr before we exit..."
pkill -INT -P $PID
sleep 2
done

exit ${exitcode}
echo "UI is responsive."
175 changes: 136 additions & 39 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,102 +1,199 @@
name: CI
# Touch this file to keep GitHub Actions registered on the default branch.

on:
push:
branches: [development]
paths:
- frontend/**
- bazarr/**
- libs/**
- migrations/**
- bazarr.py
- requirements.txt
- dev-requirements.txt
- .github/workflows/ci.yml
- "bazarr.py"
- "bazarr/**"
- "custom_libs/**"
- "frontend/**"
- "libs/**"
- "migrations/**"
- "tests/**"
- "dev-requirements.txt"
- "pytest.ini"
- "requirements.txt"
- ".github/scripts/**"
- ".github/workflows/ci.yml"
pull_request:
branches: [development]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
ROOT_DIRECTORY: .
UI_DIRECTORY: ./frontend
SCRIPTS_DIRECTORY: .github/scripts
UI_ARTIFACT_NAME: ui
PYTHON_VERSION: "3.13"
HUSKY: "0"
PIP_DISABLE_PIP_VERSION_CHECK: "1"

jobs:
Frontend:
frontend:
name: Frontend
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
timeout-minutes: 15

- name: Cache node_modules
uses: actions/cache@v4
steps:
- name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
path: "${{ env.UI_DIRECTORY }}/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-modules-
persist-credentials: false

- name: Setup NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version-file: "${{ env.UI_DIRECTORY }}/.nvmrc"
cache: npm
cache-dependency-path: "${{ env.UI_DIRECTORY }}/package-lock.json"

- name: Install dependencies
run: npm install
run: npm ci
working-directory: ${{ env.UI_DIRECTORY }}

- name: Check Types
- name: Check types
run: npm run check:ts
working-directory: ${{ env.UI_DIRECTORY }}

- name: Check Styles
- name: Lint
run: npm run check
working-directory: ${{ env.UI_DIRECTORY }}

- name: Check Format
- name: Check format
run: npm run check:fmt
working-directory: ${{ env.UI_DIRECTORY }}

- name: Unit Test
run: npm test
- name: Test
run: npm test -- --run
working-directory: ${{ env.UI_DIRECTORY }}

- name: Build
run: npm run build:ci
working-directory: ${{ env.UI_DIRECTORY }}

- uses: actions/upload-artifact@v4
- name: Upload UI build
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1
with:
name: ${{ env.UI_ARTIFACT_NAME }}
path: "${{ env.UI_DIRECTORY }}/build"
if-no-files-found: error
retention-days: 1

backend-tests:
name: Backend tests
runs-on: ubuntu-latest
timeout-minutes: 20

Backend:
steps:
- name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
persist-credentials: false

- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
cache-dependency-path: |
requirements.txt
dev-requirements.txt

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install -r requirements.txt -r dev-requirements.txt

- name: Compile Python
run: PYTHONWARNINGS=ignore::SyntaxWarning python -m compileall -q bazarr custom_libs libs tests

- name: Test focused backend coverage
run: >
python -m pytest
tests/bazarr/test_wanted_search_fixtures.py
tests/bazarr/test_sync_performance_paths.py
-q

python-compat:
name: Python ${{ matrix.python-version }} compatibility
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
needs: Frontend
timeout-minutes: 20

strategy:
fail-fast: false
matrix:
python-version: [ '3.10', '3.11', '3.12', '3.13' ]
name: Python ${{ matrix.python-version }} backend
python-version: ["3.10", "3.11", "3.12"]

steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
persist-credentials: false

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: |
requirements.txt
dev-requirements.txt

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install -r requirements.txt -r dev-requirements.txt

- name: Compile Python
run: PYTHONWARNINGS=ignore::SyntaxWarning python -m compileall -q bazarr custom_libs libs tests

- name: Test focused backend coverage
run: >
python -m pytest
tests/bazarr/test_wanted_search_fixtures.py
tests/bazarr/test_sync_performance_paths.py
-q

smoke:
name: App smoke test
runs-on: ubuntu-latest
needs: [frontend, backend-tests]
timeout-minutes: 15

steps:
- name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
persist-credentials: false

- name: Install UI
uses: actions/download-artifact@v7
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
cache-dependency-path: |
requirements.txt
dev-requirements.txt

- name: Download UI build
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: ${{ env.UI_ARTIFACT_NAME }}
path: "${{ env.UI_DIRECTORY }}/build"

- name: Install Python dependencies
run: pip install -r requirements.txt

- name: Unit Tests
run: |
bash '${{ env.SCRIPTS_DIRECTORY }}/build_test.sh'
python -m pip install --upgrade pip setuptools wheel
python -m pip install -r requirements.txt -r dev-requirements.txt

- name: Start app and check UI
run: bash '${{ env.SCRIPTS_DIRECTORY }}/build_test.sh'
57 changes: 0 additions & 57 deletions .github/workflows/test_bazarr_execution.yml

This file was deleted.

2 changes: 1 addition & 1 deletion bazarr/api/providers/providers_episodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def get(self):
if not os.path.exists(episodePath):
return 'Episode file not found. Path mapping issue?', 500

sceneName = episodeInfo.sceneName or "None"
sceneName = episodeInfo.sceneName
profileId = episodeInfo.profileId

providers_list = get_providers()
Expand Down
2 changes: 1 addition & 1 deletion bazarr/api/providers/providers_movies.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def get(self):
if not os.path.exists(moviePath):
return 'Movie file not found. Path mapping issue?', 500

sceneName = movieInfo.sceneName or "None"
sceneName = movieInfo.sceneName
profileId = movieInfo.profileId

providers_list = get_providers()
Expand Down
Loading
Loading