Skip to content

Conversation

@Adam-Aghili
Copy link
Collaborator

@Adam-Aghili Adam-Aghili commented Jan 15, 2026

update pre-release flow to be useable for qa

  • create python script to auto incremenet rc version so we do not need to manually maintain what version we are on
  • fix pre-release flow to create identifiable langflow images. They are in out main image distros and not seperated like our nigtlys
  • we can use standard v1.8.0 or 1.8.0 tags and just select pre-release to create a rc image
  • should prevent overwritting images will close other pr if this one works better

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced Local storage location option across multiple starter project templates (Document Q&A, News Aggregator, Portfolio Website Code Generator, Text Sentiment Analysis, Vector Store RAG), enabling users to save project outputs to local file systems.
  • Chores

    • Updated package dependency versions.

✏️ Tip: You can customize this high-level summary in your review settings.

allow prerelease versions dedicated to qa
use a python script to auto incremenet rc version so we do not have to manually maintain what rc version we are on.
add it to both release.yml and docker-build-v2.yml for pypi, docker and ghrc.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR introduces centralized version determination logic into GitHub Actions workflows, replacing per-job version extraction with reusable jobs that compute versions, compare against PyPI, and output skip flags to gate dependent builds. Additionally, a pre-release tagging utility is added, starter project templates gain local storage options, and version dependencies are adjusted.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow Refactoring
.github/workflows/docker-build-v2.yml, .github/workflows/release.yml
Introduces three new version-determination jobs (determine-base-version, determine-main-version, determine-lfx-version) that extract versions from source files and PyPI, handle pre-release tagging, and emit skip flags. Build jobs (build-base, build-main, build-main-backend, build-main-frontend, build-main-ep, build-main-all, build-lfx) and create-manifest/create_release now depend on these jobs and use their outputs for version tags and conditional execution. Removes inline per-job version extraction steps.
Pre-release Tagging Utility
scripts/ci/langflow_pre_release_tag.py
New script with create_tag() function that generates pre-release tags (e.g., .rc1, .rc2) by comparing against PyPI versions and incrementing RC numbers. Includes CLI interface accepting package version and optional PyPI version arguments.
Starter Project Configurations
src/backend/base/langflow/initial_setup/starter_projects/* (Document Q&A.json, News Aggregator.json, Portfolio Website Code Generator.json, Text Sentiment Analysis.json, Vector Store RAG.json)
Adds "Local" storage location option (icon: hard-drive) to storage_location field across multiple starter project templates, enabling local file path selection alongside existing AWS/Google Drive options.
Dependency Version Updates
src/backend/base/pyproject.toml, src/lfx/pyproject.toml
Reverts lfx dependency from ~0.3.0 to ~0.2.1 in base package; updates lfx package version from 0.3.0 to 0.2.1.
Secrets Configuration
.secrets.baseline
Updates recorded secret location reference in release.yml from line 122 to line 254; updates baseline timestamp.

Sequence Diagram(s)

sequenceDiagram
    participant Source as Source Files<br/>(pyproject.toml)
    participant Determine as determine-*-version<br/>Job
    participant PyPI
    participant Output as Job Outputs<br/>(version, skipped)
    
    Source->>Determine: Extract version from source
    Determine->>PyPI: Query latest released version
    PyPI-->>Determine: Return latest version
    
    alt Version already exists on PyPI
        Determine->>Output: skipped=true
    else Version is new
        Determine->>Output: skipped=false, version=X.Y.Z
    end
    
    Note over Determine: Handle pre-release logic<br/>if needed (append .rcN)
Loading
sequenceDiagram
    participant Job as determine-*-version
    participant BuildJob as build-* Job
    participant Registry as Container Registry
    
    Job->>Job: Compute version & skip flag
    Job-->>BuildJob: Output version, skipped
    
    alt skipped == false
        BuildJob->>BuildJob: Build container/artifact
        BuildJob->>BuildJob: Tag with version from determine output
        BuildJob->>Registry: Push image with version tags
    else skipped == true
        BuildJob->>BuildJob: Skip execution
        Note over BuildJob: Version already exists
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 3 warnings)
Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error PR introduces new langflow_pre_release_tag.py script with version increment logic but includes no unit tests for the critical functionality. Add test file for scripts/ci/langflow_pre_release_tag.py covering RC version generation, increment logic, edge cases, and error handling scenarios.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Quality And Coverage ⚠️ Warning New create_tag() function in scripts/ci/langflow_pre_release_tag.py lacks unit tests despite implementing critical release version incrementing logic with known bugs. Create scripts/ci/test_langflow_pre_release_tag.py with pytest tests covering RC creation, incrementing, strict version matching, error handling, and edge cases.
Test File Naming And Structure ⚠️ Warning The PR adds a critical utility script for pre-release versioning used in CI/CD workflows but includes no corresponding test file or test coverage. Add a test file tests/scripts/ci/test_langflow_pre_release_tag.py with comprehensive pytest test cases covering RC version increment logic, edge cases, error handling, and boundary conditions.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main objective: updating the pre-release flow to be usable for QA, which aligns with the primary changes across the workflow files and new script.
Excessive Mock Usage Warning ✅ Passed This custom check is not applicable to the provided pull request. While the repository contains test files, the PR modifications do not include any test files.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch aka-qa-pre-release

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the enhancement New feature or request label Jan 15, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 15, 2026
@codecov
Copy link

codecov bot commented Jan 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 34.22%. Comparing base (0e03376) to head (779b375).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #11322      +/-   ##
==========================================
- Coverage   34.25%   34.22%   -0.03%     
==========================================
  Files        1409     1409              
  Lines       66892    66896       +4     
  Branches     9860     9860              
==========================================
- Hits        22912    22897      -15     
- Misses      42787    42806      +19     
  Partials     1193     1193              
Flag Coverage Δ
backend 53.51% <ø> (-0.09%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 15, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/workflows/docker-build-v2.yml (1)

355-382: build-main-backend references a missing version step.

steps.version.outputs.version is never set in this job, so LANGFLOW_IMAGE becomes empty and builds will fail or use wrong tags.

🛠️ Suggested fix
-            LANGFLOW_IMAGE=langflowai/langflow:${{ steps.version.outputs.version }}-${{ matrix.arch }}
+            LANGFLOW_IMAGE=langflowai/langflow:${{ needs.determine-main-version.outputs.version }}-${{ matrix.arch }}-            LANGFLOW_IMAGE=ghcr.io/langflow-ai/langflow:${{ steps.version.outputs.version }}-${{ matrix.arch }}
+            LANGFLOW_IMAGE=ghcr.io/langflow-ai/langflow:${{ needs.determine-main-version.outputs.version }}-${{ matrix.arch }}
.github/workflows/release.yml (1)

774-782: GitHub release tag will be created without the v prefix, differing from the input tag.

The determine-main-version job strips the v prefix from the extracted version (line 29: sed 's/^v//'), resulting in a version like 1.8.0. This is then used directly as the GitHub release tag (line 781), creating a release tagged 1.8.0 instead of v1.8.0. This diverges from the input release_tag (e.g., v1.8.0) and also differs from the create-release.yml workflow, which explicitly prepends v to the tag (see line 36 of that workflow: tag: v${{ inputs.version }}). Confirm whether this is intentional or if the v prefix should be added back.

🤖 Fix all issues with AI agents
In @.github/workflows/docker-build-v2.yml:
- Around line 91-98: The workflow treats "already released" as a failure because
the block that detects version == last_released_version calls exit 1; change
that to treat it as a skip by removing the non-zero exit or replacing it with
exit 0 (or simply allow the job to finish after writing skipped=true to
$GITHUB_OUTPUT) in the snippet that checks if [ "$version" =
"$last_released_version" ]; do the same change in the determine-main-version
occurrence so the job completes successfully while signalling skipped=true
instead of failing the workflow.
- Around line 84-89: The workflow is querying the wrong Docker Hub repo
(langflowai/langflow-base) so base-* tags are missed; update both curl
invocations that set last_released_version to point to the langflowai/langflow
repository (i.e., replace "langflowai/langflow-base" with "langflowai/langflow"
in the two curl URL strings referenced where last_released_version is assigned),
leaving the rest of the logic (grep/sort/uv script call) unchanged so base-*
tags are correctly discovered for version comparison.

In @.github/workflows/release.yml:
- Around line 136-143: The version extraction is using awk '{print $3}' on the
uv tree output which yields the wrong field for lines like "langflow-base
v0.8.0"; update the run step that sets the version variable (the block that
calls uv tree and sets version) to extract the second token instead (e.g.,
replace the awk field extraction with a space-split using cut -d' ' -f2) or
alternatively call a small Python helper to read src/backend/base/pyproject.toml
via tomllib and return the version; change only the extraction command that
produces the version variable to use the correct field/parser so version
contains the actual semantic version string.

In `@scripts/ci/langflow_pre_release_tag.py`:
- Around line 16-24: The runtime argument check and handling are misleading:
update the __main__ block that checks len(sys.argv) against ARGUMENT_NUMBER and
the variables package_version and latest_pypi_version so the error message
correctly describes the expected args (e.g., "Specify package_version and
latest_pypi_version") and explicitly normalize an empty string for
latest_pypi_version to None before calling create_tag; locate the argument
parsing in the if __name__ == "__main__" section that uses ARGUMENT_NUMBER,
sys.argv, package_version and latest_pypi_version and ensure you convert
latest_pypi_version = None if sys.argv[2] == "" (or similar) and then pass those
normalized values to create_tag.
- Around line 10-12: The substring check "package_version in
latest_pypi_version" and naive int() of split(".rc") are brittle; update the
logic in langflow_pre_release_tag.py where latest_pypi_version, package_version,
rc_number, and new_pre_release_version are computed: replace the loose
containment check with a strict prefix check like
latest_pypi_version.startswith(package_version + ".rc") and extract the RC
number using a regex that captures only the numeric part after ".rc" (or split
and strip non-digits) and wrap the int() parse in a try/except to fall back to 1
on parse failure; then compute new_pre_release_version = package_version + ".rc"
+ str(rc_number + 1) only when a valid rc_number was obtained (otherwise use
".rc1").
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c57e527 and f061132.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • .github/workflows/docker-build-v2.yml
  • .github/workflows/release.yml
  • .secrets.baseline
  • scripts/ci/langflow_pre_release_tag.py
  • src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json
  • src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json
  • src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json
  • src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json
  • src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json
  • src/backend/base/pyproject.toml
  • src/lfx/pyproject.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (61)
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 42/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 31/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 41/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 50/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 49/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 46/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 29/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 47/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 23/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 30/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 35/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 32/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 48/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 39/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 43/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 28/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 16/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 45/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 26/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 27/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 34/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 40/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 21/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 24/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 44/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 33/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 38/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 36/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 37/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 17/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 20/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 25/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 19/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 7/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 22/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 18/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 9/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 6/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 14/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 11/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 15/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 10/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 5/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 3/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 12/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 4/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 13/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 1/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 8/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 2/50
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 3
  • GitHub Check: Test Docker Images / Test docker images
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 1
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 5
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 2
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 4
  • GitHub Check: Run Backend Tests / Integration Tests - Python 3.10
  • GitHub Check: Run Backend Tests / LFX Tests - Python 3.10
  • GitHub Check: Test Starter Templates
  • GitHub Check: test-starter-projects
  • GitHub Check: Optimize new Python code in this PR
🔇 Additional comments (6)
src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json (1)

2031-2034: LGTM!

The Local storage option is correctly added to the storage_location.options array with the proper structure (icon and name keys) matching the existing AWS and Google Drive options. This aligns with the component's existing _save_to_local() implementation and the pre-selected value already referencing Local storage.

src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json (1)

3230-3233: LGTM — Local storage option added cleanly.
The new "Local" option and icon are consistent with the selector structure.

src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json (1)

1889-1892: LGTM — Local option is clear and consistent.

src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json (1)

1485-1488: LGTM — Local option addition looks correct.

src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json (1)

3296-3299: LGTM — clear Local storage option added.

No issues spotted with this config update.

src/backend/base/pyproject.toml (1)

19-21: Confirm the LFX downgrade is intentional and published.

Please verify that lfx version 0.2.1 is available on PyPI and remains API‑compatible with current langflow-base usage.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines 84 to 89
if [ ${{inputs.pre_release}} == "true" ]; then
last_released_version=$(curl -s "https://registry.hub.docker.com/v2/repositories/langflowai/langflow-base/tags?page_size=100" | jq -r '.results[].name' | grep -E '\.rc[0-9]+' | sort -V | tail -n 1)
version="$(uv run ./scripts/ci/langflow_pre_release_tag.py $version $last_released_version)"
else
last_released_version=$(curl -s "https://registry.hub.docker.com/v2/repositories/langflowai/langflow-base/tags?page_size=100" | jq -r '.results[].name' | grep -v 'latest' | sort -V | tail -n 1)
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Base version check targets the wrong Docker Hub repo.

The workflow publishes base images to langflowai/langflow:base-*, but the comparison reads tags from langflowai/langflow-base, so existing base tags can be missed and RCs can be miscomputed.

🛠️ Suggested fix
-            last_released_version=$(curl -s "https://registry.hub.docker.com/v2/repositories/langflowai/langflow-base/tags?page_size=100" | jq -r '.results[].name' | grep -E '\.rc[0-9]+' | sort -V | tail -n 1)
+            last_released_version=$(curl -s "https://registry.hub.docker.com/v2/repositories/langflowai/langflow/tags?page_size=100" \
+              | jq -r '.results[].name' \
+              | grep -E '^base-.*rc[0-9]+$' \
+              | sed 's/^base-//' \
+              | sort -V | tail -n 1)-            last_released_version=$(curl -s "https://registry.hub.docker.com/v2/repositories/langflowai/langflow-base/tags?page_size=100" | jq -r '.results[].name' | grep -v 'latest' | sort -V | tail -n 1)
+            last_released_version=$(curl -s "https://registry.hub.docker.com/v2/repositories/langflowai/langflow/tags?page_size=100" \
+              | jq -r '.results[].name' \
+              | grep -E '^base-[0-9]' \
+              | sed 's/^base-//' \
+              | sort -V | tail -n 1)
🤖 Prompt for AI Agents
In @.github/workflows/docker-build-v2.yml around lines 84 - 89, The workflow is
querying the wrong Docker Hub repo (langflowai/langflow-base) so base-* tags are
missed; update both curl invocations that set last_released_version to point to
the langflowai/langflow repository (i.e., replace "langflowai/langflow-base"
with "langflowai/langflow" in the two curl URL strings referenced where
last_released_version is assigned), leaving the rest of the logic (grep/sort/uv
script call) unchanged so base-* tags are correctly discovered for version
comparison.

Comment on lines 91 to 98
if [ "$version" = "$last_released_version" ]; then
echo "Version $version is already released. Skipping release."
echo skipped=true >> $GITHUB_OUTPUT
exit 1
else
echo version=$version >> $GITHUB_OUTPUT
echo skipped=false >> $GITHUB_OUTPUT
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Treat “already released” as a skip, not a job failure.

exit 1 fails the job and the workflow even though you’re setting skipped=true. This likely defeats the skip-gating. Same pattern appears in determine-main-version.

🛠️ Suggested fix
-            echo skipped=true >> $GITHUB_OUTPUT
-            exit 1
+            echo skipped=true >> $GITHUB_OUTPUT
+            exit 0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ "$version" = "$last_released_version" ]; then
echo "Version $version is already released. Skipping release."
echo skipped=true >> $GITHUB_OUTPUT
exit 1
else
echo version=$version >> $GITHUB_OUTPUT
echo skipped=false >> $GITHUB_OUTPUT
fi
if [ "$version" = "$last_released_version" ]; then
echo "Version $version is already released. Skipping release."
echo skipped=true >> $GITHUB_OUTPUT
exit 0
else
echo version=$version >> $GITHUB_OUTPUT
echo skipped=false >> $GITHUB_OUTPUT
fi
🤖 Prompt for AI Agents
In @.github/workflows/docker-build-v2.yml around lines 91 - 98, The workflow
treats "already released" as a failure because the block that detects version ==
last_released_version calls exit 1; change that to treat it as a skip by
removing the non-zero exit or replacing it with exit 0 (or simply allow the job
to finish after writing skipped=true to $GITHUB_OUTPUT) in the snippet that
checks if [ "$version" = "$last_released_version" ]; do the same change in the
determine-main-version occurrence so the job completes successfully while
signalling skipped=true instead of failing the workflow.

Comment on lines 136 to 143
id: version
run: |
version=$(uv tree | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 2 | xargs)
if [ ${{inputs.pre_release}} == "true" ]; then
last_released_version=$(curl -s "https://pypi.org/pypi/langflow-base/json" | jq -r '.releases | keys | .[]' | grep -E '(a|b|rc|dev|alpha|beta)' | sort -V | tail -n 1)
version="$(uv run ./scripts/ci/langflow_pre_release_tag.py $version $last_released_version)"
else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the release workflow file to see the full context
cat -n .github/workflows/release.yml | sed -n '130,150p'

Repository: langflow-ai/langflow

Length of output: 1223


🏁 Script executed:

# Search for pyproject.toml files, especially the base one
find . -name "pyproject.toml" -type f | head -20

Repository: langflow-ai/langflow

Length of output: 139


🏁 Script executed:

# Look at the structure of the langflow-base pyproject.toml if it exists
fd "pyproject.toml" --exec grep -l "langflow-base" {} \;

Repository: langflow-ai/langflow

Length of output: 114


🏁 Script executed:

# Search for how langflow-base version is defined
rg "langflow-base" --type toml -A 2 -B 2 | head -50

Repository: langflow-ai/langflow

Length of output: 892


🏁 Script executed:

# Let's check uv documentation or see if there are examples in the repo
rg "uv tree" --type yaml -A 2 -B 2

Repository: langflow-ai/langflow

Length of output: 46


🏁 Script executed:

# Look for any scripts or documentation that might show uv tree output format
fd "uv" --type f | xargs grep -l "tree" 2>/dev/null | head -10

Repository: langflow-ai/langflow

Length of output: 96


🏁 Script executed:

# Check if there are CI logs or documentation about uv tree format
cat README.md 2>/dev/null | grep -A 5 -B 5 "uv tree" || echo "Not found in README"

Repository: langflow-ai/langflow

Length of output: 83


🏁 Script executed:

# Let's also verify the actual structure of the version output by checking the workflow more thoroughly
cat -n .github/workflows/release.yml | sed -n '135,160p'

Repository: langflow-ai/langflow

Length of output: 1508


🏁 Script executed:

# Check uv.lock to understand the dependency structure
head -50 uv.lock | grep -A 3 "langflow-base"

Repository: langflow-ai/langflow

Length of output: 159


🌐 Web query:

uv tree output format documentation

💡 Result:

The official uv CLI docs (uv tree) show the supported output formats and related options. Key points:

  • Output formats: text (default) and json (use --output-format json). [1]
  • Useful uv tree flags: --depth / -d, --outdated, --invert (show dependents), --no-dev / --all-groups, --universal / --no-sync, and --project. [1]
  • There is an open discussion about richer machine-readable/tree outputs (e.g., JSON for graph tools). [2]

Docs: uv reference (uv tree / --output-format). [1]
Discussion about machine-readable/tree output. [2]

Sources:
[1] uv CLI reference — Commands / uv tree (docs.astral.sh).
[2] Issue: "uv pip tree machine readable output" (astral-sh/uv on GitHub).


🌐 Web query:

uv tree text output format example langflow

💡 Result:

Short answer and example.

  • Context: In LangFlow workflows you may run flows with the lfx/uv CLI; it supports a plain text output format (--format text) and the uv tool also prints dependency trees with uv tree. Examples below show typical "text" output from lfx and a sample uv tree output.

Example — lfx run text output (from lfx/lfx CLI):
Output when running a flow with --format text:
Hello, world!
(This returns the flow's text result only). [1]

Example — uv tree (dependency tree) text output:
project-name v0.1.0
├── requests v2.32.5
├── langflow v0.8.0
│ ├── fastapi v0.95.0
│ └── pydantic v2.4.0
└── uvx-tool v1.2.3
(Shows nested dependency tree lines). [2]

Sources:
[1] lfx (Langflow Executor) PyPI project page — shows lfx run/serve and --format text.
[2] uv documentation (uv tool) — describes uv tree dependency-tree text output.


🏁 Script executed:

# Look for any test files or documentation that show uv tree output
find . -name "*.md" -o -name "*.txt" | xargs grep -l "uv tree" 2>/dev/null | head -5

Repository: langflow-ai/langflow

Length of output: 46


🏁 Script executed:

# Check if there are any comments or documentation in the release workflow about the version extraction
cat -n .github/workflows/release.yml | sed -n '100,180p' | grep -A 10 -B 10 "tree"

Repository: langflow-ai/langflow

Length of output: 1232


🏁 Script executed:

# Let's look at the actual uv.lock structure to understand langflow-base entry
rg "name = \"langflow-base\"" -A 10 uv.lock

Repository: langflow-ai/langflow

Length of output: 1276


🏁 Script executed:

# Check the langflow-base pyproject.toml directly
cat src/backend/base/pyproject.toml | head -30

Repository: langflow-ai/langflow

Length of output: 1146


🌐 Web query:

"uv tree" output format "workspace" example

💡 Result:

Here’s a short example of the kind of output uv produces for a workspace dependency tree (illustrative — exact formatting may vary by uv version and options):

Example (uv tree --workspace)
uv 0.x.x
albatross (workspace root)
├─ bird-feeder 1.2.3
│ ├─ requests 2.31.0
│ │ └─ urllib3 2.1.0
│ └─ tqdm 4.65.0
├─ packages/bird-feeder (workspace member)
│ └─ click 8.1.3
└─ packages/cli-tool (workspace member)
├─ rich 13.3.0
└─ tomli 2.0.1

Notes:

  • Use --workspace to show the whole workspace. uv prints top-level workspace root + members and their dependency subtrees. [1][2][3]

Sources:

  • uv CLI reference (uv tree options). [1]
  • uv workspaces docs (how workspaces/members are displayed). [2]
  • Quick usage / examples mentioning uv tree and --workspace. [3]

🏁 Script executed:

# Verify the suggested fix path is correct
cat src/backend/base/pyproject.toml | grep -A 1 "^\[project\]" | head -5

Repository: langflow-ai/langflow

Length of output: 96


🏁 Script executed:

# Check if Python 3.10+ is available (tomllib requires 3.11+, or need tomli for earlier versions)
cat .github/workflows/release.yml | grep -A 2 "python-version"

Repository: langflow-ai/langflow

Length of output: 1289


🏁 Script executed:

# See if there's a better way to extract version using json output
cat -n .github/workflows/release.yml | sed -n '135,155p'

Repository: langflow-ai/langflow

Length of output: 1267


🏁 Script executed:

# Check what Python version is in use during the release workflow
cat .github/workflows/release.yml | sed -n '1,50p' | grep -i python

Repository: langflow-ai/langflow

Length of output: 46


🏁 Script executed:

# Let's check if tomllib is available in Python 3.13 (it was added in 3.11)
python3 << 'EOF'
import sys
print(f"Python version: {sys.version}")
try:
    import tomllib
    print("tomllib is available")
except ImportError:
    print("tomllib not available, would need tomli")
EOF

Repository: langflow-ai/langflow

Length of output: 150


🏁 Script executed:

# Verify the exact pyproject.toml location and structure for the suggested fix
cat src/backend/base/pyproject.toml | head -20

Repository: langflow-ai/langflow

Length of output: 832


🏁 Script executed:

# Test the suggested fix logic
python3 << 'EOF'
import tomllib
from pathlib import Path

try:
    data = tomllib.loads(Path("src/backend/base/pyproject.toml").read_text())
    version = data["project"]["version"]
    print(f"Extracted version: {version}")
except Exception as e:
    print(f"Error: {e}")
EOF

Repository: langflow-ai/langflow

Length of output: 88


🏁 Script executed:

# Check if uv tree supports JSON output format (mentioned in web search)
# This would be more robust than the current awk parsing
cd /tmp && python3 << 'EOF'
import subprocess
import json

# Test if uv tree has json output support
result = subprocess.run(
    ["uv", "tree", "--help"],
    capture_output=True,
    text=True,
    cwd="/repo"
)

# Look for output-format option
if "--output-format" in result.stdout:
    print("uv tree supports --output-format option")
    # Check what formats are available
    lines = result.stdout.split('\n')
    for i, line in enumerate(lines):
        if 'output-format' in line or 'json' in line:
            print(f"  {line}")
else:
    print("--output-format not mentioned in help")
EOF

Repository: langflow-ai/langflow

Length of output: 617


🏁 Script executed:

# Check git history to see if the uv tree approach was recently added and how it evolved
git log --oneline -n 20 -- .github/workflows/release.yml 2>/dev/null || echo "Git not available"

Repository: langflow-ai/langflow

Length of output: 107


🏁 Script executed:

# Look for alternative approaches already used in the codebase for version extraction
rg "uv run" .github/workflows/ -A 2 -B 2 | head -30

Repository: langflow-ai/langflow

Length of output: 3289


🏁 Script executed:

# Let me verify if there's an alternative approach already in the codebase for version extraction
# Check the langflow_pre_release_tag.py script
cat scripts/ci/langflow_pre_release_tag.py 2>/dev/null | head -30 || echo "Script not found"

Repository: langflow-ai/langflow

Length of output: 827


🏁 Script executed:

# Check if there are other workflows that extract version more reliably
rg "version=" .github/workflows/ -B 3 -A 3 | grep -E "(pyproject|toml|version)" | head -20

Repository: langflow-ai/langflow

Length of output: 2760


🏁 Script executed:

# Let's also check the recent git change to see what was modified
git show f0611322 -- .github/workflows/release.yml 2>/dev/null | head -100 || echo "Cannot show git diff"

Repository: langflow-ai/langflow

Length of output: 3481


Base version extraction uses incorrect awk field.

The command uv tree … | awk '{print $3}' extracts the wrong field. For workspace packages, uv tree outputs langflow-base v0.8.0, making the version in field 2, not field 3. This will produce empty or invalid values.

The established pattern in docker-build-v2.yml uses cut -d' ' -f2 instead. Either align with that approach or parse the version directly from src/backend/base/pyproject.toml using tomllib (available in Python 3.10+):

🛠️ Suggested fix (parse pyproject directly)
-          version=$(uv tree | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 2 | xargs)
+          version=$(python - <<'PY'
+import tomllib, pathlib
+data = tomllib.loads(pathlib.Path("src/backend/base/pyproject.toml").read_text())
+print(data["project"]["version"])
+PY
+)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
id: version
run: |
version=$(uv tree | grep 'langflow-base' | awk '{print $3}' | sed 's/^v//' | head -n 2 | xargs)
if [ ${{inputs.pre_release}} == "true" ]; then
last_released_version=$(curl -s "https://pypi.org/pypi/langflow-base/json" | jq -r '.releases | keys | .[]' | grep -E '(a|b|rc|dev|alpha|beta)' | sort -V | tail -n 1)
version="$(uv run ./scripts/ci/langflow_pre_release_tag.py $version $last_released_version)"
else
id: version
run: |
version=$(python - <<'PY'
import tomllib, pathlib
data = tomllib.loads(pathlib.Path("src/backend/base/pyproject.toml").read_text())
print(data["project"]["version"])
PY
)
if [ ${{inputs.pre_release}} == "true" ]; then
last_released_version=$(curl -s "https://pypi.org/pypi/langflow-base/json" | jq -r '.releases | keys | .[]' | grep -E '(a|b|rc|dev|alpha|beta)' | sort -V | tail -n 1)
version="$(uv run ./scripts/ci/langflow_pre_release_tag.py $version $last_released_version)"
else
🤖 Prompt for AI Agents
In @.github/workflows/release.yml around lines 136 - 143, The version extraction
is using awk '{print $3}' on the uv tree output which yields the wrong field for
lines like "langflow-base v0.8.0"; update the run step that sets the version
variable (the block that calls uv tree and sets version) to extract the second
token instead (e.g., replace the awk field extraction with a space-split using
cut -d' ' -f2) or alternatively call a small Python helper to read
src/backend/base/pyproject.toml via tomllib and return the version; change only
the extraction command that produces the version variable to use the correct
field/parser so version contains the actual semantic version string.

Comment on lines 10 to 12
if latest_pypi_version and package_version in latest_pypi_version and ".rc" in latest_pypi_version:
rc_number = int(latest_pypi_version.split(".rc")[-1])
new_pre_release_version = package_version + ".rc" + str(rc_number + 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Substring check may match unintended versions; int() may fail on unexpected formats.

Two potential issues:

  1. Line 10: package_version in latest_pypi_version is a loose substring check. For example, "1.8.0" in "1.18.0.rc1" evaluates to True, which would incorrectly increment based on an unrelated version.

  2. Line 11: If latest_pypi_version contains additional suffixes after the RC number (e.g., "1.8.0.rc1.post1" or "1.8.0.rc1dev0"), split(".rc")[-1] yields a non-numeric string, causing int() to raise a ValueError.

Consider using stricter version comparison (e.g., check if latest_pypi_version.startswith(package_version + ".rc")) and adding error handling for the RC number extraction.

🐛 Proposed fix
 def create_tag(package_version: str, latest_pypi_version: str | None) -> str:
     new_pre_release_version = package_version + ".rc1"
-    if latest_pypi_version and package_version in latest_pypi_version and ".rc" in latest_pypi_version:
-        rc_number = int(latest_pypi_version.split(".rc")[-1])
-        new_pre_release_version = package_version + ".rc" + str(rc_number + 1)
+    if latest_pypi_version and latest_pypi_version.startswith(package_version + ".rc"):
+        rc_suffix = latest_pypi_version[len(package_version) + 3:]  # skip ".rc"
+        # Extract leading digits from rc_suffix
+        rc_digits = ""
+        for char in rc_suffix:
+            if char.isdigit():
+                rc_digits += char
+            else:
+                break
+        if rc_digits:
+            rc_number = int(rc_digits)
+            new_pre_release_version = package_version + ".rc" + str(rc_number + 1)
     return new_pre_release_version
🤖 Prompt for AI Agents
In `@scripts/ci/langflow_pre_release_tag.py` around lines 10 - 12, The substring
check "package_version in latest_pypi_version" and naive int() of split(".rc")
are brittle; update the logic in langflow_pre_release_tag.py where
latest_pypi_version, package_version, rc_number, and new_pre_release_version are
computed: replace the loose containment check with a strict prefix check like
latest_pypi_version.startswith(package_version + ".rc") and extract the RC
number using a regex that captures only the numeric part after ".rc" (or split
and strip non-digits) and wrap the int() parse in a try/except to fall back to 1
on parse failure; then compute new_pre_release_version = package_version + ".rc"
+ str(rc_number + 1) only when a valid rc_number was obtained (otherwise use
".rc1").

Comment on lines 16 to 24
if __name__ == "__main__":
if len(sys.argv) != ARGUMENT_NUMBER:
msg = "Specify base or main"
raise ValueError(msg)

package_version: str = sys.argv[1]
latest_pypi_version: str = sys.argv[2]
tag = create_tag(package_version, latest_pypi_version)
print(tag)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Error message is misleading; consider handling empty string for latest_pypi_version.

  1. Line 18: The error message "Specify base or main" doesn't reflect the actual expected arguments (package_version and latest_pypi_version).

  2. Line 22-23: If the caller passes an empty string "" for latest_pypi_version, it will be truthy and passed to create_tag, where the condition on line 10 will evaluate "" and ... as falsy anyway. This works but is implicit—consider explicitly converting empty string to None for clarity.

✏️ Proposed fix
 if __name__ == "__main__":
     if len(sys.argv) != ARGUMENT_NUMBER:
-        msg = "Specify base or main"
+        msg = f"Usage: {sys.argv[0]} <package_version> <latest_pypi_version>"
         raise ValueError(msg)

     package_version: str = sys.argv[1]
-    latest_pypi_version: str = sys.argv[2]
+    latest_pypi_version: str | None = sys.argv[2] or None
     tag = create_tag(package_version, latest_pypi_version)
     print(tag)
🤖 Prompt for AI Agents
In `@scripts/ci/langflow_pre_release_tag.py` around lines 16 - 24, The runtime
argument check and handling are misleading: update the __main__ block that
checks len(sys.argv) against ARGUMENT_NUMBER and the variables package_version
and latest_pypi_version so the error message correctly describes the expected
args (e.g., "Specify package_version and latest_pypi_version") and explicitly
normalize an empty string for latest_pypi_version to None before calling
create_tag; locate the argument parsing in the if __name__ == "__main__" section
that uses ARGUMENT_NUMBER, sys.argv, package_version and latest_pypi_version and
ensure you convert latest_pypi_version = None if sys.argv[2] == "" (or similar)
and then pass those normalized values to create_tag.

@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 15, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 15, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 16, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 16, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 16, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 16, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 16, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 16, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants