Repository navigation
Merge pull request #664 from pinecone-io/dependabot/uv/soupsieve-2.9 #331
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| # Allow other workflows (e.g. release-rc.yaml) to reuse this file as a | |
| # validation gate. Reusable invocations inherit the caller's permissions | |
| # and ref, so no extra inputs/secrets are required. | |
| workflow_call: | |
| concurrency: | |
| # Scoping by event_name as well as ref keeps reusable invocations from | |
| # release workflows in a different group than push/PR runs on the same ref. | |
| group: ci-${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| PROTOC_VERSION: "28.3" | |
| # arduino/setup-protoc@v3.0.0 has no Node.js 24 release yet; remove once a node24 version ships | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Python lint & format | |
| # --------------------------------------------------------------------------- | |
| lint: | |
| name: Lint & format (ruff) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| run: uv python install 3.12 | |
| - name: Install dev deps (no project build) | |
| run: uv sync --group dev --no-install-project | |
| - name: ruff check | |
| run: uv run --no-sync ruff check | |
| - name: ruff format --check | |
| run: uv run --no-sync ruff format --check | |
| # --------------------------------------------------------------------------- | |
| # Python type check | |
| # --------------------------------------------------------------------------- | |
| typecheck: | |
| name: mypy --strict | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install protoc | |
| uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 | |
| with: | |
| version: ${{ env.PROTOC_VERSION }} | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| with: | |
| toolchain: "1.98.0" | |
| - name: Cache cargo build artifacts | |
| uses: Swatinem/rust-cache@23869a5bd66c73db3c0ac40331f3206eb23791dc # v2.9.1 | |
| with: | |
| workspaces: rust | |
| shared-key: typecheck | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| run: uv python install 3.12 | |
| - name: Install deps + build Rust extension | |
| run: uv sync --group dev | |
| - name: Check pinecone/__init__.pyi is in sync with _LAZY_IMPORTS | |
| run: uv run --no-sync python scripts/generate_init_stub.py --check | |
| - name: How to fix __init__.pyi drift | |
| if: failure() | |
| run: | | |
| echo "::error::pinecone/__init__.pyi is out of sync with _LAZY_IMPORTS." | |
| echo "Run: cd sdks/python-sdk && uv run python scripts/generate_init_stub.py" | |
| echo "Then commit the regenerated pinecone/__init__.pyi." | |
| - name: mypy --strict | |
| run: uv run --no-sync mypy --strict pinecone/ | |
| # --------------------------------------------------------------------------- | |
| # Python unit tests (matrix across supported versions) | |
| # --------------------------------------------------------------------------- | |
| unit-tests: | |
| name: Unit tests (py${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install protoc | |
| uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 | |
| with: | |
| version: ${{ env.PROTOC_VERSION }} | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| with: | |
| toolchain: "1.98.0" | |
| - name: Cache cargo build artifacts | |
| uses: Swatinem/rust-cache@23869a5bd66c73db3c0ac40331f3206eb23791dc # v2.9.1 | |
| with: | |
| workspaces: rust | |
| shared-key: unit-tests | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| run: uv python install ${{ matrix.python-version }} | |
| - name: Install deps + build Rust extension | |
| run: uv sync --group dev | |
| - name: pytest tests/unit | |
| # --durations makes the runner's own timings visible per Python version. | |
| # The scoped pytest.mark.timeout values are sized against measured | |
| # runtimes (#327), and without this the only way to check a claimed | |
| # margin against real CI hardware is to push a throwaway commit. | |
| run: uv run pytest tests/unit -x -v --cov --cov-report=term-missing --durations=25 --durations-min=0.5 | |
| # One matrix leg is enough to see the shape of coverage; posting it five | |
| # times over would just be noise on the PR checks tab. See | |
| # tests/unit/README.md for why there's no threshold yet. | |
| - name: Post coverage to job summary | |
| if: matrix.python-version == '3.12' | |
| run: uv run --no-sync coverage report --format=markdown >> "$GITHUB_STEP_SUMMARY" | |
| # --------------------------------------------------------------------------- | |
| # Wheel-only install verify, on THIS ref | |
| # | |
| # A missing runtime dependency is invisible to every job above: they all run | |
| # `uv sync`, which installs the dev group, and the dev group carries the | |
| # transitives that mask the gap. It was also invisible to | |
| # release-readiness.yml's multi-python-install-verify for two independent | |
| # reasons — that job runs `import pinecone`, which is lazy and reaches almost | |
| # no code, and it installs a dev wheel published from `main`, so its result | |
| # says nothing about the ref under test. #411 shipped past both. | |
| # | |
| # So: build the wheel from this checkout, install it and nothing but its | |
| # declared dependencies, and touch every lazy export. | |
| # --------------------------------------------------------------------------- | |
| wheel-install-verify: | |
| name: Wheel-only install verify (declared deps, py3.10-3.14) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install protoc | |
| uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 | |
| with: | |
| version: ${{ env.PROTOC_VERSION }} | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| with: | |
| toolchain: "1.98.0" | |
| - name: Cache cargo build artifacts | |
| uses: Swatinem/rust-cache@23869a5bd66c73db3c0ac40331f3206eb23791dc # v2.9.1 | |
| with: | |
| workspaces: rust | |
| shared-key: unit-tests | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 | |
| with: | |
| enable-cache: true | |
| # The wheel is abi3 (cp310-abi3), so one build serves the whole matrix. | |
| - name: Build wheel from this checkout | |
| run: uv build --wheel --out-dir "${RUNNER_TEMP}/wheel" | |
| - name: Import the full public surface on each supported Python | |
| run: | | |
| set -euo pipefail | |
| wheel=$(ls "${RUNNER_TEMP}"/wheel/*.whl) | |
| echo "wheel: ${wheel}" | |
| cat > "${RUNNER_TEMP}/verify.py" <<'PY' | |
| import sys | |
| import pinecone | |
| names = sorted(pinecone._LAZY_IMPORTS) | |
| if len(names) < 100: | |
| sys.exit(f"only {len(names)} lazy exports found") | |
| broken = [] | |
| for name in names: | |
| try: | |
| getattr(pinecone, name) | |
| except ModuleNotFoundError as exc: | |
| broken.append(f"{name}: missing {exc.name}") | |
| if broken: | |
| sys.exit("undeclared runtime dependency: " + "; ".join(broken[:8])) | |
| import pinecone._grpc | |
| print(f"OK {sys.version_info[:2]}: {len(names)} lazy exports, _grpc loaded") | |
| PY | |
| for v in 3.10 3.11 3.12 3.13 3.14; do | |
| echo "::group::py${v}" | |
| uv python install "${v}" | |
| uv venv -p "${v}" "${RUNNER_TEMP}/venv-${v}" | |
| # No --group/--extra: only the wheel and [project].dependencies. | |
| uv pip install --python "${RUNNER_TEMP}/venv-${v}/bin/python" "${wheel}" | |
| uv pip list --python "${RUNNER_TEMP}/venv-${v}/bin/python" | |
| # Run from RUNNER_TEMP: the repo's pinecone/ would shadow the wheel, | |
| # because Python puts the script's directory on sys.path first. | |
| (cd "${RUNNER_TEMP}" && "${RUNNER_TEMP}/venv-${v}/bin/python" "${RUNNER_TEMP}/verify.py") | |
| echo "::endgroup::" | |
| done | |
| # --------------------------------------------------------------------------- | |
| # Rust check / clippy / fmt | |
| # --------------------------------------------------------------------------- | |
| rust: | |
| name: Rust check / clippy / fmt | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: rust | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install protoc | |
| uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 | |
| with: | |
| version: ${{ env.PROTOC_VERSION }} | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install Rust toolchain (rustfmt + clippy) | |
| uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| with: | |
| toolchain: "1.98.0" | |
| components: rustfmt, clippy | |
| - name: Cache cargo build artifacts | |
| uses: Swatinem/rust-cache@23869a5bd66c73db3c0ac40331f3206eb23791dc # v2.9.1 | |
| with: | |
| workspaces: rust | |
| shared-key: rust-checks | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: cargo fmt --check | |
| run: cargo fmt --all --check | |
| - name: cargo clippy | |
| run: cargo clippy --all-targets -- -D warnings | |
| - name: cargo check | |
| run: cargo check --all-targets | |
| - name: Install cargo-audit | |
| run: cargo install cargo-audit --locked | |
| - name: cargo audit | |
| run: cargo audit --file ../Cargo.lock | |
| # --no-default-features turns off pyo3's extension-module so the test | |
| # binaries can link against libpython. With it on, Python symbols are | |
| # left undefined and rust/tests/ cannot be linked — which is why these | |
| # tests had never run in CI. | |
| - name: cargo test | |
| run: cargo test --no-default-features | |
| # --------------------------------------------------------------------------- | |
| # Sphinx docs build (warnings are errors) | |
| # | |
| # Same warnings-as-errors invocation as the doc-build job in | |
| # release-readiness.yml, so a PR that breaks the docs build fails here rather | |
| # than surfacing days later in the Monday cron. | |
| # --------------------------------------------------------------------------- | |
| docs: | |
| name: Sphinx docs build | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| run: uv python install 3.12 | |
| # No protoc / Rust toolchain / project build: docs/conf.py mocks | |
| # pinecone._grpc and pandas via autodoc_mock_imports, so autodoc never | |
| # loads the compiled extension. --no-install-project still installs the | |
| # project's runtime deps, which conf.py needs to import pinecone from the | |
| # source tree (it puts the repo root on sys.path). | |
| - name: Install docs deps (no project build) | |
| run: uv sync --extra docs --no-install-project --no-default-groups | |
| # SPHINXBUILD override drops the Makefile's inner `uv run --extra docs`, | |
| # which would re-sync and build the Rust extension. The resulting | |
| # sphinx-build command line is identical to release-readiness's. | |
| - name: Build HTML docs | |
| run: make -C docs html SPHINXOPTS="-W" SPHINXBUILD="uv run --no-sync sphinx-build" | |
| # Pages the site has already published must keep resolving: a link | |
| # someone saved before a restructure should not 404. Deleting a page is | |
| # still allowed — add a redirect in docs/conf.py and sphinx-reredirects | |
| # emits a forwarding stub at the old path, which satisfies this. Offline | |
| # and deterministic; docs/published-urls.txt is the committed inventory. | |
| - name: Check published docs URLs still resolve | |
| run: uv run --no-sync python scripts/check_docs_urls.py | |
| # A stub pointing a fragment at nothing fails silently: the page loads | |
| # and does not scroll. Nothing else in the build notices. | |
| - name: Check redirect anchor targets still exist | |
| run: uv run --no-sync python scripts/check_redirect_anchors.py |