diff --git a/.github/actions/setup-uv/action.yml b/.github/actions/setup-uv/action.yml new file mode 100644 index 000000000..02da15594 --- /dev/null +++ b/.github/actions/setup-uv/action.yml @@ -0,0 +1,30 @@ +name: "Setup uv" +description: "Checks out code, installs uv, and sets up Python environment" +inputs: + ref: + description: "Reference to check out" + required: false + default: "github.ref" + +runs: + using: "composite" + steps: + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + cache-dependency-glob: "uv.lock" + + - name: "Set up Python" + uses: actions/setup-python@v5 + with: + python-version-file: "pyproject.toml" + + - name: Restore uv cache + uses: actions/cache@v4 + with: + path: /tmp/.uv-cache + key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} + restore-keys: | + uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} + uv-${{ runner.os }} diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 007209920..d8faf3dc3 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -22,7 +22,7 @@ on: required: false type: string default: '' - + workflow_dispatch: inputs: version: @@ -48,7 +48,7 @@ on: required: false type: string default: '' - + env: POETRY_VERSION: "1.8.2" TEST_TAG: "langflowai/langflow:test" @@ -65,44 +65,70 @@ jobs: - name: Resolve nightly tag id: resolve-nightly-tag run: | - if [[ "${{ inputs.nightly_tag_main }}" != '' ]]; then - echo "nightly_tag=${{ inputs.nightly_tag_main }}" >> $GITHUB_OUTPUT - echo "nightly_build=true" >> $GITHUB_OUTPUT - elif [[ "${{ inputs.nightly_tag_base }}" != '' ]]; then + # Note - this is more complex than I'd like. For `main` builds, we just pass the `main` tag. + # For `base` builds, we pass both the `base` and `main` tags. This is because the `main` tag is the + # version we need to check out for the build, but the `base` tag is the version we need to build. + # + # So, you need to check for `base` existence before `main`. + + if [[ "${{ inputs.nightly_tag_base }}" != '' ]]; then + if [[ "${{ inputs.release_type }}" != "base" ]]; then + echo "Release type is not 'base'. Exiting the workflow." + exit 1 + fi + + # Main tag must not be empty, otherwise we have no valid tag to check out. + if [[ "${{ inputs.nightly_tag_main }}" == '' ]]; then + echo "Nightly tag main is empty. Exiting the workflow." + exit 1 + fi + echo "nightly_tag=${{ inputs.nightly_tag_base }}" >> $GITHUB_OUTPUT echo "nightly_build=true" >> $GITHUB_OUTPUT + elif [[ "${{ inputs.nightly_tag_main }}" != '' ]]; then + if [[ "${{ inputs.release_type }}" != "main" ]]; then + echo "Release type is not 'main'. Exiting the workflow." + exit 1 + fi + echo "nightly_tag=${{ inputs.nightly_tag_main }}" >> $GITHUB_OUTPUT + echo "nightly_build=true" >> $GITHUB_OUTPUT else echo "nightly_tag=" >> $GITHUB_OUTPUT echo "nightly_build=false" >> $GITHUB_OUTPUT fi - - name: Check out the code at a specific ref uses: actions/checkout@v4 with: ref: ${{ inputs.nightly_tag_main || github.ref }} - - name: Set up Python 3.12 + Poetry ${{ env.POETRY_VERSION }} - uses: "./.github/actions/poetry_caching" + persist-credentials: true + - name: "Setup Environment" + uses: ./.github/actions/setup-uv with: - python-version: "3.12" - poetry-version: ${{ env.POETRY_VERSION }} - cache-key: ${{ runner.os }}-poetry-${{ env.POETRY_VERSION }}-${{ hashFiles('**/poetry.lock') }} + ref: ${{ inputs.nightly_tag_main || github.ref }} + + - name: Install the project + run: uv sync --dev + - name: Get Version from Input if: ${{ inputs.version != '' }} id: get-version-input run: | version=${{ inputs.version }} + echo version=$version echo version=$version >> $GITHUB_OUTPUT - name: Get Version Base if: ${{ inputs.version == '' && inputs.release_type == 'base' }} id: get-version-base run: | - version=$(cd src/backend/base && poetry version --short) + version=$(uv tree | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//') + echo version=$version echo version=$version >> $GITHUB_OUTPUT - name: Get Version Main if: ${{ inputs.version == '' && inputs.release_type == 'main' }} id: get-version-main run: | - version=$(poetry version --short) + version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//') + echo version=$version echo version=$version >> $GITHUB_OUTPUT setup: runs-on: ubuntu-latest @@ -111,8 +137,6 @@ jobs: docker_tags: ${{ steps.set-vars.outputs.docker_tags }} ghcr_tags: ${{ steps.set-vars.outputs.ghcr_tags }} file: ${{ steps.set-vars.outputs.file }} - env: - NIGHTLY_TAG: ${{ needs.get-version.outputs.nightly-tag }} steps: - name: Check out the code at a specific ref uses: actions/checkout@v4 @@ -123,7 +147,7 @@ jobs: id: set-vars run: | nightly_suffix='' - if [[ "${{ env.NIGHTLY_TAG }}" != '' ]]; then + if [[ "${{ needs.get-version.outputs.nightly-build }}" == "true" ]]; then nightly_suffix="-nightly" fi @@ -148,7 +172,21 @@ jobs: - name: Check out the code at a specific ref uses: actions/checkout@v4 with: - ref: ${{ inputs.nightly_tag_main || github.ref }} + ref: ${{ inputs.ref }} + persist-credentials: true + - name: "Setup Environment" + uses: ./.github/actions/setup-uv + with: + ref: ${{ inputs.nightly_tag_main || github.ref }} + + - name: Install the project + run: | + if [[ "${{ inputs.release_type }}" == "base" ]]; then + cd src/backend/base && uv sync --no-dev --no-sources + else + uv sync --no-dev --no-sources + fi + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -213,8 +251,8 @@ jobs: - name: Check out the code at a specific ref uses: actions/checkout@v4 with: - ref: ${{ inputs.nightly_tag_main || github.ref }} - + ref: ${{ inputs.nightly_tag_main || github.ref }} + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -224,7 +262,7 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - + - name: Login to Github Container Registry if: ${{ matrix.component == 'ghcr-backend' }} || ${{ matrix.component == 'ghcr-frontend' }} uses: docker/login-action@v3 @@ -232,7 +270,7 @@ jobs: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.TEMP_GHCR_TOKEN}} - + - name: Wait for propagation (for backend) run: sleep 120 diff --git a/.github/workflows/lint-py.yml b/.github/workflows/lint-py.yml index 656646aeb..e14921bb0 100644 --- a/.github/workflows/lint-py.yml +++ b/.github/workflows/lint-py.yml @@ -23,26 +23,15 @@ jobs: - "3.11" - "3.10" steps: - - uses: actions/checkout@v4 + - name: Check out the code at a specific ref + uses: actions/checkout@v4 with: ref: ${{ inputs.branch || github.ref }} - - name: Install uv - uses: astral-sh/setup-uv@v3 + persist-credentials: true + - name: "Setup Environment" + uses: ./.github/actions/setup-uv with: - enable-cache: true - cache-dependency-glob: "uv.lock" - - name: "Set up Python" - uses: actions/setup-python@v5 - with: - python-version-file: "pyproject.toml" - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} + ref: ${{ inputs.branch || github.ref }} - name: Install the project run: uv sync --dev - name: Run Mypy diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index dc15c384a..4e062cc1c 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -24,28 +24,11 @@ jobs: main_tag: ${{ steps.generate_main_tag.outputs.main_tag }} base_tag: ${{ steps.set_base_tag.outputs.base_tag }} steps: - - name: Checkout code - uses: actions/checkout@v4 + - name: "Setup Environment" + uses: ./.github/actions/setup-uv with: - persist-credentials: true + ref: ${{ github.ref }} - - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: true - cache-dependency-glob: "uv.lock" - - name: "Set up Python" - uses: actions/setup-python@v5 - with: - python-version-file: "pyproject.toml" - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} - name: Install the project run: uv sync --dev @@ -53,7 +36,7 @@ jobs: id: generate_main_tag run: | # NOTE: This outputs the tag with the `v` prefix. - MAIN_TAG="$(uv run python ./scripts/ci/pypi_nightly_tag.py main)" + MAIN_TAG="$(uv run ./scripts/ci/pypi_nightly_tag.py main)" echo "main_tag=$MAIN_TAG" >> $GITHUB_OUTPUT echo "main_tag=$MAIN_TAG" @@ -72,7 +55,7 @@ jobs: if: ${{ steps.check_main_tag.outputs.main_tag_exists == 'false' }} run: | # NOTE: This outputs the tag with the `v` prefix. - BASE_TAG="$(uv run python ./scripts/ci/pypi_nightly_tag.py base)" + BASE_TAG="$(uv run ./scripts/ci/pypi_nightly_tag.py base)" echo "base_tag=$BASE_TAG" >> $GITHUB_OUTPUT echo "base_tag=$BASE_TAG" @@ -85,24 +68,25 @@ jobs: git config --global user.email "bot-nightly-builds@langflow.org" git config --global user.name "Langflow Bot" - # WARNING: These scripts must be run in this order. - # Poetry will use a different cached virtual environment once the main pyproject.toml - # project-name is updated, which does not have dependencies installed. BASE_TAG="${{ steps.generate_base_tag.outputs.base_tag }}" echo "Updating base project version to $BASE_TAG" - uv run python ./scripts/ci/update_pyproject_name.py langflow-base-nightly base - uv run python ./scripts/ci/update_pyproject_version.py $BASE_TAG base + uv run ./scripts/ci/update_pyproject_name.py langflow-base-nightly base + uv run ./scripts/ci/update_pyproject_version.py $BASE_TAG base # This updates the dependency of langflow-base to langflow-base-nightly in {project_root}/pyproject.toml - uv run python ./scripts/ci/update_lf_base_dependency.py $BASE_TAG + # Note: Still necessary for poetry + uv run ./scripts/ci/update_lf_base_dependency.py $BASE_TAG # Use the main tag created earlier MAIN_TAG="${{ steps.generate_main_tag.outputs.main_tag }}" echo "Updating main project version to $MAIN_TAG" - uv run python ./scripts/ci/update_pyproject_version.py $MAIN_TAG main - uv run python ./scripts/ci/update_pyproject_name.py langflow-nightly main + uv run ./scripts/ci/update_pyproject_version.py $MAIN_TAG main + uv run ./scripts/ci/update_pyproject_name.py langflow-nightly main + uv run ./scripts/ci/update_uv_dependency.py $BASE_TAG + uv lock + cd src/backend/base && uv lock - git add pyproject.toml src/backend/base/pyproject.toml + git add pyproject.toml src/backend/base/pyproject.toml uv.lock src/backend/base/uv.lock git commit -m "Update version and project name" echo "Tagging main with $MAIN_TAG" diff --git a/.github/workflows/python_test.yml b/.github/workflows/python_test.yml index 277674de8..34497f709 100644 --- a/.github/workflows/python_test.yml +++ b/.github/workflows/python_test.yml @@ -113,27 +113,16 @@ jobs: matrix: python-version: ${{ fromJson(inputs.python-versions || '["3.10", "3.11", "3.12"]') }} steps: - - uses: actions/checkout@v4 + - name: Check out the code at a specific ref + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.ref }} + persist-credentials: true + - name: "Setup Environment" + uses: ./.github/actions/setup-uv with: ref: ${{ inputs.ref || github.ref }} - - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: true - cache-dependency-glob: "uv.lock" - - name: "Set up Python" - uses: actions/setup-python@v5 - with: - python-version-file: "pyproject.toml" - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} - name: Check Version id: check-version # We need to print $3 because langflow-base is a dependency of langflow diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bc096d992..c5adacfdb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,24 +56,10 @@ jobs: version: ${{ steps.check-version.outputs.version }} skipped: ${{ steps.check-version.outputs.skipped }} steps: - - uses: actions/checkout@v4 - - name: Install uv - uses: astral-sh/setup-uv@v3 + - name: Setup Environment + uses: ./.github/workflows/setup-uv.yml with: - enable-cache: true - cache-dependency-glob: "uv.lock" - - name: "Set up Python" - uses: actions/setup-python@v5 - with: - python-version-file: "pyproject.toml" - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} + ref: ${{ github.ref }} - name: Install the project run: uv sync --dev - name: Check Version @@ -130,32 +116,19 @@ jobs: outputs: version: ${{ steps.check-version.outputs.version }} steps: - - uses: actions/checkout@v4 - - name: Install uv - uses: astral-sh/setup-uv@v3 + - name: Setup Environment + uses: ./.github/workflows/setup-uv.yml with: - enable-cache: true - cache-dependency-glob: "uv.lock" - - name: "Set up Python" - uses: actions/setup-python@v5 - with: - python-version-file: "pyproject.toml" - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} + ref: ${{ github.ref }} - name: Install the project run: uv sync --dev + # If pre-release is true, we need to check if ["a", "b", "rc", "dev", "post"] is in the version string # if the version string is incorrect, we need to exit the workflow - name: Check if pre-release if: inputs.pre_release == 'true' run: | - version=$(uv tree | grep 'langflow' | awk '{print $2}' | sed 's/^v//') + version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//') if [[ "${version}" =~ ^([0-9]+\.)?([0-9]+\.)?[0-9]+((a|b|rc|dev|post)([0-9]+))$ ]]; then echo "Pre-release version detected. Continuing with the release." else @@ -165,7 +138,7 @@ jobs: - name: Check Version id: check-version run: | - version=$(uv tree | grep 'langflow' | awk '{print $2}' | sed 's/^v//') + version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//') last_released_version=$(curl -s "https://pypi.org/pypi/langflow/json" | jq -r '.releases | keys | .[]' | sort -V | tail -n 1) if [ "$version" = "$last_released_version" ]; then echo "Version $version is already released. Skipping release." diff --git a/.github/workflows/release_nightly.yml b/.github/workflows/release_nightly.yml index 326b2d1d3..58b6c1e69 100644 --- a/.github/workflows/release_nightly.yml +++ b/.github/workflows/release_nightly.yml @@ -54,41 +54,26 @@ jobs: defaults: run: shell: bash + outputs: + version: ${{ steps.verify.outputs.version }} steps: - name: Check out the code at a specific ref uses: actions/checkout@v4 with: ref: ${{ inputs.nightly_tag_main }} persist-credentials: true - - name: Install uv - uses: astral-sh/setup-uv@v3 + - name: "Setup Environment" + uses: ./.github/actions/setup-uv with: - enable-cache: true - cache-dependency-glob: "uv.lock" - - name: "Set up Python" - uses: actions/setup-python@v5 - with: - python-version-file: "pyproject.toml" - - name: Set up Nodejs 20 - uses: actions/setup-node@v4 - with: - node-version: "20" - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} + ref: ${{ inputs.nightly_tag_main }} - name: Install the project run: uv sync --dev - name: Verify Nightly Name and Version - working-directory: src/backend/base + id: verify run: | - name=$(uv tree | grep 'langflow-base' | awk '{print $1}') - version=$(uv tree | grep 'langflow-base' | awk '{print $2}') + name=$(uv tree | grep 'langflow-base' | awk '{print $2}') + version=$(uv tree | grep 'langflow-base' | awk '{print $3}') if [ "$name" != "langflow-base-nightly" ]; then echo "Name $name does not match langflow-base-nightly. Exiting the workflow." exit 1 @@ -97,14 +82,21 @@ jobs: echo "Version $version does not match nightly tag ${{ inputs.nightly_tag_base }}. Exiting the workflow." exit 1 fi + # Strip the leading `v` from the version + version=$(echo $version | sed 's/^v//') + echo "version=$version" >> $GITHUB_OUTPUT - name: Build project for distribution - run: make build base=true + run: make build base=true args="--wheel" - name: Test CLI run: | - python -m pip install src/backend/base/dist/*.whl - python -m langflow run --host 127.0.0.1 --port 7860 & + # TODO: unsure why the whl is not built in src/backend/base + # uv pip install src/backend/base/dist/*.whl + mkdir src/backend/base/dist + mv dist/*.whl src/backend/base/dist/ + uv pip install src/backend/base/dist/*.whl + uv run python -m langflow run --host 127.0.0.1 --port 7860 --backend-only & SERVER_PID=$! # Wait for the server to start timeout 120 bash -c 'until curl -f http://127.0.0.1:7860/api/v1/auto_login; do sleep 2; done' || (echo "Server did not start in time" && kill $SERVER_PID && exit 1) @@ -122,6 +114,7 @@ jobs: - name: Publish to PyPI env: POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} + UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }} run: | make publish base=true @@ -135,56 +128,49 @@ jobs: name: Release Langflow Nightly Main needs: [release-nightly-base] runs-on: ubuntu-latest + outputs: + version: ${{ steps.verify.outputs.version }} defaults: run: shell: bash steps: - name: Check out the code at a specific ref uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + persist-credentials: true + - name: "Setup Environment" + uses: ./.github/actions/setup-uv with: ref: ${{ inputs.nightly_tag_main }} - - - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: true - cache-dependency-glob: "uv.lock" - - name: "Set up Python" - uses: actions/setup-python@v5 - with: - python-version-file: "pyproject.toml" - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} - name: Install the project run: uv sync --dev - name: Verify Nightly Name and Version + id: verify run: | - name=$(uv tree | grep 'langflow' | awk '{print $1}') - version=$(uv tree | grep 'langflow' | awk '{print $2}') + name=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $1}') + version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}') if [ "$name" != "langflow-nightly" ]; then echo "Name $name does not match langflow-nightly. Exiting the workflow." 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." + if [ "$version" != "${{ inputs.nightly_tag_main }}" ]; then + echo "Version $version does not match nightly tag ${{ inputs.nightly_tag_main }}. Exiting the workflow." exit 1 fi + # Strip the leading `v` from the version + version=$(echo $version | sed 's/^v//') + echo "version=$version" >> $GITHUB_OUTPUT - name: Wait for PyPI Propagation run: sleep 300 # wait for 5 minutes to ensure PyPI propagation of base - name: Build project for distribution - run: make build main=true args="--no-sources" + run: make build main=true args="--no-sources --wheel" - name: Test CLI run: | - python -m pip install dist/*.whl - python -m langflow run --host 127.0.0.1 --port 7860 --backend-only & + uv pip install dist/*.whl + uv run python -m langflow run --host 127.0.0.1 --port 7860 --backend-only & SERVER_PID=$! # Wait for the server to start timeout 120 bash -c 'until curl -f http://127.0.0.1:7860/health_check; do sleep 2; done' || (echo "Server did not start in time" && kill $SERVER_PID && exit 1) @@ -201,6 +187,7 @@ jobs: - name: Publish to PyPI env: POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} + UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }} run: | make publish main=true - name: Upload Artifact @@ -212,18 +199,14 @@ jobs: call_docker_build_base: name: Call Docker Build Workflow for Langflow Base if: always() && ${{ inputs.build_docker_base == 'true' }} - needs: [release-nightly-base] + needs: [release-nightly-base, release-nightly-main] uses: ./.github/workflows/docker-build.yml - strategy: - matrix: - release_type: - - base with: - # version should be needs.release-base.outputs.version if release_type is base - # version should be needs.release-main.outputs.version if release_type is main - version: "" - release_type: ${{ matrix.release_type }} + # Version should _not_ contain the leading `v` + version: ${{ needs.release-nightly-base.outputs.version }} + release_type: base nightly_tag_base: ${{ inputs.nightly_tag_base }} + nightly_tag_main: ${{ inputs.nightly_tag_main }} secrets: inherit call_docker_build_main: @@ -231,14 +214,9 @@ jobs: if: always() && ${{ inputs.build_docker_main == 'true' }} needs: [release-nightly-main] uses: ./.github/workflows/docker-build.yml - strategy: - matrix: - release_type: - - main with: - # version should be needs.release-base.outputs.version if release_type is base - # version should be needs.release-main.outputs.version if release_type is main - version: "" - release_type: ${{ matrix.release_type }} + # Version should _not_ contain the leading `v` + version: ${{ needs.release-nightly-main.outputs.version }} + release_type: main nightly_tag_main: ${{ inputs.nightly_tag_main }} secrets: inherit diff --git a/.github/workflows/style-check-py.yml b/.github/workflows/style-check-py.yml index 1f82bb05f..34cc46e60 100644 --- a/.github/workflows/style-check-py.yml +++ b/.github/workflows/style-check-py.yml @@ -17,24 +17,15 @@ jobs: python-version: - "3.12" steps: - - uses: actions/checkout@v4 - - name: Install uv - uses: astral-sh/setup-uv@v3 + - name: Check out the code at a specific ref + uses: actions/checkout@v4 with: - enable-cache: true - cache-dependency-glob: "uv.lock" - - name: "Set up Python" - uses: actions/setup-python@v5 + ref: ${{ github.ref }} + persist-credentials: true + - name: "Setup Environment" + uses: ./.github/actions/setup-uv with: - python-version-file: "pyproject.toml" - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} + ref: ${{ github.ref }} - name: Register problem matcher run: echo "::add-matcher::.github/workflows/matchers/ruff.json" - name: Run Ruff Check diff --git a/Makefile b/Makefile index 7a4c2588c..6fa3b6293 100644 --- a/Makefile +++ b/Makefile @@ -315,18 +315,18 @@ build: setup_env ## build the frontend static files and package the project ifdef base make install_frontendci make build_frontend - make build_langflow_base + make build_langflow_base args="$(args)" endif ifdef main make install_frontendci make build_frontend - make build_langflow_base + make build_langflow_base args="$(args)" make build_langflow args="$(args)" endif build_langflow_base: - cd src/backend/base && uv build + cd src/backend/base && uv build $(args) rm -rf src/backend/base/langflow/frontend build_langflow_backup: diff --git a/docker/build_and_push_base.Dockerfile b/docker/build_and_push_base.Dockerfile index 148547fcc..7c5cb9f1e 100644 --- a/docker/build_and_push_base.Dockerfile +++ b/docker/build_and_push_base.Dockerfile @@ -31,6 +31,7 @@ RUN apt-get update \ gcc \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* + # Install the project's dependencies using the lockfile and settings RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=src/backend/base/README.md,target=src/backend/base/README.md \ diff --git a/pyproject.toml b/pyproject.toml index c9947fa1a..d180bc4c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,8 +22,8 @@ include = ["src/backend/langflow/*", "src/backend/langflow/**/*"] documentation = "https://docs.langflow.org" [tool.uv.sources] -langflow-base = {workspace = true} -langflow = {workspace = true} +langflow-base = { workspace = true } +langflow = { workspace = true } [tool.uv.workspace] members = ["src/backend/base", "."] @@ -38,7 +38,7 @@ description = "A Python package with a built-in web application" requires-python = ">=3.10,<3.13" # Define your main dependencies here dependencies = [ - "langflow-base==0.0.96", # Local editable package + "langflow-base==0.0.96", "beautifulsoup4>=4.12.2", "google-search-results>=2.4.1", "google-api-python-client>=2.130.0", diff --git a/scripts/ci/update_lf_base_dependency.py b/scripts/ci/update_lf_base_dependency.py index e0eb870c1..adf4d1a33 100755 --- a/scripts/ci/update_lf_base_dependency.py +++ b/scripts/ci/update_lf_base_dependency.py @@ -13,25 +13,13 @@ def update_base_dep(pyproject_path: str, new_version: str) -> None: with open(filepath, "r") as file: content = file.read() - # Regex to match the langflow-base dep line under [tool.poetry] - # NOTE: this functions similarly to `update_dependencies.py`. - # The order of operations for these scripts is more complex than it needs to be; - # this is a reminder to revisit this process. - # Currently, the process is as follows: - # 1. nightly-build workflow updates all names, version, and the langflow-base - # dependency in pyproject.toml, and commits the changes and creates a tag. - # 2. release-nightly workflow runs, which calls update_dependencies.py to update - # the langflow-base dependency in pyproject.toml _again_. This is redundant, but - # necessary because the release workflow relies on that script to update the base - # dependency. - pattern = re.compile(r'langflow-base = \{ path = "\./src/backend/base", develop = true \}') - - if not pattern.search(content): - raise Exception(f'langflow-base dependency not found in "{filepath}"') - replacement = f'langflow-base-nightly = "{new_version}"' - content = pattern.sub(replacement, content) + # Updates the pattern for poetry + pattern = re.compile(r'langflow-base = \{ path = "\./src/backend/base", develop = true \}') + if not pattern.search(content): + raise Exception(f'langflow-base poetry dependency not found in "{filepath}"') + content = pattern.sub(replacement, content) with open(filepath, "w") as file: file.write(content) diff --git a/scripts/ci/update_pyproject_name.py b/scripts/ci/update_pyproject_name.py index e944fab3e..e846ec87d 100755 --- a/scripts/ci/update_pyproject_name.py +++ b/scripts/ci/update_pyproject_name.py @@ -16,13 +16,35 @@ def update_pyproject_name(pyproject_path: str, new_project_name: str) -> None: if not pattern.search(content): raise Exception(f'Project name not found in "{filepath}"') - content = pattern.sub(new_project_name, content) with open(filepath, "w") as file: file.write(content) +def update_uv_dep(pyproject_path: str, new_project_name: str) -> None: + """Update the langflow-base dependency in pyproject.toml.""" + filepath = os.path.join(BASE_DIR, pyproject_path) + with open(filepath, "r") as file: + content = file.read() + + if new_project_name == "langflow-nightly": + pattern = re.compile(r"langflow = \{ workspace = true \}") + replacement = "langflow-nightly = { workspace = true }" + elif new_project_name == "langflow-base-nightly": + pattern = re.compile(r"langflow-base = \{ workspace = true \}") + replacement = "langflow-base-nightly = { workspace = true }" + else: + raise ValueError(f"Invalid project name: {new_project_name}") + + # Updates the dependency name for uv + if not pattern.search(content): + raise Exception(f"{replacement} uv dependency not found in {filepath}") + content = pattern.sub(replacement, content) + with open(filepath, "w") as file: + file.write(content) + + def main() -> None: if len(sys.argv) != 3: raise Exception("Must specify project name and build type, e.g. langflow-nightly base") @@ -31,8 +53,10 @@ def main() -> None: if build_type == "base": update_pyproject_name("src/backend/base/pyproject.toml", new_project_name) + update_uv_dep("pyproject.toml", new_project_name) elif build_type == "main": update_pyproject_name("pyproject.toml", new_project_name) + update_uv_dep("pyproject.toml", new_project_name) else: raise ValueError(f"Invalid build type: {build_type}") diff --git a/scripts/ci/update_uv_dependency.py b/scripts/ci/update_uv_dependency.py new file mode 100755 index 000000000..6f3032a52 --- /dev/null +++ b/scripts/ci/update_uv_dependency.py @@ -0,0 +1,42 @@ +import os +import sys +import re + +BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")) + + +def update_uv_dep(base_version: str) -> None: + """Update the langflow-base dependency in pyproject.toml.""" + + pyproject_path = os.path.join(BASE_DIR, "pyproject.toml") + + # Read the pyproject.toml file content + with open(pyproject_path, "r") as file: + content = file.read() + + # For the main project, update the langflow-base dependency in the UV section + pattern = re.compile(r'(dependencies\s*=\s*\[\s*\n\s*)("langflow-base==[\d.]+")') + replacement = r'\1"langflow-base-nightly=={}"'.format(base_version) + + # Check if the pattern is found + if not pattern.search(content): + raise Exception(f"{pattern} UV dependency not found in {pyproject_path}") + + # Replace the matched pattern with the new one + content = pattern.sub(replacement, content) + + # Write the updated content back to the file + with open(pyproject_path, "w") as file: + file.write(content) + + +def main() -> None: + if len(sys.argv) != 2: + raise Exception("specify base version") + base_version = sys.argv[1] + base_version = base_version.lstrip("v") + update_uv_dep(base_version) + + +if __name__ == "__main__": + main()