From 86d4310821f709e2d289a0b8f5a01519e9a8797a Mon Sep 17 00:00:00 2001 From: Cosmin Maria Date: Wed, 20 May 2026 17:05:14 +0300 Subject: [PATCH] ci: gate langchain CD on uv resolvability, not just PyPI simple index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous wait step polled pypi.org/simple/ with curl, which confirmed PyPI knew about the new core version but did not guarantee uv would see it. setup-uv@v7 with enable-cache: true restores uv's metadata cache across job runs, so the cached simple-index page for uipath-llm-client could still show only the previous version even after PyPI had published the new one — causing the smoke test's `uv run --with "${WHEEL}[all]"` to fail to resolve uipath-llm-client>=NEW_VERSION (see run 25555638070). Switch the readiness probe to `uv pip install --dry-run --refresh-package uipath-llm-client`, which invalidates uv's local cache for the package and forces a fresh fetch each attempt. Once it succeeds, uv's cache is warm with the new version and the downstream smoke tests inherit it. Also pass --refresh-package on the smoke tests themselves as belt-and-suspenders. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/cd-langchain.yml | 53 +++++++++++++++++------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/.github/workflows/cd-langchain.yml b/.github/workflows/cd-langchain.yml index 7fda328c..10934f73 100644 --- a/.github/workflows/cd-langchain.yml +++ b/.github/workflows/cd-langchain.yml @@ -23,6 +23,17 @@ jobs: with: fetch-depth: 2 + - name: Setup uv + uses: astral-sh/setup-uv@v7 + with: + version: "0.9.27" + enable-cache: true + + - name: "Set up Python" + uses: actions/setup-python@v6 + with: + python-version-file: ".python-version" + - name: Wait for uipath-llm-client publish if: github.event_name == 'push' env: @@ -44,21 +55,26 @@ jobs: case "$STATUS" in completed:success) - echo "cd workflow succeeded — polling PyPI until uipath-llm-client==$CORE_VERSION is available..." + echo "cd workflow succeeded — verifying uv can resolve uipath-llm-client==$CORE_VERSION from PyPI..." + # Use uv itself as the readiness check (not curl). The setup-uv action + # restores uv's metadata cache across job runs, so the simple-index entry + # for uipath-llm-client may be stale (without the new version). Polling + # pypi.org/simple/ with curl proves only that PyPI knows about the version, + # not that uv will see it. --refresh-package invalidates uv's cache for + # this specific project and forces a fresh fetch each attempt. Retry rides + # out PyPI CDN propagation across Fastly edges (a fresh publish can be + # visible on one edge but stale on another for tens of seconds). for j in $(seq 1 40); do - # Query the simple index directly with Cache-Control: no-cache so Fastly - # revalidates with origin on every request. PyPI purges the per-project - # simple page within seconds of a publish, so uv's local cache (max-age=600) - # would otherwise serve a stale miss for up to 10 minutes. - if curl -sf -H "Cache-Control: no-cache" \ - "https://pypi.org/simple/uipath-llm-client/" | grep -q "$CORE_VERSION"; then - echo "uipath-llm-client==$CORE_VERSION is available on PyPI." + if uv pip install --dry-run --system --no-deps \ + --refresh-package uipath-llm-client \ + "uipath-llm-client==$CORE_VERSION" >/dev/null 2>&1; then + echo "uv can resolve uipath-llm-client==$CORE_VERSION from PyPI." exit 0 fi - echo " Not yet available, retrying in 15s ($j/40)..." + echo " Not yet resolvable by uv, retrying in 15s ($j/40)..." sleep 15 done - echo "::error::uipath-llm-client==$CORE_VERSION never appeared on PyPI (10 min)" + echo "::error::uipath-llm-client==$CORE_VERSION never became resolvable on PyPI (10 min)" exit 1 ;; completed:*) @@ -73,17 +89,6 @@ jobs: echo "::error::Timed out waiting for cd workflow (15 min)" exit 1 - - name: Setup uv - uses: astral-sh/setup-uv@v7 - with: - version: "0.9.27" - enable-cache: true - - - name: "Set up Python" - uses: actions/setup-python@v6 - with: - python-version-file: ".python-version" - - name: "Install dependencies" run: uv sync --dev --all-extras --locked @@ -93,12 +98,14 @@ jobs: - name: Smoke test (wheel with all extras) run: | WHEEL=$(ls dist/*.whl) - uv run --isolated --no-project --with "${WHEEL}[all]" tests/langchain/smoke_test.py + uv run --isolated --no-project --refresh-package uipath-llm-client \ + --with "${WHEEL}[all]" tests/langchain/smoke_test.py - name: Smoke test (source distribution with all extras) run: | SDIST=$(ls dist/*.tar.gz) - uv run --isolated --no-project --with "${SDIST}[all]" tests/langchain/smoke_test.py + uv run --isolated --no-project --refresh-package uipath-llm-client \ + --with "${SDIST}[all]" tests/langchain/smoke_test.py - name: Publish package run: uv publish