mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-24 02:05:11 +08:00
fix(ci): resolve validate-version output in release-lfx changelog link
The create-release job references
needs.validate-version.outputs.current_version in its generated release
notes (the Full Changelog compare link), but validate-version was not in
the job's needs array, so the expression evaluated empty and the link
rendered as compare/v...lfx-vX.Y.Z (broken base).
Add validate-version to the create-release needs. This adds no real
serialization: create-release already waits on release-lfx, which
transitively requires validate-version via run-tests, and the job's
always() if-condition is unaffected.
Flagged by actionlint: property "validate-version" is not defined in
object type {build-docker, release-lfx}.
406 lines
13 KiB
YAML
406 lines
13 KiB
YAML
name: LFX Release
|
|
run-name: LFX Release ${{ github.event.inputs.version || 'dev' }} by @${{ github.actor }}
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: "Version to release (e.g., 0.1.0)"
|
|
required: true
|
|
type: string
|
|
publish_pypi:
|
|
description: "Publish to PyPI"
|
|
required: true
|
|
type: boolean
|
|
default: true
|
|
build_docker:
|
|
description: "Build and publish Docker images"
|
|
required: true
|
|
type: boolean
|
|
default: true
|
|
pre_release:
|
|
description: "Mark as pre-release"
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
create_github_release:
|
|
description: "Create GitHub release"
|
|
required: true
|
|
type: boolean
|
|
default: true
|
|
|
|
env:
|
|
PYTHON_VERSION: "3.13"
|
|
|
|
permissions:
|
|
contents: write
|
|
packages: write
|
|
|
|
jobs:
|
|
validate-version:
|
|
name: Validate Version
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
should_release: ${{ steps.check.outputs.should_release }}
|
|
current_version: ${{ steps.check.outputs.current_version }}
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- 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: Check version
|
|
id: check
|
|
run: |
|
|
cd src/lfx
|
|
# Use uv tree to get package info, consistent with nightly workflow
|
|
name=$(uv tree | grep 'lfx' | head -n 1 | awk '{print $1}')
|
|
version=$(uv tree | grep 'lfx' | head -n 1 | awk '{print $2}')
|
|
|
|
# Strip leading 'v' if present
|
|
version=$(echo $version | sed 's/^v//')
|
|
echo "current_version=$version" >> $GITHUB_OUTPUT
|
|
|
|
if [ "$version" != "${{ github.event.inputs.version }}" ]; then
|
|
echo "❌ Version mismatch: package has $version but input is ${{ github.event.inputs.version }}"
|
|
echo "Please update the version in pyproject.toml first"
|
|
echo "should_release=false" >> $GITHUB_OUTPUT
|
|
exit 1
|
|
fi
|
|
|
|
# Check if version already exists on PyPI
|
|
if curl -s "https://pypi.org/pypi/lfx/json" | jq -r '.releases | keys[]' | grep -q "^${{ github.event.inputs.version }}$"; then
|
|
echo "❌ Version ${{ github.event.inputs.version }} already exists on PyPI"
|
|
echo "should_release=false" >> $GITHUB_OUTPUT
|
|
exit 1
|
|
fi
|
|
|
|
echo "✅ Version ${{ github.event.inputs.version }} is valid and not yet released"
|
|
echo "should_release=true" >> $GITHUB_OUTPUT
|
|
|
|
run-tests:
|
|
name: Run Tests
|
|
needs: validate-version
|
|
if: needs.validate-version.outputs.should_release == 'true'
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Setup Environment
|
|
uses: astral-sh/setup-uv@v6
|
|
with:
|
|
enable-cache: true
|
|
cache-dependency-glob: "uv.lock"
|
|
python-version: ${{ matrix.python-version }}
|
|
prune-cache: false
|
|
|
|
- name: Run LFX tests
|
|
run: |
|
|
cd src/lfx
|
|
make test
|
|
|
|
- name: Test CLI installation
|
|
run: |
|
|
cd src/lfx
|
|
uv pip install .
|
|
uv run lfx --help
|
|
uv run lfx run --help
|
|
uv run lfx serve --help
|
|
|
|
release-lfx:
|
|
name: Build and Release LFX
|
|
needs: [validate-version, run-tests]
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
version: ${{ steps.check-version.outputs.version }}
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- 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 LFX dependencies
|
|
run: uv sync --dev --package lfx
|
|
|
|
- name: Verify Version
|
|
id: check-version
|
|
run: |
|
|
cd src/lfx
|
|
# Use uv tree to get package info, consistent with nightly workflow
|
|
name=$(uv tree | grep 'lfx' | head -n 1 | awk '{print $1}')
|
|
version=$(uv tree | grep 'lfx' | head -n 1 | awk '{print $2}')
|
|
|
|
# Verify package name
|
|
if [ "$name" != "lfx" ]; then
|
|
echo "Package name $name does not match lfx. Exiting the workflow."
|
|
exit 1
|
|
fi
|
|
|
|
# Strip leading 'v' if present
|
|
version=$(echo $version | sed 's/^v//')
|
|
|
|
# Verify version matches input
|
|
if [ "$version" != "${{ github.event.inputs.version }}" ]; then
|
|
echo "Version $version does not match input ${{ github.event.inputs.version }}. Exiting the workflow."
|
|
exit 1
|
|
fi
|
|
|
|
echo "version=$version" >> $GITHUB_OUTPUT
|
|
|
|
- name: Build distribution
|
|
run: |
|
|
cd src/lfx
|
|
rm -rf dist/
|
|
uv build --wheel --out-dir dist
|
|
|
|
- name: Check build artifacts
|
|
run: |
|
|
cd src/lfx
|
|
ls -la dist/
|
|
# Verify wheel contents
|
|
unzip -l dist/*.whl | grep -E "(lfx/__main__.py|lfx/cli/run.py|lfx/cli/commands.py)"
|
|
|
|
- name: Test installation from wheel
|
|
run: |
|
|
cd src/lfx
|
|
uv pip install dist/*.whl --force-reinstall
|
|
uv run lfx --help
|
|
echo "LFX CLI test completed successfully"
|
|
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: lfx-dist
|
|
path: src/lfx/dist/
|
|
retention-days: 5
|
|
|
|
- name: Publish to PyPI
|
|
if: github.event.inputs.publish_pypi == 'true'
|
|
env:
|
|
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
run: |
|
|
cd src/lfx
|
|
uv publish dist/*.whl
|
|
|
|
build-docker:
|
|
name: Build Docker Images
|
|
needs: [validate-version, run-tests]
|
|
if: github.event.inputs.build_docker == 'true'
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
variant: [production, alpine]
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Set up QEMU
|
|
uses: docker/setup-qemu-action@v3
|
|
|
|
- name: Docker System Info and Cleanup
|
|
run: |
|
|
echo "=== Docker System Usage Before Cleanup ==="
|
|
docker system df || true
|
|
docker buildx du || true
|
|
|
|
echo "=== Cleaning up Docker System ==="
|
|
docker system prune -af --volumes || true
|
|
docker buildx prune -af || true
|
|
|
|
echo "=== Docker System Usage After Cleanup ==="
|
|
docker system df || true
|
|
docker buildx du || true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@v3
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
- name: Login to GitHub Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Prepare Docker metadata
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: |
|
|
langflowai/lfx
|
|
ghcr.io/langflow-ai/lfx
|
|
tags: |
|
|
type=raw,value=${{ github.event.inputs.version }}${{ matrix.variant == 'alpine' && '-alpine' || '' }}
|
|
type=raw,value=latest${{ matrix.variant == 'alpine' && '-alpine' || '' }},enable=${{ github.event.inputs.pre_release == 'false' }}
|
|
labels: |
|
|
org.opencontainers.image.title=LFX
|
|
org.opencontainers.image.description=Langflow Executor - CLI tool for running Langflow AI workflows
|
|
org.opencontainers.image.vendor=Langflow
|
|
org.opencontainers.image.version=${{ github.event.inputs.version }}
|
|
|
|
- name: Build and push Docker image
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: src/lfx/docker/Dockerfile${{ matrix.variant == 'alpine' && '.alpine' || '' }}
|
|
platforms: linux/amd64,linux/arm64
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
build-args: |
|
|
LFX_VERSION=${{ github.event.inputs.version }}
|
|
|
|
create-release:
|
|
name: Create GitHub Release
|
|
needs: [validate-version, release-lfx, build-docker]
|
|
if: always() && github.event.inputs.create_github_release == 'true' && needs.release-lfx.result == 'success'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Download artifacts
|
|
uses: actions/download-artifact@v7
|
|
with:
|
|
name: lfx-dist
|
|
path: dist/
|
|
|
|
- name: Generate release notes
|
|
id: notes
|
|
run: |
|
|
cat > release_notes.md << EOF
|
|
# LFX ${{ github.event.inputs.version }}
|
|
|
|
## 🚀 Installation
|
|
|
|
### PyPI
|
|
\`\`\`bash
|
|
pip install lfx==${{ github.event.inputs.version }}
|
|
# or
|
|
uv pip install lfx==${{ github.event.inputs.version }}
|
|
# or run without installing
|
|
uvx lfx@${{ github.event.inputs.version }} --help
|
|
\`\`\`
|
|
|
|
### Docker
|
|
\`\`\`bash
|
|
# Standard image
|
|
docker pull langflowai/lfx:${{ github.event.inputs.version }}
|
|
|
|
# Alpine image (smaller)
|
|
docker pull langflowai/lfx:${{ github.event.inputs.version }}-alpine
|
|
|
|
# Run a flow
|
|
docker run --rm -v \$(pwd):/app/data langflowai/lfx:${{ github.event.inputs.version }} lfx run flow.json --input-value "Hello"
|
|
\`\`\`
|
|
|
|
## 📦 What's New
|
|
|
|
<!-- Add release notes here -->
|
|
|
|
## 📋 Checksums
|
|
|
|
\`\`\`
|
|
$(cd dist && sha256sum *)
|
|
\`\`\`
|
|
|
|
---
|
|
|
|
**Full Changelog**: https://github.com/${{ github.repository }}/compare/v${{ needs.validate-version.outputs.current_version }}...lfx-v${{ github.event.inputs.version }}
|
|
EOF
|
|
|
|
- name: Create Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: lfx-v${{ github.event.inputs.version }}
|
|
# Pin the minted tag to the commit this release was built from;
|
|
# without it GitHub creates the tag at the default-branch HEAD.
|
|
target_commitish: ${{ github.sha }}
|
|
name: LFX ${{ github.event.inputs.version }}
|
|
body_path: release_notes.md
|
|
draft: false
|
|
prerelease: ${{ github.event.inputs.pre_release }}
|
|
files: |
|
|
dist/*
|
|
generate_release_notes: true
|
|
|
|
test-release:
|
|
name: Test Release
|
|
needs: [release-lfx, build-docker]
|
|
if: always() && (needs.release-lfx.result == 'success' || needs.build-docker.result == 'success')
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Wait for PyPI propagation
|
|
if: needs.release-lfx.result == 'success'
|
|
run: sleep 60
|
|
|
|
- name: Test PyPI installation
|
|
if: needs.release-lfx.result == 'success'
|
|
run: |
|
|
# Test installation using uv
|
|
uv pip install lfx==${{ github.event.inputs.version }}
|
|
uv run lfx --help
|
|
|
|
- name: Test Docker image
|
|
if: needs.build-docker.result == 'success'
|
|
run: |
|
|
# Test standard image
|
|
docker run --rm langflowai/lfx:${{ github.event.inputs.version }} lfx --help
|
|
|
|
# Test alpine image
|
|
docker run --rm langflowai/lfx:${{ github.event.inputs.version }}-alpine lfx --help
|
|
|
|
# Test with a simple flow
|
|
cat > test_flow.json << 'EOF'
|
|
{
|
|
"nodes": [],
|
|
"edges": []
|
|
}
|
|
EOF
|
|
|
|
docker run --rm -v $(pwd):/app/data langflowai/lfx:${{ github.event.inputs.version }} \
|
|
lfx run /app/data/test_flow.json --input-value "test" || true
|
|
|
|
notify:
|
|
name: Notify Release Status
|
|
needs: [create-release, test-release]
|
|
if: always()
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Notify success
|
|
if: needs.create-release.result == 'success'
|
|
run: |
|
|
echo "✅ LFX ${{ github.event.inputs.version }} released successfully!"
|
|
echo "PyPI: https://pypi.org/project/lfx/${{ github.event.inputs.version }}/"
|
|
echo "Docker Hub: https://hub.docker.com/r/langflowai/lfx/tags"
|
|
echo "GitHub Release: https://github.com/${{ github.repository }}/releases/tag/lfx-v${{ github.event.inputs.version }}"
|
|
|
|
- name: Notify failure
|
|
if: needs.create-release.result != 'success'
|
|
run: |
|
|
echo "❌ LFX ${{ github.event.inputs.version }} release failed!"
|
|
exit 1 |