mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-24 01:22:23 +08:00
Merge remote-tracking branch 'origin/release-1.10.1' into release-1.11.0
# Conflicts: # .secrets.baseline # pyproject.toml # src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json # src/backend/base/langflow/initial_setup/starter_projects/Structured Data Analysis Agent.json # src/backend/base/langflow/services/auth/service.py # src/backend/base/langflow/services/job_queue/service.py # src/backend/base/pyproject.toml # src/backend/tests/unit/components/models_and_agents/test_cuga_agent.py # src/backend/tests/unit/test_redis_job_queue_service.py # src/bundles/lfx-bundles/src/lfx_bundles/deepseek/deepseek.py # src/bundles/lfx-bundles/src/lfx_bundles/glean/glean_search_api.py # src/bundles/lfx-bundles/src/lfx_bundles/homeassistant/home_assistant_control.py # src/bundles/lfx-bundles/src/lfx_bundles/homeassistant/list_home_assistant_states.py # src/bundles/lfx-bundles/src/lfx_bundles/huggingface/huggingface_inference_api.py # src/bundles/lfx-bundles/src/lfx_bundles/lmstudio/lmstudioembeddings.py # src/bundles/lfx-bundles/src/lfx_bundles/xai/xai.py # src/frontend/package-lock.json # src/frontend/package.json # src/lfx/pyproject.toml # src/lfx/src/lfx/_assets/component_index.json # src/lfx/src/lfx/components/files_and_knowledge/filesystem.py # src/lfx/tests/unit/components/tools/test_filesystem_deny_list.py # uv.lock
This commit is contained in:
@ -1,39 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
ARGUMENT_NUMBER = 3
|
||||
import packaging.version
|
||||
from packaging.version import Version
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterable
|
||||
|
||||
|
||||
def create_tag(package_version: str, latest_released_version: str | None) -> str:
|
||||
# normalize optional leading 'v' and whitespace
|
||||
pkg = package_version.strip().lstrip("v")
|
||||
latest = None
|
||||
if latest_released_version is not None:
|
||||
lr = latest_released_version.strip()
|
||||
if lr != "":
|
||||
latest = lr.lstrip("v")
|
||||
def _read_released_versions(values: list[str]) -> list[str]:
|
||||
if values == ["-"]:
|
||||
return [line.strip() for line in sys.stdin if line.strip()]
|
||||
return [value.strip() for value in values if value.strip()]
|
||||
|
||||
new_pre_release_version = f"{pkg}.rc0"
|
||||
|
||||
if latest:
|
||||
# match either exact pkg or pkg.rcN (with or without dot before rc, per PEP 440 normalization)
|
||||
m = re.match(rf"^{re.escape(pkg)}\.?rc(\d+)$", latest)
|
||||
if m:
|
||||
rc_number = int(m.group(1)) + 1
|
||||
new_pre_release_version = f"{pkg}.rc{rc_number}"
|
||||
elif latest == pkg:
|
||||
new_pre_release_version = f"{pkg}.rc1"
|
||||
def next_rc_number(package_version: str, released_versions: Iterable[str]) -> int:
|
||||
base_version = Version(package_version.strip().lstrip("v")).base_version
|
||||
rc_numbers: list[int] = []
|
||||
exact_final_exists = False
|
||||
|
||||
return new_pre_release_version
|
||||
for released_version_str in released_versions:
|
||||
normalized_version_str = released_version_str.strip().lstrip("v")
|
||||
if not normalized_version_str:
|
||||
continue
|
||||
try:
|
||||
released_version = Version(normalized_version_str)
|
||||
except packaging.version.InvalidVersion:
|
||||
continue
|
||||
|
||||
if released_version.base_version != base_version:
|
||||
continue
|
||||
|
||||
if released_version.pre and released_version.pre[0] == "rc":
|
||||
rc_numbers.append(released_version.pre[1])
|
||||
elif not released_version.is_prerelease:
|
||||
exact_final_exists = True
|
||||
|
||||
if rc_numbers:
|
||||
return max(rc_numbers) + 1
|
||||
if exact_final_exists:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def create_tag(
|
||||
package_version: str,
|
||||
released_versions: Iterable[str] | str | None,
|
||||
rc_number: int | None = None,
|
||||
) -> str:
|
||||
if released_versions is None:
|
||||
versions: list[str] = []
|
||||
elif isinstance(released_versions, str):
|
||||
versions = [released_versions]
|
||||
else:
|
||||
versions = list(released_versions)
|
||||
|
||||
base_version = Version(package_version.strip().lstrip("v")).base_version
|
||||
next_rc = next_rc_number(base_version, versions)
|
||||
if rc_number is not None:
|
||||
next_rc = max(next_rc, rc_number)
|
||||
|
||||
return str(Version(f"{base_version}rc{next_rc}"))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Return the next rc pre-release for a package base version.",
|
||||
)
|
||||
parser.add_argument("package_version")
|
||||
parser.add_argument(
|
||||
"released_versions",
|
||||
nargs="*",
|
||||
help="Released versions to inspect, or '-' to read one version per line from stdin.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--rc-number",
|
||||
type=int,
|
||||
default=None,
|
||||
help="Minimum rc number to use. This lets a workflow apply one shared rc number across packages.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--print-rc-number",
|
||||
action="store_true",
|
||||
help="Print only the next rc number instead of the full version.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
released_versions = _read_released_versions(args.released_versions)
|
||||
if args.print_rc_number:
|
||||
print(next_rc_number(args.package_version, released_versions))
|
||||
else:
|
||||
print(create_tag(args.package_version, released_versions, args.rc_number))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != ARGUMENT_NUMBER:
|
||||
msg = "Specify package_version and latest_released_version (use empty string for none)."
|
||||
raise ValueError(msg)
|
||||
|
||||
package_version = sys.argv[1]
|
||||
latest_released_version = sys.argv[2]
|
||||
print(create_tag(package_version, latest_released_version))
|
||||
main()
|
||||
|
||||
73
scripts/ci/test_langflow_pre_release_tag.py
Normal file
73
scripts/ci/test_langflow_pre_release_tag.py
Normal file
@ -0,0 +1,73 @@
|
||||
"""Unit tests for langflow_pre_release_tag.py.
|
||||
|
||||
Run directly or with pytest:
|
||||
|
||||
cd scripts/ci && uv run python test_langflow_pre_release_tag.py
|
||||
cd scripts/ci && uv run python -m pytest test_langflow_pre_release_tag.py -q
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
import io
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
import langflow_pre_release_tag as pr
|
||||
|
||||
|
||||
def test_ignores_unrelated_newer_pre_release_line():
|
||||
assert pr.create_tag("1.10.1", ["1.11.0.dev15"]) == "1.10.1rc0"
|
||||
|
||||
|
||||
def test_increments_same_base_rc_with_or_without_dot():
|
||||
releases = ["1.10.1rc0", "1.10.1.rc1", "1.11.0.dev15"]
|
||||
assert pr.create_tag("1.10.1", releases) == "1.10.1rc2"
|
||||
|
||||
|
||||
def test_final_same_base_starts_at_rc1():
|
||||
assert pr.create_tag("1.10.1", ["1.10.1"]) == "1.10.1rc1"
|
||||
|
||||
|
||||
def test_shared_rc_number_floor_applies_to_other_package_base():
|
||||
assert pr.create_tag("0.10.1", [], rc_number=1) == "0.10.1rc1"
|
||||
|
||||
|
||||
def test_shared_rc_number_floor_does_not_regress_existing_higher_rc():
|
||||
assert pr.create_tag("1.10.1", ["1.10.1rc5"], rc_number=1) == "1.10.1rc6"
|
||||
|
||||
|
||||
def test_cli_reads_released_versions_from_stdin():
|
||||
output = io.StringIO()
|
||||
with (
|
||||
mock.patch.object(sys, "argv", ["langflow_pre_release_tag.py", "1.10.1", "--print-rc-number", "-"]),
|
||||
mock.patch.object(sys, "stdin", io.StringIO("1.10.1rc0\n1.11.0.dev15\n")),
|
||||
contextlib.redirect_stdout(output),
|
||||
):
|
||||
pr.main()
|
||||
assert output.getvalue().strip() == "1"
|
||||
|
||||
|
||||
def test_unparseable_versions_are_skipped():
|
||||
assert pr.create_tag("1.10.1", ["not-a-version", "1.10.1rc0"]) == "1.10.1rc1"
|
||||
|
||||
|
||||
def _main():
|
||||
failures = 0
|
||||
for name, fn in sorted(globals().items()):
|
||||
if name.startswith("test_") and callable(fn):
|
||||
try:
|
||||
fn()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
failures += 1
|
||||
print(f"FAIL {name}: {exc}")
|
||||
else:
|
||||
print(f"ok {name}")
|
||||
if failures:
|
||||
msg = f"{failures} test(s) failed."
|
||||
raise SystemExit(msg)
|
||||
print("All langflow_pre_release_tag tests passed.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
||||
Reference in New Issue
Block a user