|
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions |
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions |
|
|
|
name: Python package |
|
|
|
on: |
|
push: |
|
branches: [main] |
|
pull_request: |
|
workflow_dispatch: |
|
|
|
permissions: |
|
contents: read |
|
|
|
jobs: |
|
test: |
|
name: test (${{ matrix.os-type }}, ${{ matrix.python-version }}${{ matrix.backend == 'gix' && ', gix' || '' }}) |
|
strategy: |
|
matrix: |
|
os-type: [ubuntu, macos, windows] |
|
python-version: ["3.11", "3.12", "3.13", "3.14", "3.14t", "3.15", "3.15t"] |
|
backend: [cli] |
|
exclude: |
|
- os-type: macos |
|
python-version: "3.14t" |
|
- os-type: macos |
|
python-version: "3.15t" |
|
include: |
|
- build-docs: true # We ensure documentation builds, except on very old interpreters. |
|
- experimental: false |
|
- python-version: "3.15" |
|
experimental: true |
|
- python-version: "3.15t" |
|
experimental: true |
|
- os-type: ubuntu |
|
python-version: "3.12" |
|
backend: gix |
|
build-docs: false |
|
experimental: false |
|
- os-type: macos |
|
python-version: "3.12" |
|
backend: gix |
|
build-docs: false |
|
experimental: false |
|
- os-type: windows |
|
python-version: "3.12" |
|
backend: gix |
|
build-docs: false |
|
experimental: false |
|
|
|
fail-fast: false |
|
|
|
runs-on: ${{ matrix.os-type }}-latest |
|
env: |
|
GIT_PYTHON_BACKEND: ${{ matrix.backend }} |
|
|
|
defaults: |
|
run: |
|
shell: bash --noprofile --norc -exo pipefail {0} |
|
|
|
steps: |
|
- uses: actions/checkout@v7 |
|
with: |
|
fetch-depth: 0 |
|
|
|
- name: Set up Python ${{ matrix.python-version }} |
|
uses: actions/setup-python@v7 |
|
with: |
|
python-version: ${{ matrix.python-version }} |
|
allow-prereleases: ${{ matrix.experimental }} |
|
cache: pip |
|
cache-dependency-path: | |
|
pyproject.toml |
|
requirements.txt |
|
test-requirements.txt |
|
gix-requirements.txt |
|
|
|
- name: Prepare Rust for GixPython source builds |
|
id: rust |
|
run: | |
|
# GixPython 0.2.0 publishes macOS wheels only and needs Rust >= 1.89. |
|
rustup toolchain install stable --profile minimal |
|
rustup default stable |
|
rustc --version |
|
echo "version=$(rustc --version)" >> "$GITHUB_OUTPUT" |
|
|
|
- name: Cache GixPython Cargo dependencies and build output |
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 |
|
with: |
|
path: | |
|
~/.cargo/registry |
|
~/.cargo/git |
|
${{ runner.temp }}/gix-target |
|
key: gix-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ steps.rust.outputs.version }}-${{ hashFiles('gix-requirements.txt') }} |
|
restore-keys: | |
|
gix-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ steps.rust.outputs.version }}- |
|
|
|
- name: Set up WSL (Windows) |
|
if: matrix.os-type == 'windows' |
|
uses: Vampire/setup-wsl@v7.0.0 |
|
with: |
|
wsl-version: 1 |
|
|
|
- name: Install current Git (Linux) |
|
if: matrix.os-type == 'ubuntu' |
|
run: | |
|
sudo add-apt-repository --yes ppa:git-core/ppa |
|
sudo apt-get update |
|
sudo apt-get install --yes git |
|
|
|
- name: Install current Git (macOS) |
|
if: matrix.os-type == 'macos' |
|
run: | |
|
brew install git |
|
echo "$(brew --prefix git)/bin" >> "$GITHUB_PATH" |
|
|
|
- name: Prepare this repo for tests |
|
run: | |
|
./init-tests-after-clone.sh |
|
|
|
- name: Set git user identity and command aliases for the tests |
|
run: | |
|
git config --global user.email "travis@ci.com" |
|
git config --global user.name "Travis Runner" |
|
# If we rewrite the user's config by accident, we will mess it up |
|
# and cause subsequent tests to fail |
|
cat test/fixtures/.gitconfig >> ~/.gitconfig |
|
|
|
- name: Update PyPA packages |
|
run: | |
|
python -m pip install -U pip 'setuptools; python_version<"3.12"' wheel |
|
|
|
- name: Install project and test dependencies |
|
run: | |
|
pip install ./smmap ./gitdb ".[${EXTRAS}]" |
|
python -c 'import os; from gix import testtools; from git import _backend; print("Backend:", _backend.name); assert _backend.name == os.environ["EXPECTED_BACKEND"]' |
|
env: |
|
EXTRAS: ${{ matrix.backend == 'gix' && 'test,gix' || 'test' }} |
|
EXPECTED_BACKEND: ${{ matrix.backend }} |
|
# Keep Cargo output when pip removes its temporary source directory. |
|
CARGO_TARGET_DIR: ${{ runner.temp }}/gix-target |
|
|
|
- name: Show POSIX file ownership |
|
# Linux and macOS only. On Windows, Git Bash's `ls -ld` reports a |
|
# uniform uid+gid for every path regardless of NTFS Owner (MSYS2's |
|
# SID-to-uid mapping doesn't have Cygwin's fidelity), so it would |
|
# not be informative here. The NTFS Owner check below covers Windows. |
|
if: matrix.os-type != 'windows' |
|
run: | |
|
ls -ld -- \ |
|
"$(pwd)" \ |
|
"$(pwd)/.git" \ |
|
"${HOME:?HOME is not set}/.gitconfig" \ |
|
2>&1 || true |
|
|
|
- name: Show NTFS file ownership |
|
# Windows only. Reads NTFS Owner directly via Get-Acl, which is the |
|
# authoritative view for Windows-side ownership questions; the POSIX |
|
# view via Git Bash's MSYS2 layer is not a reliable proxy here. |
|
if: matrix.os-type == 'windows' |
|
shell: pwsh |
|
run: | |
|
$paths = @( |
|
"$pwd", |
|
"$pwd\.git", |
|
"$env:USERPROFILE\.gitconfig" |
|
) |
|
foreach ($p in $paths) { |
|
if (Test-Path -LiteralPath $p) { |
|
try { |
|
$owner = (Get-Acl -LiteralPath $p).Owner |
|
} catch { |
|
$owner = "ERROR: $($_.Exception.Message)" |
|
} |
|
"{0,-44} {1}" -f $owner, $p |
|
} else { |
|
"(missing: $p)" |
|
} |
|
} |
|
|
|
- name: Show safe.directory entries |
|
# `actions/checkout`'s safe.directory add is only durable for the |
|
# checkout itself (it writes under a throwaway HOME override and |
|
# then discards it), so by the time this step runs the runner |
|
# user's `~/.gitconfig` has no entries -- and git accepts the |
|
# workspace's ownership anyway: Git for Windows via its |
|
# Admins-group exemption on the windows matrix; on Linux/macOS |
|
# the workspace is owned by the test user. Expected: `(none)`. |
|
run: git config --global --get-all safe.directory || echo "(none)" |
|
|
|
- name: Show version and platform information |
|
run: | |
|
uname -a |
|
command -v git python |
|
git version |
|
python --version |
|
python -c 'import os, sys; print(f"{sys.platform=}, {os.name=}")' |
|
|
|
# For debugging hook tests on native Windows systems that may have WSL. |
|
- name: Show bash.exe candidates (Windows) |
|
if: matrix.os-type == 'windows' |
|
run: | |
|
set +e |
|
bash.exe -c 'printenv WSL_DISTRO_NAME; uname -a' |
|
python -c 'import subprocess; subprocess.run(["bash.exe", "-c", "printenv WSL_DISTRO_NAME; uname -a"])' |
|
continue-on-error: true |
|
|
|
- name: Check types with mypy |
|
if: matrix.python-version != '3.8' |
|
run: | |
|
mypy --python-version="${PYTHON_VERSION%t}" # Version only, with no "t" for free-threaded. |
|
env: |
|
MYPY_FORCE_COLOR: "1" |
|
TERM: "xterm-256color" # For color: https://github.com/python/mypy/issues/13817 |
|
PYTHON_VERSION: ${{ matrix.python-version }} |
|
|
|
- name: Check types with basedpyright |
|
if: matrix.os-type == 'ubuntu' && matrix.python-version == '3.12' |
|
run: | |
|
basedpyright --warnings |
|
|
|
- name: Test with pytest |
|
run: | |
|
if [[ "$RUNNER_OS" == "Windows" && -z "${GIT_PYTHON_GIT_EXECUTABLE+x}" ]]; then |
|
# Absolute paths let Windows share minimum-version probes. |
|
git_executable="$(python -c 'import os, shutil; print(os.path.abspath(shutil.which("git")))')" |
|
export GIT_PYTHON_GIT_EXECUTABLE="$git_executable" |
|
fi |
|
pytest --color=yes -p no:sugar --instafail -vv --durations=30 \ |
|
--junitxml=test-results/pytest.xml --backend-report=test-results/backend.json |
|
continue-on-error: false |
|
|
|
- name: Retain test results and backend operation counts |
|
if: always() |
|
uses: actions/upload-artifact@v7 |
|
with: |
|
name: tests-${{ matrix.os-type }}-${{ matrix.python-version }}-${{ matrix.backend }} |
|
path: test-results/ |
|
|
|
- name: Documentation |
|
if: matrix.build-docs |
|
run: | |
|
pip install --group doc |
|
make -C doc html |
|
|
|
import-smoke: |
|
name: install/import (${{ matrix.os }}, ${{ matrix.python }}) |
|
runs-on: ${{ matrix.os }} |
|
strategy: |
|
fail-fast: false |
|
matrix: |
|
os: [ubuntu-latest, macos-latest, windows-latest] |
|
python: ["3.8", "3.9", "3.10"] |
|
env: |
|
GIT_PYTHON_BACKEND: cli |
|
steps: |
|
- uses: actions/checkout@v7 |
|
- uses: actions/setup-python@v7 |
|
with: |
|
python-version: ${{ matrix.python }} |
|
- name: Install the supported runtime |
|
run: python -m pip install . |
|
- name: Import the installed package |
|
run: python -I -c "import git; from git import _backend; assert _backend.name == 'cli'; print(git.__version__)" |