diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 000000000000..3ab6698bf437 --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,4 @@ +self-hosted-runner: + labels: + - langflow-ai-arm64-40gb-ephemeral + - Langflow-runner diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b63797b97e81..1e7c5368a04f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,7 @@ on: options: - ubuntu-latest - self-hosted - - "[self-hosted, linux, ARM64, langflow-ai-arm64-40gb]" + - '["self-hosted", "linux", "ARM64", "langflow-ai-arm64-40gb-ephemeral"]' default: ubuntu-latest pull_request: types: [opened, synchronize, labeled] @@ -214,7 +214,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v6 with: - python-version: '3.12' + python-version: "3.12" - name: Install deps for coverage check run: | python -m pip install --upgrade pip @@ -241,7 +241,7 @@ jobs: 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' }} + 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 }}" @@ -274,7 +274,7 @@ jobs: 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' }} + 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 }}" diff --git a/.github/workflows/docker-build-v2.yml b/.github/workflows/docker-build-v2.yml index 8d321901f00e..ab7344399660 100644 --- a/.github/workflows/docker-build-v2.yml +++ b/.github/workflows/docker-build-v2.yml @@ -156,7 +156,8 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - name: Check out the code @@ -226,7 +227,8 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - name: Check out the code @@ -296,7 +298,8 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - name: Check out the code @@ -370,7 +373,8 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - name: Check out the code @@ -440,7 +444,8 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - name: Check out the code @@ -510,7 +515,8 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - name: Check out the code diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 61ffa65be09a..3f99bb5b4daf 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -58,7 +58,6 @@ on: type: boolean default: false - env: PYTHON_VERSION: "3.13" TEST_TAG: "langflowai/langflow:test" @@ -202,7 +201,7 @@ jobs: fi fi build: - runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] needs: [get-version, setup] steps: - name: Check out the code at a specific ref @@ -289,13 +288,14 @@ jobs: build_components: if: ${{ inputs.release_type == 'main' }} - runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] permissions: packages: write needs: [build, get-version] strategy: matrix: - component: [docker-backend, docker-frontend, ghcr-backend, ghcr-frontend] + component: + [docker-backend, docker-frontend, ghcr-backend, ghcr-frontend] include: - component: docker-backend dockerfile: ./docker/build_and_push_backend.Dockerfile @@ -342,7 +342,6 @@ jobs: image=moby/buildkit:v0.22.0 network=host - - name: Login to Docker Hub if: ${{ matrix.component == 'docker-backend' }} || ${{ matrix.component == 'docker-frontend' }} uses: docker/login-action@v3 @@ -400,6 +399,3 @@ jobs: - name: Restart HuggingFace Spaces Build run: | uv run ./scripts/factory_restart_space.py --space "Langflow/Langflow" --token ${{ secrets.HUGGINGFACE_API_TOKEN }} - - - diff --git a/.github/workflows/docker-nightly-build.yml b/.github/workflows/docker-nightly-build.yml index 661a66a4399e..66337feab554 100644 --- a/.github/workflows/docker-nightly-build.yml +++ b/.github/workflows/docker-nightly-build.yml @@ -51,10 +51,10 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - - name: Check out the code uses: actions/checkout@v6 with: @@ -145,10 +145,10 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - - name: Check out the code uses: actions/checkout@v6 with: @@ -238,10 +238,10 @@ jobs: - arch: amd64 runner: [Langflow-runner] - arch: arm64 - runner: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runner: + [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] runs-on: ${{ matrix.runner }} steps: - - name: Check out the code uses: actions/checkout@v6 with: @@ -411,4 +411,4 @@ jobs: --tag "$tag" \ "$amd64_tag" \ "$arm64_tag" - done \ No newline at end of file + done diff --git a/.github/workflows/docker_test.yml b/.github/workflows/docker_test.yml index c7d138548340..b68f99a07934 100644 --- a/.github/workflows/docker_test.yml +++ b/.github/workflows/docker_test.yml @@ -14,7 +14,7 @@ env: jobs: test-docker: - runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb] + runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb-ephemeral] name: Test docker images steps: - uses: actions/checkout@v6 diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index 89407c1c21ae..b5b16c517845 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -10,7 +10,7 @@ on: options: - ubuntu-latest - self-hosted - - "[self-hosted, linux, ARM64, langflow-ai-arm64-40gb]" + - '["self-hosted", "linux", "ARM64", "langflow-ai-arm64-40gb-ephemeral"]' default: ubuntu-latest skip_frontend_tests: description: "Skip frontend tests. Only do this for testing purposes." @@ -197,7 +197,7 @@ jobs: with: ref: ${{ needs.create-nightly-tag.outputs.main_tag }} persist-credentials: true - + - name: "Setup Environment" uses: astral-sh/setup-uv@v6 with: @@ -205,32 +205,32 @@ jobs: cache-dependency-glob: "uv.lock" python-version: ${{ env.PYTHON_VERSION }} prune-cache: false - + - name: Install the project run: uv sync - + - name: Force reinstall LFX to pick up version change run: | echo "Force reinstalling lfx-nightly to ensure version metadata is updated..." uv pip install --reinstall --no-deps src/lfx - + - name: Verify LFX version run: | echo "Checking installed LFX version..." uv run python -c "from importlib.metadata import version; print(f'lfx-nightly version: {version(\"lfx-nightly\")}')" || \ uv run python -c "from importlib.metadata import version; print(f'lfx version: {version(\"lfx\")}')" - + - name: Build and validate nightly hash history run: | # The script includes append-only validation uv run python scripts/build_hash_history.py --nightly - + - name: Commit and push hash history changes run: | echo "=== Configuring git ===" git config --global user.email "bot-nightly-builds@langflow.org" git config --global user.name "Langflow Bot" - + echo "=== Checking for hash history changes ===" # Check if there are changes to commit (handles if it's a new file for first run) git add src/lfx/src/lfx/_assets/nightly_hash_history.json @@ -240,26 +240,26 @@ jobs: echo "Hash history changes detected, committing..." # Commit to the nightly tag itself so builds include the hash history git commit -m "Update nightly hash history for ${{ needs.create-nightly-tag.outputs.main_tag }}" - + echo "=== Updating nightly tag ${{ needs.create-nightly-tag.outputs.main_tag }} ===" # Update the tag to include the hash history git tag -f ${{ needs.create-nightly-tag.outputs.main_tag }} git push -f origin ${{ needs.create-nightly-tag.outputs.main_tag }} - + echo "=== Creating clean branch from main with only hash history changes ===" # Fetch latest main git fetch origin main - + # Create a new branch from main git checkout -B nightly-hash-history-updates origin/main - + # Copy ONLY the hash history file from the nightly tag git checkout ${{ needs.create-nightly-tag.outputs.main_tag }} -- src/lfx/src/lfx/_assets/nightly_hash_history.json - + # Commit only this file git add src/lfx/src/lfx/_assets/nightly_hash_history.json git commit -m "Update nightly hash history for ${{ needs.create-nightly-tag.outputs.main_tag }}" - + # Force push the clean branch git push origin nightly-hash-history-updates --force echo "Updated nightly tag and created clean branch with only hash history changes" @@ -273,7 +273,7 @@ jobs: with: tests_folder: "tests" release: true - 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' }} + runs-on: ${{ inputs['runs_on'] || github.event.inputs['runs_on'] || 'ubuntu-latest' }} secrets: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} STORE_API_KEY: ${{ secrets.STORE_API_KEY }} @@ -287,7 +287,7 @@ jobs: uses: ./.github/workflows/python_test.yml with: python-versions: '["3.10", "3.11", "3.12", "3.13"]' - 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' }} + runs-on: ${{ inputs['runs_on'] || github.event.inputs['runs_on'] || 'ubuntu-latest' }} secrets: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} @@ -341,7 +341,7 @@ jobs: elif [ "${{ needs.merge-hash-history-to-main.result }}" == "failure" ]; then FAILED_JOB="merge-hash-history-to-main" fi - + curl -X POST -H 'Content-type: application/json' \ --data "{ \"blocks\": [ @@ -395,12 +395,12 @@ jobs: ref: main fetch-depth: 0 persist-credentials: true - + - name: Configure Git run: | git config --global user.email "bot-nightly-builds@langflow.org" git config --global user.name "Langflow Bot" - + - name: "Setup Environment" uses: astral-sh/setup-uv@v6 with: @@ -408,13 +408,13 @@ jobs: cache-dependency-glob: "uv.lock" python-version: ${{ env.PYTHON_VERSION }} prune-cache: false - + - name: Fetch nightly hash history branch run: | echo "=== Fetching nightly-hash-history-updates branch ===" git fetch origin nightly-hash-history-updates || true echo "Fetch completed" - + - name: Check if branch exists and has changes id: check_branch run: | @@ -422,7 +422,7 @@ jobs: if git rev-parse --verify origin/nightly-hash-history-updates >/dev/null 2>&1; then echo "branch_exists=true" >> $GITHUB_OUTPUT echo "Branch exists" - + # Check if there are differences between main and the nightly branch echo "=== Comparing with main branch ===" if git diff --quiet main origin/nightly-hash-history-updates -- src/lfx/src/lfx/_assets/nightly_hash_history.json; then @@ -439,14 +439,14 @@ jobs: echo "This should have been created by the build-hash-history job." exit 1 fi - + - name: Validate and prepare PR if: steps.check_branch.outputs.branch_exists == 'true' && steps.check_branch.outputs.has_changes == 'true' run: | echo "=== Checking out hash history file from nightly branch ===" # Checkout the nightly hash history file to verify it git checkout origin/nightly-hash-history-updates -- src/lfx/src/lfx/_assets/nightly_hash_history.json - + echo "=== Verifying only hash history file was modified ===" # Verify that ONLY the nightly_hash_history.json file was modified CHANGED_FILES=$(git diff --name-only main) @@ -456,23 +456,23 @@ jobs: exit 1 fi echo "Only hash history file modified" - + echo "=== Validating hash history file ===" # Basic validation - ensure file exists and is valid JSON - + if [ ! -f "src/lfx/src/lfx/_assets/nightly_hash_history.json" ]; then echo "ERROR: nightly_hash_history.json file was deleted!" exit 1 fi - + if ! uv run python -c "import json; json.load(open('src/lfx/src/lfx/_assets/nightly_hash_history.json'))"; then echo "ERROR: nightly_hash_history.json is not valid JSON!" exit 1 fi - + echo "Hash history file validation passed" echo "Note: Append-only validation was performed during the build step" - + - name: Create Pull Request if: steps.check_branch.outputs.branch_exists == 'true' && steps.check_branch.outputs.has_changes == 'true' env: @@ -494,16 +494,16 @@ jobs: Auto-merge is enabled - PR will merge automatically when checks pass. run: | echo "=== Creating or updating PR ===" - + # Check if PR already exists EXISTING_PR=$(gh pr list --head nightly-hash-history-updates --base main --json number --jq '.[0].number' 2>/dev/null || echo "") - + if [ -n "$EXISTING_PR" ]; then echo "PR #$EXISTING_PR already exists, updating..." gh pr edit "$EXISTING_PR" \ --title "chore: update nightly hash history" \ --body "$PR_BODY" - + echo "PR updated successfully" PR_NUMBER="$EXISTING_PR" else @@ -513,12 +513,12 @@ jobs: --body "$PR_BODY" \ --base main \ --head nightly-hash-history-updates) - + echo "PR created: $PR_URL" # Extract PR number from URL (works with both formats) PR_NUMBER=$(echo "$PR_URL" | sed 's/.*\/pull\///' | sed 's/[^0-9].*//') fi - + # Enable auto-merge on the PR echo "=== Enabling auto-merge ===" if gh pr merge "$PR_NUMBER" --auto --squash; then diff --git a/.github/workflows/python_test.yml b/.github/workflows/python_test.yml index f1e6d7b30211..bab24fe61f52 100644 --- a/.github/workflows/python_test.yml +++ b/.github/workflows/python_test.yml @@ -43,7 +43,7 @@ on: options: - ubuntu-latest - self-hosted - - "[self-hosted, linux, ARM64, langflow-ai-arm64-40gb]" + - '["self-hosted", "linux", "ARM64", "langflow-ai-arm64-40gb-ephemeral"]' default: ubuntu-latest env: POETRY_VERSION: "1.8.2" @@ -54,7 +54,6 @@ env: jobs: build: - name: Unit Tests - Python ${{ matrix.python-version }} - Group ${{ matrix.group }} 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' }} strategy: @@ -119,7 +118,6 @@ jobs: htmlcov/ retention-days: 30 - integration-tests: name: Integration 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' }} @@ -145,7 +143,6 @@ 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' }} @@ -256,4 +253,3 @@ jobs: else echo "Server terminated successfully" fi - diff --git a/.github/workflows/typescript_test.yml b/.github/workflows/typescript_test.yml index bfd5a4479b82..32ffccd5c991 100644 --- a/.github/workflows/typescript_test.yml +++ b/.github/workflows/typescript_test.yml @@ -60,7 +60,7 @@ on: options: - ubuntu-latest - self-hosted - - "[self-hosted, linux, ARM64, langflow-ai-arm64-40gb]" + - '["self-hosted", "linux", "ARM64", "langflow-ai-arm64-40gb-ephemeral"]' default: ubuntu-latest env: diff --git a/.secrets.baseline b/.secrets.baseline index 4f3b3cde851d..c3a1c50ff905 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -153,7 +153,7 @@ "filename": ".github/workflows/nightly_build.yml", "hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0", "is_verified": false, - "line_number": 232, + "line_number": 322, "is_secret": false } ], @@ -755,6 +755,56 @@ "is_secret": false } ], + "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json": [ + { + "type": "Hex High Entropy String", + "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", + "hashed_secret": "54ed260e3bc31bc77ee06754dff850981d39a66c", + "is_verified": false, + "line_number": 357, + "is_secret": false + }, + { + "type": "Hex High Entropy String", + "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", + "hashed_secret": "35be14614e83fe56d9b2ca1c0e2c2a74890b6889", + "is_verified": false, + "line_number": 625, + "is_secret": false + }, + { + "type": "Secret Keyword", + "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", + "hashed_secret": "665b1e3851eefefa3fb878654292f16597d25155", + "is_verified": false, + "line_number": 1400, + "is_secret": false + }, + { + "type": "Secret Keyword", + "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", + "hashed_secret": "3f2df46921dd8e2c36e2ce85238705ac0774c74a", + "is_verified": false, + "line_number": 1535, + "is_secret": false + }, + { + "type": "Secret Keyword", + "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", + "hashed_secret": "d3d6fe3f7d33d0f4aa28c49544a865982a48a00a", + "is_verified": false, + "line_number": 1595, + "is_secret": false + }, + { + "type": "Secret Keyword", + "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", + "hashed_secret": "d4c3d66fd0c38547a3c7a4c6bdc29c36911bc030", + "is_verified": false, + "line_number": 1660, + "is_secret": false + } + ], "src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json": [ { "type": "Hex High Entropy String", @@ -871,56 +921,6 @@ "is_secret": false } ], - "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json": [ - { - "type": "Hex High Entropy String", - "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", - "hashed_secret": "54ed260e3bc31bc77ee06754dff850981d39a66c", - "is_verified": false, - "line_number": 357, - "is_secret": false - }, - { - "type": "Hex High Entropy String", - "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", - "hashed_secret": "35be14614e83fe56d9b2ca1c0e2c2a74890b6889", - "is_verified": false, - "line_number": 625, - "is_secret": false - }, - { - "type": "Secret Keyword", - "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", - "hashed_secret": "665b1e3851eefefa3fb878654292f16597d25155", - "is_verified": false, - "line_number": 1400, - "is_secret": false - }, - { - "type": "Secret Keyword", - "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", - "hashed_secret": "3f2df46921dd8e2c36e2ce85238705ac0774c74a", - "is_verified": false, - "line_number": 1535, - "is_secret": false - }, - { - "type": "Secret Keyword", - "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", - "hashed_secret": "d3d6fe3f7d33d0f4aa28c49544a865982a48a00a", - "is_verified": false, - "line_number": 1595, - "is_secret": false - }, - { - "type": "Secret Keyword", - "filename": "src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json", - "hashed_secret": "d4c3d66fd0c38547a3c7a4c6bdc29c36911bc030", - "is_verified": false, - "line_number": 1660, - "is_secret": false - } - ], "src/backend/base/langflow/inputs/input_mixin.py": [ { "type": "Secret Keyword", @@ -1578,5 +1578,5 @@ } ] }, - "generated_at": "2026-02-04T17:26:15Z" + "generated_at": "2026-02-12T23:14:51Z" }