Skip to content

Commit 4faf518

Browse files
committed
mereg fix
2 parents 008e05b + f307634 commit 4faf518

58 files changed

Lines changed: 1446 additions & 130 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-scripts-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
python-version: "3.13"
2222

2323
- name: Install dependencies
24-
run: pip install pytest requests packaging
24+
run: pip install orjson packaging pytest requests
2525

2626
- name: Run CI script tests
2727
run: python -m pytest scripts/ci/ -v

.github/workflows/cross-platform-test.yml

Lines changed: 140 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

.github/workflows/nightly_build.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ jobs:
171171
uv lock
172172
cd src/lfx && uv lock && cd ../..
173173
174-
git add pyproject.toml src/backend/base/pyproject.toml src/lfx/pyproject.toml src/sdk/pyproject.toml uv.lock
174+
git add pyproject.toml src/backend/base/pyproject.toml src/lfx/pyproject.toml \
175+
src/lfx/src/lfx/_assets/component_index.json src/sdk/pyproject.toml uv.lock
175176
# The nightly keeps canonical package names and the stable `lfx-*` bundles
176177
# are not modified (see src/bundles/NIGHTLY.md), so no bundle pyprojects ride this commit.
177178
git commit -m "Update version for nightly"

.github/workflows/py_autofix.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ jobs:
7070
run: |
7171
git config user.name "github-actions[bot]"
7272
git config user.email "github-actions[bot]@users.noreply.github.com"
73-
git merge origin/${{ github.base_ref }} --no-edit || {
73+
git remote add upstream "${{ github.event.pull_request.base.repo.clone_url }}"
74+
git fetch --no-tags upstream "${{ github.base_ref }}"
75+
git merge upstream/${{ github.base_ref }} --no-edit || {
7476
# Check which files have conflicts
7577
CONFLICTED=$(git diff --name-only --diff-filter=U)
7678

.github/workflows/release.yml

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ jobs:
163163
exit 1
164164
fi
165165
166+
if [ "${{ inputs.release_package_base }}" = "true" ] && [ "${{ inputs.release_lfx }}" = "false" ]; then
167+
echo "Error: Cannot release Langflow Base without releasing LFX."
168+
echo "Langflow Base depends on LFX. Please enable 'release_lfx' or disable 'release_package_base'."
169+
exit 1
170+
fi
171+
166172
if [ "${{ inputs.release_lfx }}" = "true" ] && [ "${{ inputs.release_sdk }}" = "false" ]; then
167173
echo "Error: Cannot release LFX without releasing langflow-sdk."
168174
echo "LFX depends on langflow-sdk. Please enable 'release_sdk' or disable 'release_lfx'."
@@ -311,7 +317,11 @@ jobs:
311317
version="$(read_pyproject_version "$pyproject")"
312318
output_file="$tmp_dir/${package_name}-pypi.txt"
313319
fetch_pypi_versions "$package_name" "$output_file"
314-
consider_versions "PyPI ${package_name}" "$version" "$output_file"
320+
if grep -Fxq "$version" "$output_file"; then
321+
echo "PyPI ${package_name}: final ${version} is already published; excluding its historical RCs."
322+
else
323+
consider_versions "PyPI ${package_name}" "$version" "$output_file"
324+
fi
315325
done
316326
fi
317327
@@ -667,6 +677,10 @@ jobs:
667677
# Update version in lfx pyproject.toml
668678
sed -i.bak "s/^version = .*/version = \"$VERSION\"/" pyproject.toml
669679
680+
# Keep the bundled component index version/hash aligned with the RC wheel.
681+
uv run --no-sync python ../../scripts/ci/update_component_index_version.py \
682+
src/lfx/_assets/component_index.json "$VERSION"
683+
670684
# Verify the change
671685
echo "Updated pyproject.toml version:"
672686
grep "^version" pyproject.toml
@@ -801,31 +815,11 @@ jobs:
801815
run: |
802816
LFX_VERSION="${{ needs.determine-lfx-version.outputs.version }}"
803817
echo "Updating lfx dependency to allow pre-release version: $LFX_VERSION"
804-
cd src/backend/base
805-
806-
# Extract current lfx constraint from pyproject.toml
807-
CURRENT_CONSTRAINT=$(grep -E '^\s*"lfx' pyproject.toml | head -1)
808-
echo "Current constraint: $CURRENT_CONSTRAINT"
818+
python3 scripts/ci/update_lfx_pre_release_dependency.py \
819+
src/backend/base/pyproject.toml "$LFX_VERSION"
809820
810-
# Extract the major.minor version (e.g., "1.10" from "~=1.10.0", or from the
811-
# lower bound of the range form ">=1.10.0,<1.11.dev0"). Anchor to the FIRST
812-
# version in the line so a greedy match can't pick up the range's upper bound.
813-
MAJOR_MINOR=$(echo "$CURRENT_CONSTRAINT" | sed -E 's/^[^0-9]*([0-9]+\.[0-9]+).*/\1/')
814-
MAJOR=${MAJOR_MINOR%.*}
815-
MINOR=${MAJOR_MINOR#*.}
816-
NEXT_MINOR=$((MINOR + 1))
817-
818-
# Create new constraint: >=LFX_VERSION,<MAJOR.(MINOR+1).dev0
819-
NEW_CONSTRAINT="\"lfx>=$LFX_VERSION,<$MAJOR.$NEXT_MINOR.dev0\""
820-
821-
echo "New constraint: $NEW_CONSTRAINT"
822-
823-
# Replace the constraint
824-
sed -i.bak "s|\"lfx[^\"]*\"|$NEW_CONSTRAINT|" pyproject.toml
825-
826-
# Verify the change
827821
echo "Updated lfx dependency:"
828-
grep "lfx" pyproject.toml
822+
grep "lfx" src/backend/base/pyproject.toml
829823
- name: Build project for distribution
830824
run: make build base=true args="--wheel"
831825
- name: Verify built version
@@ -1049,25 +1043,49 @@ jobs:
10491043
prune-cache: false
10501044
- name: Install the project
10511045
run: uv sync
1052-
- name: Set bundle versions for pre-release
1046+
- name: Set unpublished bundle versions for pre-release
10531047
if: ${{ inputs.pre_release }}
10541048
run: |
1049+
set -euo pipefail
1050+
1051+
pypi_final_exists() {
1052+
local package_name="$1"
1053+
local version="$2"
1054+
local response_file
1055+
response_file="$(mktemp)"
1056+
local status
1057+
status=$(curl --retry 3 --retry-delay 2 --retry-connrefused -sS -o "$response_file" -w "%{http_code}" "https://pypi.org/pypi/${package_name}/${version}/json")
1058+
if [ "$status" = "200" ]; then
1059+
return 0
1060+
fi
1061+
if [ "$status" = "404" ]; then
1062+
return 1
1063+
fi
1064+
echo "Failed to check PyPI release ${package_name} ${version}: HTTP ${status}" >&2
1065+
cat "$response_file" >&2 || true
1066+
exit 1
1067+
}
1068+
10551069
RC_NUMBER="${{ needs.determine-rc-number.outputs.rc_number }}"
1056-
echo "Setting bundle pre-release versions with shared rc number: rc$RC_NUMBER"
1070+
echo "Setting unpublished bundle pre-release versions with shared rc number: rc$RC_NUMBER"
10571071
for pyproject in src/bundles/*/pyproject.toml; do
1058-
CURRENT_VERSION=$(python3 - "$pyproject" <<'PY'
1072+
read -r PACKAGE_NAME CURRENT_VERSION < <(python3 - "$pyproject" <<'PY'
10591073
import pathlib
10601074
import sys
10611075
import tomllib
10621076
10631077
data = tomllib.loads(pathlib.Path(sys.argv[1]).read_text())
1064-
print(data["project"]["version"])
1078+
print(data["project"]["name"], data["project"]["version"])
10651079
PY
10661080
)
1081+
if pypi_final_exists "$PACKAGE_NAME" "$CURRENT_VERSION"; then
1082+
echo "Keeping ${PACKAGE_NAME} at ${CURRENT_VERSION}: final version is already published."
1083+
continue
1084+
fi
10671085
VERSION=$(uv run ./scripts/ci/langflow_pre_release_tag.py "$CURRENT_VERSION" --rc-number "$RC_NUMBER")
10681086
sed -i.bak "0,/^version = /s|^version = .*|version = \"$VERSION\"|" "$pyproject"
10691087
rm -f "${pyproject}.bak"
1070-
grep "^version" "$pyproject" | sed "s|^| ${pyproject}: |"
1088+
echo "Set ${PACKAGE_NAME} to ${VERSION}."
10711089
done
10721090
- name: Relax bundle lfx floor for pre-release
10731091
if: ${{ inputs.pre_release }}

.secrets.baseline

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
"filename": ".github/workflows/nightly_build.yml",
160160
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
161161
"is_verified": false,
162-
"line_number": 308,
162+
"line_number": 309,
163163
"is_secret": false
164164
}
165165
],
@@ -169,7 +169,7 @@
169169
"filename": ".github/workflows/release.yml",
170170
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
171171
"is_verified": false,
172-
"line_number": 564,
172+
"line_number": 574,
173173
"is_secret": false
174174
}
175175
],
@@ -2433,7 +2433,7 @@
24332433
"filename": "src/backend/tests/unit/test_initial_setup.py",
24342434
"hashed_secret": "97665ff5eecf8fe96f0462b2d08ed2a2270b4277",
24352435
"is_verified": false,
2436-
"line_number": 292,
2436+
"line_number": 367,
24372437
"is_secret": false
24382438
}
24392439
],
@@ -7246,5 +7246,5 @@
72467246
}
72477247
]
72487248
},
7249-
"generated_at": "2026-07-13T20:58:07Z"
7249+
"generated_at": "2026-07-15T23:24:48Z"
72507250
}

0 commit comments

Comments
 (0)