ci: build wheel #104
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
| name: Test | |
| on: | |
| push: | |
| branches: [ main, master, develop ] | |
| pull_request: | |
| branches: [ main, master, develop ] | |
| workflow_dispatch: | |
| workflow_call: | |
| jobs: | |
| test-linux: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| container: python:3.12-bookworm | |
| platform: linux_x86_64 | |
| arch: x86_64 | |
| arch_label: x86_64 | |
| - os: ubuntu-24.04-arm | |
| container: python:3.12-bookworm | |
| platform: linux_aarch64 | |
| arch: arm64 | |
| arch_label: arm64 | |
| runs-on: ${{ matrix.os }} | |
| container: ${{ matrix.container }} | |
| env: | |
| UV_LINK_MODE: copy | |
| UV_CACHE_DIR: /github/home/.cache/uv | |
| permissions: | |
| actions: write | |
| contents: read | |
| checks: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Cache uv downloads | |
| uses: actions/cache@v5 | |
| with: | |
| path: /github/home/.cache/uv | |
| key: uvcache-${{ runner.os }}-${{ matrix.arch_label }}-${{ hashFiles('uv.lock', 'pyproject.toml') }} | |
| restore-keys: | | |
| uvcache-${{ runner.os }}-${{ matrix.arch_label }}- | |
| - name: Cache uv virtual environment and build artifacts | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ matrix.arch_label }}-${{ hashFiles('uv.lock', 'pyproject.toml', 'setup.py') }}-${{ hashFiles('src/**/*.cpp', 'src/**/*.hpp', 'packaging/**/*.py') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ matrix.arch_label }}-${{ hashFiles('uv.lock', 'pyproject.toml', 'setup.py') }}- | |
| venv-${{ runner.os }}-${{ matrix.arch_label }}- | |
| - name: Add Debian sid repository | |
| run: | | |
| echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list | |
| echo 'Package: *\nPin: release a=sid\nPin-Priority: 100' > /etc/apt/preferences.d/sid | |
| - name: Install system dependencies | |
| run: | | |
| apt-get update | |
| # Ensure /etc/os-release exists (required by some actions' OS detection). | |
| apt-get install -y base-files | |
| apt-get install -y build-essential pkg-config libbz2-dev | |
| apt-get install -y -t sid libmapnik-dev | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| # Work around container-job failures determining Linux distribution during | |
| # setup-uv's built-in caching path; we cache UV_CACHE_DIR ourselves above. | |
| enable-cache: false | |
| - name: Install Python dependencies and build package | |
| run: | | |
| # Use lockfile when present; avoid doing two full syncs (which can rebuild twice). | |
| if [ -f uv.lock ]; then | |
| uv sync --extra test --frozen --verbose | |
| else | |
| uv sync --extra test --verbose | |
| fi | |
| - name: Run tests with coverage | |
| run: | | |
| uv run pytest test/python_tests -v \ | |
| --cov=mapnik \ | |
| --cov-report=term \ | |
| --cov-report=xml:coverage.xml \ | |
| --cov-report=html:htmlcov \ | |
| --junitxml=junit.xml | |
| - name: Upload coverage reports | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: coverage-reports-linux-${{ matrix.arch_label }} | |
| path: | | |
| coverage.xml | |
| htmlcov/ | |
| junit.xml | |
| retention-days: 30 | |
| - name: Publish test results | |
| uses: EnricoMi/publish-unit-test-result-action@v2 | |
| if: always() | |
| with: | |
| files: junit.xml | |
| check_name: Test Results (Linux ${{ matrix.arch_label }}) | |
| comment_mode: off | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| if: always() | |
| with: | |
| files: coverage.xml | |
| flags: unittests-linux-${{ matrix.arch_label }} | |
| name: python-mapnik-coverage-linux-${{ matrix.arch_label }} | |
| fail_ci_if_error: false | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Build sdist | |
| run: | | |
| uv build --sdist | |
| - name: Upload sdist | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sdist-${{ matrix.os }}-${{ matrix.arch_label }} | |
| path: dist/*.tar.gz | |
| retention-days: 7 | |
| test-macos: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: macos-15-intel | |
| platform: macosx_15_0_x86_64 | |
| arch: x86_64 | |
| arch_label: x86_64 | |
| - os: macos-15 | |
| platform: macosx_15_0_arm64 | |
| arch: arm64 | |
| arch_label: arm64 | |
| - os: macos-latest | |
| platform: macosx_15_0_arm64 | |
| arch: arm64 | |
| arch_label: arm64 | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| UV_LINK_MODE: copy | |
| UV_CACHE_DIR: /Users/runner/.cache/uv | |
| permissions: | |
| actions: write | |
| contents: read | |
| checks: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Cache uv downloads | |
| uses: actions/cache@v5 | |
| with: | |
| path: /Users/runner/.cache/uv | |
| key: uvcache-${{ runner.os }}-${{ matrix.arch_label }}-${{ hashFiles('uv.lock', 'pyproject.toml') }} | |
| restore-keys: | | |
| uvcache-${{ runner.os }}-${{ matrix.arch_label }}- | |
| - name: Cache uv virtual environment and build artifacts | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ matrix.arch_label }}-${{ hashFiles('uv.lock', 'pyproject.toml', 'setup.py') }}-${{ hashFiles('src/**/*.cpp', 'src/**/*.hpp', 'packaging/**/*.py') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ matrix.arch_label }}-${{ hashFiles('uv.lock', 'pyproject.toml', 'setup.py') }}- | |
| venv-${{ runner.os }}-${{ matrix.arch_label }}- | |
| - name: Install and cache Homebrew tools | |
| uses: tecolicom/actions-use-homebrew-tools@v1 | |
| with: | |
| tools: mapnik icu4c pkg-config boost gdal proj harfbuzz libx11 xorgproto libxext libxrender libxau libxdmcp xtrans | |
| - name: Setup pkg-config and build environment | |
| run: | | |
| # Ensure Homebrew environment is available | |
| eval $(brew shellenv) | |
| # Get package-specific prefixes using brew --prefix and save to GITHUB_ENV for reuse | |
| HOMEBREW_PREFIX=$(brew --prefix) | |
| MAPNIK_PREFIX=$(brew --prefix mapnik) | |
| ICU4C_PREFIX=$(brew --prefix icu4c) | |
| BOOST_PREFIX=$(brew --prefix boost) | |
| GDAL_PREFIX=$(brew --prefix gdal) | |
| PROJ_PREFIX=$(brew --prefix proj) | |
| HARFBUZZ_PREFIX=$(brew --prefix harfbuzz) | |
| XORGPROTO_PREFIX=$(brew --prefix xorgproto) | |
| LIBX11_PREFIX=$(brew --prefix libx11) | |
| LIBXEXT_PREFIX=$(brew --prefix libxext) | |
| LIBXRENDER_PREFIX=$(brew --prefix libxrender) | |
| LIBXAU_PREFIX=$(brew --prefix libxau) | |
| LIBXDMCP_PREFIX=$(brew --prefix libxdmcp) | |
| XTRANS_PREFIX=$(brew --prefix xtrans) | |
| # Find the actual xorgproto pkg-config directory (may be in Cellar with version) | |
| XORGPROTO_PKGCONFIG_DIR=$(find "$HOMEBREW_PREFIX/Cellar/xorgproto" -type d -name "pkgconfig" 2>/dev/null | head -1) | |
| if [ -z "$XORGPROTO_PKGCONFIG_DIR" ]; then | |
| # Fallback to opt symlink location | |
| XORGPROTO_PKGCONFIG_DIR="$XORGPROTO_PREFIX/share/pkgconfig" | |
| echo "Warning: xorgproto pkgconfig directory not found in Cellar, using fallback: $XORGPROTO_PKGCONFIG_DIR" | |
| else | |
| echo "Found xorgproto pkgconfig directory: $XORGPROTO_PKGCONFIG_DIR" | |
| fi | |
| # Save prefixes to GITHUB_ENV for reuse in subsequent steps | |
| echo "HOMEBREW_PREFIX=$HOMEBREW_PREFIX" >> $GITHUB_ENV | |
| echo "MAPNIK_PREFIX=$MAPNIK_PREFIX" >> $GITHUB_ENV | |
| echo "ICU4C_PREFIX=$ICU4C_PREFIX" >> $GITHUB_ENV | |
| echo "BOOST_PREFIX=$BOOST_PREFIX" >> $GITHUB_ENV | |
| echo "GDAL_PREFIX=$GDAL_PREFIX" >> $GITHUB_ENV | |
| echo "PROJ_PREFIX=$PROJ_PREFIX" >> $GITHUB_ENV | |
| echo "HARFBUZZ_PREFIX=$HARFBUZZ_PREFIX" >> $GITHUB_ENV | |
| echo "XORGPROTO_PREFIX=$XORGPROTO_PREFIX" >> $GITHUB_ENV | |
| echo "LIBX11_PREFIX=$LIBX11_PREFIX" >> $GITHUB_ENV | |
| echo "LIBXEXT_PREFIX=$LIBXEXT_PREFIX" >> $GITHUB_ENV | |
| echo "LIBXRENDER_PREFIX=$LIBXRENDER_PREFIX" >> $GITHUB_ENV | |
| echo "LIBXAU_PREFIX=$LIBXAU_PREFIX" >> $GITHUB_ENV | |
| echo "LIBXDMCP_PREFIX=$LIBXDMCP_PREFIX" >> $GITHUB_ENV | |
| echo "XTRANS_PREFIX=$XTRANS_PREFIX" >> $GITHUB_ENV | |
| echo "XORGPROTO_PKGCONFIG_DIR=$XORGPROTO_PKGCONFIG_DIR" >> $GITHUB_ENV | |
| echo "Homebrew prefix: $HOMEBREW_PREFIX" | |
| echo "Mapnik prefix: $MAPNIK_PREFIX" | |
| echo "xorgproto pkg-config dir: $XORGPROTO_PKGCONFIG_DIR" | |
| # Set PKG_CONFIG_PATH to include Homebrew's pkg-config directories | |
| # This ensures pkg-config can find Mapnik and its dependencies (ICU, Boost, GDAL, PROJ, HarfBuzz, X11 proto, etc.) | |
| # Note: xorgproto .pc files are in Cellar/xorgproto/<version>/share/pkgconfig | |
| echo "PKG_CONFIG_PATH=$HOMEBREW_PREFIX/lib/pkgconfig:$HOMEBREW_PREFIX/share/pkgconfig:$ICU4C_PREFIX/lib/pkgconfig:$GDAL_PREFIX/lib/pkgconfig:$PROJ_PREFIX/lib/pkgconfig:$HARFBUZZ_PREFIX/lib/pkgconfig:$LIBX11_PREFIX/lib/pkgconfig:$LIBXEXT_PREFIX/lib/pkgconfig:$LIBXRENDER_PREFIX/lib/pkgconfig:$LIBXAU_PREFIX/lib/pkgconfig:$LIBXDMCP_PREFIX/lib/pkgconfig:$XTRANS_PREFIX/share/pkgconfig:$XORGPROTO_PKGCONFIG_DIR:$XORGPROTO_PREFIX/share/pkgconfig:$XORGPROTO_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" >> $GITHUB_ENV | |
| # Set CXXFLAGS and LDFLAGS to include Boost, GDAL, PROJ, and HarfBuzz headers and libraries | |
| echo "CXXFLAGS=-I$BOOST_PREFIX/include -I$GDAL_PREFIX/include -I$PROJ_PREFIX/include -I$HARFBUZZ_PREFIX/include $CXXFLAGS" >> $GITHUB_ENV | |
| echo "LDFLAGS=-L$BOOST_PREFIX/lib -L$GDAL_PREFIX/lib -L$PROJ_PREFIX/lib -L$HARFBUZZ_PREFIX/lib $LDFLAGS" >> $GITHUB_ENV | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: false | |
| - name: Install Python dependencies and build package | |
| run: | | |
| # Ensure Homebrew environment is available | |
| eval $(brew shellenv) | |
| # Re-export environment variables (already set in previous step via GITHUB_ENV) | |
| # This ensures they're available in the current shell session for subprocess calls | |
| export PKG_CONFIG_PATH="$PKG_CONFIG_PATH" | |
| export CXXFLAGS="$CXXFLAGS" | |
| export LDFLAGS="$LDFLAGS" | |
| # Use lockfile when present; avoid doing two full syncs (which can rebuild twice). | |
| if [ -f uv.lock ]; then | |
| uv sync --extra test --frozen --verbose | |
| else | |
| uv sync --extra test --verbose | |
| fi | |
| - name: Run tests with coverage | |
| run: | | |
| uv run pytest test/python_tests -v \ | |
| --cov=mapnik \ | |
| --cov-report=term \ | |
| --cov-report=xml:coverage.xml \ | |
| --cov-report=html:htmlcov \ | |
| --junitxml=junit.xml | |
| - name: Verify coverage files | |
| if: always() | |
| run: | | |
| pwd | |
| ls -la coverage.xml || echo "coverage.xml not found" | |
| if [ -f coverage.xml ]; then | |
| echo "✅ coverage.xml exists" | |
| head -20 coverage.xml | |
| else | |
| echo "❌ coverage.xml not found" | |
| exit 1 | |
| fi | |
| - name: Upload coverage reports | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: coverage-reports-macos-${{ matrix.os }}-${{ matrix.arch_label }} | |
| path: | | |
| coverage.xml | |
| htmlcov/ | |
| junit.xml | |
| retention-days: 30 | |
| - name: Publish test results | |
| uses: EnricoMi/publish-unit-test-result-action/macos@v2 | |
| if: always() | |
| with: | |
| files: junit.xml | |
| check_name: Test Results (macOS ${{ matrix.os }} ${{ matrix.arch_label }}) | |
| comment_mode: off | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| if: always() | |
| with: | |
| files: coverage.xml | |
| flags: unittests-macos-${{ matrix.os }}-${{ matrix.arch_label }} | |
| name: python-mapnik-coverage-macos-${{ matrix.os }}-${{ matrix.arch_label }} | |
| fail_ci_if_error: false | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Build sdist | |
| run: | | |
| uv build --sdist | |
| - name: Upload sdist | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sdist-${{ matrix.os }}-${{ matrix.arch_label }} | |
| path: dist/*.tar.gz | |
| retention-days: 7 |