|
23 | 23 | type: boolean |
24 | 24 | default: false |
25 | 25 | skip_slack: |
26 | | - description: "Skip slack message on failure. Only do this for testing purposes." |
| 26 | + description: "Skip slack message. Only do this for testing purposes." |
27 | 27 | required: false |
28 | 28 | type: boolean |
29 | 29 | default: false |
|
32 | 32 | required: false |
33 | 33 | type: boolean |
34 | 34 | default: true |
| 35 | + auto_merge_hash_history: |
| 36 | + description: "Create PR to merge hash history back to main. Set to false when not running from main." |
| 37 | + required: false |
| 38 | + type: boolean |
| 39 | + default: true |
35 | 40 | schedule: |
36 | 41 | # Run job at 00:00 UTC (4:00 PM PST / 5:00 PM PDT) |
37 | 42 | - cron: "0 0 * * *" |
@@ -128,6 +133,7 @@ jobs: |
128 | 133 |
|
129 | 134 | uv lock |
130 | 135 | cd src/backend/base && uv lock && cd ../../.. |
| 136 | + cd src/lfx && uv lock && cd ../.. |
131 | 137 |
|
132 | 138 | git add pyproject.toml src/backend/base/pyproject.toml src/lfx/pyproject.toml uv.lock src/backend/base/uv.lock |
133 | 139 | git commit -m "Update version and project name" |
@@ -175,6 +181,77 @@ jobs: |
175 | 181 | exit 1 |
176 | 182 | fi |
177 | 183 |
|
| 184 | + build-hash-history: |
| 185 | + if: github.repository == 'langflow-ai/langflow' |
| 186 | + name: Build Nightly Hash History |
| 187 | + needs: create-nightly-tag |
| 188 | + runs-on: ubuntu-latest |
| 189 | + defaults: |
| 190 | + run: |
| 191 | + shell: bash -ex -o pipefail {0} |
| 192 | + permissions: |
| 193 | + contents: write |
| 194 | + steps: |
| 195 | + - name: Checkout nightly tag |
| 196 | + uses: actions/checkout@v6 |
| 197 | + with: |
| 198 | + ref: ${{ needs.create-nightly-tag.outputs.main_tag }} |
| 199 | + persist-credentials: true |
| 200 | + |
| 201 | + - name: "Setup Environment" |
| 202 | + uses: astral-sh/setup-uv@v6 |
| 203 | + with: |
| 204 | + enable-cache: true |
| 205 | + cache-dependency-glob: "uv.lock" |
| 206 | + python-version: ${{ env.PYTHON_VERSION }} |
| 207 | + prune-cache: false |
| 208 | + |
| 209 | + - name: Install the project |
| 210 | + run: uv sync |
| 211 | + |
| 212 | + - name: Force reinstall LFX to pick up version change |
| 213 | + run: | |
| 214 | + echo "Force reinstalling lfx-nightly to ensure version metadata is updated..." |
| 215 | + uv pip install --reinstall --no-deps src/lfx |
| 216 | + |
| 217 | + - name: Verify LFX version |
| 218 | + run: | |
| 219 | + echo "Checking installed LFX version..." |
| 220 | + uv run python -c "from importlib.metadata import version; print(f'lfx-nightly version: {version(\"lfx-nightly\")}')" || \ |
| 221 | + uv run python -c "from importlib.metadata import version; print(f'lfx version: {version(\"lfx\")}')" |
| 222 | + |
| 223 | + - name: Build and validate nightly hash history |
| 224 | + run: | |
| 225 | + # The script includes append-only validation |
| 226 | + uv run python scripts/build_hash_history.py --nightly |
| 227 | + |
| 228 | + - name: Commit and push hash history changes |
| 229 | + run: | |
| 230 | + echo "=== Configuring git ===" |
| 231 | + git config --global user.email "bot-nightly-builds@langflow.org" |
| 232 | + git config --global user.name "Langflow Bot" |
| 233 | + |
| 234 | + echo "=== Checking for hash history changes ===" |
| 235 | + # Check if there are changes to commit (handles if it's a new file for first run) |
| 236 | + git add src/lfx/src/lfx/_assets/nightly_hash_history.json |
| 237 | + if git diff --cached --quiet src/lfx/src/lfx/_assets/nightly_hash_history.json; then |
| 238 | + echo "No changes to nightly hash history" |
| 239 | + else |
| 240 | + echo "Hash history changes detected, committing..." |
| 241 | + # Commit to the nightly tag itself so builds include the hash history |
| 242 | + git commit -m "Update nightly hash history for ${{ needs.create-nightly-tag.outputs.main_tag }}" |
| 243 | + |
| 244 | + echo "=== Updating nightly tag ${{ needs.create-nightly-tag.outputs.main_tag }} ===" |
| 245 | + # Update the tag to include the hash history |
| 246 | + git tag -f ${{ needs.create-nightly-tag.outputs.main_tag }} |
| 247 | + git push -f origin ${{ needs.create-nightly-tag.outputs.main_tag }} |
| 248 | + |
| 249 | + echo "=== Pushing to nightly-hash-history-updates branch ===" |
| 250 | + # Also push to the branch for PR creation |
| 251 | + git push origin HEAD:refs/heads/nightly-hash-history-updates --force |
| 252 | + echo "Updated nightly tag and branch with hash history changes" |
| 253 | + fi |
| 254 | +
|
178 | 255 | frontend-tests: |
179 | 256 | if: github.repository == 'langflow-ai/langflow' && !inputs.skip_frontend_tests |
180 | 257 | name: Run Frontend Tests |
@@ -214,9 +291,9 @@ jobs: |
214 | 291 | # ref: ${{ needs.create-nightly-tag.outputs.tag }} |
215 | 292 |
|
216 | 293 | release-nightly-build: |
217 | | - if: github.repository == 'langflow-ai/langflow' && always() && needs.frontend-tests.result != 'failure' && needs.backend-unit-tests.result != 'failure' |
| 294 | + if: github.repository == 'langflow-ai/langflow' && always() && needs.frontend-tests.result != 'failure' && needs.backend-unit-tests.result != 'failure' && needs.build-hash-history.result != 'failure' |
218 | 295 | name: Run Nightly Langflow Build |
219 | | - needs: [create-nightly-tag, frontend-tests, backend-unit-tests] |
| 296 | + needs: [create-nightly-tag, frontend-tests, backend-unit-tests, build-hash-history] |
220 | 297 | uses: ./.github/workflows/release_nightly.yml |
221 | 298 | with: |
222 | 299 | build_docker_base: true |
@@ -275,8 +352,131 @@ jobs: |
275 | 352 | ] |
276 | 353 | }' ${{ secrets.LANGFLOW_ENG_SLACK_WEBHOOK_URL }} |
277 | 354 |
|
| 355 | + merge-hash-history-to-main: |
| 356 | + name: Create PR to Merge Hash History to Main |
| 357 | + needs: [create-nightly-tag, build-hash-history, release-nightly-build] |
| 358 | + # Run if auto_merge_hash_history is true (default) or not set (scheduled runs) |
| 359 | + # When triggered by schedule, inputs.auto_merge_hash_history is not set, so default to true |
| 360 | + # Only run when the base branch is 'main' to prevent PRs from feature branches |
| 361 | + if: github.repository == 'langflow-ai/langflow' && github.ref == 'refs/heads/main' && always() && needs.build-hash-history.result == 'success' && needs.release-nightly-build.result == 'success' && (github.event_name == 'schedule' || inputs.auto_merge_hash_history != false) |
| 362 | + runs-on: ubuntu-latest |
| 363 | + permissions: |
| 364 | + contents: write |
| 365 | + pull-requests: write |
| 366 | + steps: |
| 367 | + - name: Checkout main branch |
| 368 | + uses: actions/checkout@v6 |
| 369 | + with: |
| 370 | + ref: main |
| 371 | + fetch-depth: 0 |
| 372 | + persist-credentials: true |
| 373 | + |
| 374 | + - name: Configure Git |
| 375 | + run: | |
| 376 | + git config --global user.email "bot-nightly-builds@langflow.org" |
| 377 | + git config --global user.name "Langflow Bot" |
| 378 | + |
| 379 | + - name: "Setup Environment" |
| 380 | + uses: astral-sh/setup-uv@v6 |
| 381 | + with: |
| 382 | + enable-cache: true |
| 383 | + cache-dependency-glob: "uv.lock" |
| 384 | + python-version: ${{ env.PYTHON_VERSION }} |
| 385 | + prune-cache: false |
| 386 | + |
| 387 | + - name: Fetch nightly hash history branch |
| 388 | + run: | |
| 389 | + echo "=== Fetching nightly-hash-history-updates branch ===" |
| 390 | + git fetch origin nightly-hash-history-updates || echo "Branch does not exist yet, will be created" |
| 391 | + echo "Fetch completed" |
| 392 | + |
| 393 | + - name: Check if branch exists and has changes |
| 394 | + id: check_branch |
| 395 | + run: | |
| 396 | + echo "=== Checking branch status ===" |
| 397 | + if git rev-parse --verify origin/nightly-hash-history-updates >/dev/null 2>&1; then |
| 398 | + echo "branch_exists=true" >> $GITHUB_OUTPUT |
| 399 | + echo "Branch exists" |
| 400 | + |
| 401 | + # Check if there are differences between main and the nightly branch |
| 402 | + echo "=== Comparing with main branch ===" |
| 403 | + if git diff --quiet main origin/nightly-hash-history-updates -- src/lfx/src/lfx/_assets/nightly_hash_history.json; then |
| 404 | + echo "has_changes=false" >> $GITHUB_OUTPUT |
| 405 | + echo "No changes to merge" |
| 406 | + else |
| 407 | + echo "has_changes=true" >> $GITHUB_OUTPUT |
| 408 | + echo "Changes detected - PR will be created/updated" |
| 409 | + fi |
| 410 | + else |
| 411 | + echo "branch_exists=false" >> $GITHUB_OUTPUT |
| 412 | + echo "has_changes=false" >> $GITHUB_OUTPUT |
| 413 | + echo "Branch does not exist yet - will be created by build-hash-history job" |
| 414 | + fi |
| 415 | + |
| 416 | + - name: Validate and prepare PR |
| 417 | + if: steps.check_branch.outputs.branch_exists == 'true' && steps.check_branch.outputs.has_changes == 'true' |
| 418 | + run: | |
| 419 | + echo "=== Checking out hash history file from nightly branch ===" |
| 420 | + # Checkout the nightly hash history file to verify it |
| 421 | + git checkout origin/nightly-hash-history-updates -- src/lfx/src/lfx/_assets/nightly_hash_history.json |
| 422 | + |
| 423 | + echo "=== Verifying only hash history file was modified ===" |
| 424 | + # Verify that ONLY the nightly_hash_history.json file was modified |
| 425 | + CHANGED_FILES=$(git diff --name-only main) |
| 426 | + if [ "$CHANGED_FILES" != "src/lfx/src/lfx/_assets/nightly_hash_history.json" ]; then |
| 427 | + echo "ERROR: Unexpected files were modified: $CHANGED_FILES" |
| 428 | + echo "Only nightly_hash_history.json should be changed" |
| 429 | + exit 1 |
| 430 | + fi |
| 431 | + echo "Only hash history file modified" |
| 432 | + |
| 433 | + echo "=== Validating hash history file ===" |
| 434 | + # Basic validation - ensure file exists and is valid JSON |
| 435 | + |
| 436 | + if [ ! -f "src/lfx/src/lfx/_assets/nightly_hash_history.json" ]; then |
| 437 | + echo "ERROR: nightly_hash_history.json file was deleted!" |
| 438 | + exit 1 |
| 439 | + fi |
| 440 | + |
| 441 | + if ! uv run python -c "import json; json.load(open('src/lfx/src/lfx/_assets/nightly_hash_history.json'))"; then |
| 442 | + echo "ERROR: nightly_hash_history.json is not valid JSON!" |
| 443 | + exit 1 |
| 444 | + fi |
| 445 | + |
| 446 | + echo "Hash history file validation passed" |
| 447 | + echo "Note: Append-only validation was performed during the build step" |
| 448 | + |
| 449 | + - name: Create Pull Request |
| 450 | + if: steps.check_branch.outputs.branch_exists == 'true' && steps.check_branch.outputs.has_changes == 'true' |
| 451 | + env: |
| 452 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 453 | + run: | |
| 454 | + # Create or update PR from the nightly-hash-history-updates branch |
| 455 | + PR_URL=$(gh pr create \ |
| 456 | + --title "chore: update nightly hash history" \ |
| 457 | + --body "This PR updates the nightly hash history file with the latest component hashes from the nightly build. |
| 458 | +
|
| 459 | + **Automated PR** - Generated by nightly build workflow |
| 460 | + |
| 461 | + - Updates: \`src/lfx/src/lfx/_assets/nightly_hash_history.json\` |
| 462 | + - Source: Nightly build tag ${{ needs.create-nightly-tag.outputs.main_tag }} |
| 463 | + |
| 464 | + This PR is automatically updated each night with the latest hash history. |
| 465 | + Auto-merge is enabled - PR will merge automatically when checks pass." \ |
| 466 | + --base main \ |
| 467 | + --head nightly-hash-history-updates \ |
| 468 | + --label "automated" \ |
| 469 | + --label "nightly" 2>&1 || echo "") |
| 470 | + |
| 471 | + # Enable auto-merge if PR was created or get existing PR |
| 472 | + if [ -n "$PR_URL" ]; then |
| 473 | + echo "PR created or found: $PR_URL" |
| 474 | + # Enable auto-merge on the PR |
| 475 | + gh pr merge nightly-hash-history-updates --auto --squash || echo "Auto-merge may already be enabled or PR doesn't exist yet" |
| 476 | + fi |
| 477 | +
|
278 | 478 | - name: Send success notification to Slack |
279 | | - if: ${{ needs.release-nightly-build.result == 'success' }} |
| 479 | + if: ${{ !inputs.skip_slack && needs.release-nightly-build.result == 'success' }} |
280 | 480 | run: | |
281 | 481 | curl -X POST -H 'Content-type: application/json' \ |
282 | 482 | --data '{ |
|
0 commit comments