From b0d4fe064590bdd75c2ec7fa1e2cdd35c06abd86 Mon Sep 17 00:00:00 2001 From: Eric Hare Date: Mon, 22 Jun 2026 11:06:40 -0700 Subject: [PATCH] fix(ci): resolve pre-release cross-platform install failure; graduate py3.13, add py3.14 experimental (#13772) fix(ci): resolve pre-release cross-platform install + graduate py3.13, add py3.14 The cross-platform install test failed *only* on "Pre-release" release runs, in the Python 3.13 (Experimental) jobs, while normal releases passed. Root cause: the experimental job's "Force reinstall local wheels to prevent downgrades" step drops `--no-deps` when `pre_release=true` (to allow pre-release dependency resolution) but never passed `--find-links` to the local wheel dirs. uv then re-resolved langflow-base's `lfx>=X.Y.Zrc0, --- .github/workflows/cross-platform-test.md | 21 ++++--- .github/workflows/cross-platform-test.yml | 77 ++++++++++++++++++----- 2 files changed, 75 insertions(+), 23 deletions(-) diff --git a/.github/workflows/cross-platform-test.md b/.github/workflows/cross-platform-test.md index 597949c739..93d8370045 100644 --- a/.github/workflows/cross-platform-test.md +++ b/.github/workflows/cross-platform-test.md @@ -58,9 +58,12 @@ jobs: - **macOS**: Intel (AMD64), Apple Silicon (ARM64) - **Windows**: AMD64 - **Python versions**: - - **All platforms**: 3.10, 3.12, and 3.13 - - **Stability**: 3.10 and 3.12 are required to pass (blocking) - - **Preview**: 3.13 testing is optional (non-blocking) to monitor ecosystem readiness + - **All platforms**: 3.10, 3.12, 3.13, and 3.14 + - **Stability**: 3.10, 3.12, and 3.13 are required to pass (blocking) + - **Preview**: 3.14 testing is optional (non-blocking) to monitor ecosystem readiness + - **Note**: on the blocking matrix, macOS Intel (x86_64) runs only Python 3.12 to + limit use of the costly `macos-latest-large` runner; newer Python versions get + macOS Intel coverage through the non-blocking experimental (3.14) set instead ## What Gets Tested @@ -103,8 +106,8 @@ gh workflow run cross-platform-test.yml \ - **Timeout**: Configurable timeout with proper cross-platform handling ### Platform-Specific Optimizations -- **Stable versions**: Python 3.10 and 3.12 provide reliable package ecosystem support -- **Preview testing**: Python 3.13 runs as non-blocking to monitor when it becomes viable +- **Stable versions**: Python 3.10, 3.12, and 3.13 provide reliable package ecosystem support +- **Preview testing**: Python 3.14 runs as non-blocking to monitor when it becomes viable - **Virtual Environments**: Uses `uv venv --seed` for consistent pip availability ### Workflow Architecture @@ -187,9 +190,11 @@ error: command '/usr/bin/clang++' failed with exit code 1 3. **macOS clang** doesn't support `-march=native` flag used by `chroma-hnswlib` compilation **Current Status**: -- **Stable testing**: Python 3.10 and 3.12 are required to pass (blocking jobs) -- **Preview testing**: Python 3.13 runs as non-blocking to monitor ecosystem readiness -- **Compilation issues**: Python 3.13 may still fail due to `chroma-hnswlib` but won't block releases +- **Stable testing**: Python 3.10, 3.12, and 3.13 are required to pass (blocking jobs) +- **Preview testing**: Python 3.14 runs as non-blocking to monitor ecosystem readiness +- **Compilation issues**: the historical `chroma-hnswlib` failure is avoided on the tested install + paths (workspace/source builds exclude `chromadb`); a similar upstream issue surfacing on the + preview (3.14) tier stays non-blocking - **Manual testing**: Source builds now use the same dependency transformation as nightly builds for testing parity **Files Involved**: diff --git a/.github/workflows/cross-platform-test.yml b/.github/workflows/cross-platform-test.yml index 41fa298eae..d3095ca5be 100644 --- a/.github/workflows/cross-platform-test.yml +++ b/.github/workflows/cross-platform-test.yml @@ -178,6 +178,23 @@ jobs: arch: amd64 runner: windows-latest python-version: "3.12" + # Python 3.13 - graduated from experimental to stable (blocking). + # macOS Intel (amd64) is intentionally omitted here: like 3.10/3.12 above + # it stays on the costly macos-latest-large runner only at 3.12. Intel + # coverage for newer Python continues (non-blocking) in the experimental + # 3.14 set below. + - os: linux + arch: amd64 + runner: ubuntu-latest + python-version: "3.13" + - os: macos + arch: arm64 + runner: macos-latest + python-version: "3.13" + - os: windows + arch: amd64 + runner: windows-latest + python-version: "3.13" steps: - name: Determine install method @@ -454,23 +471,27 @@ jobs: fail-fast: false matrix: include: - # Python 3.13 - Experimental + # Python 3.14 - Experimental (non-blocking) to monitor ecosystem readiness. + # Mirrors the platform set that 3.13 used while it was experimental. On + # macOS Intel (x86_64) the torch-dependent extras are excluded via + # pyproject markers (sys_platform/platform_machine), so the install still + # resolves there; this job is non-blocking via continue-on-error regardless. - os: linux arch: amd64 runner: ubuntu-latest - python-version: "3.13" + python-version: "3.14" - os: windows arch: amd64 runner: windows-latest - python-version: "3.13" + python-version: "3.14" - os: macos arch: amd64 runner: macos-latest-large - python-version: "3.13" + python-version: "3.14" - os: macos arch: arm64 runner: macos-latest - python-version: "3.13" + python-version: "3.14" steps: - name: Determine install method @@ -615,6 +636,19 @@ jobs: - name: Force reinstall local wheels to prevent downgrades (Windows) if: steps.install-method.outputs.method == 'wheel' && matrix.os == 'windows' run: | + # Expose the local wheel dirs so dependency re-resolution (the + # pre-release path below drops --no-deps) can find the local + # pre-release lfx/base wheels. Without these, uv re-resolves + # langflow-base's `lfx>=X.Y.Zrc0` constraint against PyPI only, where + # the matching rc/dev wheel is not published yet, and fails with + # "No solution found when resolving dependencies". + FIND_LINKS=() + for wheel_dir in ./sdk-dist ./lfx-dist ./base-dist ./bundles-dist; do + if [ -d "$wheel_dir" ]; then + FIND_LINKS+=(--find-links "$wheel_dir") + fi + done + # Reinstall LFX if it was provided if [ -n "${{ inputs.lfx-artifact-name || needs.build-if-needed.outputs.lfx-artifact-name }}" ]; then LFX_WHEEL=$(find ./lfx-dist -name "*.whl" -type f | head -1) @@ -633,7 +667,7 @@ jobs: if [ "${{ inputs.pre_release }}" = "true" ]; then NO_DEPS="" fi - uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit --python ./test-env/Scripts/python.exe "${INSTALL_WHEELS[@]}" + uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit "${FIND_LINKS[@]}" --python ./test-env/Scripts/python.exe "${INSTALL_WHEELS[@]}" fi fi @@ -645,13 +679,26 @@ jobs: if [ "${{ inputs.pre_release }}" = "true" ]; then NO_DEPS="" fi - uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit --python ./test-env/Scripts/python.exe "$BASE_WHEEL" + uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit "${FIND_LINKS[@]}" --python ./test-env/Scripts/python.exe "$BASE_WHEEL" fi shell: bash - name: Force reinstall local wheels to prevent downgrades (Unix) if: steps.install-method.outputs.method == 'wheel' && matrix.os != 'windows' run: | + # Expose the local wheel dirs so dependency re-resolution (the + # pre-release path below drops --no-deps) can find the local + # pre-release lfx/base wheels. Without these, uv re-resolves + # langflow-base's `lfx>=X.Y.Zrc0` constraint against PyPI only, where + # the matching rc/dev wheel is not published yet, and fails with + # "No solution found when resolving dependencies". + FIND_LINKS=() + for wheel_dir in ./sdk-dist ./lfx-dist ./base-dist ./bundles-dist; do + if [ -d "$wheel_dir" ]; then + FIND_LINKS+=(--find-links "$wheel_dir") + fi + done + # Reinstall LFX if it was provided if [ -n "${{ inputs.lfx-artifact-name || needs.build-if-needed.outputs.lfx-artifact-name }}" ]; then LFX_WHEEL=$(find ./lfx-dist -name "*.whl" -type f | head -1) @@ -670,7 +717,7 @@ jobs: if [ "${{ inputs.pre_release }}" = "true" ]; then NO_DEPS="" fi - uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit --python ./test-env/bin/python "${INSTALL_WHEELS[@]}" + uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit "${FIND_LINKS[@]}" --python ./test-env/bin/python "${INSTALL_WHEELS[@]}" fi fi @@ -682,7 +729,7 @@ jobs: if [ "${{ inputs.pre_release }}" = "true" ]; then NO_DEPS="" fi - uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit --python ./test-env/bin/python "$BASE_WHEEL" + uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit "${FIND_LINKS[@]}" --python ./test-env/bin/python "$BASE_WHEEL" fi shell: bash @@ -826,9 +873,9 @@ jobs: if [ "$experimental_result" = "success" ]; then if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then if [ -n "${{ inputs.langflow-version }}" ]; then - echo "✅ All PyPI installation tests passed (including Python 3.13)" + echo "✅ All PyPI installation tests passed (including Python 3.14)" else - echo "✅ All source build and installation tests passed (including Python 3.13)" + echo "✅ All source build and installation tests passed (including Python 3.14)" fi else echo "✅ All cross-platform tests passed - PyPI upload can proceed" @@ -836,17 +883,17 @@ jobs: else if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then if [ -n "${{ inputs.langflow-version }}" ]; then - echo "✅ PyPI installation tests passed (Python 3.13 experimental failures are acceptable)" + echo "✅ PyPI installation tests passed (Python 3.14 experimental failures are acceptable)" else - echo "✅ Source build and installation tests passed (Python 3.13 experimental failures are acceptable)" + echo "✅ Source build and installation tests passed (Python 3.14 experimental failures are acceptable)" fi else - echo "✅ Cross-platform tests passed - Python 3.13 experimental failures are acceptable - PyPI upload can proceed" + echo "✅ Cross-platform tests passed - Python 3.14 experimental failures are acceptable - PyPI upload can proceed" fi fi elif [ "$stable_result" = "failure" ]; then echo "❌ Critical platform tests failed - blocking release" - echo "Stable platforms (Python 3.10, 3.12) must pass for release" + echo "Stable platforms (Python 3.10, 3.12, 3.13) must pass for release" exit 1 elif [ "$stable_result" = "cancelled" ]; then echo "❌ Critical platform tests were cancelled"