Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 125 additions & 80 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,110 +8,155 @@ on:
types:
- created
workflow_dispatch:

jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }}
# Build main pgserver package (Python code only, no binaries)
build_main_package:
name: Build main pgserver package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v6
with:
python-version: '3.14'

- name: Install build tools
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade build

- name: Remove pginstall directory (main package shouldn't include binaries)
run: rm -rf src/pgserver/pginstall

- name: Build main package wheel
run: python -m build --wheel

- name: Upload main package wheel
uses: actions/upload-artifact@v4
with:
path: dist/*.whl
name: main-package-wheels

# Build binary packages for each PostgreSQL version
build_binary_wheels:
name: Build ${{ matrix.package }} on ${{ matrix.platform }}
runs-on: ${{ matrix.os }}
needs: build_main_package # Build main package first
strategy:
fail-fast: false
matrix:
package: [pgserver-postgres-16, pgserver-postgres-17, pgserver-postgres-18]
os: [ubuntu-latest, macos-15-intel, macos-latest, windows-latest]
include:
- os: macos-12
arch: x86_64
deployment-target: '10.9'
- os: macos-latest
arch: arm64
deployment-target: '11.0'
- os: ubuntu-latest
arch: x86_64
deployment-target: ''
- os: windows-2022
arch: AMD64
deployment-target: ''
platform: linux-x86_64
- os: macos-15-intel
platform: macos-x86_64
macosx_deployment_target: '10.9'
- os: macos-latest
platform: macos-arm64
macosx_deployment_target: '11.0'
- os: windows-latest
platform: windows-amd64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
if: matrix.os != 'ubuntu-latest'

- uses: actions/setup-python@v6
with:
python-version: '3.10'
- uses: actions/setup-python@v4
if: matrix.os == 'ubuntu-latest'
# for testing due to docker env issues
with:
python-version: '3.9'
- name: Install cibuildwheel
python-version: '3.14'

- name: Install build tools
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade cibuildwheel
- name: Restore postgres build from cache
if: ${{ matrix.os != 'ubuntu-latest' }}
id: restore-postgres
uses: actions/cache/restore@v3
env:
cache-name: cache-postgres
python -m pip install --upgrade build

- name: Install patchelf (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y patchelf

- name: Install bison and flex (Windows)
if: runner.os == 'Windows'
run: |
choco install -y winflexbison3

- name: Extract PostgreSQL version from package name
id: pg-version
shell: bash
run: |
# Extract version from package name (e.g., pgserver-postgres-16 -> 16)
VERSION="${{ matrix.package }}"
VERSION="${VERSION##*-}"
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Restore PostgreSQL build from cache
id: cache-postgres
uses: actions/cache@v3
with:
path: |
pgbuild
src/pgserver/pginstall
key: ${{ runner.os }}-${{ runner.arch }}-build-${{ env.cache-name }}-${{
hashFiles('Makefile', 'pgbuild/Makefile', '.github/workflows/build-and-test.yml') }}
- name: Build postgres and pgvector
if: ${{ matrix.os != 'ubuntu-latest' && ! steps.restore-postgres.outputs.cache-hit }}
env:
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.deployment-target }}
# this step is implied by Build wheels, but we do it here for caching before python tests run
# on ubuntu, cibuildwheel will run this step within a docker container, so it cannot use the cache this way
run: make
- name: Save postgres build
if: ${{ matrix.os != 'ubuntu-latest' && ! steps.restore-postgres.outputs.cache-hit }}
id: cache-postgres
uses: actions/cache/save@v3
key: ${{ runner.os }}-${{ runner.arch }}-pg${{ steps.pg-version.outputs.version }}-${{ hashFiles('pgbuild/Makefile') }}

- name: Build binary package (Unix)
if: runner.os != 'Windows'
working-directory: packages/${{ matrix.package }}
env:
cache-name: cache-postgres
with:
path: |
pgbuild
src/pgserver/pginstall
key: ${{ runner.os }}-${{ runner.arch }}-build-${{ env.cache-name }}-${{
hashFiles('Makefile', 'pgbuild/Makefile', '.github/workflows/build-and-test.yml') }}
- name: Build wheels
env:
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_SKIP: pp* cp38-* *-musllinux*
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.deployment-target }}
run: python -m cibuildwheel --output-dir wheelhouse
- name: Save postgres build
if: ${{ matrix.os == 'ubuntu-latest' && ! steps.restore-postgres.outputs.cache-hit }}
id: cache-postgres2
uses: actions/cache/save@v3
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target || '' }}
run: |
make build
python -m build --wheel

- name: Build binary package (Windows)
if: runner.os == 'Windows'
working-directory: packages/${{ matrix.package }}
shell: bash
env:
cache-name: cache-postgres
with:
path: |
pgbuild
src/pgserver/pginstall
key: ${{ runner.os }}-${{ runner.arch }}-build-${{ env.cache-name }}-${{
hashFiles('Makefile', 'pgbuild/Makefile', '.github/workflows/build-and-test.yml') }}
- uses: actions/upload-artifact@v3
BISON: "C:/ProgramData/chocolatey/bin/win_bison.exe"
FLEX: "C:/ProgramData/chocolatey/bin/win_flex.exe"
run: |
make build
python -m build --wheel

- name: Upload binary package wheels
uses: actions/upload-artifact@v4
with:
path: wheelhouse/*.whl
name: python-package-distributions
path: packages/${{ matrix.package }}/dist/*.whl
name: binary-wheels-${{ matrix.package }}-${{ matrix.platform }}

# Publish to PyPI
publish-to-pypi:
if: ${{ startsWith(github.ref, 'refs/tags/') }}
name: Publish Python dist to PyPI
name: Publish to PyPI
needs:
- build_wheels
- build_binary_wheels
- build_main_package
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/pgserver # Replace <package-name> with your PyPI project name
url: https://pypi.org/p/pgserver
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
id-token: write
steps:
- name: Download all the dists
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
- name: Download all binary wheels
uses: actions/download-artifact@v4
with:
path: dist/
pattern: binary-wheels-*
merge-multiple: true

- name: Download main package wheels
uses: actions/download-artifact@v4
with:
path: dist/
name: main-package-wheels

- name: Flatten dist directory
run: |
find dist -name '*.whl' -exec mv {} dist/ \;
find dist -type d -empty -delete

- name: Publish all packages to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Changelog

## [0.2.0] - 2025-11-07

### Added
- Support for PostgreSQL 17 and 18 (in addition to existing PostgreSQL 16)
- Multi-version architecture with separate binary packages:
- `pgserver-postgres-16` - PostgreSQL 16.10 binaries
- `pgserver-postgres-17` - PostgreSQL 17.6 binaries
- `pgserver-postgres-18` - PostgreSQL 18.0 binaries
- Version selection via pip extras:
- `pip install pgserver` - installs PostgreSQL 18 (default)
- `pip install "pgserver[pg16]"` - installs PostgreSQL 16
- `pip install "pgserver[pg17]"` - installs PostgreSQL 17
- `INSTALLED_POSTGRES_VERSION` constant to check which version is installed

### Changed
- Main `pgserver` package is now a universal wheel (py3-none-any) compatible with all Python 3.9+ versions
- Binary packages are distributed separately from Python code, reducing download size
- Upgraded pgvector extension to v0.8.1 for PostgreSQL 18 compatibility
- PostgreSQL binaries now use RPATH to find bundled libraries, preventing conflicts with system PostgreSQL installations
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
![Python Version](https://img.shields.io/badge/python-3.9%2C%203.10%2C%203.11%2C%203.12-blue)
![Postgres Version](https://img.shields.io/badge/PostgreSQL-16.2-blue)
![Postgres Version](https://img.shields.io/badge/PostgreSQL-16%20%7C%2017%20%7C%2018-blue)

![Linux Support](https://img.shields.io/badge/Linux%20Support-manylinux-green)
![macOS Apple Silicon Support >=11](https://img.shields.io/badge/macOS%20Apple%20Silicon%20Support-%E2%89%A511(BigSur)-green)
Expand Down Expand Up @@ -62,6 +62,29 @@ def tmp_postgres():
pg.cleanup()
```

## PostgreSQL Version Selection

`pgserver` supports PostgreSQL versions 16, 17, and 18 with **pre-built wheels** for all versions:

```bash
# PostgreSQL 18 (latest, default)
pip install pgserver

# PostgreSQL 16
pip install "pgserver[pg16]"

# PostgreSQL 17
pip install "pgserver[pg17]"
```

Check which version is installed:
```py
import pgserver
print(f"PostgreSQL version: {pgserver.INSTALLED_POSTGRES_VERSION}")
```

**How it works:** The main `pgserver` package contains only Python code. PostgreSQL binaries are provided by separate packages (`pgserver-postgres-16`, `pgserver-postgres-17`, `pgserver-postgres-18`) which are automatically installed based on the extra you choose.

Postgres binaries in the package can be found in the directory pointed
to by the `pgserver.POSTGRES_BIN_PATH` to be used directly.

Expand Down
11 changes: 11 additions & 0 deletions packages/pgserver-postgres-16/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.DEFAULT_GOAL := build

build:
PGSERVER_VERSION=16 $(MAKE) -C ../../pgbuild all
rm -rf src/pgserver_binaries/pg16
mkdir -p src/pgserver_binaries/pg16
cp -r ../../src/pgserver/pginstall/* src/pgserver_binaries/pg16/

clean:
rm -rf src/pgserver_binaries/pg16
PGSERVER_VERSION=16 $(MAKE) -C ../../pgbuild clean
10 changes: 10 additions & 0 deletions packages/pgserver-postgres-16/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# pgserver-postgres-16

PostgreSQL 16 binaries for the pgserver package.

This package is automatically installed when you run:
```bash
pip install pgserver[pg16]
```

Do not install this package directly unless you know what you're doing.
24 changes: 24 additions & 0 deletions packages/pgserver-postgres-16/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[project]
name = "pgserver-postgres-16"
version = "0.2.0"
description = "PostgreSQL 16 binaries for pgserver"
readme = "README.md"
requires-python = ">=3.9"
license = {file = "../../LICENSE.txt"}
authors=[{ name="Oscar Moll", email="orm@csail.mit.edu" }]
keywords=["postgresql", "pgvector"]

[tool.setuptools.packages.find]
where = ["src"]
include = ["pgserver_binaries*"]

[tool.setuptools.package-data]
pgserver_binaries = ["**/*"]

[tool.cibuildwheel]
before-all = "cd ../../ && PGSERVER_VERSION=16 make -C pgbuild"
environment = {PGSERVER_VERSION="16"}

[build-system]
requires = ["setuptools>=58.0.0", "wheel"]
build-backend = "setuptools.build_meta"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# PostgreSQL 16 binaries for pgserver
11 changes: 11 additions & 0 deletions packages/pgserver-postgres-17/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.DEFAULT_GOAL := build

build:
PGSERVER_VERSION=17 $(MAKE) -C ../../pgbuild all
rm -rf src/pgserver_binaries/pg17
mkdir -p src/pgserver_binaries/pg17
cp -r ../../src/pgserver/pginstall/* src/pgserver_binaries/pg17/

clean:
rm -rf src/pgserver_binaries/pg17
PGSERVER_VERSION=17 $(MAKE) -C ../../pgbuild clean
10 changes: 10 additions & 0 deletions packages/pgserver-postgres-17/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# pgserver-postgres-17

PostgreSQL 17 binaries for the pgserver package.

This package is automatically installed when you run:
```bash
pip install pgserver[pg17]
```

Do not install this package directly unless you know what you're doing.
24 changes: 24 additions & 0 deletions packages/pgserver-postgres-17/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[project]
name = "pgserver-postgres-17"
version = "0.2.0"
description = "PostgreSQL 17 binaries for pgserver"
readme = "README.md"
requires-python = ">=3.9"
license = {file = "../../LICENSE.txt"}
authors=[{ name="Oscar Moll", email="orm@csail.mit.edu" }]
keywords=["postgresql", "pgvector"]

[tool.setuptools.packages.find]
where = ["src"]
include = ["pgserver_binaries*"]

[tool.setuptools.package-data]
pgserver_binaries = ["**/*"]

[tool.cibuildwheel]
before-all = "cd ../../ && PGSERVER_VERSION=17 make -C pgbuild"
environment = {PGSERVER_VERSION="17"}

[build-system]
requires = ["setuptools>=58.0.0", "wheel"]
build-backend = "setuptools.build_meta"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# PostgreSQL 17 binaries for pgserver
Loading