From f0626875538d152faa9c8b2392bfe8f254246cc1 Mon Sep 17 00:00:00 2001 From: Arshdeep54 Date: Sat, 22 Aug 2026 16:24:13 +0530 Subject: [PATCH] ci: switch release flow to tag-triggered and add PR title checks Signed-off-by: Arshdeep54 --- .github/workflows/publish-python.yml | 55 ++++++++++++++++++ .github/workflows/release.yml | 64 +++++++++++++++++++++ .github/workflows/semantic-pull-request.yml | 30 ++++++++++ RELEASING.md | 49 ++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 .github/workflows/publish-python.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/semantic-pull-request.yml create mode 100644 RELEASING.md diff --git a/.github/workflows/publish-python.yml b/.github/workflows/publish-python.yml new file mode 100644 index 0000000..d94d9a1 --- /dev/null +++ b/.github/workflows/publish-python.yml @@ -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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..ea96df5 --- /dev/null +++ b/.github/workflows/release.yml @@ -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 diff --git a/.github/workflows/semantic-pull-request.yml b/.github/workflows/semantic-pull-request.yml new file mode 100644 index 0000000..9367b7b --- /dev/null +++ b/.github/workflows/semantic-pull-request.yml @@ -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 diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..aee9141 --- /dev/null +++ b/RELEASING.md @@ -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. +