borgbackup/borg

View on GitHub
.github/workflows/ci.yml

Summary

Maintainability
Test Coverage
# badge: https://github.com/borgbackup/borg/workflows/CI/badge.svg?branch=master

name: CI

on:
  push:
    branches: [ master ]
    paths:
    - '**.py'
    - '**.pyx'
    - '**.c'
    - '**.h'
    - '**.yml'
    - '**.toml'
    - '**.cfg'
    - '**.ini'
    - 'requirements.d/*'
    - '!docs/**'
  pull_request:
    branches: [ master ]
    paths:
    - '**.py'
    - '**.pyx'
    - '**.c'
    - '**.h'
    - '**.yml'
    - '**.toml'
    - '**.cfg'
    - '**.ini'
    - 'requirements.d/*'
    - '!docs/**'

jobs:
  lint:

    runs-on: ubuntu-22.04
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v4
    - uses: chartboost/ruff-action@v1

  linux:

    needs: lint
    strategy:
      fail-fast: true
      matrix:
        include:
            - os: ubuntu-22.04
              python-version: '3.9'
              toxenv: mypy
            - os: ubuntu-22.04
              python-version: '3.11'
              toxenv: docs
            - os: ubuntu-22.04
              python-version: '3.9'
              toxenv: py39-fuse2
            - os: ubuntu-22.04
              python-version: '3.10'
              toxenv: py310-fuse3
            - os: ubuntu-22.04
              python-version: '3.11'
              toxenv: py311-fuse3
            - os: ubuntu-24.04
              python-version: '3.12'
              toxenv: py312-fuse3
            - os: ubuntu-24.04
              python-version: '3.13'
              toxenv: py313-fuse3

    env:
      TOXENV: ${{ matrix.toxenv }}

    runs-on: ${{ matrix.os }}
    timeout-minutes: 120

    steps:
    - uses: actions/checkout@v4
      with:
        # just fetching 1 commit is not enough for setuptools-scm, so we fetch all
        fetch-depth: 0
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}
    - name: Cache pip
      uses: actions/cache@v4
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-pip-${{ hashFiles('requirements.d/development.txt') }}
        restore-keys: |
            ${{ runner.os }}-pip-
            ${{ runner.os }}-

    - name: Install Linux packages
      run: |
        sudo apt-get update
        sudo apt-get install -y pkg-config build-essential
        sudo apt-get install -y libssl-dev libacl1-dev libxxhash-dev liblz4-dev libzstd-dev
        sudo apt-get install -y libfuse-dev fuse || true  # Required for Python llfuse module
        sudo apt-get install -y libfuse3-dev fuse3 || true  # Required for Python pyfuse3 module

    - name: Install Python requirements
      run: |
        python -m pip install --upgrade pip setuptools wheel
        pip install -r requirements.d/development.txt
    - name: Install borgbackup
      run: |
        pip install -e .
    - name: run tox env
      env:
        XDISTN: "4"
      run: |
        # do not use fakeroot, but run as root. avoids the dreaded EISDIR sporadic failures. see #2482.
        #sudo -E bash -c "tox -e py"
        tox --skip-missing-interpreters
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v4
      env:
        OS: ${{ runner.os }}
        python: ${{ matrix.python-version }}
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        env_vars: OS, python

  macOS:

    needs: linux
    strategy:
      fail-fast: true
      matrix:
        include:
            - os: macos-14
              python-version: '3.11'
              toxenv: py311-none  # note: no fuse testing, due to #6099, see also #6196.

    env:
      # Configure pkg-config to use OpenSSL from Homebrew
      PKG_CONFIG_PATH: "/opt/homebrew/opt/openssl@3.0/lib/pkgconfig:$PKG_CONFIG_PATH"
      TOXENV: ${{ matrix.toxenv }}

    runs-on: ${{ matrix.os }}
    timeout-minutes: 180

    steps:
    - uses: actions/checkout@v4
      with:
        # just fetching 1 commit is not enough for setuptools-scm, so we fetch all
        fetch-depth: 0
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}
    - name: Cache pip
      uses: actions/cache@v4
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-pip-${{ hashFiles('requirements.d/development.txt') }}
        restore-keys: |
            ${{ runner.os }}-pip-
            ${{ runner.os }}-

    - name: Install macOS packages
      run: brew bundle install

    - name: Install Python requirements
      run: |
        python -m pip install --upgrade pip setuptools wheel
        pip install -r requirements.d/development.txt
    - name: Install borgbackup
      env:
        # we already have that in the global env, but something is broken and overwrites that.
        # so, set it here, again.
        PKG_CONFIG_PATH: "/opt/homebrew/opt/openssl@3.0/lib/pkgconfig:$PKG_CONFIG_PATH"
      run: |
        pip install -ve .
    - name: run tox env
      env:
        # we already have that in the global env, but something is broken and overwrites that.
        # so, set it here, again.
        PKG_CONFIG_PATH: "/opt/homebrew/opt/openssl@3.0/lib/pkgconfig:$PKG_CONFIG_PATH"
        XDISTN: "6"
      run: |
        # do not use fakeroot, but run as root. avoids the dreaded EISDIR sporadic failures. see #2482.
        #sudo -E bash -c "tox -e py"
        tox --skip-missing-interpreters
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v4
      env:
        OS: ${{ runner.os }}
        python: ${{ matrix.python-version }}
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        env_vars: OS, python

  windows:

    if: false  # build temporary disabled
    runs-on: windows-latest
    timeout-minutes: 120
    needs: linux

    env:
      # Needed for setuptools < 70.2.0 to work, see: https://www.msys2.org/docs/python/#known-issues
      # SETUPTOOLS_USE_DISTUTILS: stdlib
      PY_COLORS: 1

    defaults:
      run:
        shell: msys2 {0}

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: msys2/setup-msys2@v2
        with:
          msystem: UCRT64
          update: true
      - name: Install dependencies
        run: ./scripts/msys2-install-deps development
      - name: Build
        run: |
          # build borg.exe
          pip install -e .
          pyinstaller -y scripts/borg.exe.spec
          # build sdist and wheel in dist/...
          python -m build
      - uses: actions/upload-artifact@v4
        with:
          name: borg-windows
          path: dist/borg.exe
      - name: Run tests
        run: |
          ./dist/borg.exe -V
          pytest -n4 --benchmark-skip -vv -rs -k "not remote"