mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-23 18:57:09 +08:00
ci: sync workflow fixes from main into release-1.10.0 (fix broken nightly) (#13400)
ci: sync workflow fixes from main into release-1.10.0 Brings the latest CI/workflow fixes from main into release-1.10.0 so the nightly build is unblocked and the two branches share the same hardening. Most important fix: release_nightly.yml's "Verify Nightly Name and Version" step now uses the anchored grep '^langflow(-nightly)?[[:space:]]' instead of 'grep langflow | grep -v langflow-base | grep -v langflow-sdk'. The old filter started matching two packages once the langflow-stepflow workspace package was added, so the name became multi-line and the check failed (this is what broke the nightly build). Also carries main's fixes for cross-platform install (--prerelease=if-necessary-or-explicit), docker build workflows, db-migration-validation, and the backend test timeout bump (30 -> 40). 3-way merged from the common ancestor, so release-only changes are preserved; no release-only feature workflows are modified.
This commit is contained in:
18
.github/workflows/cross-platform-test.yml
vendored
18
.github/workflows/cross-platform-test.yml
vendored
@ -293,7 +293,12 @@ jobs:
|
||||
printf 'Installing %s wheel(s):\n' "$label"
|
||||
printf '%s\n' "$@"
|
||||
refresh_find_links
|
||||
uv pip install --prerelease=allow --python "$PYTHON" "${FIND_LINKS[@]}" "$@"
|
||||
# Use `if-necessary-or-explicit` (not `allow`): nightly langflow* wheels
|
||||
# are .dev pre-releases so we need to allow them explicitly, but `allow`
|
||||
# leaks to transitive deps and resolves pre-release pydantic alphas
|
||||
# (e.g. 2.14.0a1) which break langchain-core's module-level
|
||||
# `RunnablePassthrough()` call at import time.
|
||||
uv pip install --prerelease=if-necessary-or-explicit --python "$PYTHON" "${FIND_LINKS[@]}" "$@"
|
||||
}
|
||||
|
||||
SDK_WHEELS=(./sdk-dist/*.whl)
|
||||
@ -581,7 +586,8 @@ jobs:
|
||||
printf 'Installing %s wheel(s):\n' "$label"
|
||||
printf '%s\n' "$@"
|
||||
refresh_find_links
|
||||
uv pip install --prerelease=allow --python "$PYTHON" "${FIND_LINKS[@]}" "$@"
|
||||
# See stable job above for rationale on --prerelease=if-necessary-or-explicit.
|
||||
uv pip install --prerelease=if-necessary-or-explicit --python "$PYTHON" "${FIND_LINKS[@]}" "$@"
|
||||
}
|
||||
|
||||
SDK_WHEELS=(./sdk-dist/*.whl)
|
||||
@ -631,7 +637,7 @@ jobs:
|
||||
if [ "${{ inputs.pre_release }}" = "true" ]; then
|
||||
NO_DEPS=""
|
||||
fi
|
||||
uv pip install --force-reinstall $NO_DEPS --prerelease=allow --python ./test-env/Scripts/python.exe "${INSTALL_WHEELS[@]}"
|
||||
uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit --python ./test-env/Scripts/python.exe "${INSTALL_WHEELS[@]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -643,7 +649,7 @@ jobs:
|
||||
if [ "${{ inputs.pre_release }}" = "true" ]; then
|
||||
NO_DEPS=""
|
||||
fi
|
||||
uv pip install --force-reinstall $NO_DEPS --prerelease=allow --python ./test-env/Scripts/python.exe "$BASE_WHEEL"
|
||||
uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit --python ./test-env/Scripts/python.exe "$BASE_WHEEL"
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
@ -668,7 +674,7 @@ jobs:
|
||||
if [ "${{ inputs.pre_release }}" = "true" ]; then
|
||||
NO_DEPS=""
|
||||
fi
|
||||
uv pip install --force-reinstall $NO_DEPS --prerelease=allow --python ./test-env/bin/python "${INSTALL_WHEELS[@]}"
|
||||
uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit --python ./test-env/bin/python "${INSTALL_WHEELS[@]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -680,7 +686,7 @@ jobs:
|
||||
if [ "${{ inputs.pre_release }}" = "true" ]; then
|
||||
NO_DEPS=""
|
||||
fi
|
||||
uv pip install --force-reinstall $NO_DEPS --prerelease=allow --python ./test-env/bin/python "$BASE_WHEEL"
|
||||
uv pip install --force-reinstall $NO_DEPS --prerelease=if-necessary-or-explicit --python ./test-env/bin/python "$BASE_WHEEL"
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
|
||||
@ -302,7 +302,7 @@ jobs:
|
||||
|
||||
- name: Create Docker Compose file for stable
|
||||
working-directory: docker-migration-test
|
||||
run: |
|
||||
run: | # pragma: allowlist secret
|
||||
cat > docker-compose.yml <<'EOF'
|
||||
services:
|
||||
langflow:
|
||||
|
||||
4
.github/workflows/docker-build-v2.yml
vendored
4
.github/workflows/docker-build-v2.yml
vendored
@ -124,7 +124,7 @@ jobs:
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | grep -v '^langflow-sdk' | cut -d' ' -f2 | sed 's/^v//')
|
||||
version=$(uv tree 2>/dev/null | grep -E '^langflow(-nightly)?[[:space:]]' | cut -d' ' -f2 | sed 's/^v//')
|
||||
echo "Main version from pyproject.toml: $version"
|
||||
|
||||
if [ ${{inputs.pre_release}} == "true" ]; then
|
||||
@ -604,7 +604,7 @@ jobs:
|
||||
if [[ "${{ inputs.release_type }}" == "base" ]]; then
|
||||
version=$(uv tree 2>/dev/null | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 1)
|
||||
else
|
||||
version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | grep -v '^langflow-sdk' | cut -d' ' -f2 | sed 's/^v//')
|
||||
version=$(uv tree 2>/dev/null | grep -E '^langflow(-nightly)?[[:space:]]' | cut -d' ' -f2 | sed 's/^v//')
|
||||
fi
|
||||
echo "Using version: $version"
|
||||
echo version=$version >> $GITHUB_OUTPUT
|
||||
|
||||
2
.github/workflows/docker-build.yml
vendored
2
.github/workflows/docker-build.yml
vendored
@ -150,7 +150,7 @@ jobs:
|
||||
if: ${{ inputs.main_version == '' && (inputs.release_type == 'main' || inputs.release_type == 'main-ep' || inputs.release_type == 'nightly-main' || inputs.release_type == 'main-all' || inputs.release_type == 'nightly-main-all') }}
|
||||
id: get-version-main
|
||||
run: |
|
||||
version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | grep -v 'langflow-sdk' | awk '{print $2}' | sed 's/^v//')
|
||||
version=$(uv tree | grep -E '^langflow(-nightly)?[[:space:]]' | awk '{print $2}' | sed 's/^v//')
|
||||
echo version=$version
|
||||
echo version=$version >> $GITHUB_OUTPUT
|
||||
setup:
|
||||
|
||||
6
.github/workflows/docker-nightly-build.yml
vendored
6
.github/workflows/docker-nightly-build.yml
vendored
@ -168,7 +168,7 @@ jobs:
|
||||
id: version
|
||||
run: |
|
||||
echo "Extracting main version from pyproject.toml"
|
||||
version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | grep -v '^langflow-sdk' | cut -d' ' -f2 | sed 's/^v//')
|
||||
version=$(uv tree 2>/dev/null | grep -E '^langflow(-nightly)?[[:space:]]' | cut -d' ' -f2 | sed 's/^v//')
|
||||
|
||||
# Verify nightly tag format
|
||||
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$ ]]; then
|
||||
@ -263,7 +263,7 @@ jobs:
|
||||
id: version
|
||||
run: |
|
||||
echo "Extracting main version from pyproject.toml"
|
||||
version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | grep -v '^langflow-sdk' | cut -d' ' -f2 | sed 's/^v//')
|
||||
version=$(uv tree 2>/dev/null | grep -E '^langflow(-nightly)?[[:space:]]' | cut -d' ' -f2 | sed 's/^v//')
|
||||
|
||||
# Verify nightly tag format
|
||||
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$ ]]; then
|
||||
@ -353,7 +353,7 @@ jobs:
|
||||
if [[ "${{ inputs.release_type }}" == "nightly-base" ]]; then
|
||||
version=$(uv tree 2>/dev/null | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 1)
|
||||
else
|
||||
version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | grep -v '^langflow-sdk' | cut -d' ' -f2 | sed 's/^v//')
|
||||
version=$(uv tree 2>/dev/null | grep -E '^langflow(-nightly)?[[:space:]]' | cut -d' ' -f2 | sed 's/^v//')
|
||||
fi
|
||||
echo "Using version: $version"
|
||||
echo version=$version >> $GITHUB_OUTPUT
|
||||
|
||||
2
.github/workflows/nightly_build.yml
vendored
2
.github/workflows/nightly_build.yml
vendored
@ -283,7 +283,7 @@ jobs:
|
||||
# ref: ${{ needs.create-nightly-tag.outputs.tag }}
|
||||
|
||||
release-nightly-build:
|
||||
if: github.repository == 'langflow-ai/langflow' && always() && needs.frontend-tests-linux.result != 'failure' && needs.backend-unit-tests.result != 'failure'
|
||||
if: github.repository == 'langflow-ai/langflow' && always() && needs.create-nightly-tag.result == 'success' && needs.frontend-tests-linux.result != 'failure' && needs.backend-unit-tests.result != 'failure'
|
||||
name: Run Nightly Langflow Build
|
||||
needs:
|
||||
[validate-inputs, create-nightly-tag, frontend-tests-linux, frontend-tests-windows, backend-unit-tests]
|
||||
|
||||
2
.github/workflows/python_test.yml
vendored
2
.github/workflows/python_test.yml
vendored
@ -93,7 +93,7 @@ jobs:
|
||||
- name: Run unit tests
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
timeout_minutes: 40
|
||||
max_attempts: 2
|
||||
command: make unit_tests args="-x -vv --splits ${{ matrix.splitCount }} --group ${{ matrix.group }} --reruns 5 --cov --cov-config=src/backend/.coveragerc --cov-report=xml --cov-report=html"
|
||||
|
||||
|
||||
123
.github/workflows/release.yml
vendored
123
.github/workflows/release.yml
vendored
@ -28,6 +28,11 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
release_bundles:
|
||||
description: "Release every src/bundles/* package (required when releasing main, since main pins exact bundle versions)"
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
build_docker_base:
|
||||
description: "Build Docker Image for Langflow Base"
|
||||
required: true
|
||||
@ -71,6 +76,7 @@ jobs:
|
||||
echo "release_package_main: ${{ inputs.release_package_main }}"
|
||||
echo "release_lfx: ${{ inputs.release_lfx }}"
|
||||
echo "release_sdk: ${{ inputs.release_sdk }}"
|
||||
echo "release_bundles: ${{ inputs.release_bundles }}"
|
||||
echo "build_docker_base: ${{ inputs.build_docker_base }}"
|
||||
echo "build_docker_main: ${{ inputs.build_docker_main }}"
|
||||
echo "pre_release: ${{ inputs.pre_release }}"
|
||||
@ -163,6 +169,12 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.release_package_main }}" = "true" ] && [ "${{ inputs.release_bundles }}" = "false" ]; then
|
||||
echo "Error: Cannot release Langflow Main without releasing bundles."
|
||||
echo "Langflow Main pins exact bundle versions (lfx-arxiv, lfx-duckduckgo, ...). Please enable 'release_bundles' or disable 'release_package_main'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Release dependencies validated successfully."
|
||||
|
||||
determine-base-version:
|
||||
@ -245,7 +257,7 @@ jobs:
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | grep -v 'langflow-sdk' | awk '{print $2}' | sed 's/^v//')
|
||||
version=$(uv tree | grep -E '^langflow(-nightly)?[[:space:]]' | awk '{print $2}' | sed 's/^v//')
|
||||
echo "Main version from pyproject.toml: $version"
|
||||
|
||||
if [ ${{inputs.pre_release}} == "true" ]; then
|
||||
@ -844,9 +856,63 @@ jobs:
|
||||
name: dist-main
|
||||
path: dist
|
||||
|
||||
build-bundles:
|
||||
name: Build Langflow Bundles
|
||||
needs: [build-lfx, determine-lfx-version]
|
||||
if: |
|
||||
always() &&
|
||||
!cancelled() &&
|
||||
inputs.release_bundles &&
|
||||
needs.build-lfx.result == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
outputs:
|
||||
bundles-found: ${{ steps.build.outputs.bundles-found }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.release_tag }}
|
||||
- name: Setup Environment
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
python-version: "3.13"
|
||||
prune-cache: false
|
||||
- name: Install the project
|
||||
run: uv sync
|
||||
- name: Build bundle wheels
|
||||
id: build
|
||||
run: |
|
||||
shopt -s nullglob
|
||||
bundles=(src/bundles/*/pyproject.toml)
|
||||
if [ ${#bundles[@]} -eq 0 ]; then
|
||||
echo "No bundles found under src/bundles/*/"
|
||||
echo "bundles-found=0" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
mkdir -p bundles-dist
|
||||
BUNDLES_DIST="$PWD/bundles-dist"
|
||||
for bundle_pyproject in "${bundles[@]}"; do
|
||||
bundle_dir=$(dirname "$bundle_pyproject")
|
||||
echo "Building wheel for $bundle_dir"
|
||||
(cd "$bundle_dir" && uv build --wheel --out-dir "$BUNDLES_DIST")
|
||||
done
|
||||
echo "bundles-found=1" >> $GITHUB_OUTPUT
|
||||
ls -la bundles-dist/
|
||||
- name: Upload bundles artifact
|
||||
if: steps.build.outputs.bundles-found == '1'
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: dist-bundles
|
||||
path: bundles-dist
|
||||
|
||||
test-cross-platform:
|
||||
name: Test Cross-Platform Installation
|
||||
needs: [build-base, build-main, build-lfx, build-sdk]
|
||||
needs: [build-base, build-main, build-lfx, build-sdk, build-bundles]
|
||||
if: |
|
||||
always() &&
|
||||
!cancelled() &&
|
||||
@ -857,6 +923,7 @@ jobs:
|
||||
main-artifact-name: "dist-main"
|
||||
lfx-artifact-name: "dist-lfx"
|
||||
sdk-artifact-name: ${{ needs.build-sdk.result == 'success' && 'dist-sdk' || '' }}
|
||||
bundles-artifact-name: ${{ needs.build-bundles.result == 'success' && needs.build-bundles.outputs.bundles-found == '1' && 'dist-bundles' || '' }}
|
||||
pre_release: ${{ inputs.pre_release }}
|
||||
|
||||
publish-base:
|
||||
@ -889,10 +956,58 @@ jobs:
|
||||
run: |
|
||||
cd src/backend/base && uv publish dist/*.whl
|
||||
|
||||
publish-bundles:
|
||||
name: Publish Bundles to PyPI
|
||||
needs: [build-bundles, test-cross-platform, ci, publish-lfx]
|
||||
if: |
|
||||
always() &&
|
||||
!cancelled() &&
|
||||
inputs.release_bundles &&
|
||||
needs.build-bundles.result == 'success' &&
|
||||
needs.build-bundles.outputs.bundles-found == '1' &&
|
||||
needs.test-cross-platform.result == 'success' &&
|
||||
needs.ci.result == 'success' &&
|
||||
(needs.publish-lfx.result == 'success' || needs.publish-lfx.result == 'skipped')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download bundles artifact
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: dist-bundles
|
||||
path: bundles-dist
|
||||
- name: Setup Environment
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
enable-cache: false
|
||||
python-version: "3.13"
|
||||
- name: Publish bundles to PyPI
|
||||
if: ${{ !inputs.dry_run }}
|
||||
env:
|
||||
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
||||
run: |
|
||||
shopt -s nullglob
|
||||
wheels=(bundles-dist/*.whl)
|
||||
if [ ${#wheels[@]} -eq 0 ]; then
|
||||
echo "No bundle wheels to publish."
|
||||
exit 0
|
||||
fi
|
||||
for wheel in "${wheels[@]}"; do
|
||||
echo "Publishing $wheel"
|
||||
uv publish "$wheel"
|
||||
done
|
||||
|
||||
publish-main:
|
||||
name: Publish Langflow Main to PyPI
|
||||
if: ${{ inputs.release_package_main }}
|
||||
needs: [build-main, test-cross-platform, publish-base, ci]
|
||||
if: |
|
||||
always() &&
|
||||
!cancelled() &&
|
||||
inputs.release_package_main &&
|
||||
needs.build-main.result == 'success' &&
|
||||
needs.test-cross-platform.result == 'success' &&
|
||||
needs.publish-base.result == 'success' &&
|
||||
needs.ci.result == 'success' &&
|
||||
(needs.publish-bundles.result == 'success' || needs.publish-bundles.result == 'skipped')
|
||||
needs: [build-main, test-cross-platform, publish-base, publish-bundles, ci]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download main artifact
|
||||
|
||||
7
.github/workflows/release_nightly.yml
vendored
7
.github/workflows/release_nightly.yml
vendored
@ -194,15 +194,18 @@ jobs:
|
||||
name_without_extras=$(echo $name | sed 's/\[.*\]//')
|
||||
if [ "$name_without_extras" != "langflow-base-nightly" ]; then
|
||||
echo "Name $name_without_extras does not match langflow-base-nightly. Exiting the workflow."
|
||||
echo "skipped=true" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
if [ "$version" != "${{ inputs.nightly_tag_base }}" ]; then
|
||||
echo "Version $version does not match nightly tag ${{ inputs.nightly_tag_base }}. Exiting the workflow."
|
||||
echo "skipped=true" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
# Strip the leading `v` from the version
|
||||
version=$(echo $version | sed 's/^v//')
|
||||
echo "version=$version" >> $GITHUB_OUTPUT
|
||||
echo "skipped=false" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build Langflow Base for distribution
|
||||
run: |
|
||||
@ -294,8 +297,8 @@ jobs:
|
||||
- name: Verify Nightly Name and Version
|
||||
id: verify
|
||||
run: |
|
||||
name=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | grep -v 'langflow-sdk' | awk '{print $1}')
|
||||
version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | grep -v 'langflow-sdk' | awk '{print $2}')
|
||||
name=$(uv tree | grep -E '^langflow(-nightly)?[[:space:]]' | awk '{print $1}')
|
||||
version=$(uv tree | grep -E '^langflow(-nightly)?[[:space:]]' | awk '{print $2}')
|
||||
if [ "$name" != "langflow-nightly" ]; then
|
||||
echo "Name $name does not match langflow-nightly. Exiting the workflow."
|
||||
exit 1
|
||||
|
||||
@ -127,22 +127,6 @@
|
||||
}
|
||||
],
|
||||
"results": {
|
||||
".github/workflows/db-migration-validation.yml": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": ".github/workflows/db-migration-validation.yml",
|
||||
"hashed_secret": "86267c394a92ee1c619541c3e399bb0ef3c461a9",
|
||||
"is_verified": false,
|
||||
"line_number": 305
|
||||
},
|
||||
{
|
||||
"type": "Basic Auth Credentials",
|
||||
"filename": ".github/workflows/db-migration-validation.yml",
|
||||
"hashed_secret": "e80c4f90316c87b6b24d03890493c8d1c7c1c99d",
|
||||
"is_verified": false,
|
||||
"line_number": 305
|
||||
}
|
||||
],
|
||||
".github/workflows/nightly_build.yml": [
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
@ -159,7 +143,7 @@
|
||||
"filename": ".github/workflows/release.yml",
|
||||
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
|
||||
"is_verified": false,
|
||||
"line_number": 391,
|
||||
"line_number": 403,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
@ -169,7 +153,7 @@
|
||||
"filename": ".github/workflows/release_nightly.yml",
|
||||
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
|
||||
"is_verified": false,
|
||||
"line_number": 512,
|
||||
"line_number": 515,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
@ -9297,5 +9281,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"generated_at": "2026-05-28T15:17:56Z"
|
||||
"generated_at": "2026-05-28T22:21:26Z"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user