Skip to content
Merged
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
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,28 @@ jobs:
name: pg0-macos
path: target/release/pg0

# Mirrors the windows-x86_64 build step in release-cli.yml so CI exercises
# the exact same compile path that produces the shipped Windows executable.
build-windows:
name: Build CLI (Windows)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc

- name: Build
run: cargo build --release --target x86_64-pc-windows-msvc

- name: Upload CLI artifact
uses: actions/upload-artifact@v4
with:
name: pg0-windows
path: target/x86_64-pc-windows-msvc/release/pg0.exe

sdk-tests:
name: SDK Tests (macOS)
needs: build
Expand Down Expand Up @@ -56,6 +78,43 @@ jobs:
uv pip install --system -e ".[dev]"
pytest tests/ -v

sdk-tests-windows:
name: SDK Tests (Windows)
needs: build-windows
runs-on: windows-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- name: Download CLI
uses: actions/download-artifact@v4
with:
name: pg0-windows
path: pg0-bin

- name: Put CLI on PATH
shell: pwsh
run: |
$dest = "$env:USERPROFILE\pg0-bin"
New-Item -ItemType Directory -Force -Path $dest | Out-Null
Copy-Item pg0-bin\pg0.exe $dest\pg0.exe
Add-Content $env:GITHUB_PATH $dest

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Run Python SDK tests
working-directory: sdk/python
shell: pwsh
run: |
uv pip install --system -e ".[dev]"
pytest tests/ -v

# Docker tests - one job per platform, runs both CLI and Python SDK tests
# Note: ARM64 tests are skipped because QEMU emulation is too slow for PostgreSQL setup
docker-tests:
Expand Down
20 changes: 19 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
flate2 = "1"
tar = "0.4"

# ZIP extraction for the Windows PostgreSQL bundle, which theseus-rs ships as
# .zip (unlike every other platform's tar.gz). Only pulled in on Windows
# targets to avoid bloating other platforms' binaries.
[target.'cfg(windows)'.dependencies]
zip = { version = "2", default-features = false, features = ["deflate"] }

[profile.release]
strip = true
lto = true
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ from pg0 import Pg0
# Start PostgreSQL
pg = Pg0()
pg.start()
print(pg.uri) # postgresql://postgres:postgres@localhost:5432/postgres
print(pg.uri) # postgresql://postgres:postgres@127.0.0.1:5432/postgres

# Or use context manager
with Pg0() as pg:
Expand Down
11 changes: 1 addition & 10 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,7 @@ fn bundle_pgvector(pg_version: &str, pgvector_tag: &str, pgvector_repo: &str, ou
"x86_64-unknown-linux-musl" => "x86_64-unknown-linux-gnu", // musl uses gnu pgvector
"aarch64-unknown-linux-gnu" => "aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl" => "aarch64-unknown-linux-gnu", // musl uses gnu pgvector
"x86_64-pc-windows-msvc" => {
eprintln!("Warning: pgvector not available for Windows, skipping bundle");
let marker = out_dir.join("pgvector_bundle.tar.gz");
fs::write(&marker, b"").expect("Failed to create empty pgvector marker");
println!(
"cargo:rustc-env=PGVECTOR_BUNDLE_PATH={}",
marker.display()
);
return;
}
"x86_64-pc-windows-msvc" => "x86_64-pc-windows-msvc",
_ => {
eprintln!(
"Warning: Unknown target {}, pgvector will not be bundled",
Expand Down
2 changes: 1 addition & 1 deletion sdk/node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Pg0 } from "@vectorize-io/pg0";
// Basic usage
const pg = new Pg0();
await pg.start();
console.log(await pg.getUri()); // postgresql://postgres:postgres@localhost:5432/postgres
console.log(await pg.getUri()); // postgresql://postgres:postgres@127.0.0.1:5432/postgres
await pg.execute("CREATE EXTENSION IF NOT EXISTS vector");
await pg.stop();

Expand Down
6 changes: 3 additions & 3 deletions sdk/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ from pg0 import Pg0

# Basic usage
with Pg0() as pg:
print(pg.uri) # postgresql://postgres:postgres@localhost:5432/postgres
print(pg.uri) # postgresql://postgres:postgres@127.0.0.1:5432/postgres
pg.execute("CREATE EXTENSION IF NOT EXISTS vector")
pg.execute("SELECT version()")

Expand Down Expand Up @@ -69,11 +69,11 @@ pg = Pg0()
pg.start()

# Using the uri property
print(pg.uri) # postgresql://postgres:postgres@localhost:5432/postgres
print(pg.uri) # postgresql://postgres:postgres@127.0.0.1:5432/postgres

# Or using info()
info = pg.info()
print(info.uri) # postgresql://postgres:postgres@localhost:5432/postgres
print(info.uri) # postgresql://postgres:postgres@127.0.0.1:5432/postgres
print(info.port) # 5432
print(info.username) # postgres
print(info.database) # postgres
Expand Down
35 changes: 30 additions & 5 deletions sdk/python/pg0/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import os
import shutil
import subprocess
import tempfile
import sys
from dataclasses import dataclass
from pathlib import Path
Expand Down Expand Up @@ -130,11 +131,35 @@ def _run_pg0(*args: str, check: bool = True) -> subprocess.CompletedProcess:
"""Run a pg0 command."""
pg0_path = _find_pg0()
try:
result = subprocess.run(
[pg0_path, *args],
capture_output=True,
text=True,
)
if sys.platform == "win32":
# On Windows, `pg0 start` spawns PostgreSQL which inherits pg0's
# stdio handles. pg0 exits but PostgreSQL keeps writing to those
# handles, so Python's capture_output=True pipes never see EOF
# and subprocess.run hangs forever. Route stdio through real
# files instead — subprocess.run only waits on the process exit
# code, not on file handles held by grandchildren.
with tempfile.TemporaryFile() as out_f, tempfile.TemporaryFile() as err_f:
rc = subprocess.call(
[pg0_path, *args],
stdout=out_f,
stderr=err_f,
)
out_f.seek(0)
err_f.seek(0)
stdout = out_f.read().decode("utf-8", errors="replace")
stderr = err_f.read().decode("utf-8", errors="replace")
result = subprocess.CompletedProcess(
args=[pg0_path, *args],
returncode=rc,
stdout=stdout,
stderr=stderr,
)
else:
result = subprocess.run(
[pg0_path, *args],
capture_output=True,
text=True,
)
if check and result.returncode != 0:
stderr = result.stderr.strip()
if "already running" in stderr.lower():
Expand Down
5 changes: 5 additions & 0 deletions sdk/python/tests/test_pg0.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import os
import signal
import sys
import time

import pytest
Expand Down Expand Up @@ -151,6 +152,10 @@ def test_port_conflict_error(self, clean_instance):
pg2.stop()
pg0.drop(f"{TEST_NAME}-2")

@pytest.mark.skipif(
sys.platform == "win32",
reason="signal.SIGKILL does not exist on Windows; crash-recovery behavior is exercised by the Unix matrix.",
)
def test_data_survives_crash(self, clean_instance):
"""Test that data is preserved after an unclean shutdown (SIGKILL).

Expand Down
Loading
Loading