Skip to content

ci: neutralize upstream cuVS workflow triggers (release.yml only auto… #17

ci: neutralize upstream cuVS workflow triggers (release.yml only auto…

ci: neutralize upstream cuVS workflow triggers (release.yml only auto… #17

Workflow file for this run

# SPDX-License-Identifier: Apache-2.0
#
# Tag-driven release pipeline. Builds the full VecFlow v0.2.0 package set on
# linux-64 + linux-aarch64 and uploads to anaconda.org/VecFlow:
#
# libcuvs-vecflow-cu12 C++ cuVS + VecFlow filtered-ANN extensions
# vecflow-cu12 Py filtered-ANN wrapper
# libvecflow-chamfer-cu12 C++ multi-vector / chamfer-rerank pipeline
# vecflow-chamfer-cu12 Py multi-vector wrapper
#
# To cut a release:
# 1. bump vecflow/VERSION
# 2. git tag v0.X.Y && git push --tags
# Job results land at https://anaconda.org/VecFlow/
#
# Layout: five jobs forming two dependency chains that share the same
# libcuvs-vecflow C++ build.
# build-cpp — matrix: arch (2 jobs). Builds libcuvs-vecflow.
# build-py — matrix: arch × python (8 jobs). needs build-cpp;
# downloads the C++ .conda + repodata as a local channel
# and builds the vecflow Python wrapper against it.
# build-chamfer-cpp — matrix: arch (2 jobs). needs build-cpp; downloads the
# libcuvs-vecflow channel and builds libvecflow-chamfer
# against it (chamfer links cuvs::cuvs). Re-uploads the
# combined channel (both C++ pkgs) for the next stage.
# build-chamfer-py — matrix: arch × python (8 jobs). needs
# build-chamfer-cpp; builds the vecflow-chamfer Python
# wrapper against the combined C++ channel.
# publish — needs all four build jobs. Downloads every artifact,
# de-dups by filename, and uploads the .conda files to
# anaconda.org/VecFlow on tag push.
#
# Why split cpp from py: the C++ packages are Python-independent. Bundling
# them into the Python matrix would rebuild them 4× per arch. Why split
# vecflow from chamfer: chamfer's C++ lib depends on libcuvs-vecflow, so it
# must build after it — but the vecflow Python wrapper does not, so the two
# chains fan out in parallel off the shared build-cpp.
name: release
on:
push:
tags: ['v*']
workflow_dispatch: # manual trigger from the Actions tab
env:
RAPIDS_CUDA_VERSION: "12.9"
jobs:
# ── 1. Build C++ package once per arch ─────────────────────────────────────
build-cpp:
name: cpp / ${{ matrix.subdir }}
strategy:
fail-fast: false
matrix:
include:
- { runner: ubuntu-24.04, subdir: linux-64, arch: x86_64 }
- { runner: ubuntu-24.04-arm, subdir: linux-aarch64, arch: aarch64 }
runs-on: ${{ matrix.runner }}
# NOTE: hardcoded CUDA version. Two reasons it has to be a literal:
# 1. GitHub Actions doesn't evaluate ${{ env.* }} in `container.image`.
# 2. NVIDIA only publishes patch-level tags on Docker Hub (e.g.
# `12.9.1-devel-ubuntu24.04`). The shorthand `12.9-devel-ubuntu24.04`
# does NOT exist as a manifest and pulls fail with `manifest unknown`.
# The workflow-level `env: RAPIDS_CUDA_VERSION` ("12.9", major.minor) is
# used for conda dep pinning inside recipes (cuda-version is keyed by
# major.minor on conda), so the two values intentionally diverge: the
# image gets the patch-level tag, the env var stays major.minor.
# Bump both together when CUDA moves; verify a candidate tag with
# `docker manifest inspect nvidia/cuda:<tag>` before committing.
container:
image: nvidia/cuda:12.9.1-devel-ubuntu24.04
steps:
- name: Install system tools
run: |
apt-get update -y
apt-get install -y --no-install-recommends \
curl ca-certificates git xz-utils
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Read VERSION files into env
run: |
echo "VECFLOW_VERSION=$(tr -d '[:space:]' < vecflow/VERSION)" >> $GITHUB_ENV
echo "CUVS_MINOR_VERSION=$(tr -d '[:space:]' < VERSION | awk -F. '{print $1"."$2}')" >> $GITHUB_ENV
- name: Install pixi (provides rattler-build)
run: |
curl -fsSL https://pixi.sh/install.sh | sh
echo "$HOME/.pixi/bin" >> $GITHUB_PATH
- name: Install rattler-build
run: pixi global install rattler-build
- name: Build libcuvs-vecflow
run: |
rattler-build build \
--recipe conda/recipes/libcuvs-vecflow/recipe.yaml \
--target-platform ${{ matrix.subdir }} \
--output-dir ./conda-bld \
--channel rapidsai-nightly \
--channel rapidsai \
--channel conda-forge \
--skip-existing all
# Upload the whole conda-bld tree (subdir + repodata) so the Python and
# chamfer stages can consume it as a local channel via file:// next.
- name: Upload C++ channel as artifact
uses: actions/upload-artifact@v4
with:
name: cpp-${{ matrix.subdir }}
path: ./conda-bld/
retention-days: 7
if-no-files-found: error
# ── 2. Build vecflow Python package per (arch, python) ────────────────────
build-py:
name: py / ${{ matrix.subdir }} / py${{ matrix.python }}
needs: build-cpp
strategy:
fail-fast: false
matrix:
# `subdir` and `python` are the two real axes (2 × 4 = 8 jobs).
# `include` only enriches each combination with the matching
# `runner` + `arch` — it does NOT define the arch axis itself.
# If `subdir`/`arch` live inside `include` while `python` is the lone
# base axis, GitHub's matrix rules merge both include entries into
# every `python` combination and the second (aarch64) overwrites the
# first (linux-64): 4 jobs, all aarch64 — no linux-64 wheels shipped.
subdir: [linux-64, linux-aarch64]
python: ["3.11", "3.12", "3.13", "3.14"]
include:
- { subdir: linux-64, runner: ubuntu-24.04, arch: x86_64 }
- { subdir: linux-aarch64, runner: ubuntu-24.04-arm, arch: aarch64 }
runs-on: ${{ matrix.runner }}
# See build-cpp for why the CUDA image tag is a hardcoded literal.
container:
image: nvidia/cuda:12.9.1-devel-ubuntu24.04
env:
RAPIDS_PY_VERSION: ${{ matrix.python }}
steps:
- name: Install system tools
run: |
apt-get update -y
apt-get install -y --no-install-recommends \
curl ca-certificates git xz-utils
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Read VERSION files into env
run: |
echo "VECFLOW_VERSION=$(tr -d '[:space:]' < vecflow/VERSION)" >> $GITHUB_ENV
echo "CUVS_MINOR_VERSION=$(tr -d '[:space:]' < VERSION | awk -F. '{print $1"."$2}')" >> $GITHUB_ENV
- name: Install pixi (provides rattler-build)
run: |
curl -fsSL https://pixi.sh/install.sh | sh
echo "$HOME/.pixi/bin" >> $GITHUB_PATH
- name: Install rattler-build
run: pixi global install rattler-build
- name: Download C++ channel for this arch
uses: actions/download-artifact@v4
with:
name: cpp-${{ matrix.subdir }}
path: ./conda-bld/
# Mirror local_release_test.sh: pass --variant-config as a real YAML
# file rather than inline shell-quoted JSON.
- name: Write rattler variant config
run: |
cat > /tmp/vecflow-variant.yaml <<EOF
python:
- "${{ matrix.python }}"
EOF
- name: Build vecflow (Python)
run: |
rattler-build build \
--recipe conda/recipes/vecflow/recipe.yaml \
--target-platform ${{ matrix.subdir }} \
--output-dir ./conda-bld \
--channel "file://$(pwd)/conda-bld" \
--channel rapidsai-nightly \
--channel rapidsai \
--channel conda-forge \
--variant-config /tmp/vecflow-variant.yaml \
--skip-existing all
- name: Upload Python .conda artifact
uses: actions/upload-artifact@v4
with:
name: py-${{ matrix.subdir }}-py${{ matrix.python }}
path: ./conda-bld/${{ matrix.subdir }}/vecflow-cu*.conda
retention-days: 7
if-no-files-found: error
# ── 3. Build libvecflow-chamfer (C++) once per arch ───────────────────────
build-chamfer-cpp:
name: chamfer-cpp / ${{ matrix.subdir }}
needs: build-cpp
strategy:
fail-fast: false
matrix:
include:
- { runner: ubuntu-24.04, subdir: linux-64, arch: x86_64 }
- { runner: ubuntu-24.04-arm, subdir: linux-aarch64, arch: aarch64 }
runs-on: ${{ matrix.runner }}
# See build-cpp for why the CUDA image tag is a hardcoded literal.
container:
image: nvidia/cuda:12.9.1-devel-ubuntu24.04
steps:
- name: Install system tools
run: |
apt-get update -y
apt-get install -y --no-install-recommends \
curl ca-certificates git xz-utils
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Read VERSION files into env
run: |
echo "VECFLOW_VERSION=$(tr -d '[:space:]' < vecflow/VERSION)" >> $GITHUB_ENV
echo "CUVS_MINOR_VERSION=$(tr -d '[:space:]' < VERSION | awk -F. '{print $1"."$2}')" >> $GITHUB_ENV
- name: Install pixi (provides rattler-build)
run: |
curl -fsSL https://pixi.sh/install.sh | sh
echo "$HOME/.pixi/bin" >> $GITHUB_PATH
- name: Install rattler-build
run: pixi global install rattler-build
# libvecflow-chamfer's host dep is `libcuvs-vecflow-cu12 =${version}`, so
# the freshly-built C++ channel must be present and listed FIRST.
- name: Download libcuvs-vecflow channel for this arch
uses: actions/download-artifact@v4
with:
name: cpp-${{ matrix.subdir }}
path: ./conda-bld/
- name: Build libvecflow-chamfer
run: |
rattler-build build \
--recipe conda/recipes/libvecflow-chamfer/recipe.yaml \
--target-platform ${{ matrix.subdir }} \
--output-dir ./conda-bld \
--channel "file://$(pwd)/conda-bld" \
--channel rapidsai-nightly \
--channel rapidsai \
--channel conda-forge \
--skip-existing all
# Upload the combined channel (libcuvs-vecflow + libvecflow-chamfer +
# repodata) so build-chamfer-py can resolve both C++ packages from a
# single file:// channel. The publish job de-dups the libcuvs-vecflow
# .conda that also appears in the cpp-* artifact.
- name: Upload chamfer C++ channel as artifact
uses: actions/upload-artifact@v4
with:
name: chamfer-cpp-${{ matrix.subdir }}
path: ./conda-bld/
retention-days: 7
if-no-files-found: error
# ── 4. Build vecflow-chamfer Python package per (arch, python) ────────────
build-chamfer-py:
name: chamfer-py / ${{ matrix.subdir }} / py${{ matrix.python }}
needs: build-chamfer-cpp
strategy:
fail-fast: false
matrix:
# Two real axes (subdir × python = 8 jobs); `include` only enriches
# each with runner/arch. See build-py for why subdir must NOT live
# inside `include` (aarch64 would overwrite linux-64 in every combo).
subdir: [linux-64, linux-aarch64]
python: ["3.11", "3.12", "3.13", "3.14"]
include:
- { subdir: linux-64, runner: ubuntu-24.04, arch: x86_64 }
- { subdir: linux-aarch64, runner: ubuntu-24.04-arm, arch: aarch64 }
runs-on: ${{ matrix.runner }}
# See build-cpp for why the CUDA image tag is a hardcoded literal.
container:
image: nvidia/cuda:12.9.1-devel-ubuntu24.04
env:
RAPIDS_PY_VERSION: ${{ matrix.python }}
steps:
- name: Install system tools
run: |
apt-get update -y
apt-get install -y --no-install-recommends \
curl ca-certificates git xz-utils
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Read VERSION files into env
run: |
echo "VECFLOW_VERSION=$(tr -d '[:space:]' < vecflow/VERSION)" >> $GITHUB_ENV
echo "CUVS_MINOR_VERSION=$(tr -d '[:space:]' < VERSION | awk -F. '{print $1"."$2}')" >> $GITHUB_ENV
- name: Install pixi (provides rattler-build)
run: |
curl -fsSL https://pixi.sh/install.sh | sh
echo "$HOME/.pixi/bin" >> $GITHUB_PATH
- name: Install rattler-build
run: pixi global install rattler-build
# The combined channel carries BOTH C++ packages: vecflow-chamfer's host
# dep is libvecflow-chamfer, which transitively pulls libcuvs-vecflow.
- name: Download chamfer C++ channel for this arch
uses: actions/download-artifact@v4
with:
name: chamfer-cpp-${{ matrix.subdir }}
path: ./conda-bld/
- name: Write rattler variant config
run: |
cat > /tmp/vecflow-chamfer-variant.yaml <<EOF
python:
- "${{ matrix.python }}"
EOF
- name: Build vecflow-chamfer (Python)
run: |
rattler-build build \
--recipe conda/recipes/vecflow-chamfer/recipe.yaml \
--target-platform ${{ matrix.subdir }} \
--output-dir ./conda-bld \
--channel "file://$(pwd)/conda-bld" \
--channel rapidsai-nightly \
--channel rapidsai \
--channel conda-forge \
--variant-config /tmp/vecflow-chamfer-variant.yaml \
--skip-existing all
- name: Upload Python .conda artifact
uses: actions/upload-artifact@v4
with:
name: chamfer-py-${{ matrix.subdir }}-py${{ matrix.python }}
path: ./conda-bld/${{ matrix.subdir }}/vecflow-chamfer-cu*.conda
retention-days: 7
if-no-files-found: error
# ── 5. Publish to anaconda.org/VecFlow on tag push ────────────────────────
publish:
name: publish to anaconda.org/VecFlow
needs: [build-cpp, build-py, build-chamfer-cpp, build-chamfer-py]
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-24.04
steps:
# Pin to v1 — v2 deprecated the `anaconda upload --user <org>` syntax
# used below. Revisit after we've validated v2 flag names.
#
# Use `pip install --user` (not pixi, not pipx):
# * pixi v0.30+ doesn't auto-expose binaries whose name differs from
# the package name — `anaconda` would not land on PATH.
# * pipx on the GH ubuntu-24.04 image is configured with
# PIPX_BIN_DIR=/opt/pipx_bin (root-owned), so a non-root install
# does not reliably surface the binary either.
# pip --user drops the binary in ~/.local/bin; we explicitly append
# that to $GITHUB_PATH so subsequent steps can find `anaconda`.
# --break-system-packages is required because ubuntu-24.04's system
# Python is PEP 668-marked.
- name: Install anaconda-client (v1)
run: |
python3 -m pip install --break-system-packages --user 'anaconda-client<2'
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Download all build artifacts
uses: actions/download-artifact@v4
with:
path: ./artifacts
- name: Upload .conda files to anaconda.org/VecFlow
env:
ANACONDA_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
run: |
# Collect every .conda from every artifact dir, then de-dup by
# filename. The C++ artifacts (cpp-* and chamfer-cpp-*) both carry
# the full conda-bld tree, so libcuvs-vecflow's .conda appears in
# more than one artifact dir — upload it once.
mapfile -t all < <(find ./artifacts -type f -name '*.conda' | sort)
declare -A seen
pkgs=()
for f in "${all[@]}"; do
b=$(basename "$f")
if [ -z "${seen[$b]:-}" ]; then
seen[$b]=1
pkgs+=("$f")
fi
done
if [ ${#pkgs[@]} -eq 0 ]; then
echo "ERROR: no .conda artifacts found to upload" >&2
exit 1
fi
echo "Uploading ${#pkgs[@]} unique package(s):"
printf ' %s\n' "${pkgs[@]}"
anaconda -t "$ANACONDA_TOKEN" upload \
--user VecFlow \
--label main \
--skip-existing \
"${pkgs[@]}"