feat: uv migration (#3493)

* uv migration

smaller runners, freeze test runs, remove dev, ruff,hatchling, previw,
poetry, generates wheel, installs wheel, docker

* fix tests and dependency groups

* test fixes

* test fixing and main

* resolve merge conflict

* dev + test dependency group

* Test

* trigger CI

* trigger CI

* add debugging info

* trigger CI

* uv for reusable and sdk preview

* resolve mc and reformat black

* staged-api

* mypy

* fix fern

* prod Dockerfile

* model sweep, and project.toml and uvlock

* --group test -> --extra dev

* remove redundant --extra dev and rename tests to dev

* sdk backwards compat install sqlite

* install sqlite group for sdk-backwards-compat

* install uv on gh runner for cloud-api-integration-tests

* stage+publish

* pytest asyncio

* bug causing pytest package to get removed

* try to fix async event loop issues

* migrate to --with google-cloud-secret-manager

---------

Co-authored-by: Kian Jones <kian@letta.com>
This commit is contained in:
Andy Li
2025-08-26 18:11:09 -07:00
committed by GitHub
parent 11b447a02b
commit ff718d8c40
34 changed files with 670 additions and 9855 deletions

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"] # Adjust Python version matrix if needed
python-version: ["3.11"] # Removed 3.12+ as minimal sets the standard. Adjust Python version matrix if needed
steps:
- name: Checkout code
@@ -20,12 +20,21 @@ jobs:
ref: ${{ github.head_ref }} # Checkout the PR branch
fetch-depth: 0 # Fetch all history for all branches and tags
- name: "Setup Python, Poetry and Dependencies"
uses: packetcoders/action-setup-cache-python-poetry@main
- name: Set up python
id: setup-python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
poetry-version: "2.1.3"
install-args: "-E dev -E postgres -E external-tools -E tests" # Adjust as necessary
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
activate-environment: true
- name: Install Dependencies
run: |
uv sync --extra dev --extra postgres --extra external-tools --extra dev
- name: Validate PR Title
if: github.event_name == 'pull_request'
@@ -41,10 +50,10 @@ jobs:
continue-on-error: true
- name: Run isort
run: poetry run isort --profile black --check-only --diff .
run: uv run isort --profile black --check-only --diff .
- name: Run Black
run: poetry run black --check .
run: uv run black --check .
- name: Run Autoflake
run: poetry run autoflake --remove-all-unused-imports --remove-unused-variables --in-place --recursive --ignore-init-module-imports .
run: uv run autoflake --remove-all-unused-imports --remove-unused-variables --in-place --recursive --ignore-init-module-imports .

View File

@@ -13,10 +13,17 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Python
- name: Set up python 3.11
id: setup-python
uses: actions/setup-python@v5
with:
python-version: '3.11'
python-version: 3.11
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
- name: Set permissions for log directory
run: |
@@ -34,12 +41,6 @@ jobs:
run: |
docker compose -f dev-compose.yaml up --build -d
#- name: "Setup Python, Poetry and Dependencies"
# uses: packetcoders/action-setup-cache-python-poetry@v1.2.0
# with:
# python-version: "3.11"
# poetry-version: "1.8.2"
# install-args: "--all-extras"
- name: Wait for service
run: bash scripts/wait_for_service.sh http://localhost:8283 -- echo "Service is ready"
@@ -55,9 +56,8 @@ jobs:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PYTHONPATH: ${{ github.workspace }}:${{ env.PYTHONPATH }}
run: |
pipx install poetry==2.1.3
poetry install -E dev -E postgres
poetry run pytest -s tests/test_client.py
uv sync --extra dev --extra postgres
uv run pytest -s tests/test_client.py
- name: Print docker logs if tests fail
if: failure()

View File

@@ -26,12 +26,22 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- run: psql -h localhost -U postgres -d postgres -c 'CREATE EXTENSION vector'
- name: "Setup Python, Poetry and Dependencies"
uses: packetcoders/action-setup-cache-python-poetry@main
- name: Set up python 3.11
id: setup-python
uses: actions/setup-python@v5
with:
python-version: "3.11"
poetry-version: "1.8.2"
install-args: "--all-extras"
python-version: 3.11
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
- name: Install Dependencies
run: |
uv sync --all-extras
- name: Test alembic migration
env:
LETTA_PG_PORT: 5432
@@ -40,5 +50,5 @@ jobs:
LETTA_PG_DB: postgres
LETTA_PG_HOST: localhost
run: |
poetry run alembic upgrade head
poetry run alembic check
uv run alembic upgrade head
uv run alembic check

View File

@@ -61,7 +61,7 @@ jobs:
- name: Install dependencies
shell: bash
run: poetry install --no-interaction --no-root ${{ inputs.install-args || '-E dev -E postgres -E external-tools -E tests -E cloud-tool-sandbox -E google' }}
run: uv sync --extra dev --extra postgres --extra external-tools --extra cloud-tool-sandbox --extra google
- name: Migrate database
env:
LETTA_PG_PORT: 5432
@@ -71,7 +71,7 @@ jobs:
LETTA_PG_HOST: localhost
run: |
psql -h localhost -U postgres -d postgres -c 'CREATE EXTENSION vector'
poetry run alembic upgrade head
uv run alembic upgrade head
- name: Run integration tests
# if any of the 1000+ test cases fail, pytest reports exit code 1 and won't procces/upload the results
@@ -94,7 +94,7 @@ jobs:
DEEPSEEK_API_KEY: ${{ env.DEEPSEEK_API_KEY}}
LETTA_USE_EXPERIMENTAL: 1
run: |
poetry run pytest \
uv run pytest \
-s -vv \
.github/scripts/model-sweep/model_sweep.py \
--json-report --json-report-file=.github/scripts/model-sweep/model_sweep_report.json --json-report-indent=4
@@ -103,7 +103,7 @@ jobs:
continue-on-error: true
# file path args to generate_model_sweep_markdown.py are relative to the script
run: |
poetry run python \
uv run python \
.github/scripts/model-sweep/generate_model_sweep_markdown.py \
.github/scripts/model-sweep/model_sweep_report.json \
.github/scripts/model-sweep/supported-models.mdx

View File

@@ -1,4 +1,4 @@
name: poetry-publish-nightly
name: uv-publish-nightly
on:
schedule:
- cron: '35 10 * * *' # 10:35am UTC, 2:35am PST, 5:35am EST
@@ -31,11 +31,17 @@ jobs:
- name: Check out the repository
uses: actions/checkout@v4
- name: "Setup Python, Poetry and Dependencies"
uses: packetcoders/action-setup-cache-python-poetry@main
- name: Set up python 3.12
id: setup-python
uses: actions/setup-python@v5
with:
python-version: "3.11"
poetry-version: "1.7.1"
python-version: 3.12
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
activate-environment: true
- name: Set release version
run: |
@@ -50,13 +56,10 @@ jobs:
cat pyproject.toml
cat letta/__init__.py
- name: Configure poetry
env:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN}}
run: poetry config pypi-token.pypi "$PYPI_TOKEN"
- name: Build the Python package
run: poetry build
run: uv build
- name: Publish the package to PyPI
run: poetry publish
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: uv publish

