Skip to content

feat!: adopt the CoordiNode v0.6.0 protocol #362

feat!: adopt the CoordiNode v0.6.0 protocol

feat!: adopt the CoordiNode v0.6.0 protocol #362

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
with:
python-version: "3.11"
# --locked: install exactly what uv.lock pins, and fail if the lock no
# longer matches pyproject.toml; a pull request that changes
# dependencies commits the regenerated lock with them. The release PR
# gets its lock refreshed by release-please.yml, so it passes too.
#
# --no-build: third-party packages come from wheels only, so no setup
# script from a source distribution runs here. uv still builds this
# workspace's own three packages from a matching lock; only resolving a
# stale one would need those builds, and --locked refuses that first.
- run: uv sync --locked --no-build
- run: uv run --locked --no-build ruff check coordinode/ langchain-coordinode/ llama-index-coordinode/ tests/
- run: uv run --locked --no-build ruff format --check coordinode/ langchain-coordinode/ llama-index-coordinode/ tests/
test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
submodules: recursive
- uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
with:
python-version: ${{ matrix.python-version }}
# --locked --no-build: see the lint job.
- name: Install dependencies
run: uv sync --all-packages --locked --no-build
- name: Generate proto stubs
run: uv run --all-packages --locked --no-build make proto
- name: Unit tests
run: uv run --all-packages --locked --no-build pytest tests/unit/ -v
build-embedded:
name: Build embedded (CI check)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
submodules: recursive
- name: Build (maturin / Linux x86_64)
uses: PyO3/maturin-action@32307a466a178317e8c2ae343b38e73896a047be # v1.47.0
with:
command: build
args: >-
--manifest-path coordinode-embedded/Cargo.toml
--out dist
manylinux: manylinux_2_28
before-script-linux: |
dnf install -y protobuf-compiler
- uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
with:
python-version: "3.12"
- name: Install wheel + run embedded tests
# The main `test` job skips coordinode_embedded with importorskip
# because that runner doesn't build the wheel. This job has the
# wheel, so install it and run the embedded tests here, then assert
# nothing was skipped (a skip with the wheel installed means a
# broken manylinux glibc / missing numpy / etc., not the expected
# "no wheel" condition).
# maturin-action runs inside a manylinux container; only paths
# under $GITHUB_WORKSPACE are bind-mounted back to the host, so
# the wheel goes to ./dist/ (workspace-relative), not /tmp/.
run: |
set -euo pipefail
WHL=$(find dist -name 'coordinode_embedded-*.whl' -print -quit)
test -n "$WHL"
uv venv --python 3.12 /tmp/test-venv
# Pinned to the versions uv.lock already resolves for the workspace,
# so this throwaway venv tests against the same stack as the other
# jobs instead of whatever is newest on PyPI that morning.
# Wheels only (--no-build), as everywhere else in this workflow.
uv pip install --no-build --python /tmp/test-venv/bin/python "$WHL" \
numpy==2.4.6 pytest==9.1.1 pytest-timeout==2.4.0
# Every test file that needs the extension belongs here: the main
# `test` job skips them all for want of a wheel, so a file left out
# of this list runs in no job at all.
OUTPUT=$(/tmp/test-venv/bin/python -m pytest \
tests/unit/test_hnsw.py tests/unit/test_embedded_values.py \
-v --strict-markers -ra 2>&1)
echo "$OUTPUT"
# `-ra` prints a "SKIPPED [N]" short summary header when anything was
# skipped; importorskip-based skip also surfaces this way. Use the
# full output instead of the exit code because pytest treats skips
# as success.
if echo "$OUTPUT" | grep -qE '^SKIPPED|=+ .* skipped'; then
echo "::error::Tests were skipped in build-embedded; the wheel is installed so this is a real failure (broken glibc / missing numpy / etc.)"
exit 1
fi
if ! echo "$OUTPUT" | grep -qE '=+ [0-9]+ passed'; then
echo "::error::No tests passed; the module was likely not collected"
exit 1
fi
test-integration:
name: Integration tests
runs-on: ubuntu-latest
services:
coordinode:
# Pinned by digest, not by tag: the proto submodule pins a server
# version, and a tag can be re-pushed, so `:0.6.0` alone does not name
# one fixed server. The digest below is 0.6.0; bump both together with
# the submodule.
image: ghcr.io/structured-world/coordinode@sha256:f7e0ee8515868bc068f1e2f66d499a4acf5e9b7bce76bd5913bf805c7f9fd6da
ports:
- 7080:7080
- 7084:7084
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
submodules: recursive
- uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
with:
python-version: "3.11"
- name: Wait for coordinode
run: |
echo "Waiting for coordinode to be ready (HTTP :7084 + gRPC :7080)..."
for i in $(seq 1 30); do
if curl -sf http://localhost:7084/health >/dev/null 2>&1 && \
(echo > /dev/tcp/localhost/7080) 2>/dev/null; then
echo "coordinode is ready (attempt $i)"
exit 0
fi
echo "Attempt $i/30, not ready yet, sleeping 5s..."
sleep 5
done
echo "Error: coordinode did not become healthy after 150s" >&2
exit 1
# --locked --no-build: see the lint job.
- name: Install + generate proto
run: |
uv sync --all-packages --locked --no-build
uv run --all-packages --locked --no-build make proto
- name: Integration tests
env:
COORDINODE_ADDR: "localhost:7080"
run: uv run --all-packages --locked --no-build pytest tests/integration/ -v --timeout=30