From 9b74fecf7be74aa9432474216641a7910bf125c3 Mon Sep 17 00:00:00 2001 From: radu-mocanu Date: Tue, 16 Jun 2026 17:46:26 +0300 Subject: [PATCH 1/3] ci: force local wheels via uv override in cross-tests --- .../workflows/test-uipath-integrations.yml | 48 +++++++++++++++---- .github/workflows/test-uipath-langchain.yml | 48 +++++++++++++++---- 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/.github/workflows/test-uipath-integrations.yml b/.github/workflows/test-uipath-integrations.yml index ed50a4b3d..8ed622d45 100644 --- a/.github/workflows/test-uipath-integrations.yml +++ b/.github/workflows/test-uipath-integrations.yml @@ -102,13 +102,27 @@ jobs: repository: 'UiPath/uipath-integrations-python' path: 'uipath-integrations-python' - - name: Update uipath packages + - name: Override uipath packages with local wheels shell: bash - working-directory: uipath-integrations-python/packages/${{ matrix.package }} run: | - uv add ../../../wheels/uipath-core/dist/*.whl --dev - uv add ../../../wheels/uipath-platform/dist/*.whl --dev - uv add ../../../wheels/uipath/dist/*.whl --dev + # Force the freshly built local wheels in via uv override-dependencies + # so a backward-compatible minor bump in uipath-python does not break + # the cross-test purely on the downstream version cap. + PYBIN=$(command -v python || command -v python3) + "$PYBIN" - <<'PY' + import glob, os, pathlib + wheels = pathlib.Path("wheels").resolve() + lines = [] + for name in ("uipath", "uipath-core", "uipath-platform"): + matches = glob.glob(str(wheels / name / "dist" / "*.whl")) + assert matches, f"no wheel found for {name}" + lines.append(f"{name} @ {pathlib.Path(matches[0]).as_uri()}") + out = wheels / "overrides.txt" + out.write_text("\n".join(lines) + "\n") + with open(os.environ["GITHUB_ENV"], "a") as fh: + fh.write(f"UV_OVERRIDE={out}\n") + print("\n".join(lines)) + PY - name: Install dependencies and run tests shell: bash @@ -202,13 +216,27 @@ jobs: repository: 'UiPath/uipath-integrations-python' path: 'uipath-integrations-python' - - name: Update uipath packages + - name: Override uipath packages with local wheels shell: bash - working-directory: uipath-integrations-python/packages/${{ matrix.package }} run: | - uv add ../../../wheels/uipath-core/dist/*.whl - uv add ../../../wheels/uipath-platform/dist/*.whl - uv add ../../../wheels/uipath/dist/*.whl + # Force the freshly built local wheels in via uv override-dependencies + # so a backward-compatible minor bump in uipath-python does not break + # the cross-test purely on the downstream version cap. + PYBIN=$(command -v python || command -v python3) + "$PYBIN" - <<'PY' + import glob, os, pathlib + wheels = pathlib.Path("wheels").resolve() + lines = [] + for name in ("uipath", "uipath-core", "uipath-platform"): + matches = glob.glob(str(wheels / name / "dist" / "*.whl")) + assert matches, f"no wheel found for {name}" + lines.append(f"{name} @ {pathlib.Path(matches[0]).as_uri()}") + out = wheels / "overrides.txt" + out.write_text("\n".join(lines) + "\n") + with open(os.environ["GITHUB_ENV"], "a") as fh: + fh.write(f"UV_OVERRIDE={out}\n") + print("\n".join(lines)) + PY - name: Install dependencies working-directory: uipath-integrations-python/packages/${{ matrix.package }} diff --git a/.github/workflows/test-uipath-langchain.yml b/.github/workflows/test-uipath-langchain.yml index f7ccb2cf9..48a537f3d 100644 --- a/.github/workflows/test-uipath-langchain.yml +++ b/.github/workflows/test-uipath-langchain.yml @@ -72,13 +72,27 @@ jobs: repository: 'UiPath/uipath-langchain-python' path: 'uipath-langchain-python' - - name: Update uipath packages + - name: Override uipath packages with local wheels shell: bash - working-directory: uipath-langchain-python run: | - uv add ../wheels/uipath-core/dist/*.whl --dev - uv add ../wheels/uipath-platform/dist/*.whl --dev - uv add ../wheels/uipath/dist/*.whl --dev + # Force the freshly built local wheels in via uv override-dependencies + # so a backward-compatible minor bump in uipath-python does not break + # the cross-test purely on the downstream version cap. + PYBIN=$(command -v python || command -v python3) + "$PYBIN" - <<'PY' + import glob, os, pathlib + wheels = pathlib.Path("wheels").resolve() + lines = [] + for name in ("uipath", "uipath-core", "uipath-platform"): + matches = glob.glob(str(wheels / name / "dist" / "*.whl")) + assert matches, f"no wheel found for {name}" + lines.append(f"{name} @ {pathlib.Path(matches[0]).as_uri()}") + out = wheels / "overrides.txt" + out.write_text("\n".join(lines) + "\n") + with open(os.environ["GITHUB_ENV"], "a") as fh: + fh.write(f"UV_OVERRIDE={out}\n") + print("\n".join(lines)) + PY - name: Run uipath-langchain tests working-directory: uipath-langchain-python @@ -146,13 +160,27 @@ jobs: repository: 'UiPath/uipath-langchain-python' path: 'uipath-langchain-python' - - name: Update uipath packages + - name: Override uipath packages with local wheels shell: bash - working-directory: uipath-langchain-python run: | - uv add ../wheels/uipath-core/dist/*.whl - uv add ../wheels/uipath-platform/dist/*.whl - uv add ../wheels/uipath/dist/*.whl + # Force the freshly built local wheels in via uv override-dependencies + # so a backward-compatible minor bump in uipath-python does not break + # the cross-test purely on the downstream version cap. + PYBIN=$(command -v python || command -v python3) + "$PYBIN" - <<'PY' + import glob, os, pathlib + wheels = pathlib.Path("wheels").resolve() + lines = [] + for name in ("uipath", "uipath-core", "uipath-platform"): + matches = glob.glob(str(wheels / name / "dist" / "*.whl")) + assert matches, f"no wheel found for {name}" + lines.append(f"{name} @ {pathlib.Path(matches[0]).as_uri()}") + out = wheels / "overrides.txt" + out.write_text("\n".join(lines) + "\n") + with open(os.environ["GITHUB_ENV"], "a") as fh: + fh.write(f"UV_OVERRIDE={out}\n") + print("\n".join(lines)) + PY - name: Install dependencies working-directory: uipath-langchain-python From 3c9dff2ff909c9b282ae4fed13c6d8b1128eb964 Mon Sep 17 00:00:00 2001 From: radu-mocanu Date: Tue, 16 Jun 2026 18:04:45 +0300 Subject: [PATCH 2/3] ci: extract uv override logic to shared script --- .github/scripts/write_uv_overrides.py | 45 +++++++++++++++++++ .../workflows/test-uipath-integrations.yml | 36 +-------------- .github/workflows/test-uipath-langchain.yml | 36 +-------------- 3 files changed, 49 insertions(+), 68 deletions(-) create mode 100644 .github/scripts/write_uv_overrides.py diff --git a/.github/scripts/write_uv_overrides.py b/.github/scripts/write_uv_overrides.py new file mode 100644 index 000000000..50b17ee5e --- /dev/null +++ b/.github/scripts/write_uv_overrides.py @@ -0,0 +1,45 @@ +"""Write a uv override file forcing the locally built uipath wheels. + +Cross-test workflows build uipath-core/uipath-platform/uipath wheels from the PR +and run them against downstream repos (uipath-langchain-python, +uipath-integrations-python). Those downstreams cap the uipath version (e.g. +``uipath<2.11.0``), so a backward-compatible minor bump would fail resolution +purely on the cap. uv ``override-dependencies`` bypass the declared version +specifier, so pointing them at the local wheels lets the cross-test exercise the +real new code regardless of the cap. + +The wheels are resolved relative to ``GITHUB_WORKSPACE`` (where the +``download-artifact`` step places them) rather than the current directory, so the +script is robust to a step- or job-level ``working-directory``. + +The resulting override file path is appended to ``GITHUB_ENV`` as ``UV_OVERRIDE`` +so every subsequent ``uv`` invocation in the job honors it. +""" + +import glob +import os +import pathlib + + +def main() -> None: + workspace = pathlib.Path(os.environ.get("GITHUB_WORKSPACE", ".")).resolve() + wheels = workspace / "wheels" + + lines = [] + for name in ("uipath", "uipath-core", "uipath-platform"): + matches = glob.glob(str(wheels / name / "dist" / "*.whl")) + if not matches: + raise SystemExit(f"no wheel found for {name} under {wheels / name / 'dist'}") + lines.append(f"{name} @ {pathlib.Path(matches[0]).resolve().as_uri()}") + + out = wheels / "overrides.txt" + out.write_text("\n".join(lines) + "\n") + + with open(os.environ["GITHUB_ENV"], "a") as fh: + fh.write(f"UV_OVERRIDE={out}\n") + + print("\n".join(lines)) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/test-uipath-integrations.yml b/.github/workflows/test-uipath-integrations.yml index 8ed622d45..265ecf8e0 100644 --- a/.github/workflows/test-uipath-integrations.yml +++ b/.github/workflows/test-uipath-integrations.yml @@ -105,24 +105,8 @@ jobs: - name: Override uipath packages with local wheels shell: bash run: | - # Force the freshly built local wheels in via uv override-dependencies - # so a backward-compatible minor bump in uipath-python does not break - # the cross-test purely on the downstream version cap. PYBIN=$(command -v python || command -v python3) - "$PYBIN" - <<'PY' - import glob, os, pathlib - wheels = pathlib.Path("wheels").resolve() - lines = [] - for name in ("uipath", "uipath-core", "uipath-platform"): - matches = glob.glob(str(wheels / name / "dist" / "*.whl")) - assert matches, f"no wheel found for {name}" - lines.append(f"{name} @ {pathlib.Path(matches[0]).as_uri()}") - out = wheels / "overrides.txt" - out.write_text("\n".join(lines) + "\n") - with open(os.environ["GITHUB_ENV"], "a") as fh: - fh.write(f"UV_OVERRIDE={out}\n") - print("\n".join(lines)) - PY + "$PYBIN" "$GITHUB_WORKSPACE/.github/scripts/write_uv_overrides.py" - name: Install dependencies and run tests shell: bash @@ -219,24 +203,8 @@ jobs: - name: Override uipath packages with local wheels shell: bash run: | - # Force the freshly built local wheels in via uv override-dependencies - # so a backward-compatible minor bump in uipath-python does not break - # the cross-test purely on the downstream version cap. PYBIN=$(command -v python || command -v python3) - "$PYBIN" - <<'PY' - import glob, os, pathlib - wheels = pathlib.Path("wheels").resolve() - lines = [] - for name in ("uipath", "uipath-core", "uipath-platform"): - matches = glob.glob(str(wheels / name / "dist" / "*.whl")) - assert matches, f"no wheel found for {name}" - lines.append(f"{name} @ {pathlib.Path(matches[0]).as_uri()}") - out = wheels / "overrides.txt" - out.write_text("\n".join(lines) + "\n") - with open(os.environ["GITHUB_ENV"], "a") as fh: - fh.write(f"UV_OVERRIDE={out}\n") - print("\n".join(lines)) - PY + "$PYBIN" "$GITHUB_WORKSPACE/.github/scripts/write_uv_overrides.py" - name: Install dependencies working-directory: uipath-integrations-python/packages/${{ matrix.package }} diff --git a/.github/workflows/test-uipath-langchain.yml b/.github/workflows/test-uipath-langchain.yml index 48a537f3d..23c87edcb 100644 --- a/.github/workflows/test-uipath-langchain.yml +++ b/.github/workflows/test-uipath-langchain.yml @@ -75,24 +75,8 @@ jobs: - name: Override uipath packages with local wheels shell: bash run: | - # Force the freshly built local wheels in via uv override-dependencies - # so a backward-compatible minor bump in uipath-python does not break - # the cross-test purely on the downstream version cap. PYBIN=$(command -v python || command -v python3) - "$PYBIN" - <<'PY' - import glob, os, pathlib - wheels = pathlib.Path("wheels").resolve() - lines = [] - for name in ("uipath", "uipath-core", "uipath-platform"): - matches = glob.glob(str(wheels / name / "dist" / "*.whl")) - assert matches, f"no wheel found for {name}" - lines.append(f"{name} @ {pathlib.Path(matches[0]).as_uri()}") - out = wheels / "overrides.txt" - out.write_text("\n".join(lines) + "\n") - with open(os.environ["GITHUB_ENV"], "a") as fh: - fh.write(f"UV_OVERRIDE={out}\n") - print("\n".join(lines)) - PY + "$PYBIN" "$GITHUB_WORKSPACE/.github/scripts/write_uv_overrides.py" - name: Run uipath-langchain tests working-directory: uipath-langchain-python @@ -163,24 +147,8 @@ jobs: - name: Override uipath packages with local wheels shell: bash run: | - # Force the freshly built local wheels in via uv override-dependencies - # so a backward-compatible minor bump in uipath-python does not break - # the cross-test purely on the downstream version cap. PYBIN=$(command -v python || command -v python3) - "$PYBIN" - <<'PY' - import glob, os, pathlib - wheels = pathlib.Path("wheels").resolve() - lines = [] - for name in ("uipath", "uipath-core", "uipath-platform"): - matches = glob.glob(str(wheels / name / "dist" / "*.whl")) - assert matches, f"no wheel found for {name}" - lines.append(f"{name} @ {pathlib.Path(matches[0]).as_uri()}") - out = wheels / "overrides.txt" - out.write_text("\n".join(lines) + "\n") - with open(os.environ["GITHUB_ENV"], "a") as fh: - fh.write(f"UV_OVERRIDE={out}\n") - print("\n".join(lines)) - PY + "$PYBIN" "$GITHUB_WORKSPACE/.github/scripts/write_uv_overrides.py" - name: Install dependencies working-directory: uipath-langchain-python From f122aa22e6500913b8005e943ef7a7991bd9599f Mon Sep 17 00:00:00 2001 From: radu-mocanu Date: Tue, 16 Jun 2026 18:21:58 +0300 Subject: [PATCH 3/3] ci: share uv override script via sparse checkout, cover runtime --- .github/scripts/write_uv_overrides.py | 33 +++++++++++-------- .../workflows/test-uipath-integrations.yml | 16 +++++++-- .github/workflows/test-uipath-langchain.yml | 16 +++++++-- .github/workflows/test-uipath-runtime.yml | 13 ++++++-- 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/.github/scripts/write_uv_overrides.py b/.github/scripts/write_uv_overrides.py index 50b17ee5e..557f9d26e 100644 --- a/.github/scripts/write_uv_overrides.py +++ b/.github/scripts/write_uv_overrides.py @@ -1,16 +1,17 @@ """Write a uv override file forcing the locally built uipath wheels. -Cross-test workflows build uipath-core/uipath-platform/uipath wheels from the PR -and run them against downstream repos (uipath-langchain-python, -uipath-integrations-python). Those downstreams cap the uipath version (e.g. +Cross-test workflows build uipath wheels from the PR and run them against +downstream repos (uipath-langchain-python, uipath-integrations-python, +uipath-runtime-python). Those downstreams cap the uipath* version (e.g. ``uipath<2.11.0``), so a backward-compatible minor bump would fail resolution -purely on the cap. uv ``override-dependencies`` bypass the declared version +purely on the cap. uv ``override-dependencies`` ignore the declared version specifier, so pointing them at the local wheels lets the cross-test exercise the real new code regardless of the cap. -The wheels are resolved relative to ``GITHUB_WORKSPACE`` (where the -``download-artifact`` step places them) rather than the current directory, so the -script is robust to a step- or job-level ``working-directory``. +The script is layout-agnostic: it overrides whatever ``uipath*`` wheels exist +under ``$GITHUB_WORKSPACE/wheels`` (recursively), so it works for the +three-wheel layout (``wheels//dist/*.whl``) and the single-wheel runtime +layout (``wheels/*.whl``) alike. The resulting override file path is appended to ``GITHUB_ENV`` as ``UV_OVERRIDE`` so every subsequent ``uv`` invocation in the job honors it. @@ -22,15 +23,19 @@ def main() -> None: - workspace = pathlib.Path(os.environ.get("GITHUB_WORKSPACE", ".")).resolve() - wheels = workspace / "wheels" + wheels = pathlib.Path(os.environ.get("GITHUB_WORKSPACE", ".")).resolve() / "wheels" lines = [] - for name in ("uipath", "uipath-core", "uipath-platform"): - matches = glob.glob(str(wheels / name / "dist" / "*.whl")) - if not matches: - raise SystemExit(f"no wheel found for {name} under {wheels / name / 'dist'}") - lines.append(f"{name} @ {pathlib.Path(matches[0]).resolve().as_uri()}") + for whl in sorted(glob.glob(str(wheels / "**" / "*.whl"), recursive=True)): + # Wheel filename is ``{distribution}-{version}-...whl`` where the + # distribution escapes hyphens to underscores (uipath_core -> uipath-core). + dist = pathlib.Path(whl).name.split("-", 1)[0].replace("_", "-") + if not dist.startswith("uipath"): + continue + lines.append(f"{dist} @ {pathlib.Path(whl).resolve().as_uri()}") + + if not lines: + raise SystemExit(f"no uipath wheels found under {wheels}") out = wheels / "overrides.txt" out.write_text("\n".join(lines) + "\n") diff --git a/.github/workflows/test-uipath-integrations.yml b/.github/workflows/test-uipath-integrations.yml index 265ecf8e0..95c621941 100644 --- a/.github/workflows/test-uipath-integrations.yml +++ b/.github/workflows/test-uipath-integrations.yml @@ -102,11 +102,17 @@ jobs: repository: 'UiPath/uipath-integrations-python' path: 'uipath-integrations-python' + - name: Checkout uipath-python scripts + uses: actions/checkout@v4 + with: + path: _scripts + sparse-checkout: .github/scripts + - name: Override uipath packages with local wheels shell: bash run: | PYBIN=$(command -v python || command -v python3) - "$PYBIN" "$GITHUB_WORKSPACE/.github/scripts/write_uv_overrides.py" + "$PYBIN" "$GITHUB_WORKSPACE/_scripts/.github/scripts/write_uv_overrides.py" - name: Install dependencies and run tests shell: bash @@ -200,11 +206,17 @@ jobs: repository: 'UiPath/uipath-integrations-python' path: 'uipath-integrations-python' + - name: Checkout uipath-python scripts + uses: actions/checkout@v4 + with: + path: _scripts + sparse-checkout: .github/scripts + - name: Override uipath packages with local wheels shell: bash run: | PYBIN=$(command -v python || command -v python3) - "$PYBIN" "$GITHUB_WORKSPACE/.github/scripts/write_uv_overrides.py" + "$PYBIN" "$GITHUB_WORKSPACE/_scripts/.github/scripts/write_uv_overrides.py" - name: Install dependencies working-directory: uipath-integrations-python/packages/${{ matrix.package }} diff --git a/.github/workflows/test-uipath-langchain.yml b/.github/workflows/test-uipath-langchain.yml index 23c87edcb..25b027633 100644 --- a/.github/workflows/test-uipath-langchain.yml +++ b/.github/workflows/test-uipath-langchain.yml @@ -72,11 +72,17 @@ jobs: repository: 'UiPath/uipath-langchain-python' path: 'uipath-langchain-python' + - name: Checkout uipath-python scripts + uses: actions/checkout@v4 + with: + path: _scripts + sparse-checkout: .github/scripts + - name: Override uipath packages with local wheels shell: bash run: | PYBIN=$(command -v python || command -v python3) - "$PYBIN" "$GITHUB_WORKSPACE/.github/scripts/write_uv_overrides.py" + "$PYBIN" "$GITHUB_WORKSPACE/_scripts/.github/scripts/write_uv_overrides.py" - name: Run uipath-langchain tests working-directory: uipath-langchain-python @@ -144,11 +150,17 @@ jobs: repository: 'UiPath/uipath-langchain-python' path: 'uipath-langchain-python' + - name: Checkout uipath-python scripts + uses: actions/checkout@v4 + with: + path: _scripts + sparse-checkout: .github/scripts + - name: Override uipath packages with local wheels shell: bash run: | PYBIN=$(command -v python || command -v python3) - "$PYBIN" "$GITHUB_WORKSPACE/.github/scripts/write_uv_overrides.py" + "$PYBIN" "$GITHUB_WORKSPACE/_scripts/.github/scripts/write_uv_overrides.py" - name: Install dependencies working-directory: uipath-langchain-python diff --git a/.github/workflows/test-uipath-runtime.yml b/.github/workflows/test-uipath-runtime.yml index 13ad019ef..200a1b8ca 100644 --- a/.github/workflows/test-uipath-runtime.yml +++ b/.github/workflows/test-uipath-runtime.yml @@ -64,10 +64,17 @@ jobs: repository: 'UiPath/uipath-runtime-python' path: 'uipath-runtime-python' - - name: Update uipath-core version + - name: Checkout uipath-python scripts + uses: actions/checkout@v4 + with: + path: _scripts + sparse-checkout: .github/scripts + + - name: Override uipath packages with local wheels shell: bash - working-directory: uipath-runtime-python - run: uv add ../wheels/*.whl --dev + run: | + PYBIN=$(command -v python || command -v python3) + "$PYBIN" "$GITHUB_WORKSPACE/_scripts/.github/scripts/write_uv_overrides.py" - name: Run uipath-runtime tests working-directory: uipath-runtime-python