@@ -889,19 +889,158 @@ jobs:
889889 "
890890 shell : bash
891891
892+ test-core-runtime :
893+ name : Core Runtime Wheel - Linux Python 3.14
894+ needs : [build-if-needed]
895+ if : |
896+ always() &&
897+ inputs.langflow-version == '' &&
898+ (needs.build-if-needed.result == 'success' || needs.build-if-needed.result == 'skipped')
899+ runs-on : ubuntu-latest
900+ steps :
901+ - name : Setup UV
902+ uses : astral-sh/setup-uv@v6
903+ with :
904+ enable-cache : false
905+ python-version : " 3.14"
906+
907+ - name : Download langflow-sdk package artifact
908+ if : inputs.sdk-artifact-name != '' || needs.build-if-needed.outputs.sdk-artifact-name != ''
909+ uses : actions/download-artifact@v7
910+ with :
911+ name : ${{ inputs.sdk-artifact-name || needs.build-if-needed.outputs.sdk-artifact-name || 'adhoc-dist-sdk' }}
912+ path : ./sdk-dist
913+
914+ - name : Download LFX package artifact
915+ uses : actions/download-artifact@v7
916+ with :
917+ name : ${{ inputs.lfx-artifact-name || needs.build-if-needed.outputs.lfx-artifact-name || 'adhoc-dist-lfx' }}
918+ path : ./lfx-dist
919+
920+ - name : Download base package artifact
921+ uses : actions/download-artifact@v7
922+ with :
923+ name : ${{ inputs.base-artifact-name || needs.build-if-needed.outputs.base-artifact-name || 'adhoc-dist-base' }}
924+ path : ./base-dist
925+
926+ - name : Install only core wheels
927+ shell : bash
928+ run : |
929+ set -euo pipefail
930+ shopt -s nullglob
931+
932+ SDK_WHEELS=(./sdk-dist/*.whl)
933+ LFX_WHEELS=(./lfx-dist/*.whl)
934+ BASE_WHEELS=(./base-dist/*.whl)
935+ [ ${#LFX_WHEELS[@]} -eq 1 ] || { echo "Expected one LFX wheel, found ${#LFX_WHEELS[@]}"; exit 1; }
936+ [ ${#BASE_WHEELS[@]} -eq 1 ] || { echo "Expected one base wheel, found ${#BASE_WHEELS[@]}"; exit 1; }
937+ [ ${#SDK_WHEELS[@]} -le 1 ] || { echo "Expected at most one SDK wheel, found ${#SDK_WHEELS[@]}"; exit 1; }
938+
939+ FIND_LINKS=(--find-links ./lfx-dist --find-links ./base-dist)
940+ if [ ${#SDK_WHEELS[@]} -eq 1 ]; then
941+ FIND_LINKS+=(--find-links ./sdk-dist)
942+ fi
943+
944+ uv venv core-test-env --seed --python 3.14
945+ uv pip install --python core-test-env/bin/python \
946+ --prerelease=if-necessary-or-explicit \
947+ "${FIND_LINKS[@]}" "${SDK_WHEELS[@]}" "${LFX_WHEELS[@]}" "${BASE_WHEELS[0]}"
948+ uv pip check --python core-test-env/bin/python
949+
950+ - name : Verify core boundary and indexed imports
951+ shell : bash
952+ run : |
953+ core-test-env/bin/python - <<'PY'
954+ import importlib
955+ import re
956+ from importlib.metadata import distributions, entry_points
957+
958+ from lfx.interface.components import _read_component_index
959+
960+ normalize = lambda value: re.sub(r"[-_.]+", "-", value).lower()
961+ installed = {normalize(dist.metadata["Name"]) for dist in distributions() if dist.metadata["Name"]}
962+ assert {"langflow-base", "langflow-sdk", "lfx"} <= installed, installed
963+ assert "langflow" not in installed, installed
964+ extensions = sorted(name for name in installed if name.startswith("lfx-"))
965+ assert not extensions, f"Extension distributions installed: {extensions}"
966+ for group in ("lfx.bundles", "langflow.extensions", "langflow.plugins"):
967+ assert not entry_points(group=group), f"Extension entry points registered in {group}"
968+
969+ index = _read_component_index()
970+ assert index is not None, "Installed LFX rejected its bundled component index"
971+ assert index["metadata"] == {"num_modules": 17, "num_components": 130}
972+ for category, components in index["entries"]:
973+ for component_name, component in components.items():
974+ module_path = component.get("metadata", {}).get("module")
975+ assert module_path, f"{category}.{component_name} has no module"
976+ module_name, class_name = module_path.rsplit(".", 1)
977+ getattr(importlib.import_module(module_name), class_name)
978+ PY
979+
980+ - name : Boot installed core server
981+ shell : bash
982+ timeout-minutes : 5
983+ run : |
984+ set -euo pipefail
985+ RUNTIME_DIR=$(mktemp -d)
986+ export LANGFLOW_CONFIG_DIR="$RUNTIME_DIR/config"
987+ export LANGFLOW_SAVE_DB_IN_CONFIG_DIR=true
988+ export LANGFLOW_AUTO_LOGIN=true
989+ export DO_NOT_TRACK=true
990+ LOG_FILE="$RUNTIME_DIR/server.log"
991+
992+ core-test-env/bin/langflow-base run \
993+ --host 127.0.0.1 --port 7861 --backend-only --workers 1 >"$LOG_FILE" 2>&1 &
994+ SERVER_PID=$!
995+ cleanup() {
996+ kill "$SERVER_PID" 2>/dev/null || true
997+ wait "$SERVER_PID" 2>/dev/null || true
998+ }
999+ trap cleanup EXIT
1000+
1001+ READY=false
1002+ for _ in $(seq 1 90); do
1003+ if curl -fsS http://127.0.0.1:7861/health_check >/dev/null 2>&1; then
1004+ READY=true
1005+ break
1006+ fi
1007+ if ! kill -0 "$SERVER_PID" 2>/dev/null; then
1008+ cat "$LOG_FILE"
1009+ exit 1
1010+ fi
1011+ sleep 2
1012+ done
1013+ if [ "$READY" != true ]; then
1014+ cat "$LOG_FILE"
1015+ exit 1
1016+ fi
1017+
1018+ curl -fsS -c "$RUNTIME_DIR/cookies" http://127.0.0.1:7861/api/v1/auto_login >/dev/null
1019+ curl -fsS --compressed -b "$RUNTIME_DIR/cookies" \
1020+ http://127.0.0.1:7861/api/v1/all >"$RUNTIME_DIR/catalog.json"
1021+ jq -e 'del(.component_display_names) | (length == 17 and ([.[] | length] | add) == 130)' \
1022+ "$RUNTIME_DIR/catalog.json"
1023+
8921024 test-summary :
8931025 name : Cross-Platform Test Summary
894- needs : [test-installation-stable, test-installation-experimental]
1026+ needs : [test-installation-stable, test-installation-experimental, test-core-runtime ]
8951027 runs-on : ubuntu-latest
8961028 if : always()
8971029 steps :
8981030 - name : Check test results
8991031 run : |
9001032 stable_result="${{ needs.test-installation-stable.result }}"
9011033 experimental_result="${{ needs.test-installation-experimental.result }}"
1034+ core_result="${{ needs.test-core-runtime.result }}"
9021035
9031036 echo "Stable platforms result: $stable_result"
9041037 echo "Experimental platforms result: $experimental_result"
1038+ echo "Core runtime result: $core_result"
1039+
1040+ if [ "${{ inputs.langflow-version }}" = "" ] && [ "$core_result" != "success" ]; then
1041+ echo "❌ Core runtime wheel test failed: $core_result"
1042+ exit 1
1043+ fi
9051044
9061045 # Stable platforms must succeed, experimental can fail
9071046 if [ "$stable_result" = "success" ]; then
0 commit comments