Skip to content
Merged
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
111 changes: 97 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,75 @@ jobs:
env:
PYTHON_ZLIB_NG_LINK_DYNAMIC: True

deploy:
# Run the tests on CPython builds with AddressSanitizer and ThreadSanitizer
# from https://github.com/nascheme/cpython_sanity.
test-sanitizers:
runs-on: ubuntu-latest
# A crash under ThreadSanitizer can hang instead of exiting.
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- sanitizer: address
image: ghcr.io/nascheme/cpython-asan:3.14
# The free-threaded build runs Python threads in parallel.
- sanitizer: thread
image: ghcr.io/nascheme/cpython-tsan:3.14t
container:
image: ${{ matrix.image }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install build dependencies
run: apt-get update && apt-get install -y cmake
- name: Install python-isal with ${{ matrix.sanitizer }} sanitizer
# setuptools-scm needs git, and the container user does not own the
# repository.
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
python -m pip install . pytest pytest-timeout
env:
# The extension modules get -fsanitize from CPython. CFLAGS adds it
# to the C code of ISA-L.
CFLAGS: -fsanitize=${{ matrix.sanitizer }} -fno-omit-frame-pointer -g
- name: Run tests
# Do not set PYTHONDEVMODE. Its debug allocator pads each allocation,
# so AddressSanitizer misses small overflows. --capture=sys prints
# sanitizer reports from C code even when they end the process, and
# -v prints the name of the test before its report.
run: python -m pytest -v tests --capture=sys
env:
# Exit at the first data race. A crash after a race can hang.
TSAN_OPTIONS: halt_on_error=1

make_sdist:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
needs:
- lint
- package-checks
- test-static
- test-dynamic
- test-arch
- test-sanitizers
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Optional, use if you use setuptools_scm
submodules: true # Optional, use if you have submodules
persist-credentials: false # Highly recommended as a good security practice to not store credentials in disk, unless you need this for your specific use case

- name: Build SDist
run: pipx run build --sdist

- uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz

build_wheels:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
runs-on: ${{ matrix.os }}
needs:
Expand All @@ -165,6 +233,7 @@ jobs:
- test-static
- test-dynamic
- test-arch
- test-sanitizers
strategy:
matrix:
os:
Expand Down Expand Up @@ -239,19 +308,33 @@ jobs:
python -m build --sdist
- uses: actions/upload-artifact@v7
with:
name: "dist-${{ runner.os }}-${{ runner.arch }}-${{ matrix.cibw_archs_linux }}"
name: "cibw-${{ runner.os }}-${{ runner.arch }}-${{ matrix.cibw_archs_linux }}"
path: "dist/"
- name: Publish package to TestPyPI
# pypa/gh-action-pypi-publish@master does not work on OSX

upload_to_pypi:
needs: [ build_wheels, make_sdist ]
environment: pypi
permissions:
id-token: write
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
steps:
- uses: actions/download-artifact@v5
with:
pattern: cibw-*
path: dist
merge-multiple: true

- name: Publish to test PyPI
# Alpha, Beta and dev releases contain a - in the tag.
if: contains(github.ref, '-') && startsWith(github.ref, 'refs/tags')
run: twine upload --skip-existing -r testpypi dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
- name: Publish package to PyPI
if: "contains(github.ref, '-') && startsWith(github.ref, 'refs/tags')"
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
skip-existing: true

- name: Publish to PyPI
if: "!contains(github.ref, '-') && startsWith(github.ref, 'refs/tags')"
run: twine upload --skip-existing dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
uses: pypa/gh-action-pypi-publish@release/v1
with:
skip-existing: true
Loading