Repository navigation
ci(python): build pygosqlx platform wheels and publish to PyPI - #851
Conversation
Make pygosqlx pip-installable with prebuilt wheels that bundle libgosqlx. - pyproject.toml is the only metadata source; setup.py is reduced to a shim that marks the distribution non-pure and tags wheels py3-none-<platform>, so a wheel with a bundled native library is never tagged py3-none-any. requires-python >=3.10, classifiers 3.10-3.14, SPDX license metadata. - New pygosqlx-release.yml: cibuildwheel builds and tests wheels for manylinux x86_64/aarch64 (Go installed in the container from a pinned, checksum-verified tarball), macOS x86_64/arm64 and Windows AMD64, plus an sdist. PRs build and test only; pygosqlx-v* tags publish to PyPI via Trusted Publishing; workflow_dispatch can publish to TestPyPI or PyPI. - Tests can run against an installed wheel (PYGOSQLX_TEST_INSTALLED=1); test_installed_wheel.py fails if the checkout is imported or the wheel does not bundle a loadable library. - README: pip install pygosqlx as primary install, supported platforms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
Claude finished @ajitpratap0's task in 30s —— View job Review of PR #851: pygosqlx wheels and PyPI pipelineI read the workflow, Likely bug (Windows CI)
Smaller issues
Looks good
I made no code changes, since I can't modify files under |
On Windows the installed package (C:) and the checkout (D:) are on different drives, where os.path.commonpath raises ValueError. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9
|
Claude finished @ajitpratap0's task in 17s —— View job Review of PR #851 (updated for the latest push)I read the workflow and Resolved since the earlier review
Remaining suggestions, most important first
Looks good
I made no code changes. I can't edit |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9
|
Claude finished @ajitpratap0's task in 19s —— View job Review of PR #851 (updated after the latest push)I re-read Resolved since the earlier review
Still open (none blocks merge)
Looks good
The real proof is the five wheel jobs and the sdist job, which haven't reported yet. Wait for the Windows and aarch64 jobs before merging. |
- release.yml: pin GORELEASER_CURRENT_TAG/PREVIOUS_TAG to the v* series so pygosqlx-v* tags cannot truncate the Go release changelog (git.ignore_tags is GoReleaser Pro-only) - PyPI publishes only from pygosqlx-v* tags; dispatch offers testpypi/none - refuse to publish a tag whose commit is not on origin/main - TestPyPI publish uses skip-existing for repeatable dry runs - build c-shared libraries with -trimpath via GOFLAGS - run the wheel build on pkg/** changes, not only pkg/cbinding/** - fail if the workflow and install-go-linux.sh Go versions differ - ship tests/conftest.py in the sdist; add Windows OS classifier Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9
|
Claude finished @ajitpratap0's task in 21s —— View job Review of PR #851 (head c172b07)I read the workflow, the Earlier suggestions that are now addressed
Remaining points, none blocking
Looks good
|
- publish-pypi now requires github.event_name == 'push'; a
workflow_dispatch run on a pygosqlx-v* tag ref no longer uploads to
PyPI regardless of the 'target' input.
- Linux wheels are repaired with --plat manylinux_2_17_{arch} so the
x86_64 wheel no longer claims untested glibc 2.5-2.16 distros; README
states the actual tag.
- setup.py warns at build time when the native library is missing, and
the runtime FileNotFoundError points at the README build-from-source
section.
- Drop an extra blank line in test_package_version.py (E303).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9
|
Claude finished @ajitpratap0's task in 25s —— View job Review of PR #851 (head 47c4dc1)I read the workflow, the Earlier review points that are now addressed
Remaining points, most important first
Looks good
|
cibuildwheel does not expand {arch} in CIBW_REPAIR_WHEEL_COMMAND_LINUX,
so auditwheel rejected the literal manylinux_2_17_{arch}. Take the
architecture from the matrix instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9
|
Claude finished @ajitpratap0's task in 20s —— View job Review of PR #851 (head c76437c)I re-read Resolved since the earlier reviews
Remaining points, most important first
Looks good
|
…uide Record the pygosqlx 0.3.0 API and wheels, the gosqlx_version double free, LSP serverInfo/CLI version reporting, the Python CI and release workflows and the #848 docs. MIGRATION companion table lists pygosqlx 0.3.0, libgosqlx exports and the LSP serverInfo version, with matching behaviour-change notes. Regenerate the v1.16.0 blog page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9
* chore(parser): remove stray parser.go-e backup with conflict markers [vercel skip] The sed backup file was committed by accident in #791. It is not compiled but ships in the module zip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * chore(release): bump version to 1.16.0 [vercel skip] gosqlx.Version and the CLI version were still 1.14.0 (v1.15.0 shipped with them), so gosqlx --version, the MCP server info and /health reported 1.14.0. Also bumps the VS Code extension, Claude Code plugin and marketplace, glama, performance baseline label, llms.txt and the site's release badge. pygosqlx __version__ now matches pyproject (0.2.0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * docs(changelog): finalize 1.16.0 release notes [vercel skip] Turns [Unreleased] into [1.16.0] - 2026-10-21, adds the missing entries for #734, #735, #780, #786, #789, #790, #791, #826, #835, #836, #837, #840, #841, #843 and #844, updates the MCP and composite-field entries amended by #841 and #843, adds PR refs, and adds the compare links. The VS Code extension gets a 1.16.0 entry, and split-changelog.js generates the /changelog page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * docs: v1.15 to v1.16 migration guide and release doc fixes [vercel skip] MIGRATION gains a v1.15.0 -> v1.16.0 section with a behaviour-change checklist. ERROR_CODES documents E4001 dialect gating and the 11 dialect names. CLI_GUIDE lists --dialect on format, parse, analyze and lint and all 11 dialects. SQL_COMPATIBILITY marks Oracle CONNECT BY/PRIOR and SQL Server PIVOT as parsed. api/mcp.md matches the current Config and middleware API, api/models.md drops the nonexistent Location.Offset and documents byte columns, and HIGHLIGHTING notes ANSI control-character neutralization. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * chore(website): regenerate sample AST and changelog pages The website build rewrote both files on main: sample-ast.json gains the WithOrdinality and ColumnAliases fields from #843, and v1-9-1.md drops the emoji the changelog splitter strips. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * docs(release): correct allocation claim, plugin history, E4001 and LoadConfig errors Address review notes on #845: the lead paragraph understated the perf audit's allocation cuts, the MIGRATION table listed a v1.15.0 plugin that never shipped, E4001 also covers LIMIT under SQL Server, and LoadConfig rejects more trusted-proxy misconfigurations than the API doc listed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * docs(release): make glama.json match the MCP server List all 11 validate_sql dialects, describe lint_sql as the 10 rules it runs (L001-L010; the CLI and SDK have 30), sync tool descriptions with pkg/mcp/server.go, and drop the unsourced 1.38M ops/sec claim in favour of a link to the benchmarks page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * docs(release): add #846-#851 to the v1.16.0 CHANGELOG and migration guide Record the pygosqlx 0.3.0 API and wheels, the gosqlx_version double free, LSP serverInfo/CLI version reporting, the Python CI and release workflows and the #848 docs. MIGRATION companion table lists pygosqlx 0.3.0, libgosqlx exports and the LSP serverInfo version, with matching behaviour-change notes. Regenerate the v1.16.0 blog page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * docs(release): address v1.16.0 release review; add #852 - Release date 2026-10-22 in CHANGELOG, MIGRATION, the extension changelog and the generated blog post (re-stamp at tag time if it slips). - vscode-extension CHANGELOG: Fixed entry for the #846 version reporting. - CHANGELOG: keep the Behavior changes list tight; name TranspileError and the LintResult/SecurityScanResult types in the pygosqlx 0.3.0 entry. - MIGRATION: PyPI wheels row is conditional on the pygosqlx-v0.3.0 tag. - Add #852 (sdist builds fail without libgosqlx; release tag lookup skips v1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * build(release): replace deprecated goreleaser keys (formats, version_template) goreleaser check (v2.12.7) flagged archives.format, format_overrides.format and snapshot.name_template as deprecated; release.yml runs goreleaser 'latest'. Snapshot release dry-run builds all six archives. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * docs(release): add #853 to the v1.16.0 CHANGELOG Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 * feat(python): version pygosqlx in lockstep with GoSQLX (1.16.0) pygosqlx wheels bundle libgosqlx built from the same commit, so its version now matches the GoSQLX release. The first PyPI release is 1.16.0 (it was 0.2.0, never published); no older versions are backfilled. - pygosqlx-release.yml also publishes on GoSQLX 'vX.Y.Z' tags (the floating 'v1' tag does not match); 'pygosqlx-v*' stays for Python-only .postN releases. Both must match pyproject.toml and be on main. - pyproject.toml / __version__ 1.16.0; the version test now asserts __version__ equals the bundled library's version(). - CHANGELOG, MIGRATION and python/README describe the lockstep scheme. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9 --------- Co-authored-by: Ajit Pratap Singh <ajitpratapsingh@Ajits-Mac-mini-2655.local> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Makes
pygosqlxinstallable withpip install pygosqlxthrough prebuilt platform wheels that bundlelibgosqlx, and adds a PyPI release pipeline. Builds on the 0.3.0 API (#850). The version stays at 0.3.0.Packaging (
python/)pyproject.tomlis now the only source of metadata:requires-python >=3.10, classifiers for 3.10–3.14 (3.8/3.9 dropped), SPDXlicense = "Apache-2.0"pluslicense-files(setuptools>=77). Development Status stays Alpha.setup.pyis now only a shim with no metadata. It declares the distribution non-pure (has_ext_modules) and tags the wheelpy3-none-<platform>. Without it, a wheel that bundles a native.so/.dylib/.dllwould be taggedpy3-none-any.py3-noneis correct because the library is loaded through ctypes and does not depend on the CPython ABI, so one wheel per OS/arch covers every Python version.package-databundlespygosqlx/lib/libgosqlx.*.python/LICENSEis a copy of the root license, becauselicense-filescannot point outside the project dir.New workflow
.github/workflows/pygosqlx-release.ymlwheelsuses cibuildwheel v4.3.0, pinned by SHA, with native runners only:ubuntu-24.04,ubuntu-24.04-arm). They are built in the manylinux_2_28 image and repaired withauditwheel repair --plat manylinux_2_17_{arch}, so both arches are taggedmanylinux_2_17(manylinux2014). Without the pin auditwheel tagged x86_64manylinux_2_5, claiming untested glibc 2.5–2.16 distros. Go 1.26.10 is installed inside the container bypython/scripts/install-go-linux.sh, from the official tarball checked against a pinned SHA-256.macos-15-intel,macos-15) with deployment target 13.0. The cgo CFLAGS/LDFLAGS are pinned to the same minimum.windows-2025, runner MinGW gcc).CIBW_BEFORE_BUILDbuilds libgosqlx withGOFLAGS=-trimpath(no absolute build paths in the binaries) intopython/pygosqlx/lib. Each platform's single wheel is tested with pytest on CPython 3.10–3.14.sdistfails ifGO_VERSIONin the workflow andinstall-go-linux.shdiffer, checks that apygosqlx-v*tag matches thepyproject.tomlversion, runstwine check --strict, and fails if the sdist contains a native binary.pull_requestonpython/**,pkg/**(cbinding links the whole parser viapkg/gosqlx),go.mod,go.sumand the workflow only builds and tests.pygosqlx-v*tag builds, tests and publishes to PyPI. This is the only path to PyPI. The sdist job refuses a tag whose commit is not an ancestor oforigin/main. The mainv*tags never trigger the workflow.workflow_dispatchbuilds and tests, then publishes to thetargetinput:testpypi(default) ornone. A dispatch can publish only frommain. The TestPyPI upload usesskip-existing: trueso repeated dry runs of the same version do not fail.publish-pypiandpublish-testpypiuseenvironment: pypi/testpypi,permissions: id-token: writeonly, andpypa/gh-action-pypi-publishv1.14.2 pinned by SHA (Trusted Publishing, no token). The rest of the workflow hascontents: read, and checkouts usepersist-credentials: false.ajitpratap0, repoGoSQLX, workflowpygosqlx-release.yml, environmentpypi), create thepypiGitHub environment, and optionally the TestPyPI equivalents.Keeping
pygosqlx-v*tags out of the Go release (.github/workflows/release.yml)git describe --tags, so after the firstpygosqlx-v*tag the nextv1.xrelease would compute its changelog and compare link from the pygosqlx tag. A new step setsGORELEASER_CURRENT_TAGto the pushed tag andGORELEASER_PREVIOUS_TAGtogit describe --tags --abbrev=0 --match 'v[0-9]*' "$TAG^".git.ignore_tagsin.goreleaser.ymlwas not used because it is GoReleaser Pro-only.Testing against the installed wheel
tests/conftest.py. SettingPYGOSQLX_TEST_INSTALLED=1keeps the checkout offsys.path; cibuildwheel also runs pytest with--import-mode=importlib. The per-filesys.path.inserthacks are removed. The_lib_available()skip checks now use the package's owncore._get_lib_path(), so they also see a library bundled in an installed wheel.tests/test_installed_wheel.py, which runs only in installed mode. It fails (does not skip) if the checkout was imported, ifGOSQLX_LIB_PATHis set, or if the wheel lacks a loadable bundled library. Without it, a wheel missing its library would pass CI with every library test skipped.test_package_version.pyno longer checks asetup.pyversion. It now asserts thatsetup.pycarries no metadata.Docs
python/README.md:pip install pygosqlxis the primary install, noting it works once the firstpygosqlx-v*tag is published. Build from source comes second. Adds a supported-platforms table and release notes for maintainers.Design decisions (conservative choices, recorded per brief)
pygosqlx/lib/libgosqlx.*is missing, rather than failing the install (failing would also break pure-Python dev installs); the runtimeFileNotFoundErrornow links the README build-from-source section.py3-none-<platform>rather than onecp3XXwheel per Python version. cibuildwheel builds once and reuses the wheel for the test runs on the other Pythons.pygosqlx-v*tag on a commit already onmain(publish-pypichecksgithub.event_name == 'push', so aworkflow_dispatchrun on a tag ref cannot reach PyPI whatevertargetis).workflow_dispatchcan only publish to TestPyPI (the default) or build only. This keeps the recommendedpypienvironment policy (tagspygosqlx-v*only) consistent, and every published version has a git tag.GOSQLX_LIB_PATH).go.mod/go.sumwere added to the PR path filter because they change what gets compiled into the library.Test Plan
bash pkg/cbinding/build.sh+python -m build(macOS arm64) givespygosqlx-0.3.0-py3-none-macosx_<ver>_arm64.whl, withpygosqlx/lib/libgosqlx.dylibat the wheel root (platlib,Root-Is-Purelib: false). It is notpy3-none-any.PYGOSQLX_TEST_INSTALLED=1 python -m pytest --import-mode=importlib python/testsgave 187 passed, 0 skipped.tests/conftest.py(recursive-include tests *.py). Added theOperating System :: Microsoft :: Windowsclassifier. Ran the Go-version check locally.git describe --match 'v[0-9]*'on this branch resolves tov1.15.0. actionlint is clean apart from its pre-existing unknown-label warning formacos-15-intel, a valid GitHub-hosted label that is newer than actionlint v1.7.7.pytest python/testsgave 184 passed, 3 skipped (the installed-only tests). Editable installpip install -e "python[dev]"works on Python 3.10.twine check --strictpasses on the sdist and wheel. actionlint is clean.pygosqlx Releasebuiltpy3-none-manylinux…_x86_64,py3-none-manylinux…_aarch64,py3-none-macosx_13_0_{x86_64,arm64}andpy3-none-win_amd64wheels. Each was tested on CPython 3.10–3.14 against the installed wheel; cibuildwheel built once and reused the wheel for the other versions. The sdist job passes.{arch}in the repair command. The arch now comes from the matrix (--plat manylinux_2_17_${{ matrix.arch }}). auditwheel producedpygosqlx-0.3.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whland the x86_64 equivalent. All five wheel jobs and the sdist job pass.os.path.commonpathbug in the new installed-wheel test, fixed in dc1fc88.Python Bindingsworkflow still passes (ubuntu/macOS, Python 3.10/3.13).Breaking Changes
setup.pyno longer carries package metadata. Anything that read the version fromsetup.pymust readpyproject.tomlinstead.Release note
🤖 Generated with Claude Code
https://claude.ai/code/session_01RkzVu3JY9Y6BRWfjesWts9