mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-24 06:10:49 +08:00
ci: stop publishing -nightly bundle variants; release bundles on demand (#13206)
Bundles (lfx-arxiv, lfx-duckduckgo) change infrequently enough that a nightly cadence is overkill. Drop the rename-to-`-nightly` and bundle publish lanes from the nightly pipeline and add a dedicated workflow_dispatch-only release_bundles.yml for purposeful releases. - nightly_build.yml: drop update_bundle_versions.py invocation and the src/bundles/*/pyproject.toml git-add guard. - release_nightly.yml: remove build-nightly-bundles and publish-nightly-bundles jobs; untether test-cross-platform and publish-nightly-main from them. - release_bundles.yml (new): build all src/bundles/* wheels, run a cross-OS install smoke test, then publish to PyPI under their stable names. Tolerates already-published versions so re-runs without a version bump are no-ops. release.yml still owns bundle publishing as part of main releases. Manual follow-up (PyPI admin): delete the lfx-arxiv-nightly and lfx-duckduckgo-nightly projects from PyPI.
This commit is contained in:
9
.github/workflows/nightly_build.yml
vendored
9
.github/workflows/nightly_build.yml
vendored
@ -163,12 +163,6 @@ jobs:
|
||||
uv run --no-sync ./scripts/ci/update_sdk_version.py $SDK_TAG
|
||||
echo "Updating LFX project version to $LFX_TAG"
|
||||
uv run --no-sync ./scripts/ci/update_lfx_version.py $LFX_TAG $SDK_TAG
|
||||
if [ -f ./scripts/ci/update_bundle_versions.py ]; then
|
||||
echo "Renaming bundle packages to their -nightly counterparts (lfx dev suffix: $LFX_TAG)"
|
||||
uv run --no-sync ./scripts/ci/update_bundle_versions.py $LFX_TAG
|
||||
else
|
||||
echo "Skipping bundle rename: scripts/ci/update_bundle_versions.py not present on this branch"
|
||||
fi
|
||||
echo "Updating base project version to $BASE_TAG and updating main project version to $RELEASE_TAG"
|
||||
uv run --no-sync ./scripts/ci/update_pyproject_combined.py main $RELEASE_TAG $BASE_TAG $LFX_TAG
|
||||
|
||||
@ -177,9 +171,6 @@ jobs:
|
||||
cd src/lfx && uv lock && cd ../..
|
||||
|
||||
git add pyproject.toml src/backend/base/pyproject.toml src/lfx/pyproject.toml src/sdk/pyproject.toml uv.lock src/backend/base/uv.lock
|
||||
if compgen -G "src/bundles/*/pyproject.toml" > /dev/null; then
|
||||
git add src/bundles/*/pyproject.toml
|
||||
fi
|
||||
git commit -m "Update version and project name"
|
||||
|
||||
echo "Tagging main with $RELEASE_TAG"
|
||||
|
||||
189
.github/workflows/release_bundles.yml
vendored
Normal file
189
.github/workflows/release_bundles.yml
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
name: Release Bundles
|
||||
|
||||
# Manually-triggered workflow for publishing stable `lfx-<name>` bundle wheels
|
||||
# from src/bundles/* to PyPI. Bundles change infrequently, so we release them
|
||||
# on demand rather than on a schedule. Re-running the workflow without a
|
||||
# version bump is a no-op (PyPI rejects the duplicate upload and we tolerate
|
||||
# the conflict).
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
description: "Git ref to build from (branch, tag, or SHA). Defaults to the workflow's checked-out ref."
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
dry_run:
|
||||
description: "Build and test only; skip the PyPI publish step."
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: "3.13"
|
||||
|
||||
jobs:
|
||||
build-bundles:
|
||||
name: Build Langflow Bundles
|
||||
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 || github.ref }}
|
||||
- name: Setup Environment
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
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-install:
|
||||
name: Install Smoke Test - ${{ matrix.os }} ${{ matrix.python-version }}
|
||||
needs: [build-bundles]
|
||||
if: needs.build-bundles.outputs.bundles-found == '1'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
runner: ubuntu-latest
|
||||
python-version: "3.10"
|
||||
- os: linux
|
||||
runner: ubuntu-latest
|
||||
python-version: "3.12"
|
||||
- os: macos
|
||||
runner: macos-latest
|
||||
python-version: "3.12"
|
||||
- os: windows
|
||||
runner: windows-latest
|
||||
python-version: "3.12"
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Setup UV
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
enable-cache: false
|
||||
ignore-empty-workdir: true
|
||||
- name: Download bundles artifact
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: dist-bundles
|
||||
path: ./bundles-dist
|
||||
- name: Create fresh virtual environment
|
||||
run: uv venv test-env --seed
|
||||
shell: bash
|
||||
- name: Install bundle wheels (Unix)
|
||||
if: matrix.os != 'windows'
|
||||
run: |
|
||||
shopt -s nullglob
|
||||
BUNDLE_WHEELS=(./bundles-dist/*.whl)
|
||||
if [ ${#BUNDLE_WHEELS[@]} -eq 0 ]; then
|
||||
echo "No bundle wheels found in ./bundles-dist/"
|
||||
exit 1
|
||||
fi
|
||||
printf 'Installing: %s\n' "${BUNDLE_WHEELS[@]}"
|
||||
uv pip install --prerelease=allow --python ./test-env/bin/python "${BUNDLE_WHEELS[@]}"
|
||||
shell: bash
|
||||
- name: Install bundle wheels (Windows)
|
||||
if: matrix.os == 'windows'
|
||||
run: |
|
||||
shopt -s nullglob
|
||||
BUNDLE_WHEELS=(./bundles-dist/*.whl)
|
||||
if [ ${#BUNDLE_WHEELS[@]} -eq 0 ]; then
|
||||
echo "No bundle wheels found in ./bundles-dist/"
|
||||
exit 1
|
||||
fi
|
||||
printf 'Installing: %s\n' "${BUNDLE_WHEELS[@]}"
|
||||
uv pip install --prerelease=allow --python ./test-env/Scripts/python.exe "${BUNDLE_WHEELS[@]}"
|
||||
shell: bash
|
||||
|
||||
publish-bundles:
|
||||
name: Publish Bundles to PyPI
|
||||
needs: [build-bundles, test-install]
|
||||
if: |
|
||||
always() &&
|
||||
!cancelled() &&
|
||||
!inputs.dry_run &&
|
||||
needs.build-bundles.result == 'success' &&
|
||||
needs.build-bundles.outputs.bundles-found == '1' &&
|
||||
needs.test-install.result == 'success'
|
||||
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: ${{ env.PYTHON_VERSION }}
|
||||
- name: Publish bundles to PyPI
|
||||
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
|
||||
failed=0
|
||||
for wheel in "${wheels[@]}"; do
|
||||
echo "Publishing $wheel"
|
||||
# Capture stderr so we can tolerate "already exists" without failing
|
||||
# the whole run — re-running this workflow without bumping a bundle
|
||||
# version should be a no-op for that bundle.
|
||||
if ! err=$(uv publish "$wheel" 2>&1); then
|
||||
echo "$err"
|
||||
if echo "$err" | grep -qiE 'already exists|file already exists|HTTP 400|duplicate'; then
|
||||
echo "Skipping $wheel: already published."
|
||||
else
|
||||
echo "Publish failed for $wheel"
|
||||
failed=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$failed" = "1" ]; then
|
||||
exit 1
|
||||
fi
|
||||
95
.github/workflows/release_nightly.yml
vendored
95
.github/workflows/release_nightly.yml
vendored
@ -339,67 +339,15 @@ jobs:
|
||||
name: dist-nightly-main
|
||||
path: dist
|
||||
|
||||
build-nightly-bundles:
|
||||
name: Build Langflow Nightly Bundles
|
||||
needs: [build-nightly-lfx]
|
||||
if: ${{ always() && (needs.build-nightly-lfx.result == 'success' || inputs.build_lfx == false) }}
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
outputs:
|
||||
bundles-found: ${{ steps.build.outputs.bundles-found }}
|
||||
steps:
|
||||
- name: Check out the code at a specific ref
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.nightly_tag_release }}
|
||||
persist-credentials: true
|
||||
- name: "Setup Environment"
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
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-nightly-bundles
|
||||
path: bundles-dist
|
||||
|
||||
test-cross-platform:
|
||||
name: Test Cross-Platform Installation
|
||||
needs: [build-nightly-lfx, build-nightly-base, build-nightly-main, build-nightly-bundles]
|
||||
needs: [build-nightly-lfx, build-nightly-base, build-nightly-main]
|
||||
uses: ./.github/workflows/cross-platform-test.yml
|
||||
with:
|
||||
base-artifact-name: "dist-nightly-base"
|
||||
main-artifact-name: "dist-nightly-main"
|
||||
lfx-artifact-name: "dist-nightly-lfx"
|
||||
sdk-artifact-name: "dist-nightly-sdk"
|
||||
bundles-artifact-name: ${{ needs.build-nightly-bundles.outputs.bundles-found == '1' && 'dist-nightly-bundles' || '' }}
|
||||
|
||||
publish-nightly-lfx:
|
||||
name: Publish LFX Nightly to PyPI
|
||||
@ -486,47 +434,10 @@ jobs:
|
||||
run: |
|
||||
make publish base=true
|
||||
|
||||
publish-nightly-bundles:
|
||||
name: Publish Bundle Nightlies to PyPI
|
||||
needs: [build-nightly-bundles, test-cross-platform, publish-nightly-lfx]
|
||||
if: ${{ always() && needs.build-nightly-bundles.result == 'success' && needs.build-nightly-bundles.outputs.bundles-found == '1' && needs.test-cross-platform.result == 'success' && (needs.publish-nightly-lfx.result == 'success' || inputs.build_lfx == false) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.nightly_tag_release }}
|
||||
persist-credentials: true
|
||||
- name: Download bundles artifact
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: dist-nightly-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
|
||||
env:
|
||||
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }}
|
||||
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-nightly-main:
|
||||
name: Publish Langflow Main Nightly to PyPI
|
||||
needs: [build-nightly-main, test-cross-platform, publish-nightly-base, publish-nightly-bundles]
|
||||
if: ${{ always() && needs.build-nightly-main.result == 'success' && needs.test-cross-platform.result == 'success' && needs.publish-nightly-base.result == 'success' && (needs.publish-nightly-bundles.result == 'success' || needs.publish-nightly-bundles.result == 'skipped') }}
|
||||
needs: [build-nightly-main, test-cross-platform, publish-nightly-base]
|
||||
if: ${{ always() && needs.build-nightly-main.result == 'success' && needs.test-cross-platform.result == 'success' && needs.publish-nightly-base.result == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
||||
@ -187,7 +187,7 @@
|
||||
"filename": ".github/workflows/nightly_build.yml",
|
||||
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
|
||||
"is_verified": false,
|
||||
"line_number": 306,
|
||||
"line_number": 297,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
@ -207,7 +207,7 @@
|
||||
"filename": ".github/workflows/release_nightly.yml",
|
||||
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
|
||||
"is_verified": false,
|
||||
"line_number": 473,
|
||||
"line_number": 474,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
@ -8287,5 +8287,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"generated_at": "2026-05-19T01:41:00Z"
|
||||
"generated_at": "2026-05-19T16:19:23Z"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user