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
30 changes: 28 additions & 2 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,32 @@ env:
CARGO_TERM_COLOR: always

jobs:
release-package-sanity:
runs-on: ubuntu-latest

name: Release package sanity test

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10.x'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip poetry
- name: Build package
run: |
poetry build
- name: Check installed release package
run: |
python -m venv .release-smoke
. .release-smoke/bin/activate
python -m pip install --upgrade pip
python -m pip install dist/qdrant_client-*.whl
python tools/check_release_package.py dist/qdrant_client-*.whl
shell: bash

test:

strategy:
Expand All @@ -26,9 +52,9 @@ jobs:
name: Python ${{ matrix.python-version }} on ${{ matrix.os }} test

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install jq
Expand Down
102 changes: 102 additions & 0 deletions tools/check_release_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from __future__ import annotations

import importlib
import importlib.metadata
import pkgutil
import sys
from pathlib import Path


def remove_repo_from_sys_path() -> None:
"""Remove repository paths so imports resolve from the installed distribution."""

repo_root = Path(__file__).resolve().parents[1]
excluded_paths = {
str(repo_root),
str(repo_root / "tools"),
}

normalized_excluded = {str(Path(path).resolve()) for path in excluded_paths}
sanitized_sys_path: list[str] = []
for entry in sys.path:
if entry == "":
continue

try:
resolved = str(Path(entry).resolve())
except OSError:
sanitized_sys_path.append(entry)
continue

if resolved not in normalized_excluded:
sanitized_sys_path.append(entry)

sys.path[:] = sanitized_sys_path


def get_distribution_requirements() -> list[str]:
"""Return the installed qdrant-client distribution requirements."""

for distribution in importlib.metadata.distributions():
name = distribution.metadata.get("Name", "")
if name in {"qdrant-client", "qdrant_client"}:
return distribution.requires or []

raise RuntimeError("Installed qdrant-client distribution metadata was not found")


def check_runtime_dependencies() -> None:
"""Fail if pytest leaks into the installed runtime requirements."""

requirements = get_distribution_requirements()
pytest_requirements = [requirement for requirement in requirements if "pytest" in requirement.lower()]
if pytest_requirements:
joined = ", ".join(pytest_requirements)
raise RuntimeError(f"Unexpected pytest runtime dependency found: {joined}")


def import_non_test_modules() -> None:
"""Import installed non-test qdrant_client modules and collect failures."""

import qdrant_client

failed_imports: list[tuple[str, str]] = []
for module in sorted(
{
module_info.name
for module_info in pkgutil.walk_packages(
qdrant_client.__path__,
prefix=f"{qdrant_client.__name__}.",
)
if ".tests" not in module_info.name
}
):
try:
importlib.import_module(module)
except Exception as exc: # pragma: no cover - script exits on failure
failed_imports.append((module, repr(exc)))

if failed_imports:
details = "\n".join(f"{module}: {error}" for module, error in failed_imports)
raise RuntimeError(f"Failed to import installed package modules:\n{details}")


def main() -> int:
"""Run release package sanity checks for a built wheel."""

if len(sys.argv) != 2:
raise SystemExit("Usage: python tools/check_release_package.py <wheel-path>")

wheel_path = Path(sys.argv[1])
if not wheel_path.exists():
raise SystemExit(f"Wheel not found: {wheel_path}")

remove_repo_from_sys_path()
check_runtime_dependencies()
import_non_test_modules()
print(f"Release package sanity checks passed for {wheel_path.name}")
return 0


if __name__ == "__main__":
raise SystemExit(main())