-
Notifications
You must be signed in to change notification settings - Fork 8.3k
feat: update pre-release flow to be useable for qa #11322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
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.
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis 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
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)
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 3 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ 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
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
There was a problem hiding this 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-backendreferences a missingversionstep.
steps.version.outputs.versionis never set in this job, soLANGFLOW_IMAGEbecomes 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 thevprefix, differing from the input tag.The
determine-main-versionjob strips thevprefix from the extracted version (line 29:sed 's/^v//'), resulting in a version like1.8.0. This is then used directly as the GitHub release tag (line 781), creating a release tagged1.8.0instead ofv1.8.0. This diverges from the inputrelease_tag(e.g.,v1.8.0) and also differs from thecreate-release.ymlworkflow, which explicitly prependsvto the tag (see line 36 of that workflow:tag: v${{ inputs.version }}). Confirm whether this is intentional or if thevprefix 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
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (11)
.github/workflows/docker-build-v2.yml.github/workflows/release.yml.secrets.baselinescripts/ci/langflow_pre_release_tag.pysrc/backend/base/langflow/initial_setup/starter_projects/Document Q&A.jsonsrc/backend/base/langflow/initial_setup/starter_projects/News Aggregator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.jsonsrc/backend/base/pyproject.tomlsrc/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.optionsarray with the proper structure (iconandnamekeys) 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
lfxversion0.2.1is 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.
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 -20Repository: 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 -50Repository: 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 2Repository: 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 -10Repository: 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 -5Repository: 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.lockRepository: langflow-ai/langflow
Length of output: 1276
🏁 Script executed:
# Check the langflow-base pyproject.toml directly
cat src/backend/base/pyproject.toml | head -30Repository: 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 -5Repository: 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 pythonRepository: 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")
EOFRepository: 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 -20Repository: 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}")
EOFRepository: 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")
EOFRepository: 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 -30Repository: 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 -20Repository: 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.
| 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.
| 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Substring check may match unintended versions; int() may fail on unexpected formats.
Two potential issues:
-
Line 10:
package_version in latest_pypi_versionis a loose substring check. For example,"1.8.0" in "1.18.0.rc1"evaluates toTrue, which would incorrectly increment based on an unrelated version. -
Line 11: If
latest_pypi_versioncontains 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, causingint()to raise aValueError.
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").
| 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error message is misleading; consider handling empty string for latest_pypi_version.
-
Line 18: The error message
"Specify base or main"doesn't reflect the actual expected arguments (package_versionandlatest_pypi_version). -
Line 22-23: If the caller passes an empty string
""forlatest_pypi_version, it will be truthy and passed tocreate_tag, where the condition on line 10 will evaluate"" and ...as falsy anyway. This works but is implicit—consider explicitly converting empty string toNonefor 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.
update pre-release flow to be useable for qa
Summary by CodeRabbit
Release Notes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.