View File

@@ -1,4 +1,4 @@
name: poetry-publish
name: uv-publish
on:
release:
types: [published]
@@ -13,20 +13,23 @@ jobs:
- name: Check out the repository
uses: actions/checkout@v4
- name: "Setup Python, Poetry and Dependencies"
uses: packetcoders/action-setup-cache-python-poetry@main
- name: Set up python 3.12
id: setup-python
uses: actions/setup-python@v5
with:
python-version: "3.11"
poetry-version: "1.7.1"
python-version: 3.12
- name: Configure poetry
env:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: |
poetry config pypi-token.pypi "$PYPI_TOKEN"
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
activate-environment: true
cache-dependency-glob: "uv.lock"
- name: Build the Python package
run: poetry build
run: uv build
- name: Publish the package to PyPI
run: poetry publish
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: uv publish

View File

@@ -100,35 +100,25 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Load cached Poetry Binary
id: cached-poetry-binary
uses: actions/cache@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
path: ~/.local
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-1.8.3
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.8.3
virtualenvs-create: true
virtualenvs-in-project: true
version: "latest"
- name: Load cached venv
id: cached-poetry-dependencies
id: cached-uv-dependencies
uses: actions/cache@v4
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}${{ inputs.install-args || '-E dev -E postgres -E external-tools -E tests -E cloud-tool-sandbox' }}
# Restore cache with this prefix if not exact match with key
# Note cache-hit returns false in this case, so the below step will run
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/uv.lock') }}
restore-keys: |
venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
if: steps.cached-uv-dependencies.outputs.cache-hit != 'true'
shell: bash
run: poetry install --no-interaction --no-root ${{ inputs.install-args || '-E dev -E postgres -E external-tools -E tests -E cloud-tool-sandbox -E google' }}
- name: Install letta packages via Poetry
run: uv sync --extra dev --extra postgres --extra external-tools --extra cloud-tool-sandbox --extra google
- name: Install letta packages
run: |
poetry run pip install --upgrade letta-client letta
uv run pip install --upgrade letta-client letta
- name: Migrate database
env:
LETTA_PG_PORT: 5432
@@ -138,7 +128,7 @@ jobs:
LETTA_PG_HOST: localhost
run: |
psql -h localhost -U postgres -d postgres -c 'CREATE EXTENSION vector'
poetry run alembic upgrade head
uv run alembic upgrade head
- name: Run integration tests for ${{ matrix.config_file }}
env:
LLM_CONFIG_FILE: ${{ matrix.config_file }}
@@ -161,7 +151,7 @@ jobs:
GOOGLE_CLOUD_LOCATION: ${{ secrets.GOOGLE_CLOUD_LOCATION }}
LETTA_GEMINI_FORCE_MINIMUM_THINKING_BUDGET: true
run: |
poetry run pytest \
uv run pytest \
-s -vv \
tests/integration_test_send_message.py \
--maxfail=1 --durations=10

