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
64 changes: 25 additions & 39 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,18 @@ jobs:
with:
python-version: "3.11"

# Plain `uv sync`, deliberately, on two counts.
# --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.
#
# Resolving fresh is wanted on the pull requests where it actually
# happens, which is not all of them. `uv sync` follows the committed lock
# while that lock satisfies pyproject.toml, so an ordinary pull request
# installs the locked versions. When a pull request moves dependency
# metadata without regenerating the lock, uv resolves the new set and
# these jobs exercise it. `--locked` would instead refuse to run and
# report that the lock needs updating, which says nothing about whether
# the new version works.
#
# The two flags tried here also break the release, and for one shared
# reason: the release bumps the version in pyproject.toml and leaves
# uv.lock naming the old one, so uv has to re-resolve.
#
# --locked fails on exactly that mismatch, reporting that the
# lockfile needs to be updated.
# --no-build fails because re-resolving means building this
# workspace's own three packages, which are source rather
# than wheels: "Building source distributions for
# coordinode is disabled".
#
# Verified on the release branch with a cold cache: both fail there, and
# both pass on that same branch once uv.lock carries the new version. So
# restoring either one means first making the release regenerate the
# lock, and even then it gives up the fresh resolution described above.
- run: uv sync
- run: uv run ruff check coordinode/ langchain-coordinode/ llama-index-coordinode/ tests/
- run: uv run ruff format --check coordinode/ langchain-coordinode/ llama-index-coordinode/ tests/
# --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
Comment thread
polaz marked this conversation as resolved.
- 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 }})
Expand All @@ -62,14 +45,15 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

# --locked --no-build: see the lint job.
- name: Install dependencies
run: uv sync --all-packages
run: uv sync --all-packages --locked --no-build

- name: Generate proto stubs
run: uv run make proto
run: uv run --all-packages --locked --no-build make proto

- name: Unit tests
run: uv run pytest tests/unit/ -v
run: uv run --all-packages --locked --no-build pytest tests/unit/ -v

build-embedded:
name: Build embedded (CI check)
Expand Down Expand Up @@ -106,13 +90,14 @@ jobs:
# the wheel goes to ./dist/ (workspace-relative), not /tmp/.
run: |
set -euo pipefail
WHL=$(ls dist/coordinode_embedded-*.whl | head -1)
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.
uv pip install --python /tmp/test-venv/bin/python "$WHL" \
# 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
Expand Down Expand Up @@ -140,10 +125,10 @@ jobs:
services:
coordinode:
# Pinned by digest, not by tag: the proto submodule pins a server
# version, and a tag can be re-pushed, so `:0.5.7` alone does not name
# one fixed server. The digest below is 0.5.7; bump both together with
# 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:75a6242beb4cea8ab6726c842898fafc03ca9f59c6f7e36e462934a4ca64874c
image: ghcr.io/structured-world/coordinode@sha256:f7e0ee8515868bc068f1e2f66d499a4acf5e9b7bce76bd5913bf805c7f9fd6da
ports:
- 7080:7080
- 7084:7084
Expand Down Expand Up @@ -171,12 +156,13 @@ jobs:
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
uv run make proto
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 pytest tests/integration/ -v --timeout=30
run: uv run --all-packages --locked --no-build pytest tests/integration/ -v --timeout=30
46 changes: 46 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,49 @@ jobs:
token: ${{ steps.app-token.outputs.token }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json

# The release PR bumps the workspace version in pyproject.toml, and
# uv.lock records that version too. Left stale, every `uv sync --locked`
# in CI refuses the branch, and without --locked uv re-resolves, which
# builds source distributions. release-please cannot edit the lock
# itself: its TOML updater cannot select the workspace entry by name.
# So the lock is refreshed here, on the release branch, whenever the
# release PR was created or updated. Pushed with the bot token so CI
# runs on the new commit.
- name: Check out the release branch
if: steps.rp.outputs.pr
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ fromJSON(steps.rp.outputs.pr).headBranchName }}
token: ${{ steps.app-token.outputs.token }}
# hatch-vcs derives the member versions from tags while locking.
fetch-depth: 0

- uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
if: steps.rp.outputs.pr
with:
python-version: "3.11"

- name: Sync uv.lock with the release version
if: steps.rp.outputs.pr
# Locking reads the workspace members' metadata, and their version is
# dynamic (hatch-vcs), so uv has to build these three packages of this
# repository; --no-build refuses exactly that. Third-party packages
# keep their locked versions, and the CI run this push triggers
# installs them with `--locked --no-build`, failing if any of them
# would need a source build.
run: uv lock # NOSONAR
- name: Commit the refreshed lock
if: steps.rp.outputs.pr
env:
BRANCH: ${{ fromJSON(steps.rp.outputs.pr).headBranchName }}
run: |
if git diff --quiet -- uv.lock; then
echo "uv.lock already matches the release version"
exit 0
fi
git config user.name "sw-release-bot[bot]"
git config user.email "255865126+sw-release-bot[bot]@users.noreply.github.com"
git add uv.lock
git commit -m "chore: sync uv.lock with the release version"
git push origin "HEAD:$BRANCH"
10 changes: 7 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,23 @@ jobs:
with:
python-version: "3.11"

# --locked --no-build: install exactly the locked set, third-party
# packages from wheels only (see ci.yml).
- name: Install build tools
run: uv sync
run: uv sync --locked --no-build

- name: Generate proto stubs (coordinode only)
if: matrix.package.name == 'coordinode'
run: uv run make proto
run: uv run --locked --no-build make proto

- name: Build wheel + sdist
working-directory: ${{ matrix.package.path }}
run: |
# Force hatch-vcs / setuptools_scm to use the tag version, not dirty-tree dev version
export SETUPTOOLS_SCM_PRETEND_VERSION="${GITHUB_REF_NAME#v}"
uv run python -m build
# Builds this package; --no-build keeps its build backend
# (hatchling, hatch-vcs) to wheels, so nothing else's setup runs.
uv build --no-build --out-dir dist
Comment thread
polaz marked this conversation as resolved.

- name: Upload dist artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ with CoordinodeClient("localhost:7080") as db:
raise
```

Requires a CoordiNode server of **v0.5.7 or newer** — the release this client
Requires a CoordiNode server of **v0.6.0 or newer** — the release this client
is integration-tested against. `health()` exercises a different service, so a
server without the transaction RPCs passes the health check and then refuses
`transaction()`.
Expand Down
Loading
Loading