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
55 changes: 55 additions & 0 deletions .github/workflows/publish-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Publish Python Client

on:
push:
tags:
- "python-v*.*.*"
workflow_dispatch:
inputs:
tag:
description: "Tag to publish (e.g. python-v0.2.0) — must already exist"
required: true

defaults:
run:
working-directory: client/python

jobs:
publish:
name: Build and Publish to PyPI
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag || github.ref }}

- name: Resolve tag and version
id: version
run: |
tag="${{ inputs.tag || github.ref_name }}"
version="${tag#python-v}"
pkg_version=$(awk -F'"' '/^version *=/ {print $2; exit}' pyproject.toml)
if [ "$version" != "$pkg_version" ]; then
echo "Tag $tag does not match pyproject.toml version $pkg_version" >&2
exit 1
fi

- name: Set Up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install build tooling
run: pip install build

- name: Build sdist and wheel
run: python -m build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: client/python/dist
64 changes: 64 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Release

on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
tag:
description: "Tag to release (e.g. v0.1.0) — must already exist"
required: true

permissions:
contents: write

jobs:
build-and-release:
name: Build and Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag || github.ref }}
fetch-depth: 0

- name: Resolve tag and version
id: version
run: |
tag="${{ inputs.tag || github.ref_name }}"
version="${tag#v}"
cargo_version=$(awk -F'"' '/^version *=/ {print $2; exit}' Cargo.toml)
if [ "$version" != "$cargo_version" ]; then
echo "Tag $tag does not match Cargo.toml version $cargo_version" >&2
exit 1
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"

- name: Verify tag points at a commit on main
run: |
git fetch origin main
if ! git merge-base --is-ancestor HEAD origin/main; then
echo "Tagged commit $(git rev-parse HEAD) is not on main" >&2
exit 1
fi

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Build release binaries
run: cargo build --release --workspace

- name: Run tests
run: cargo test --release --workspace

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
run: |
gh release create "$TAG" \
--title "$TAG" \
--target "${{ github.sha }}" \
--generate-notes
30 changes: 30 additions & 0 deletions .github/workflows/semantic-pull-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Semantic Pull Request

on:
pull_request_target:
types: [opened, edited, reopened, synchronize]

permissions:
pull-requests: read

jobs:
check:
name: Check PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
docs
style
refactor
perf
test
build
ci
chore
revert
49 changes: 49 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Releasing VortexDB

This document describes the release process. It is intended for maintainers with push access to `main`.

## Branch model

- `main` is the only long-lived branch.
- Direct pushes to `main` are disabled; all changes go through a PR.
- PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/), enforced by the `semantic-pull-request` check.

## Releasing the server (Rust)

Merging a PR into `main` does not trigger a release. Releases are triggered by pushing a version tag.

1. Bump `version` under `[workspace.package]` in the root `Cargo.toml`, and merge via PR.
2. From `main`, tag and push:
```
git tag v0.1.0
git push origin v0.1.0
```
3. The tag push triggers `.github/workflows/release.yml`, which:
- Verifies the tag matches the version in `Cargo.toml`.
- Verifies the tagged commit is on `main`.
- Builds and runs the test suite.
- Creates the GitHub Release.

A failing test suite stops the workflow before the release step runs.

## Releasing the Python client

The Python client (`client/python/`) is versioned and released independently of the server, using its own tag prefix.

1. Bump `version` in `client/python/pyproject.toml`, and merge via PR.
2. Tag and push with the `python-v` prefix:
```
git tag python-v0.2.0
git push origin python-v0.2.0
```
3. The tag push triggers `.github/workflows/publish-python.yml`, which builds the package and publishes to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC, no stored API token).

### One-time PyPI setup

1. On PyPI: project page → **Publishing** → add a GitHub publisher with owner `sdslabs`, repo `vector-db`, workflow `publish-python.yml`, environment `pypi`.
2. On GitHub: Settings → Environments → create an environment named `pypi`, matching the `environment: pypi` value in the workflow.

## Secrets

Neither workflow requires manually configured secrets. `release.yml` uses the default `GITHUB_TOKEN`. `publish-python.yml` uses OIDC trusted publishing.

Loading