Skip to content

Commit e613828

Browse files
authored
Merge pull request #4 from caiyunapp/ci/release
ci: release
2 parents 4674619 + 8a750cf commit e613828

3 files changed

Lines changed: 143 additions & 141 deletions

File tree

.github/workflows/release.yml

Lines changed: 42 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -29,157 +29,70 @@ jobs:
2929
echo "version=${VERSION}" >> $GITHUB_OUTPUT
3030
echo "version_number=${VERSION#v}" >> $GITHUB_OUTPUT
3131
32-
linux-build:
32+
build-wheels:
3333
needs: [extract-version]
3434
strategy:
3535
fail-fast: false
3636
matrix:
37-
include:
38-
- os: ubuntu-latest
39-
container: python:3.12-bookworm
40-
platform: linux_x86_64
41-
arch: x86_64
42-
arch_label: x86_64
43-
- os: ubuntu-24.04-arm
44-
container: python:3.12-bookworm
45-
platform: linux_aarch64
46-
arch: arm64
47-
arch_label: arm64
37+
os: [ubuntu-latest, macos-latest, macos-15-intel]
4838
runs-on: ${{ matrix.os }}
49-
container: ${{ matrix.container }}
50-
env:
51-
UV_LINK_MODE: copy
52-
UV_CACHE_DIR: /github/home/.cache/uv
5339
permissions:
54-
actions: write
5540
contents: write
56-
5741
steps:
5842
- name: Checkout code
5943
uses: actions/checkout@v6
6044
with:
6145
submodules: recursive
6246

