ci: release #54
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 fonts-noto-cjk | |
| - 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 }} | |
| 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 | |
| key: mapnik-${{ matrix.arch_label }} | |
| - 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) | |
| # 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 "Homebrew prefix: $HOMEBREW_PREFIX" | |
| echo "Mapnik prefix: $MAPNIK_PREFIX" | |
| # 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, etc.) | |
| echo "PKG_CONFIG_PATH=$HOMEBREW_PREFIX/lib/pkgconfig:$ICU4C_PREFIX/lib/pkgconfig:$BOOST_PREFIX/lib/pkgconfig:$GDAL_PREFIX/lib/pkgconfig:$PROJ_PREFIX/lib/pkgconfig:$HARFBUZZ_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 | |
| # Verify the paths exist | |
| echo "Checking PKG_CONFIG_PATH directories:" | |
| for dir in "$HOMEBREW_PREFIX/lib/pkgconfig" "$ICU4C_PREFIX/lib/pkgconfig" "$BOOST_PREFIX/lib/pkgconfig"; do | |
| if [ -d "$dir" ]; then | |
| echo " ✓ $dir exists" | |
| else | |
| echo " ✗ $dir does not exist" | |
| fi | |
| done | |
| # Check if libmapnik.pc exists | |
| if [ -f "$HOMEBREW_PREFIX/lib/pkgconfig/libmapnik.pc" ]; then | |
| echo " ✓ libmapnik.pc found at $HOMEBREW_PREFIX/lib/pkgconfig/libmapnik.pc" | |
| else | |
| echo " ✗ libmapnik.pc not found at $HOMEBREW_PREFIX/lib/pkgconfig/libmapnik.pc" | |
| echo " Searching for libmapnik.pc..." | |
| find "$HOMEBREW_PREFIX" -name "libmapnik.pc" 2>/dev/null || echo " Not found anywhere" | |
| fi | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: false | |
| - name: Verify pkg-config can find libmapnik | |
| run: | | |
| eval $(brew shellenv) | |
| echo "Current PKG_CONFIG_PATH: $PKG_CONFIG_PATH" | |
| echo "Testing pkg-config --variable=prefix libmapnik:" | |
| pkg-config --variable=prefix libmapnik || echo "ERROR: pkg-config cannot find libmapnik" | |
| echo "Testing pkg-config --print-errors --libs libmapnik:" | |
| pkg-config --print-errors --libs libmapnik || echo "ERROR: pkg-config --libs failed (see errors above)" | |
| echo "Testing pkg-config --print-errors --cflags libmapnik:" | |
| pkg-config --print-errors --cflags libmapnik || echo "ERROR: pkg-config --cflags failed (see errors above)" | |
| # Check what dependencies libmapnik.pc requires | |
| echo "Checking libmapnik.pc dependencies:" | |
| if [ -f "$HOMEBREW_PREFIX/lib/pkgconfig/libmapnik.pc" ]; then | |
| grep -E "^Requires|^Libs.private" "$HOMEBREW_PREFIX/lib/pkgconfig/libmapnik.pc" || true | |
| fi | |
| - 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.arch_label }} | |
| path: | | |
| coverage.xml | |
| htmlcov/ | |
| junit.xml | |
| retention-days: 30 | |
| # Note: publish-unit-test-result-action doesn't support macOS (container action limitation) | |
| # Test results are still uploaded as artifacts above | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| if: always() | |
| with: | |
| files: coverage.xml | |
| flags: unittests-macos-${{ matrix.arch_label }} | |
| name: python-mapnik-coverage-macos-${{ matrix.arch_label }} | |
| fail_ci_if_error: false | |
| token: ${{ secrets.CODECOV_TOKEN }} |