Merge pull request #5 from caiyunapp/ci/release #128
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 | |
| # Install build tools and common dependencies | |
| apt-get install -y \ | |
| build-essential \ | |
| pkg-config \ | |
| libbz2-dev \ | |
| libssl-dev \ | |
| libboost-dev \ | |
| libboost-filesystem-dev \ | |
| libboost-program-options-dev \ | |
| libboost-regex-dev \ | |
| libboost-system-dev | |
| # Install Mapnik from sid (version 4.2) | |
| # This will automatically install most dependencies like ICU, Cairo, HarfBuzz, etc. | |
| 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 Homebrew dependencies | |
| run: | | |
| # Install Mapnik which will automatically install all required dependencies | |
| # including boost, cairo, harfbuzz, icu4c, gdal, proj, freetype, and 100+ other packages | |
| brew install mapnik pkg-config | |
| - name: Setup build environment | |
| run: | | |
| # Ensure Homebrew environment is available | |
| eval $(brew shellenv) | |
| # Note: setup.py now auto-detects Homebrew paths for Boost, HarfBuzz, etc. | |
| # We only need to ensure PKG_CONFIG_PATH includes ICU and Mapnik | |
| HOMEBREW_PREFIX=$(brew --prefix) | |
| # Get ICU prefix (could be icu4c@78 or icu4c) | |
| ICU4C_PREFIX=$(brew --prefix icu4c@78 2>/dev/null || brew --prefix icu4c 2>/dev/null || echo "") | |
| MAPNIK_PREFIX=$(brew --prefix mapnik 2>/dev/null || echo "$HOMEBREW_PREFIX/opt/mapnik") | |
| # Set up minimal PKG_CONFIG_PATH (setup.py will handle the rest) | |
| PKG_CONFIG_PATH="$HOMEBREW_PREFIX/lib/pkgconfig:$HOMEBREW_PREFIX/share/pkgconfig" | |
| [ -n "$ICU4C_PREFIX" ] && PKG_CONFIG_PATH="$ICU4C_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" | |
| [ -d "$MAPNIK_PREFIX/lib/pkgconfig" ] && PKG_CONFIG_PATH="$MAPNIK_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" | |
| echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" >> $GITHUB_ENV | |
| # Verify environment | |
| echo "Homebrew prefix: $HOMEBREW_PREFIX" | |
| echo "ICU prefix: $ICU4C_PREFIX" | |
| echo "Mapnik version: $(mapnik-config --version 2>/dev/null || echo 'not found')" | |
| echo "PKG_CONFIG_PATH: $PKG_CONFIG_PATH" | |
| - 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) | |
| # Use lockfile when present; avoid doing two full syncs (which can rebuild twice). | |
| # Note: setup.py will automatically detect and configure Homebrew paths | |
| 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 |