Skip to content

Commit 170b491

Browse files
cpsievertclaudeCopilot
authored
ci: add PyPI release workflow for ggsql Python package (#112)
* ci: add PyPI release workflow for ggsql Python package Adds a GitHub Actions workflow to build and publish the ggsql Python package to PyPI. Uses PyO3 abi3-py310 so one wheel per platform covers all Python 3.10+. Workflow structure: - `generate` job: runs tree-sitter generate on a regular runner, uploads parser artifacts - Build jobs (linux, macos, windows, sdist): download parser artifacts, build wheels with maturin - `publish` + `github-release`: deploy on tag push Build details: - Linux: manylinux_2_28 for x86_64 and aarch64 - macOS: macos-latest for both x86_64 (cross-compile) and aarch64 - Windows: x64 - build.rs skips parser generation when parser.c already exists (provided by the generate job artifact) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Improve comment Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: use env var to skip parser generation in CI instead of file check Restore default behavior of always regenerating parser.c on local builds so grammar changes are picked up automatically. CI build jobs set GGSQL_SKIP_GENERATE=1 to use pre-generated parser artifacts instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent ccf4b28 commit 170b491

3 files changed

Lines changed: 232 additions & 11 deletions

File tree

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
name: Python Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "py/v*"
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
env:
13+
# Must match the abi3-py3XX feature in ggsql-python/Cargo.toml.
14+
# abi3 wheels built against 3.10 are forward-compatible with all later
15+
# Python versions, so this should be the minimum supported version.
16+
PYTHON_VERSION: "3.10"
17+
18+
jobs:
19+
generate:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- uses: actions/setup-node@v4
25+
with:
26+
node-version: "20"
27+
28+
- name: Install tree-sitter-cli
29+
run: npm install -g tree-sitter-cli
30+
31+
- name: Generate parser
32+
working-directory: tree-sitter-ggsql
33+
run: tree-sitter generate
34+
35+
- uses: actions/upload-artifact@v4
36+
with:
37+
name: tree-sitter-generated
38+
path: tree-sitter-ggsql/src/
39+
40+
linux:
41+
needs: generate
42+
runs-on: ubuntu-latest
43+
strategy:
44+
matrix:
45+
target: [x86_64, aarch64]
46+
env:
47+
GGSQL_SKIP_GENERATE: "1"
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- uses: actions/download-artifact@v4
52+
with:
53+
name: tree-sitter-generated
54+
path: tree-sitter-ggsql/src/
55+
56+
- uses: actions/setup-python@v5
57+
with:
58+
python-version: ${{ env.PYTHON_VERSION }}
59+
60+
- name: Build wheels
61+
uses: PyO3/maturin-action@v1
62+
with:
63+
target: ${{ matrix.target }}
64+
args: --release --out dist --interpreter python${{ env.PYTHON_VERSION }}
65+
working-directory: ggsql-python
66+
# manylinux2014's cross-compiler is too old for the `ring` crate's
67+
# aarch64 assembly (missing __ARM_ARCH). 2_28 (AlmaLinux 8, gcc 8+)
68+
# provides a new enough toolchain.
69+
manylinux: 2_28
70+
71+
- uses: actions/upload-artifact@v4
72+
with:
73+
name: wheels-linux-${{ matrix.target }}
74+
path: ggsql-python/dist
75+
76+
macos:
77+
needs: generate
78+
runs-on: ${{ matrix.runner }}
79+
strategy:
80+
matrix:
81+
include:
82+
- target: x86_64
83+
runner: macos-latest
84+
- target: aarch64
85+
runner: macos-latest
86+
env:
87+
GGSQL_SKIP_GENERATE: "1"
88+
steps:
89+
- uses: actions/checkout@v4
90+
91+
- uses: actions/download-artifact@v4
92+
with:
93+
name: tree-sitter-generated
94+
path: tree-sitter-ggsql/src/
95+
96+
- uses: actions/setup-python@v5
97+
with:
98+
python-version: ${{ env.PYTHON_VERSION }}
99+
100+
- name: Build wheels
101+
uses: PyO3/maturin-action@v1
102+
with:
103+
target: ${{ matrix.target }}
104+
args: --release --out dist --interpreter python${{ env.PYTHON_VERSION }}
105+
working-directory: ggsql-python
106+
107+
- uses: actions/upload-artifact@v4
108+
with:
109+
name: wheels-macos-${{ matrix.target }}
110+
path: ggsql-python/dist
111+
112+
windows:
113+
needs: generate
114+
runs-on: windows-latest
115+
env:
116+
GGSQL_SKIP_GENERATE: "1"
117+
steps:
118+
- uses: actions/checkout@v4
119+
120+
- uses: actions/download-artifact@v4
121+
with:
122+
name: tree-sitter-generated
123+
path: tree-sitter-ggsql/src/
124+
125+
- uses: actions/setup-python@v5
126+
with:
127+
python-version: ${{ env.PYTHON_VERSION }}
128+
129+
- name: Build wheels
130+
uses: PyO3/maturin-action@v1
131+
with:
132+
target: x64
133+
args: --release --out dist --interpreter python${{ env.PYTHON_VERSION }}
134+
working-directory: ggsql-python
135+
136+
- uses: actions/upload-artifact@v4
137+
with:
138+
name: wheels-windows-x64
139+
path: ggsql-python/dist
140+
141+
sdist:
142+
needs: generate
143+
runs-on: ubuntu-latest
144+
env:
145+
GGSQL_SKIP_GENERATE: "1"
146+
steps:
147+
- uses: actions/checkout@v4
148+
149+
- uses: actions/download-artifact@v4
150+
with:
151+
name: tree-sitter-generated
152+
path: tree-sitter-ggsql/src/
153+
154+
- name: Build sdist
155+
uses: PyO3/maturin-action@v1
156+
with:
157+
command: sdist
158+
args: --out dist
159+
working-directory: ggsql-python
160+
161+
- uses: actions/upload-artifact@v4
162+
with:
163+
name: wheels-sdist
164+
path: ggsql-python/dist
165+
166+
publish:
167+
needs: [linux, macos, windows, sdist]
168+
runs-on: ubuntu-latest
169+
if: startsWith(github.ref, 'refs/tags/')
170+
environment: pypi
171+
permissions:
172+
id-token: write
173+
steps:
174+
- uses: actions/download-artifact@v4
175+
with:
176+
pattern: wheels-*
177+
merge-multiple: true
178+
path: dist
179+
180+
- name: List wheels
181+
run: ls -lh dist/
182+
183+
- name: Publish to PyPI
184+
uses: pypa/gh-action-pypi-publish@release/v1
185+
186+
github-release:
187+
needs: publish
188+
runs-on: ubuntu-latest
189+
if: startsWith(github.ref, 'refs/tags/')
190+
permissions:
191+
contents: write
192+
steps:
193+
- uses: actions/download-artifact@v4
194+
with:
195+
pattern: wheels-*
196+
merge-multiple: true
197+
path: dist
198+
199+
- name: Create GitHub Release
200+
uses: softprops/action-gh-release@v2
201+
with:
202+
files: dist/*
203+
generate_release_notes: true

ggsql-python/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ name = "_ggsql"
1010
crate-type = ["cdylib"]
1111

1212
[dependencies]
13-
pyo3 = { version = "0.26", features = ["extension-module"] }
13+
pyo3 = { version = "0.26", features = ["extension-module", "abi3-py310"] }
1414
polars = { workspace = true, features = ["ipc"] }
1515
ggsql = { path = "../src", default-features = false, features = ["duckdb", "vegalite"] }
1616

tree-sitter-ggsql/bindings/rust/build.rs

Lines changed: 28 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)