Skip to content

ci: build wheel

ci: build wheel #21

Workflow file for this run

name: Release
on:
pull_request:
branches: [ main, master, develop ]
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to release (e.g., v4.2.0)'
required: true
type: string
jobs:
extract-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
version_number: ${{ steps.version.outputs.version_number }}
steps:
- name: Extract version from tag
id: version
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
VERSION=${{ inputs.tag }}
else
VERSION=${GITHUB_REF#refs/tags/}
fi
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "version_number=${VERSION#v}" >> $GITHUB_OUTPUT
build-wheels:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, macos-15-intel]
runs-on: ${{ matrix.os }}
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
submodules: recursive
- name: Install cibuildwheel
run: |
python -m pip install --upgrade pip
pip install cibuildwheel
- name: Build wheels
env:
CIBW_BUILD_VERBOSITY: 1
CIBW_BEFORE_BUILD: "pip install uv && uv sync --frozen --no-dev || uv sync --no-dev"
# Ensure pkg-config can find libmapnik.pc across manylinux/apt paths.
CIBW_ENVIRONMENT_LINUX: >-
PKG_CONFIG_PATH=/usr/lib64/pkgconfig:/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:/opt/lib/pkgconfig:$PKG_CONFIG_PATH
# Linux: install system dependencies in manylinux container
CIBW_BEFORE_ALL_LINUX: |
set -euo pipefail
if command -v apt-get >/dev/null 2>&1; then
mkdir -p /etc/apt/sources.list.d /etc/apt/preferences.d
echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
echo 'Package: *
Pin: release a=sid
Pin-Priority: 100' > /etc/apt/preferences.d/sid
apt-get update
apt-get install -y build-essential pkg-config libbz2-dev
apt-get install -y -t sid libmapnik-dev fonts-noto-cjk
elif command -v dnf >/dev/null 2>&1 || command -v yum >/dev/null 2>&1; then
DNF_BIN=$(command -v dnf || command -v yum)
if command -v dnf >/dev/null 2>&1; then
dnf install -y dnf-plugins-core
# Enable repo variants across EL8/EL9.
dnf config-manager --set-enabled powertools || true
dnf config-manager --set-enabled crb || true
else
yum install -y yum-utils || true
fi
$DNF_BIN install -y epel-release || true
$DNF_BIN install -y \
bzip2-devel \
gcc gcc-c++ make \
pkgconfig
if ! $DNF_BIN install -y mapnik-devel; then
echo "mapnik-devel not available in enabled repos; building Mapnik from source." >&2
$DNF_BIN repolist || true
$DNF_BIN list available "mapnik*" || true
$DNF_BIN install -y \
boost-devel \
freetype-devel \
libpng-devel \
libjpeg-turbo-devel \
libtiff-devel \
libicu-devel \
zlib-devel \
libxml2-devel \
proj-devel \
gdal-devel \
harfbuzz-devel \
cairo-devel \
libcurl-devel \
sqlite-devel \
git \
curl \
wget \
tar
PYBIN=$(ls -d /opt/python/cp312-cp312/bin/python /opt/python/cp3*/bin/python | head -1)
"$PYBIN" -m pip install --upgrade pip
"$PYBIN" -m pip install scons
# Build a newer Boost (>=1.83) since EL8 provides 1.66.
BOOST_VER=1.83.0
BOOST_VER_UNDERSCORE=1_83_0
rm -rf /tmp/boost-src
mkdir -p /tmp/boost-src
cd /tmp/boost-src
BOOST_TARBALL="boost-${BOOST_VER}.tar.gz"
curl -L -o "$BOOST_TARBALL" "https://github.com/boostorg/boost/releases/download/boost-${BOOST_VER}/boost-${BOOST_VER}.tar.gz"
tar -xzf "$BOOST_TARBALL"
cd "boost_${BOOST_VER_UNDERSCORE}"
./bootstrap.sh --prefix=/usr/local --with-libraries=regex,program_options,system,filesystem,thread
./b2 -j"$(nproc)" link=shared runtime-link=shared install
rm -rf /tmp/mapnik-src
git clone --depth 1 --branch v4.2.0 https://github.com/mapnik/mapnik.git /tmp/mapnik-src
cd /tmp/mapnik-src
SCBIN="$(dirname "$PYBIN")/scons"
"$SCBIN" configure PREFIX=/usr/local BOOST_INCLUDES=/usr/local/include BOOST_LIBS=/usr/local/lib
"$SCBIN" -j"$(nproc)"
"$SCBIN" install
cd /
fi
# Fonts are optional for building; try common package names.
$DNF_BIN install -y google-noto-sans-cjk-ttc-fonts || \
$DNF_BIN install -y google-noto-cjk-fonts || \
$DNF_BIN install -y noto-sans-cjk-fonts || true
else
echo "No supported package manager found (apt-get or dnf/yum)." >&2
exit 1
fi
echo "libmapnik.pc locations (if any):"
find /usr /opt /usr/local -name "libmapnik.pc" -print 2>/dev/null || true
# macOS: install dependencies via Homebrew
CIBW_BEFORE_ALL_MACOS: "brew install mapnik icu4c pkg-config boost gdal proj harfbuzz libx11 xorgproto libxext libxrender libxau libxdmcp xtrans"
# macOS: set up build environment
CIBW_BEFORE_BUILD_MACOS: |
eval $(brew shellenv)
HOMEBREW_PREFIX=$(brew --prefix)
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)
XORGPROTO_PKGCONFIG_DIR=$(find "$HOMEBREW_PREFIX/Cellar/xorgproto" -type d -name "pkgconfig" 2>/dev/null | head -1)
[ -z "$XORGPROTO_PKGCONFIG_DIR" ] && XORGPROTO_PKGCONFIG_DIR="$XORGPROTO_PREFIX/share/pkgconfig"
export 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"
export CXXFLAGS="-I$BOOST_PREFIX/include -I$GDAL_PREFIX/include -I$PROJ_PREFIX/include -I$HARFBUZZ_PREFIX/include $CXXFLAGS"
export LDFLAGS="-L$BOOST_PREFIX/lib -L$GDAL_PREFIX/lib -L$PROJ_PREFIX/lib -L$HARFBUZZ_PREFIX/lib $LDFLAGS"
run: |
cibuildwheel --output-dir wheelhouse
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.os }}
path: wheelhouse/*.whl
retention-days: 7
release:
needs:
- extract-version
- build-wheels
runs-on: ubuntu-latest
permissions:
contents: write
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || github.event_name == 'workflow_dispatch'
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist-all
- name: Combine artifacts
run: |
mkdir -p dist
# Copy all wheels
find dist-all -name "*.whl" -exec cp {} dist/ \;
# Copy sdist (should be only one)
find dist-all -name "*.tar.gz" -exec cp {} dist/ \;
echo "Artifacts in dist/:"
ls -lh dist/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: ${{ needs.extract-version.outputs.version }}
name: Release ${{ needs.extract-version.outputs.version }}
body: |
## Python Mapnik ${{ needs.extract-version.outputs.version_number }}
### Installation
Download the wheel file for your platform and install:
```bash
pip install mapnik-${{ needs.extract-version.outputs.version_number }}-*.whl
```
Or install directly from GitHub (replace platform tag as needed):
```bash
pip install https://github.com/${{ github.repository }}/releases/download/${{ needs.extract-version.outputs.version }}/mapnik-${{ needs.extract-version.outputs.version_number }}-cp312-cp312-linux_x86_64.whl
```
Or install from source:
```bash
pip install git+https://github.com/${{ github.repository }}.git@${{ needs.extract-version.outputs.version }}
```
### Requirements
- Python >= 3.12
- Mapnik >= 4.2.0
### Changes
See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.extract-version.outputs.version }}/CHANGELOG.md) for details.
files: |
dist/*.whl
dist/*.tar.gz
draft: false
prerelease: false
- name: Summary
run: |
echo "## Release Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "✅ Released version: **${{ needs.extract-version.outputs.version }}**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Artifacts Built:" >> $GITHUB_STEP_SUMMARY
ls -lh dist/ >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Supported Platforms:" >> $GITHUB_STEP_SUMMARY
echo "- Linux x86_64: ✅" >> $GITHUB_STEP_SUMMARY
echo "- Linux arm64: ✅" >> $GITHUB_STEP_SUMMARY
echo "- macOS x86_64: ✅" >> $GITHUB_STEP_SUMMARY
echo "- macOS arm64: ✅" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Distribution:" >> $GITHUB_STEP_SUMMARY
echo "- GitHub Release: ✅" >> $GITHUB_STEP_SUMMARY