63-
- name: Cache uv downloads
64-
uses: actions/cache@v5
65-
with:
66-
path: /github/home/.cache/uv
67-
key: uvcache-${{ runner.os }}-${{ matrix.arch_label }}-${{ hashFiles('uv.lock', 'pyproject.toml') }}
68-
restore-keys: |
69-
uvcache-${{ runner.os }}-${{ matrix.arch_label }}-
70-
71-
- name: Add Debian sid repository
72-
if: matrix.container != null
47+
- name: Install cibuildwheel
7348
run: |
74-
echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
75-
echo 'Package: *\nPin: release a=sid\nPin-Priority: 100' > /etc/apt/preferences.d/sid
49+
python -m pip install --upgrade pip
50+
pip install cibuildwheel
7651
77-
- name: Install system dependencies (Linux)
78-
if: matrix.container != null
52+
- name: Build wheels
53+
env:
54+
CIBW_BUILD_VERBOSITY: 1
55+
CIBW_BEFORE_BUILD: "pip install uv && uv sync --frozen --no-dev || uv sync --no-dev"
7956
run: |
80-
apt-get update
81-
apt-get install -y base-files
82-
apt-get install -y build-essential pkg-config libbz2-dev
83-
apt-get install -y -t sid libmapnik-dev
57+
cibuildwheel --output-dir wheelhouse
8458
85-
- name: Install uv
86-
uses: astral-sh/setup-uv@v7
59+
- name: Upload wheels
60+
uses: actions/upload-artifact@v4
8761
with:
88-
enable-cache: false
62+
name: wheels-${{ matrix.os }}
63+
path: wheelhouse/*.whl
64+
retention-days: 7
8965

90-
- name: Update version from tag
91-
run: |
92-
# Extract base version from pyproject.toml
93-
BASE_VERSION=$(grep -E '^version = ' pyproject.toml | sed -E 's/^version = "([^"]+)"/\1/')
94-
TAG=${{ needs.extract-version.outputs.version }}
95-
VERSION="${BASE_VERSION}-${TAG}"
96-
echo "Base version from pyproject.toml: $BASE_VERSION"
97-
echo "Git tag: $TAG"
98-
echo "Setting version to: $VERSION"
99-
# Update pyproject.toml
100-
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
101-
# Update setup.py
102-
sed -i "s/version=\"[^\"]*\"/version=\"$VERSION\"/" setup.py
103-
# Verify changes
104-
echo "pyproject.toml version:"
105-
grep "^version = " pyproject.toml
106-
echo "setup.py version:"
107-
grep "version=" setup.py | head -1
66+
build-sdist:
67+
needs: [extract-version]
68+
runs-on: ubuntu-latest
69+
permissions:
70+
contents: write
71+
steps:
72+
- name: Checkout code
73+
uses: actions/checkout@v6
74+
with:
75+
submodules: recursive
10876

109-
- name: Build wheel and sdist
77+
- name: Install uv
78+
uses: astral-sh/setup-uv@v7
79+
80+
- name: Build sdist
11081
run: |
111-
uv build --wheel --sdist
82+
uv build --sdist
11283
113-
- name: Upload build artifacts
84+
- name: Upload sdist
11485
uses: actions/upload-artifact@v4
11586
with:
116-
name: dist-${{ matrix.platform }}
117-
path: dist/
87+
name: sdist
88+
path: dist/*.tar.gz
11889
retention-days: 7
11990

120-
# macos-build:
121-
# needs: [extract-version]
122-
# strategy:
123-
# fail-fast: false
124-
# matrix:
125-
# include:
126-
# - os: macos-15-intel
127-
# platform: macosx_10_9_x86_64
128-
# arch: x86_64
129-
# arch_label: x86_64
130-
# - os: macos-15
131-
# platform: macosx_15_0_arm64
132-
# arch: arm64
133-
# arch_label: arm64
134-
# runs-on: ${{ matrix.os }}
135-
# env:
136-
# UV_LINK_MODE: copy
137-
# UV_CACHE_DIR: /Users/runner/.cache/uv
138-
# permissions:
139-
# actions: write
140-
# contents: write
141-
142-
# steps:
143-
# - name: Checkout code
144-
# uses: actions/checkout@v6
145-
# with:
146-
# submodules: recursive
147-
148-
# - name: Cache uv downloads
149-
# uses: actions/cache@v5
150-
# with:
151-
# path: /Users/runner/.cache/uv
152-
# key: uvcache-${{ runner.os }}-${{ matrix.arch_label }}-${{ hashFiles('uv.lock', 'pyproject.toml') }}
153-
# restore-keys: |
154-
# uvcache-${{ runner.os }}-${{ matrix.arch_label }}-
155-
156-
# - name: Install and cache Homebrew tools
157-
# uses: tecolicom/actions-use-homebrew-tools@v1
158-
# with:
159-
# tools: mapnik icu4c pkg-config
160-
# key: mapnik-${{ matrix.arch_label }}
161-
162-
# - name: Install uv
163-
# uses: astral-sh/setup-uv@v7
164-
# with:
165-
# enable-cache: false
166-
167-
# - name: Build wheel and sdist
168-
# run: |
169-
# uv build --wheel --sdist
170-
171-
# - name: Upload build artifacts
172-
# uses: actions/upload-artifact@v4
173-
# with:
174-
# name: dist-${{ matrix.platform }}
175-
# path: dist/
176-
# retention-days: 7
177-
17891
release:
17992
needs:
18093
- extract-version
181-
- linux-build
182-
# - macos-build
94+
- build-wheels
95+
- build-sdist
18396
runs-on: ubuntu-latest
18497
permissions:
18598
contents: write
@@ -194,8 +107,12 @@ jobs:
194107
- name: Combine artifacts
195108
run: |
196109
mkdir -p dist
110+
# Copy all wheels
197111
find dist-all -name "*.whl" -exec cp {} dist/ \;
198-
find dist-all -name "*.tar.gz" -exec head -1 {} \; | head -1 | xargs -I {} find dist-all -name "{}" -exec cp {} dist/ \;
112+
# Copy sdist (should be only one)
113+
find dist-all -name "*.tar.gz" -exec cp {} dist/ \;
114+
echo "Artifacts in dist/:"
115+
ls -lh dist/
199116
200117
- name: Create GitHub Release
201118
uses: softprops/action-gh-release@v2
@@ -250,8 +167,8 @@ jobs:
250167
echo "### Supported Platforms:" >> $GITHUB_STEP_SUMMARY
251168
echo "- Linux x86_64: ✅" >> $GITHUB_STEP_SUMMARY
252169
echo "- Linux arm64: ✅" >> $GITHUB_STEP_SUMMARY
253-
# echo "- macOS x86_64: ✅" >> $GITHUB_STEP_SUMMARY
254-
# echo "- macOS arm64: ✅" >> $GITHUB_STEP_SUMMARY
170+
echo "- macOS x86_64: ✅" >> $GITHUB_STEP_SUMMARY
171+
echo "- macOS arm64: ✅" >> $GITHUB_STEP_SUMMARY
255172
echo "" >> $GITHUB_STEP_SUMMARY
256173
echo "### Distribution:" >> $GITHUB_STEP_SUMMARY
257174
echo "- GitHub Release: ✅" >> $GITHUB_STEP_SUMMARY

.github/workflows/test.yml

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -176,20 +176,51 @@ jobs:
176176
- name: Install and cache Homebrew tools
177177
uses: tecolicom/actions-use-homebrew-tools@v1
178178
with:
179-
tools: mapnik icu4c pkg-config boost gdal proj harfbuzz
180-
key: mapnik-${{ matrix.arch_label }}
179+
tools: mapnik icu4c pkg-config boost gdal proj harfbuzz libx11 xorgproto libxext libxrender libxau libxdmcp
180+
key: mapnik-${{ matrix.os }}-${{ matrix.arch_label }}-20260118
181181

182182
- name: Setup pkg-config and build environment
183183
run: |
184+
# Ensure Homebrew environment is available
185+
eval $(brew shellenv)
186+
# Get package-specific prefixes using brew --prefix and save to GITHUB_ENV for reuse
187+
HOMEBREW_PREFIX=$(brew --prefix)
188+
MAPNIK_PREFIX=$(brew --prefix mapnik)
189+
ICU4C_PREFIX=$(brew --prefix icu4c)
190+
BOOST_PREFIX=$(brew --prefix boost)
191+
GDAL_PREFIX=$(brew --prefix gdal)
192+
PROJ_PREFIX=$(brew --prefix proj)
193+
HARFBUZZ_PREFIX=$(brew --prefix harfbuzz)
194+
XORGPROTO_PREFIX=$(brew --prefix xorgproto)
195+
# Find the actual xorgproto pkg-config directory (may be in Cellar with version)
196+
XORGPROTO_PKGCONFIG_DIR=$(find "$HOMEBREW_PREFIX/Cellar/xorgproto" -type d -name "pkgconfig" 2>/dev/null | head -1)
197+
if [ -z "$XORGPROTO_PKGCONFIG_DIR" ]; then
198+
# Fallback to opt symlink location
199+
XORGPROTO_PKGCONFIG_DIR="$XORGPROTO_PREFIX/share/pkgconfig"
200+
echo "Warning: xorgproto pkgconfig directory not found in Cellar, using fallback: $XORGPROTO_PKGCONFIG_DIR"
201+
else
202+
echo "Found xorgproto pkgconfig directory: $XORGPROTO_PKGCONFIG_DIR"
203+
fi
204+
# Save prefixes to GITHUB_ENV for reuse in subsequent steps
205+
echo "HOMEBREW_PREFIX=$HOMEBREW_PREFIX" >> $GITHUB_ENV
206+
echo "MAPNIK_PREFIX=$MAPNIK_PREFIX" >> $GITHUB_ENV
207+
echo "ICU4C_PREFIX=$ICU4C_PREFIX" >> $GITHUB_ENV
208+
echo "BOOST_PREFIX=$BOOST_PREFIX" >> $GITHUB_ENV
209+
echo "GDAL_PREFIX=$GDAL_PREFIX" >> $GITHUB_ENV
210+
echo "PROJ_PREFIX=$PROJ_PREFIX" >> $GITHUB_ENV
211+
echo "HARFBUZZ_PREFIX=$HARFBUZZ_PREFIX" >> $GITHUB_ENV
212+
echo "XORGPROTO_PREFIX=$XORGPROTO_PREFIX" >> $GITHUB_ENV
213+
echo "XORGPROTO_PKGCONFIG_DIR=$XORGPROTO_PKGCONFIG_DIR" >> $GITHUB_ENV
214+
echo "Homebrew prefix: $HOMEBREW_PREFIX"
215+
echo "Mapnik prefix: $MAPNIK_PREFIX"
216+
echo "xorgproto pkg-config dir: $XORGPROTO_PKGCONFIG_DIR"
184217
# Set PKG_CONFIG_PATH to include Homebrew's pkg-config directories
185-
# This ensures pkg-config can find Mapnik and its dependencies (ICU, Boost, GDAL, PROJ, HarfBuzz, etc.)
186-
echo "PKG_CONFIG_PATH=$(brew --prefix)/lib/pkgconfig:$(brew --prefix)/opt/icu4c/lib/pkgconfig:$(brew --prefix)/opt/boost/lib/pkgconfig:$(brew --prefix)/opt/gdal/lib/pkgconfig:$(brew --prefix)/opt/proj/lib/pkgconfig:$(brew --prefix)/opt/harfbuzz/lib/pkgconfig:$PKG_CONFIG_PATH" >> $GITHUB_ENV
218+
# This ensures pkg-config can find Mapnik and its dependencies (ICU, Boost, GDAL, PROJ, HarfBuzz, X11 proto, etc.)
219+
# Note: xorgproto .pc files are in Cellar/xorgproto/<version>/share/pkgconfig
220+
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:$XORGPROTO_PKGCONFIG_DIR:$XORGPROTO_PREFIX/share/pkgconfig:$PKG_CONFIG_PATH" >> $GITHUB_ENV
187221
# Set CXXFLAGS and LDFLAGS to include Boost, GDAL, PROJ, and HarfBuzz headers and libraries
188-
echo "CXXFLAGS=-I$(brew --prefix)/opt/boost/include -I$(brew --prefix)/opt/gdal/include -I$(brew --prefix)/opt/proj/include -I$(brew --prefix)/opt/harfbuzz/include $CXXFLAGS" >> $GITHUB_ENV
189-
echo "LDFLAGS=-L$(brew --prefix)/opt/boost/lib -L$(brew --prefix)/opt/gdal/lib -L$(brew --prefix)/opt/proj/lib -L$(brew --prefix)/opt/harfbuzz/lib $LDFLAGS" >> $GITHUB_ENV
190-
echo "PKG_CONFIG_PATH set to: $PKG_CONFIG_PATH"
191-
echo "CXXFLAGS set to: $CXXFLAGS"
192-
echo "LDFLAGS set to: $LDFLAGS"
222+
echo "CXXFLAGS=-I$BOOST_PREFIX/include -I$GDAL_PREFIX/include -I$PROJ_PREFIX/include -I$HARFBUZZ_PREFIX/include $CXXFLAGS" >> $GITHUB_ENV
223+
echo "LDFLAGS=-L$BOOST_PREFIX/lib -L$GDAL_PREFIX/lib -L$PROJ_PREFIX/lib -L$HARFBUZZ_PREFIX/lib $LDFLAGS" >> $GITHUB_ENV
193224
194225
- name: Install uv
195226
uses: astral-sh/setup-uv@v7
@@ -198,6 +229,13 @@ jobs:
198229

199230
- name: Install Python dependencies and build package
200231
run: |
232+
# Ensure Homebrew environment is available
233+
eval $(brew shellenv)
234+
# Re-export environment variables (already set in previous step via GITHUB_ENV)
235+
# This ensures they're available in the current shell session for subprocess calls
236+
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
237+
export CXXFLAGS="$CXXFLAGS"
238+
export LDFLAGS="$LDFLAGS"
201239
# Use lockfile when present; avoid doing two full syncs (which can rebuild twice).
202240
if [ -f uv.lock ]; then
203241
uv sync --extra test --frozen --verbose
@@ -231,22 +269,27 @@ jobs:
231269
uses: actions/upload-artifact@v4
232270
if: always()
233271
with:
234-
name: coverage-reports-macos-${{ matrix.arch_label }}
272+
name: coverage-reports-macos-${{ matrix.os }}-${{ matrix.arch_label }}
235273
path: |
236274
coverage.xml
237275
htmlcov/
238276
junit.xml
239277
retention-days: 30
240278

241-
# Note: publish-unit-test-result-action doesn't support macOS (container action limitation)
242-
# Test results are still uploaded as artifacts above
243-
279+
- name: Publish test results
280+
uses: EnricoMi/publish-unit-test-result-action/macos@v2
281+
if: always()
282+
with:
283+
files: junit.xml
284+
check_name: Test Results (macOS ${{ matrix.os }} ${{ matrix.arch_label }})
285+
comment_mode: off
286+
244287
- name: Upload coverage to Codecov
245288
uses: codecov/codecov-action@v5
246289
if: always()
247290
with:
248291
files: coverage.xml
249-
flags: unittests-macos-${{ matrix.arch_label }}
250-
name: python-mapnik-coverage-macos-${{ matrix.arch_label }}
292+
flags: unittests-macos-${{ matrix.os }}-${{ matrix.arch_label }}
293+
name: python-mapnik-coverage-macos-${{ matrix.os }}-${{ matrix.arch_label }}
251294
fail_ci_if_error: false
252295
token: ${{ secrets.CODECOV_TOKEN }}

pyproject.toml

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,46 @@ testpaths = [
4545

4646
[tool.uv]
4747
# Pin uv version for CI/dev consistency (used by astral-sh/setup-uv).
48-
required-version = ">=0.9.0"
48+
required-version = ">=0.9.0"
49+
50+
[tool.cibuildwheel]
51+
# Build only Python 3.12+ (matches requires-python)
52+
build = "cp312-*"
53+
skip = ["*-win32", "*-manylinux_i686", "*-musllinux_*"]
54+
test-command = "uv run pytest test/python_tests -v"
55+
test-extras = ["test"]
56+
57+
# Linux build configuration
58+
[tool.cibuildwheel.linux]
59+
# Use manylinux_2_28 (Debian 12 / Bookworm based)
60+
manylinux-x86_64-image = "manylinux_2_28_x86_64"
61+
manylinux-aarch64-image = "manylinux_2_28_aarch64"
62+
63+
# Install system dependencies before build
64+
before-all = """
65+
# Add Debian sid repository for Mapnik 4.2
66+
echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
67+
echo 'Package: *\nPin: release a=sid\nPin-Priority: 100' > /etc/apt/preferences.d/sid
68+
69+
# Install build dependencies
70+
apt-get update
71+
apt-get install -y build-essential pkg-config libbz2-dev
72+
apt-get install -y -t sid libmapnik-dev fonts-noto-cjk
73+
"""
74+
75+
# macOS build configuration
76+
[tool.cibuildwheel.macos]
77+
# Build for both x86_64 and arm64
78+
archs = ["x86_64", "arm64"]
79+
80+
# Install dependencies via Homebrew (run once before all builds)
81+
before-all = "brew install mapnik icu4c pkg-config boost gdal proj harfbuzz"
82+
83+
# Set environment variables for each build
84+
# These are exported in the build environment
85+
before-build = """
86+
eval $(brew shellenv)
87+
export PKG_CONFIG_PATH=$(brew --prefix)/lib/pkgconfig:$(brew --prefix)/opt/icu4c/lib/pkgconfig:$(brew --prefix)/opt/boost/lib/pkgconfig:$(brew --prefix)/opt/gdal/lib/pkgconfig:$(brew --prefix)/opt/proj/lib/pkgconfig:$(brew --prefix)/opt/harfbuzz/lib/pkgconfig:$PKG_CONFIG_PATH
88+
export CXXFLAGS="-I$(brew --prefix)/opt/boost/include -I$(brew --prefix)/opt/gdal/include -I$(brew --prefix)/opt/proj/include -I$(brew --prefix)/opt/harfbuzz/include $CXXFLAGS"
89+
export LDFLAGS="-L$(brew --prefix)/opt/boost/lib -L$(brew --prefix)/opt/gdal/lib -L$(brew --prefix)/opt/proj/lib -L$(brew --prefix)/opt/harfbuzz/lib $LDFLAGS"
90+
"""

0 commit comments

Comments
 (0)