View File

@@ -1,13 +1,13 @@
name: Check Poetry Dependencies Changes
name: Check uv Dependencies Changes
on:
pull_request:
paths:
- 'poetry.lock'
- 'uv.lock'
- 'pyproject.toml'
jobs:
check-poetry-changes:
check-uv-changes:
runs-on: ubuntu-latest
permissions:
pull-requests: write
@@ -17,13 +17,13 @@ jobs:
with:
fetch-depth: 0
- name: Check for poetry.lock changes
id: check-poetry-lock
- name: Check for uv.lock changes
id: check-uv-lock
run: |
if git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | grep -q "poetry.lock"; then
echo "poetry_lock_changed=true" >> $GITHUB_OUTPUT
if git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | grep -q "uv.lock"; then
echo "uv_lock_changed=true" >> $GITHUB_OUTPUT
else
echo "poetry_lock_changed=false" >> $GITHUB_OUTPUT
echo "uv_lock_changed=false" >> $GITHUB_OUTPUT
fi
- name: Check for pyproject.toml changes
@@ -36,19 +36,19 @@ jobs:
fi
- name: Create PR comment
if: steps.check-poetry-lock.outputs.poetry_lock_changed == 'true' || steps.check-pyproject.outputs.pyproject_changed == 'true'
if: steps.check-uv-lock.outputs.uv_lock_changed == 'true' || steps.check-pyproject.outputs.pyproject_changed == 'true'
uses: actions/github-script@v7
with:
script: |
const poetryLockChanged = ${{ steps.check-poetry-lock.outputs.poetry_lock_changed }};
const uvLockChanged = ${{ steps.check-uv-lock.outputs.uv_lock_changed }};
const pyprojectChanged = ${{ steps.check-pyproject.outputs.pyproject_changed }};
let message = '📦 Dependencies Alert:\n\n';
if (poetryLockChanged && pyprojectChanged) {
message += '- Both `poetry.lock` and `pyproject.toml` have been modified\n';
} else if (poetryLockChanged) {
message += '- `poetry.lock` has been modified\n';
if (uvLockChanged && pyprojectChanged) {
message += '- Both `uv.lock` and `pyproject.toml` have been modified\n';
} else if (uvLockChanged) {
message += '- `uv.lock` has been modified\n';
} else if (pyprojectChanged) {
message += '- `pyproject.toml` has been modified\n';
}