[dist] Split scenedetect into scenedetect-core #558 #1540
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Test PySceneDetect on Linux/OSX/Windows and generate Python distribution (sdist/wheel). | |
| name: Python Distribution | |
| on: | |
| schedule: | |
| - cron: '0 0 * * *' | |
| pull_request: | |
| paths: | |
| - packaging/** | |
| - scripts/** | |
| - scenedetect/** | |
| - tests/** | |
| - pyproject.toml | |
| - .github/workflows/build.yml | |
| - .github/actions/setup-ffmpeg/** | |
| push: | |
| paths: | |
| - packaging/** | |
| - scripts/** | |
| - scenedetect/** | |
| - tests/** | |
| - pyproject.toml | |
| - .github/workflows/build.yml | |
| - .github/actions/setup-ffmpeg/** | |
| branches: | |
| - main | |
| - 'releases/**' | |
| tags: | |
| - v*-release | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [macos-14, macos-latest, ubuntu-22.04, ubuntu-latest, windows-latest] | |
| python-version: ["3.10", "3.11", "3.12", "3.13"] | |
| env: | |
| # Version is extracted below and used to find correct package install path. | |
| scenedetect_version: "" | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Setup FFmpeg | |
| uses: ./.github/actions/setup-ffmpeg | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: 'pip' | |
| - name: Install Dependencies | |
| run: | | |
| python -m pip install --upgrade pip build wheel virtualenv setuptools | |
| pip install -e .[dev] --only-binary av,opencv-python | |
| - name: Checkout test resources | |
| run: | | |
| git fetch --depth=1 https://github.com/Breakthrough/PySceneDetect.git refs/heads/resources:refs/remotes/origin/resources | |
| git checkout refs/remotes/origin/resources -- tests/resources/ | |
| - name: Unit Tests | |
| run: | | |
| python -m pytest -vv | |
| - name: Smoke Test (Module) | |
| run: | | |
| python -m scenedetect version | |
| python -m scenedetect -i tests/resources/testvideo.mp4 -b opencv time --end 2s | |
| python -m scenedetect -i tests/resources/testvideo.mp4 -b pyav time --end 2s | |
| python -m pip uninstall -y scenedetect-core | |
| - name: Build Package | |
| shell: bash | |
| run: | | |
| # Builds scenedetect-core plus the scenedetect/scenedetect-headless variants. | |
| python packaging/build_all.py | |
| echo "scenedetect_version=`python -c \"import scenedetect; print(scenedetect.__version__.replace('-', '.'))\"`" >> "$GITHUB_ENV" | |
| - name: Smoke Test Package (Source Dist) | |
| shell: bash | |
| run: | | |
| python -m venv .smoke-sdist | |
| VENV_BIN=.smoke-sdist/bin | |
| [ -d .smoke-sdist/Scripts ] && VENV_BIN=.smoke-sdist/Scripts | |
| source "$VENV_BIN/activate" | |
| pip install "dist/scenedetect-${{ env.scenedetect_version }}.tar.gz[pyav]" --only-binary av | |
| python -c "import importlib.metadata as m; ds = sorted(d.metadata['Name'] for d in m.distributions() if d.metadata['Name'] in ('opencv-python', 'opencv-python-headless')); assert ds == ['opencv-python'], f'Expected only opencv-python, got: {ds}'" | |
| scenedetect version | |
| scenedetect -i tests/resources/testvideo.mp4 -b opencv time --end 2s | |
| scenedetect -i tests/resources/testvideo.mp4 -b pyav time --end 2s | |
| - name: Smoke Test Package (Wheel) | |
| shell: bash | |
| run: | | |
| python -m venv .smoke-wheel | |
| VENV_BIN=.smoke-wheel/bin | |
| [ -d .smoke-wheel/Scripts ] && VENV_BIN=.smoke-wheel/Scripts | |
| source "$VENV_BIN/activate" | |
| pip install "dist/scenedetect-${{ env.scenedetect_version }}-py3-none-any.whl[pyav]" --only-binary av | |
| scenedetect version | |
| scenedetect -i tests/resources/testvideo.mp4 -b opencv time --end 2s | |
| scenedetect -i tests/resources/testvideo.mp4 -b pyav time --end 2s | |
| - name: Smoke Test Package (Headless Wheel) | |
| shell: bash | |
| run: | | |
| python -m venv .smoke-headless | |
| VENV_BIN=.smoke-headless/bin | |
| [ -d .smoke-headless/Scripts ] && VENV_BIN=.smoke-headless/Scripts | |
| source "$VENV_BIN/activate" | |
| pip install "dist/scenedetect_headless-${{ env.scenedetect_version }}-py3-none-any.whl[pyav]" --only-binary av | |
| # Confirm the install pulled `opencv-python-headless`, not the GUI variant. | |
| # If both are present, cv2 imports may silently come from either. | |
| python -c "import importlib.metadata as m; ds = sorted(d.metadata['Name'] for d in m.distributions() if d.metadata['Name'] in ('opencv-python', 'opencv-python-headless')); assert ds == ['opencv-python-headless'], f'Expected only opencv-python-headless, got: {ds}'" | |
| scenedetect version | |
| scenedetect -i tests/resources/testvideo.mp4 -b opencv time --end 2s | |
| scenedetect -i tests/resources/testvideo.mp4 -b pyav time --end 2s | |
| - name: Smoke Test Package (Core Only) | |
| shell: bash | |
| run: | | |
| python -m venv .smoke-core | |
| VENV_BIN=.smoke-core/bin | |
| [ -d .smoke-core/Scripts ] && VENV_BIN=.smoke-core/Scripts | |
| source "$VENV_BIN/activate" | |
| pip install "dist/scenedetect_core-${{ env.scenedetect_version }}-py3-none-any.whl" | |
| # Core declares no OpenCV variant; importing without one must raise the friendly error. | |
| python -c " | |
| try: | |
| import scenedetect | |
| raise AssertionError('import should fail without cv2') | |
| except ModuleNotFoundError as ex: | |
| assert ex.name == 'cv2', ex | |
| " | |
| # Any variant satisfies the library; core must not drag in CLI deps or the entry point. | |
| pip install opencv-python-headless | |
| python -c "import scenedetect; print(scenedetect.__version__)" | |
| python -c "import importlib.util as u; assert u.find_spec('click') is None, 'click must not be a core dependency'" | |
| python -c "import importlib.util as u; assert u.find_spec('tqdm') is None, 'tqdm must not be a core dependency'" | |
| if command -v scenedetect >/dev/null 2>&1; then | |
| echo "The scenedetect entry point must not be installed by scenedetect-core" | |
| exit 1 | |
| fi | |
| - name: Smoke Test Package (Upgrade From 0.7) | |
| shell: bash | |
| run: | | |
| # All three packages ship the code (no metapackage layering) precisely so that | |
| # in-place upgrades from pre-0.7.1 installs keep working - a code-carrying dist | |
| # flipped to a code-free metapackage would break here, since uninstalling the old | |
| # version deletes module files a dependency just wrote. Keep this as a regression | |
| # guard for that failure mode (https://scenedetect.com/issues/558). | |
| python -m venv .smoke-upgrade | |
| VENV_BIN=.smoke-upgrade/bin | |
| [ -d .smoke-upgrade/Scripts ] && VENV_BIN=.smoke-upgrade/Scripts | |
| source "$VENV_BIN/activate" | |
| pip install "scenedetect==0.7" | |
| pip install --upgrade --find-links dist/ "scenedetect==${{ env.scenedetect_version }}" | |
| python -c "import scenedetect; print(scenedetect.__version__)" | |
| scenedetect version | |
| - name: Upload Package | |
| if: ${{ matrix.python-version == '3.13' && matrix.os == 'ubuntu-latest' }} | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: scenedetect-dist | |
| path: | | |
| dist/*.tar.gz | |
| dist/*.whl |