diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f4eec7d7bde..682e0d85302b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,8 @@ name: CI on: workflow_call: inputs: - branch: - description: "(Optional) Branch to checkout" + ref: + description: "(Optional) Ref to checkout" required: false type: string python-versions: @@ -22,6 +22,11 @@ on: required: false type: boolean default: false + run-all-tests: + description: "Run all tests regardless of file changes (skips path filtering)" + required: false + type: boolean + default: false runs-on: description: "Runner to use for the tests" required: false @@ -29,8 +34,8 @@ on: default: "ubuntu-latest" workflow_dispatch: inputs: - branch: - description: "(Optional) Branch to checkout" + ref: + description: "(Optional) Ref to checkout" required: false type: string openai_api_key: @@ -69,6 +74,20 @@ env: TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }} jobs: + echo-inputs: + name: Echo Inputs + runs-on: ubuntu-latest + steps: + - name: Echo inputs + run: | + echo "Inputs:" + echo " ref: ${{ inputs.ref }}" + echo " python-versions: ${{ inputs.python-versions }}" + echo " frontend-tests-folder: ${{ inputs.frontend-tests-folder }}" + echo " release: ${{ inputs.release }}" + echo " run-all-tests: ${{ inputs.run-all-tests }}" + echo " runs-on: ${{ inputs.runs-on }}" + check-nightly-status: name: Check PyPI Version Update runs-on: ubuntu-latest @@ -151,7 +170,7 @@ jobs: path-filter: needs: set-ci-condition - if: ${{ needs.set-ci-condition.outputs.should-run-ci == 'true' }} + if: ${{ needs.set-ci-condition.outputs.should-run-ci == 'true' && !inputs.run-all-tests }} name: Filter Paths runs-on: ubuntu-latest outputs: @@ -184,7 +203,7 @@ jobs: - name: Checkout code uses: actions/checkout@v5 with: - ref: ${{ inputs.branch || github.ref }} + ref: ${{ inputs.ref || github.ref }} - name: Filter Paths id: filter uses: dorny/paths-filter@v3 @@ -194,11 +213,16 @@ jobs: test-backend: needs: [path-filter, set-ci-condition] name: Run Backend Tests - if: ${{ needs.path-filter.outputs.python == 'true' && needs.set-ci-condition.outputs.should-run-tests == 'true' }} + if: | + always() && + !cancelled() && + needs.set-ci-condition.outputs.should-run-tests == 'true' && + (inputs.run-all-tests || needs.path-filter.outputs.python == 'true') uses: ./.github/workflows/python_test.yml with: python-versions: ${{ inputs.python-versions || '["3.10"]' }} runs-on: ${{ (inputs['runs-on'] && startsWith(format('{0}', inputs['runs-on']), '[') && fromJSON(inputs['runs-on'])) || inputs['runs-on'] || github.event.inputs['runs-on'] || 'ubuntu-latest' }} + ref: ${{ inputs.ref || github.ref }} secrets: OPENAI_API_KEY: "${{ secrets.OPENAI_API_KEY }}" ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}" @@ -207,20 +231,31 @@ jobs: test-frontend-unit: needs: [path-filter, set-ci-condition] name: Run Frontend Unit Tests - if: ${{ needs.path-filter.outputs.frontend == 'true' && needs.set-ci-condition.outputs.should-run-tests == 'true' }} + if: | + always() && + !cancelled() && + needs.set-ci-condition.outputs.should-run-tests == 'true' && + (inputs.run-all-tests || needs.path-filter.outputs.frontend == 'true') uses: ./.github/workflows/jest_test.yml + with: + ref: ${{ inputs.ref || github.ref }} secrets: CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}" test-frontend: needs: [path-filter, set-ci-condition] name: Run Frontend Tests - if: ${{ (needs.path-filter.outputs.frontend == 'true' || needs.path-filter.outputs.frontend-tests == 'true' || needs.path-filter.outputs.components-changes == 'true' || needs.path-filter.outputs.starter-projects-changes == 'true' || needs.path-filter.outputs.starter-projects == 'true' || needs.path-filter.outputs.components == 'true' || needs.path-filter.outputs.workspace == 'true' || needs.path-filter.outputs.api == 'true' || needs.path-filter.outputs.database == 'true') && needs.set-ci-condition.outputs.should-run-tests == 'true' }} + if: | + always() && + !cancelled() && + needs.set-ci-condition.outputs.should-run-tests == 'true' && + (inputs.run-all-tests || needs.path-filter.outputs.frontend == 'true' || needs.path-filter.outputs.frontend-tests == 'true' || needs.path-filter.outputs.components-changes == 'true' || needs.path-filter.outputs.starter-projects-changes == 'true' || needs.path-filter.outputs.starter-projects == 'true' || needs.path-filter.outputs.components == 'true' || needs.path-filter.outputs.workspace == 'true' || needs.path-filter.outputs.api == 'true' || needs.path-filter.outputs.database == 'true') uses: ./.github/workflows/typescript_test.yml with: tests_folder: ${{ inputs.frontend-tests-folder }} release: ${{ inputs.release || false }} runs-on: ${{ (inputs['runs-on'] && startsWith(format('{0}', inputs['runs-on']), '[') && fromJSON(inputs['runs-on'])) || inputs['runs-on'] || github.event.inputs['runs-on'] || 'ubuntu-latest' }} + ref: ${{ inputs.ref || github.ref }} secrets: OPENAI_API_KEY: "${{ secrets.OPENAI_API_KEY }}" STORE_API_KEY: "${{ secrets.STORE_API_KEY }}" @@ -229,26 +264,36 @@ jobs: lint-backend: needs: path-filter - if: ${{ needs.path-filter.outputs.python == 'true'}} + if: | + always() && + !cancelled() && + (inputs.run-all-tests || needs.path-filter.outputs.python == 'true') name: Lint Backend uses: ./.github/workflows/lint-py.yml test-docs-build: needs: path-filter - if: ${{ needs.path-filter.outputs.docs == 'true' }} + if: | + always() && + !cancelled() && + (inputs.run-all-tests || needs.path-filter.outputs.docs == 'true') name: Test Docs Build uses: ./.github/workflows/docs_test.yml test-templates: needs: [path-filter, set-ci-condition] name: Test Starter Templates - if: ${{ (needs.path-filter.outputs.python == 'true' || needs.path-filter.outputs.frontend == 'true') && needs.set-ci-condition.outputs.should-run-tests == 'true' }} + if: | + always() && + !cancelled() && + needs.set-ci-condition.outputs.should-run-tests == 'true' && + (inputs.run-all-tests || needs.path-filter.outputs.python == 'true' || needs.path-filter.outputs.frontend == 'true') runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v5 with: - ref: ${{ inputs.branch || github.ref }} + ref: ${{ inputs.ref || github.ref }} - name: Set up Python 3.12 uses: actions/setup-python@v5 @@ -284,7 +329,7 @@ jobs: check-nightly-status ] - if: always() + if: ${{ always() }} runs-on: ubuntu-latest env: JOBS_JSON: ${{ toJSON(needs) }} diff --git a/.github/workflows/deploy-docs-draft.yml b/.github/workflows/deploy-docs-draft.yml index a1c9ea040e48..2bdb1999f9be 100644 --- a/.github/workflows/deploy-docs-draft.yml +++ b/.github/workflows/deploy-docs-draft.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: yarn cache-dependency-path: ./docs/yarn.lock diff --git a/.github/workflows/deploy_gh-pages.yml b/.github/workflows/deploy_gh-pages.yml index 77e8baf1b5d3..a975a50a8702 100644 --- a/.github/workflows/deploy_gh-pages.yml +++ b/.github/workflows/deploy_gh-pages.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: yarn cache-dependency-path: ./docs/yarn.lock diff --git a/.github/workflows/docker-build-v2.yml b/.github/workflows/docker-build-v2.yml index 1aeb643db8f3..2b8fb304c092 100644 --- a/.github/workflows/docker-build-v2.yml +++ b/.github/workflows/docker-build-v2.yml @@ -54,7 +54,7 @@ env: jobs: build-base: name: Build Base Package - if: inputs.release_type == 'base' + if: ${{ inputs.release_type == 'base' }} strategy: matrix: include: @@ -82,7 +82,7 @@ jobs: id: version run: | echo "Extracting base version from pyproject.toml" - version=$(uv tree | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') echo "Using version: $version" echo version=$version >> $GITHUB_OUTPUT @@ -122,6 +122,7 @@ jobs: file: ./docker/build_and_push_base.Dockerfile tags: ${{ steps.tags.outputs.docker_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -133,12 +134,13 @@ jobs: file: ./docker/build_and_push_base.Dockerfile tags: ${{ steps.tags.outputs.ghcr_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max build-main: name: Build Main Package - if: inputs.release_type == 'main' + if: ${{ inputs.release_type == 'main' }} strategy: matrix: include: @@ -166,7 +168,7 @@ jobs: id: version run: | echo "Extracting main version from pyproject.toml" - version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') echo "Using version: $version" echo version=$version >> $GITHUB_OUTPUT @@ -206,6 +208,7 @@ jobs: file: ./docker/build_and_push.Dockerfile tags: ${{ steps.tags.outputs.docker_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -217,12 +220,13 @@ jobs: file: ./docker/build_and_push.Dockerfile tags: ${{ steps.tags.outputs.ghcr_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max build-main-ep: name: Build Main EP Package - if: inputs.release_type == 'main-ep' + if: ${{ inputs.release_type == 'main-ep' }} strategy: matrix: include: @@ -250,7 +254,7 @@ jobs: id: version run: | echo "Extracting main version from pyproject.toml" - version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') echo "Using version: $version" echo version=$version >> $GITHUB_OUTPUT @@ -290,6 +294,7 @@ jobs: file: ./docker/build_and_push_ep.Dockerfile tags: ${{ steps.tags.outputs.docker_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -301,12 +306,13 @@ jobs: file: ./docker/build_and_push_ep.Dockerfile tags: ${{ steps.tags.outputs.ghcr_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max build-main-all: name: Build Main All Package - if: inputs.release_type == 'main-all' + if: ${{ inputs.release_type == 'main-all' }} strategy: matrix: include: @@ -333,7 +339,7 @@ jobs: id: version run: | echo "Extracting main version from pyproject.toml" - version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') echo "Using version: $version" echo version=$version >> $GITHUB_OUTPUT @@ -373,6 +379,7 @@ jobs: file: ./docker/build_and_push_with_extras.Dockerfile tags: ${{ steps.tags.outputs.docker_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -384,6 +391,7 @@ jobs: file: ./docker/build_and_push_with_extras.Dockerfile tags: ${{ steps.tags.outputs.ghcr_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -391,7 +399,7 @@ jobs: name: Create Multi-Arch Manifest needs: [build-base, build-main, build-main-ep, build-main-all] runs-on: ubuntu-latest - if: always() && inputs.push_to_registry && (needs.build-base.result == 'success' || needs.build-main.result == 'success' || needs.build-main-ep.result == 'success' || needs.build-main-all.result == 'success') + if: ${{ always() && inputs.push_to_registry && (needs.build-base.result == 'success' || needs.build-main.result == 'success' || needs.build-main-ep.result == 'success' || needs.build-main-all.result == 'success') }} steps: - name: Setup Environment uses: astral-sh/setup-uv@v6 @@ -410,9 +418,9 @@ jobs: id: version run: | if [[ "${{ inputs.release_type }}" == "base" ]]; then - version=$(uv tree | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') else - version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') fi echo "Using version: $version" echo version=$version >> $GITHUB_OUTPUT diff --git a/.github/workflows/docker-nightly-build.yml b/.github/workflows/docker-nightly-build.yml index 575997147d31..3a870920309a 100644 --- a/.github/workflows/docker-nightly-build.yml +++ b/.github/workflows/docker-nightly-build.yml @@ -44,7 +44,7 @@ env: jobs: build-nightly-base: name: Build Nightly Base Package - if: inputs.release_type == 'nightly-base' + if: ${{ inputs.release_type == 'nightly-base' }} strategy: matrix: include: @@ -72,7 +72,8 @@ jobs: id: version run: | echo "Extracting base version from pyproject.toml" - version=$(uv tree | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') + # Verify nightly tag format if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$ ]]; then @@ -87,8 +88,8 @@ jobs: id: tags run: | version="${{ steps.version.outputs.version }}" - echo "docker_tags=langflowai/langflow:nightly-base-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - echo "ghcr_tags=ghcr.io/langflow-ai/langflow:nightly-base-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "docker_tags=langflowai/langflow-nightly:base-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly:base-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - name: Docker cleanup run: | @@ -119,6 +120,7 @@ jobs: file: ./docker/build_and_push_base.Dockerfile tags: ${{ steps.tags.outputs.docker_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -130,12 +132,13 @@ jobs: file: ./docker/build_and_push_base.Dockerfile tags: ${{ steps.tags.outputs.ghcr_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max build-nightly-main: name: Build Nightly Main Package - if: inputs.release_type == 'nightly-main' + if: ${{ inputs.release_type == 'nightly-main' }} strategy: matrix: include: @@ -163,7 +166,7 @@ jobs: id: version run: | echo "Extracting main version from pyproject.toml" - version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') # Verify nightly tag format if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$ ]]; then @@ -178,8 +181,8 @@ jobs: id: tags run: | version="${{ steps.version.outputs.version }}" - echo "docker_tags=langflowai/langflow:nightly-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - echo "ghcr_tags=ghcr.io/langflow-ai/langflow:nightly-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "docker_tags=langflowai/langflow-nightly:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - name: Docker cleanup run: | @@ -210,6 +213,7 @@ jobs: file: ./docker/build_and_push.Dockerfile tags: ${{ steps.tags.outputs.docker_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -221,12 +225,13 @@ jobs: file: ./docker/build_and_push.Dockerfile tags: ${{ steps.tags.outputs.ghcr_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max build-nightly-main-all: name: Build Nightly Main All Package - if: inputs.release_type == 'nightly-main-all' + if: ${{ inputs.release_type == 'nightly-main-all' }} strategy: matrix: include: @@ -254,7 +259,7 @@ jobs: id: version run: | echo "Extracting main version from pyproject.toml" - version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') # Verify nightly tag format if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$ ]]; then @@ -269,8 +274,8 @@ jobs: id: tags run: | version="${{ steps.version.outputs.version }}" - echo "docker_tags=langflowai/langflow-all:nightly-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - echo "ghcr_tags=ghcr.io/langflow-ai/langflow-all:nightly-${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "docker_tags=langflowai/langflow-nightly-all:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT + echo "ghcr_tags=ghcr.io/langflow-ai/langflow-nightly-all:${version}-${{ matrix.arch }}" >> $GITHUB_OUTPUT - name: Docker cleanup run: | @@ -301,6 +306,7 @@ jobs: file: ./docker/build_and_push_with_extras.Dockerfile tags: ${{ steps.tags.outputs.docker_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -312,6 +318,7 @@ jobs: file: ./docker/build_and_push_with_extras.Dockerfile tags: ${{ steps.tags.outputs.ghcr_tags }} platforms: linux/${{ matrix.arch }} + provenance: false cache-from: type=gha cache-to: type=gha,mode=max @@ -319,7 +326,7 @@ jobs: name: Create Multi-Arch Nightly Manifest needs: [build-nightly-base, build-nightly-main, build-nightly-main-all] runs-on: ubuntu-latest - if: always() && inputs.push_to_registry && (needs.build-nightly-base.result == 'success' || needs.build-nightly-main.result == 'success' || needs.build-nightly-main-all.result == 'success') + if: ${{ always() && inputs.push_to_registry && (needs.build-nightly-base.result == 'success' || needs.build-nightly-main.result == 'success' || needs.build-nightly-main-all.result == 'success') }} steps: - name: Setup Environment uses: astral-sh/setup-uv@v6 @@ -338,9 +345,9 @@ jobs: id: version run: | if [[ "${{ inputs.release_type }}" == "nightly-base" ]]; then - version=$(uv tree | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') else - version=$(uv tree | grep 'langflow' | grep -v 'langflow-base' | awk '{print $2}' | sed 's/^v//' | head -n 1) + version=$(uv tree 2>/dev/null | grep '^langflow' | grep -v '^langflow-base' | cut -d' ' -f2 | sed 's/^v//') fi echo "Using version: $version" echo version=$version >> $GITHUB_OUTPUT @@ -351,19 +358,19 @@ jobs: version="${{ steps.version.outputs.version }}" case "${{ inputs.release_type }}" in "nightly-base") - echo "final_tags=langflowai/langflow:nightly-base-${version},langflowai/langflow:nightly-base-latest,ghcr.io/langflow-ai/langflow:nightly-base-${version},ghcr.io/langflow-ai/langflow:nightly-base-latest" >> $GITHUB_OUTPUT - echo "arch_base=langflowai/langflow:nightly-base-${version}" >> $GITHUB_OUTPUT - echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow:nightly-base-${version}" >> $GITHUB_OUTPUT + echo "final_tags=langflowai/langflow-nightly:base-${version},langflowai/langflow-nightly:base-latest,ghcr.io/langflow-ai/langflow-nightly:base-${version},ghcr.io/langflow-ai/langflow-nightly:base-latest" >> $GITHUB_OUTPUT + echo "arch_base=langflowai/langflow-nightly:base-${version}" >> $GITHUB_OUTPUT + echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow-nightly:base-${version}" >> $GITHUB_OUTPUT ;; "nightly-main") - echo "final_tags=langflowai/langflow:nightly-${version},langflowai/langflow:nightly-latest,ghcr.io/langflow-ai/langflow:nightly-${version},ghcr.io/langflow-ai/langflow:nightly-latest" >> $GITHUB_OUTPUT - echo "arch_base=langflowai/langflow:nightly-${version}" >> $GITHUB_OUTPUT - echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow:nightly-${version}" >> $GITHUB_OUTPUT + echo "final_tags=langflowai/langflow-nightly:${version},langflowai/langflow-nightly:latest,ghcr.io/langflow-ai/langflow-nightly:${version},ghcr.io/langflow-ai/langflow-nightly:latest" >> $GITHUB_OUTPUT + echo "arch_base=langflowai/langflow-nightly:${version}" >> $GITHUB_OUTPUT + echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow-nightly:${version}" >> $GITHUB_OUTPUT ;; "nightly-main-all") - echo "final_tags=langflowai/langflow-all:nightly-${version},langflowai/langflow-all:nightly-latest,ghcr.io/langflow-ai/langflow-all:nightly-${version},ghcr.io/langflow-ai/langflow-all:nightly-latest" >> $GITHUB_OUTPUT - echo "arch_base=langflowai/langflow-all:nightly-${version}" >> $GITHUB_OUTPUT - echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow-all:nightly-${version}" >> $GITHUB_OUTPUT + echo "final_tags=langflowai/langflow-nightly-all:${version},langflowai/langflow-nightly-all:latest,ghcr.io/langflow-ai/langflow-nightly-all:${version},ghcr.io/langflow-ai/langflow-nightly-all:latest" >> $GITHUB_OUTPUT + echo "arch_base=langflowai/langflow-nightly-all:${version}" >> $GITHUB_OUTPUT + echo "ghcr_arch_base=ghcr.io/langflow-ai/langflow-nightly-all:${version}" >> $GITHUB_OUTPUT ;; *) echo "Error: Invalid release_type: ${{ inputs.release_type }}" >&2 diff --git a/.github/workflows/docs_test.yml b/.github/workflows/docs_test.yml index a18700b99a0f..b626bd97a8d1 100644 --- a/.github/workflows/docs_test.yml +++ b/.github/workflows/docs_test.yml @@ -10,7 +10,7 @@ on: type: string env: - NODE_VERSION: "21" + NODE_VERSION: "22" jobs: test-docs-build: diff --git a/.github/workflows/jest_test.yml b/.github/workflows/jest_test.yml index 82c4c0539789..fcdd149b4680 100644 --- a/.github/workflows/jest_test.yml +++ b/.github/workflows/jest_test.yml @@ -18,7 +18,7 @@ on: type: string env: - NODE_VERSION: "21" + NODE_VERSION: "22" jobs: jest-unit-tests: diff --git a/.github/workflows/js_autofix.yml b/.github/workflows/js_autofix.yml index 2b45392613a6..da20c6acb0dd 100644 --- a/.github/workflows/js_autofix.yml +++ b/.github/workflows/js_autofix.yml @@ -9,7 +9,7 @@ permissions: contents: read env: - NODE_VERSION: "21" + NODE_VERSION: "22" jobs: autofix: runs-on: ubuntu-latest diff --git a/.github/workflows/lint-js.yml b/.github/workflows/lint-js.yml index f8ad87222359..46684ad6e1f4 100644 --- a/.github/workflows/lint-js.yml +++ b/.github/workflows/lint-js.yml @@ -11,7 +11,7 @@ on: env: - NODE_VERSION: "21" + NODE_VERSION: "22" jobs: run-linters: diff --git a/.github/workflows/python_test.yml b/.github/workflows/python_test.yml index 6d2ccec737fc..447d7ba9c39d 100644 --- a/.github/workflows/python_test.yml +++ b/.github/workflows/python_test.yml @@ -47,7 +47,7 @@ on: default: ubuntu-latest env: POETRY_VERSION: "1.8.2" - NODE_VERSION: "21" + NODE_VERSION: "22" PYTEST_RUN_PATH: "src/backend/tests" OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} @@ -145,6 +145,7 @@ jobs: PYLEAK_LOG_LEVEL: debug # enable pyleak logging DO_NOT_TRACK: true # disable telemetry reporting + lfx-tests: name: LFX Tests - Python ${{ matrix.python-version }} runs-on: ${{ (inputs['runs-on'] && startsWith(format('{0}', inputs['runs-on']), '[') && fromJSON(inputs['runs-on'])) || inputs['runs-on'] || github.event.inputs['runs-on'] || 'ubuntu-latest' }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ba3a216655c4..9329218bcd8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,11 @@ on: required: true type: boolean default: false + release_lfx: + description: "WARNING: Not implemented yet." + required: true + type: boolean + default: false build_docker_base: description: "Build Docker Image for Langflow Base" required: true @@ -28,11 +33,6 @@ on: required: true type: boolean default: false - build_docker_ep: - description: "Build Docker Image for Langflow with Entrypoint" - required: false - type: boolean - default: false pre_release: description: "Pre-release" required: false @@ -42,22 +42,12 @@ on: description: "Whether to create a gh release" required: false type: boolean - default: true - release_lfx: - description: "Release LFX" - required: false - type: boolean default: false - runs_on: - description: "Runner to use for CI tests (use self-hosted for safe/release code)" + dry_run: + description: "Dry run mode - disables all pushes to external services (PyPI, Docker, GitHub releases)" required: false - type: choice - options: - - ubuntu-latest - - self-hosted - - "[Langflow-runner]" - - "[self-hosted, linux, ARM64, langflow-ai-arm64-40gb]" - default: ubuntu-latest + type: boolean + default: true @@ -74,10 +64,9 @@ jobs: echo "release_lfx: ${{ inputs.release_lfx }}" echo "build_docker_base: ${{ inputs.build_docker_base }}" echo "build_docker_main: ${{ inputs.build_docker_main }}" - echo "build_docker_ep: ${{ inputs.build_docker_ep }}" echo "pre_release: ${{ inputs.pre_release }}" echo "create_release: ${{ inputs.create_release }}" - echo "runs_on: ${{ inputs.runs_on }}" + echo "dry_run: ${{ inputs.dry_run }}" validate-tag: name: Validate Tag Input @@ -105,24 +94,46 @@ jobs: echo "Validated: '${{ inputs.release_tag }}' is a valid tag." + validate-dependencies: + name: Validate Release Dependencies + runs-on: ubuntu-latest + if: ${{ inputs.release_package_base || inputs.release_package_main || inputs.release_lfx || inputs.build_docker_base || inputs.build_docker_main }} + needs: [validate-tag] + steps: + - name: Validate that build-base is enabled if build-main is enabled + run: | + if [ "${{ inputs.release_package_main }}" = "true" ] && [ "${{ inputs.release_package_base }}" = "false" ]; then + echo "Error: Cannot release Langflow Main without releasing Langflow Base." + echo "Please enable 'release_package_base' or disable 'release_package_main'." + exit 1 + fi + + if [ "${{ inputs.release_lfx }}" = "true" ]; then + echo "Error: Release LFX is not implemented yet." + echo "Please disable 'release_lfx' or wait for it to be implemented." + exit 1 + fi + + echo "✅ Release dependencies validated successfully." + ci: - if: inputs.release_package_base || inputs.release_package_main || inputs.release_lfx name: CI - needs: [validate-tag] + needs: [validate-tag, validate-dependencies] uses: ./.github/workflows/ci.yml with: - branch: ${{ inputs.release_tag }} + ref: ${{ inputs.release_tag }} python-versions: "['3.10', '3.11', '3.12', '3.13']" frontend-tests-folder: "tests" release: true - runs-on: ${{ (inputs['runs_on'] && startsWith(format('{0}', inputs['runs_on']), '[') && fromJSON(inputs['runs_on'])) || inputs['runs_on'] || inputs['runs_on'] || 'ubuntu-latest' }} + run-all-tests: true + runs-on: ubuntu-latest secrets: inherit build-base: name: Build Langflow Base needs: [ci] - if: inputs.release_package_base + if: ${{ inputs.release_package_base }} runs-on: ubuntu-latest outputs: version: ${{ steps.check-version.outputs.version }} @@ -151,7 +162,7 @@ jobs: if [ "$version" = "$last_released_version" ]; then echo "Version $version is already released. Skipping release." echo skipped=true >> $GITHUB_OUTPUT - exit 0 + exit 1 else echo version=$version >> $GITHUB_OUTPUT echo skipped=false >> $GITHUB_OUTPUT @@ -192,7 +203,7 @@ jobs: build-main: name: Build Langflow Main - if: inputs.release_package_main + if: ${{ inputs.release_package_main }} needs: [build-base] runs-on: ubuntu-latest outputs: @@ -234,7 +245,7 @@ jobs: if [ "$version" = "$last_released_version" ]; then echo "Version $version is already released. Skipping release." echo skipped=true >> $GITHUB_OUTPUT - exit 0 + exit 1 else echo version=$version >> $GITHUB_OUTPUT fi @@ -272,18 +283,21 @@ jobs: test-cross-platform: name: Test Cross-Platform Installation - if: inputs.release_package_base || inputs.release_package_main - needs: [build-base, build-main, build-lfx] + needs: [build-base, build-main] + if: | + always() && + !cancelled() && + (needs.build-base.result == 'success' || needs.build-main.result == 'success') uses: ./.github/workflows/cross-platform-test.yml with: base-artifact-name: "dist-base" main-artifact-name: "dist-main" - lfx-artifact-name: ${{ inputs.release_lfx && 'dist-lfx' || '' }} + lfx-artifact-name: "${{ inputs.release_lfx && 'dist-lfx' || '' }}" publish-base: name: Publish Langflow Base to PyPI - if: inputs.release_package_base + if: ${{ inputs.release_package_base }} needs: [build-base, test-cross-platform] runs-on: ubuntu-latest steps: @@ -298,7 +312,7 @@ jobs: enable-cache: false python-version: "3.13" - name: Publish base to PyPI - if: needs.build-base.outputs.skipped == 'false' + if: ${{ !inputs.dry_run }} env: UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }} run: | @@ -306,7 +320,7 @@ jobs: publish-main: name: Publish Langflow Main to PyPI - if: inputs.release_package_main + if: ${{ inputs.release_package_main }} needs: [build-main, test-cross-platform, publish-base] runs-on: ubuntu-latest steps: @@ -321,6 +335,7 @@ jobs: enable-cache: false python-version: "3.13" - name: Publish main to PyPI + if: ${{ !inputs.dry_run }} env: UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }} run: | @@ -329,7 +344,7 @@ jobs: build-lfx: name: Build LFX needs: [ci] - if: inputs.release_lfx + if: ${{ inputs.release_lfx }} runs-on: ubuntu-latest outputs: version: ${{ steps.check-version.outputs.version }} @@ -377,7 +392,7 @@ jobs: test-lfx-cross-platform: name: Test LFX Cross-Platform Installation - if: inputs.release_lfx + if: ${{ inputs.release_lfx }} needs: [build-lfx] runs-on: ${{ matrix.os }} strategy: @@ -402,7 +417,7 @@ jobs: publish-lfx: name: Publish LFX to PyPI - if: inputs.release_lfx + if: ${{ inputs.release_lfx }} needs: [build-lfx, test-lfx-cross-platform] runs-on: ubuntu-latest steps: @@ -417,6 +432,7 @@ jobs: enable-cache: false python-version: "3.13" - name: Publish LFX to PyPI + if: ${{ !inputs.dry_run }} env: UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }} run: | @@ -424,46 +440,50 @@ jobs: call_docker_build_base: name: Call Docker Build Workflow for Langflow Base - if: inputs.build_docker_base - needs: [validate-tag] + if: ${{ inputs.build_docker_base }} + needs: [ci] uses: ./.github/workflows/docker-build-v2.yml with: ref: ${{ inputs.release_tag }} release_type: base pre_release: ${{ inputs.pre_release }} + push_to_registry: ${{ !inputs.dry_run }} secrets: inherit - call_docker_build_main_ep: - name: Call Docker Build Workflow for Langflow with Entrypoint - if: inputs.build_docker_ep - needs: [validate-tag] + call_docker_build_main: + name: Call Docker Build Workflow for Langflow + if: ${{ inputs.build_docker_main }} + needs: [ci] uses: ./.github/workflows/docker-build-v2.yml with: ref: ${{ inputs.release_tag }} - release_type: main-ep - pre_release: False + release_type: main + pre_release: ${{ inputs.pre_release }} + push_to_registry: ${{ !inputs.dry_run }} secrets: inherit - call_docker_build_main: - name: Call Docker Build Workflow for Langflow - if: inputs.build_docker_main - needs: [validate-tag] + call_docker_build_main_ep: + name: Call Docker Build Workflow for Langflow with Entrypoint + if: ${{ inputs.build_docker_main }} + needs: [ci] uses: ./.github/workflows/docker-build-v2.yml with: ref: ${{ inputs.release_tag }} - release_type: main + release_type: main-ep pre_release: ${{ inputs.pre_release }} + push_to_registry: ${{ !inputs.dry_run }} secrets: inherit call_docker_build_main_all: name: Call Docker Build Workflow for langflow-all - if: inputs.build_docker_main - needs: [validate-tag] + if: ${{ inputs.build_docker_main }} + needs: [ci] uses: ./.github/workflows/docker-build-v2.yml with: ref: ${{ inputs.release_tag }} release_type: main-all pre_release: ${{ inputs.pre_release }} + push_to_registry: ${{ !inputs.dry_run }} secrets: inherit @@ -471,29 +491,27 @@ jobs: create_release: name: Create Release runs-on: ubuntu-latest - needs: [build-main, build-lfx, publish-main, publish-lfx] - if: always() && inputs.create_release && (needs.publish-main.result == 'success' || needs.publish-lfx.result == 'success') + needs: [build-main, publish-main] + if: | + always() && + !cancelled() && + !inputs.dry_run && + inputs.create_release && + needs.build-main.result == 'success' && + needs.publish-main.result == 'success' steps: - - uses: actions/download-artifact@v5 - if: needs.publish-main.result == 'success' + - uses: actions/download-artifact@v4 with: name: dist-main path: dist - - uses: actions/download-artifact@v5 - if: needs.publish-lfx.result == 'success' - with: - name: dist-lfx - path: dist-lfx - name: Create Release uses: ncipollo/release-action@v1 with: - artifacts: | - dist/* - dist-lfx/* + artifacts: dist/* token: ${{ secrets.GITHUB_TOKEN }} draft: false generateReleaseNotes: true prerelease: ${{ inputs.pre_release }} - tag: ${{ needs.build-main.outputs.version || needs.build-lfx.outputs.version }} + tag: ${{ needs.build-main.outputs.version }} allowUpdates: true updateOnlyUnreleased: false diff --git a/.github/workflows/release_nightly.yml b/.github/workflows/release_nightly.yml index 4f6bbf2b3f1d..ea03795bb137 100644 --- a/.github/workflows/release_nightly.yml +++ b/.github/workflows/release_nightly.yml @@ -49,7 +49,7 @@ env: jobs: build-nightly-lfx: name: Build LFX Nightly - if: inputs.build_lfx + if: ${{ inputs.build_lfx }} runs-on: ubuntu-latest outputs: version: ${{ steps.verify.outputs.version }} @@ -114,7 +114,7 @@ jobs: build-nightly-base: name: Build Langflow Nightly Base needs: [build-nightly-lfx] - if: always() && (needs.build-nightly-lfx.result == 'success' || inputs.build_lfx == false) + if: ${{ always() && (needs.build-nightly-lfx.result == 'success' || inputs.build_lfx == false) }} runs-on: ubuntu-latest defaults: run: @@ -279,7 +279,7 @@ jobs: publish-nightly-lfx: name: Publish LFX Nightly to PyPI needs: [build-nightly-lfx, test-cross-platform] - if: inputs.build_lfx + if: ${{ inputs.build_lfx }} runs-on: ubuntu-latest steps: - name: Check out the code @@ -307,7 +307,7 @@ jobs: publish-nightly-base: name: Publish Langflow Base Nightly to PyPI needs: [build-nightly-base, test-cross-platform, publish-nightly-lfx] - if: always() && needs.build-nightly-base.result == 'success' && needs.test-cross-platform.result == 'success' && (needs.publish-nightly-lfx.result == 'success' || inputs.build_lfx == false) + if: ${{ always() && needs.build-nightly-base.result == 'success' && needs.test-cross-platform.result == 'success' && (needs.publish-nightly-lfx.result == 'success' || inputs.build_lfx == false) }} runs-on: ubuntu-latest steps: - name: Checkout code @@ -362,7 +362,7 @@ jobs: call_docker_build_base: name: Call Docker Build Workflow for Langflow Base - if: always() && inputs.build_docker_base + if: ${{ always() && inputs.build_docker_base }} needs: [build-nightly-base, build-nightly-main] uses: ./.github/workflows/docker-nightly-build.yml with: @@ -373,7 +373,7 @@ jobs: call_docker_build_main: name: Call Docker Build Workflow for Langflow - if: always() && inputs.build_docker_main + if: ${{ always() && inputs.build_docker_main }} needs: [build-nightly-main, call_docker_build_base] uses: ./.github/workflows/docker-nightly-build.yml with: @@ -396,7 +396,7 @@ jobs: call_docker_build_main_ep: name: Call Docker Build Workflow for Langflow with Entrypoint - if: always() && inputs.build_docker_ep + if: ${{ always() && inputs.build_docker_ep }} needs: [build-nightly-main, call_docker_build_main] uses: ./.github/workflows/docker-build-v2.yml with: diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 42090e09a280..e4c7511ac136 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -61,7 +61,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: "21" + node-version: "22" cache: "npm" cache-dependency-path: src/frontend/package-lock.json diff --git a/.github/workflows/typescript_test.yml b/.github/workflows/typescript_test.yml index 4f78d5272d57..4174ea753d83 100644 --- a/.github/workflows/typescript_test.yml +++ b/.github/workflows/typescript_test.yml @@ -64,7 +64,7 @@ on: default: ubuntu-latest env: - NODE_VERSION: "21" + NODE_VERSION: "22" PYTHON_VERSION: "3.13" # Define the directory where Playwright browsers will be installed. # This path is used for caching across workflows @@ -379,6 +379,8 @@ jobs: - name: Checkout code if: ${{ steps.should_merge_reports.outputs.should_merge_reports == 'true' }} uses: actions/checkout@v5 + with: + ref: ${{ inputs.ref || github.ref }} - name: Setup Node.js