Skip to content

Migrate project dependency management from Pipenv to uv#1231

Merged
Strift merged 4 commits into
meilisearch:mainfrom
DhavalGojiya:feat/migrate-to-uv
May 25, 2026
Merged

Migrate project dependency management from Pipenv to uv#1231
Strift merged 4 commits into
meilisearch:mainfrom
DhavalGojiya:feat/migrate-to-uv

Conversation

@DhavalGojiya
Copy link
Copy Markdown
Contributor

@DhavalGojiya DhavalGojiya commented May 24, 2026

Pull Request

Related issue

Fixes #1220 (comment)

Description

Migrate to uv from pipenv.

Now to Setup meilisearch-python project in any machine,
Run:
% uv sync

It will take care of everything.

Changes

  1. Converted Pipfile.lock --> uv.lock
  2. Add uv support in ci pipelines
  3. Add uv support in tox
  4. Adjusted contributing file according to uv

Removed Files

  • Pipfile
  • Pipfile.lock

Removed Dependencies

  • tox-pipenv (End of life + Without pipenv doesn't work)
  • pytest-ordering (Not used in the codebase)
  • wrapt (Not used in the codebase)
  • pdoc3 (Not used in the codebase)

Tests

  1. % uv run tox -e pylint
pylint-tox
  1. % uv run tox -e mypy
mypy-tox
  1. % uv run tox -e py39
pytest-tox

PR checklist

Please check if your PR fulfills the following requirements:

  • Did you use any AI tool while implementing this PR (code, tests, docs, etc.)? If yes, disclose it in the PR description and describe what it was used for. AI usage is allowed when it is disclosed.
  • Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
  • Have you read the contributing guidelines?
  • Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!

Summary

Migrates the project's dependency management from Pipenv to uv (https://docs.astral.sh/uv/). This resolves CI determinism and lockfile drift described in issue #1220 by replacing Pipenv installs (which could mutate Pipfile.lock) with deterministic uv-based installs and lockfiles.

Changes

Configuration & Dependency Files

  • Removed: Pipfile, Pipfile.lock.
  • Added/Converted: uv.lock (converted from Pipfile.lock); added [tool.uv] configuration in pyproject.toml.
  • pyproject.toml: Reorganized metadata; added [dependency-groups] for dev/test/lint/docs; added uv config (fork-strategy, default-groups); removed an empty [tool.pylint] table.
  • tox.ini: Switched to tox-uv (requires tox-uv), set runner = uv-venv-lock-runner for environments, removed pipenv-specific deps/whitelist_externals, and added py312 and py313 to envlist in addition to py39–py311.

CI/CD Workflows

All GitHub Actions workflows were updated to install and use uv (via astral-sh/setup-uv, pinned) instead of Pipenv:

  • .github/workflows/tests.yml: Replaced pipenv install/run steps with uv (uv run ...) for pytest, pylint, mypy, black, isort; produces coverage XML for integration tests.
  • .github/workflows/documentation.yml: Builds docs using uv run --only-group docs (sphinx-apidoc, sphinx-build).
  • .github/workflows/pre-release-tests.yml: Runs integration tests via uv run pytest and installs uv via the setup action.
  • .github/workflows/pypi-publish.yml: Uses uv build and uvx (twine@6.2.0) upload for packaging/publishing; uv installation step pinned and caching disabled.
  • Common job-level changes: set PYTHONUNBUFFERED=1, UV_PYTHON, UV_LOCKED and removed pipenv installation/caches and pipenv-based install commands.

Docker, Docs & Contributing

  • Dockerfile: Copies uv/uvx binaries from ghcr.io/astral-sh/uv and installs dependencies with uv sync --frozen --no-install-project (replaces pipenv flow); handles uv sync running without project sources during build.
  • CONTRIBUTING.md: Replaced pipenv instructions with uv sync and uv run examples; updated examples for running checks and tox with Docker.
  • .gitignore: Updated comment for .python-version from “# pyenv” to “# uv”.

Dependencies Removed

  • Removed tox-pipenv (EOL/incompatible without pipenv), pytest-ordering, wrapt, and pdoc3 (not used).

New Local Setup Command

  • Introduces uv sync as the new command to prepare the project environment on any machine.

Verification

PR includes evidence of successful checks executed via uv-run tox:

  • uv run tox -e pylint: pylint score 10.00/10.
  • uv run tox -e mypy: "Success: no issues found" across checked files.
  • uv run tox -e py39: pytest run reported 357 collected tests; tests executed via tox under uv environments.

Impact

  • Restores deterministic, consistent dependency installation across local and CI environments and prevents Pipenv-induced lockfile mutation during CI runs by migrating to uv.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 24, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 960d3cdb-50c8-40d9-9b35-877afe8361f5

📥 Commits

Reviewing files that changed from the base of the PR and between 086968c and b16aa4d.

📒 Files selected for processing (1)
  • .github/workflows/pypi-publish.yml

📝 Walkthrough

Walkthrough

Replaces Pipenv with uv across project metadata, CI workflows, Dockerfile, tox, CONTRIBUTING, and ignores; workflows install pinned astral-sh/setup-uv and use uv run/uv build/uvx instead of pipenv commands.

Changes

Pipenv to uv Migration

Layer / File(s) Summary
Dependency configuration and build system
pyproject.toml
Project metadata reformatted; dynamic = ["version"] moved earlier; added [project.urls], [dependency-groups], and [tool.uv]; removed empty [tool.pylint] placeholder.
GitHub Actions Workflows
.github/workflows/documentation.yml, .github/workflows/pre-release-tests.yml, .github/workflows/tests.yml, .github/workflows/pypi-publish.yml
Workflows set PYTHONUNBUFFERED, UV_PYTHON, UV_LOCKED; remove pipenv caching/install steps; add pinned astral-sh/setup-uv; replace pipenv run/pipenv build/pipenv twine with uv run/uv build/uvx twine.
Local Development and Container Tooling
Dockerfile, tox.ini, CONTRIBUTING.md, .gitignore
Dockerfile copies pyproject.toml and uv.lock, uses uv multi-stage binaries and uv sync --frozen; tox.ini adds py312/py313, requires tox-uv, and uses uv-venv-lock-runner; CONTRIBUTING and .gitignore updated to reference uv commands.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I swapped Pipenv crumbs for a brave new uv run,
Lockfiles aligned beneath the morning sun,
Docs, tests, and builds now follow one small track,
CI and Docker carry the uv pack,
A rabbit hops onward — tidy, quick, and fun.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately summarizes the main change: migrating from Pipenv to uv for dependency management across the entire project.
Linked Issues check ✅ Passed The PR fully addresses issue #1220 by replacing Pipenv with uv to fix matrix variable resolution and ensure deterministic, locked dependency installation without mutations to lock files.
Out of Scope Changes check ✅ Passed All changes are directly related to the Pipenv-to-uv migration. Removed dependencies (tox-pipenv, pytest-ordering, wrapt, pdoc3) align with the migration objectives and are documented as unused.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/pre-release-tests.yml:
- Around line 31-35: Remove the trailing whitespace in the GitHub Actions
"Install uv" step: edit the step with name "Install uv" (the block containing
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b and with:
version: "0.11.16") and delete any trailing spaces on the empty/closing lines so
there are no trailing whitespace characters; save and re-run yamllint/CI to
confirm the lint error is resolved.

In @.github/workflows/tests.yml:
- Around line 105-109: In the "black" job's uv setup step (step name "Install
uv" using astral-sh/setup-uv), remove trailing whitespace from the version line
— the value version: "0.11.16" currently has extra spaces at the end; delete
those trailing spaces so the line ends immediately after the closing quote and
re-run yamllint to confirm the fix.
- Around line 123-129: The isort step calls the CLI "uv" but never installs it;
add a job step before the "isort" run to install the required package (e.g., run
pip install --upgrade pip && pip install uv) after the existing "Set up Python
3.9" step so that the "uv run isort meilisearch tests --check-only" command in
the isort step can be found and executed; reference the isort job step and the
exact run invocation "uv run isort meilisearch tests --check-only" when applying
the change.

In `@Dockerfile`:
- Line 6: The Dockerfile currently runs "RUN apt-get update -y" in its own
layer; combine that update with the following install command(s) into a single
RUN instruction (e.g., "RUN apt-get update -y && apt-get install -y <packages>
&& rm -rf /var/lib/apt/lists/*") or remove the standalone update if no packages
are installed, ensuring package installation and cleanup occur in one layer to
improve reproducibility and satisfy scanners; locate the standalone RUN apt-get
update -y line and merge it with the subsequent apt-get install usages in the
Dockerfile.
- Around line 3-4: In the Dockerfile layer that only copies pyproject.toml and
uv.lock (the COPY pyproject.toml . and COPY uv.lock . step), change the uv
command to use --no-install-project so that uv sync --frozen does not try to
install the local project before source is added; update the uv sync invocation
in that Dockerfile layer to include --no-install-project (keeping --frozen) to
avoid failing when the local package is not present yet.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7c1f8b76-47cf-48c4-8962-a9a336c9b3fb

📥 Commits

Reviewing files that changed from the base of the PR and between bc78e12 and a795d90.

⛔ Files ignored due to path filters (2)
  • Pipfile.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • .github/workflows/documentation.yml
  • .github/workflows/pre-release-tests.yml
  • .github/workflows/pypi-publish.yml
  • .github/workflows/tests.yml
  • .gitignore
  • CONTRIBUTING.md
  • Dockerfile
  • Pipfile
  • pyproject.toml
  • tox.ini
💤 Files with no reviewable changes (1)
  • Pipfile

Comment thread .github/workflows/pre-release-tests.yml Outdated
Comment thread .github/workflows/tests.yml
Comment thread .github/workflows/tests.yml
Comment thread Dockerfile
Comment thread Dockerfile
Copy link
Copy Markdown
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/pypi-publish.yml:
- Around line 36-37: Replace the current secret-based upload (TWINE_USERNAME:
__token__, TWINE_PASSWORD: pypi-${{ secrets.PYPI_API_TOKEN }}) and the direct
twine invocation in the step that runs "uv run --with=twine -- twine upload
dist/*" with an OIDC-based publish flow: stop setting TWINE_PASSWORD from
secrets.PYPI_API_TOKEN, enable id-token: write and packages: write in the
workflow permissions, and use an OIDC-capable publisher (for example, switch to
the pypa/gh-action-pypi-publish action with use_oidc: true or request an OIDC
token and feed that token to TWINE_PASSWORD) so the twine upload step no longer
depends on the long-lived secrets.PYPI_API_TOKEN value.
- Around line 26-29: The workflow step "Install uv" (uses:
astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b) should explicitly
disable setup-uv's cache by adding the with key enable-cache: "false" alongside
the existing version: "0.11.16" so the PyPI publish job does not rely on GitHub
Actions cache restore/upload.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b7fa490c-f5ea-45f1-97e0-3c5ddd610a22

📥 Commits

Reviewing files that changed from the base of the PR and between a795d90 and 07f8086.

⛔ Files ignored due to path filters (2)
  • Pipfile.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • .github/workflows/documentation.yml
  • .github/workflows/pre-release-tests.yml
  • .github/workflows/pypi-publish.yml
  • .github/workflows/tests.yml
  • .gitignore
  • CONTRIBUTING.md
  • Dockerfile
  • Pipfile
  • pyproject.toml
  • tox.ini
💤 Files with no reviewable changes (1)
  • Pipfile
✅ Files skipped from review due to trivial changes (1)
  • .gitignore

Comment thread .github/workflows/pypi-publish.yml
Comment thread .github/workflows/pypi-publish.yml Outdated
Comment on lines +36 to +37
uv build
uv run --with=twine -- twine upload dist/*
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 24, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ls -la .github/workflows || true
sed -n '1,140p' .github/workflows/pypi-publish.yml | nl -ba

Repository: meilisearch/meilisearch-python

Length of output: 647


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- pypi-publish.yml (full) ----"
cat -n .github/workflows/pypi-publish.yml | sed -n '1,200p'

Repository: meilisearch/meilisearch-python

Length of output: 1163


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find all usages of PyPI API token / twine password
rg -n "PYPI_API_TOKEN|TWINE_PASSWORD|TWINE_USERNAME|twine upload|trusted publishing|oidc|OIDC" .github/workflows -S || true

# Look for uv cache-related hardening/controls
rg -n "UV_CACHE|cache|setup-uv|astral-sh/setup-uv|cache-poison" .github/workflows -S || true

# Also scan any mentioned scripts
rg -n "trusted publishing|oidc|twine|TWINE_PASSWORD|PYPI_API_TOKEN" .github/scripts -S || true

Repository: meilisearch/meilisearch-python

Length of output: 1289


Switch PyPI publishing to OIDC trusted publishing (stop using PYPI_API_TOKEN for TWINE_PASSWORD).

The workflow uploads with TWINE_USERNAME: __token__ and TWINE_PASSWORD: "pypi-${{ secrets.PYPI_API_TOKEN }}", which requires a long-lived secret; using PyPI Trusted Publishing (OIDC) would avoid secret injection and reduce exposure/rotation burden.

🧰 Tools
🪛 zizmor (1.25.2)

[info] 37-37: prefer trusted publishing for authentication (use-trusted-publishing): this command

(use-trusted-publishing)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pypi-publish.yml around lines 36 - 37, Replace the current
secret-based upload (TWINE_USERNAME: __token__, TWINE_PASSWORD: pypi-${{
secrets.PYPI_API_TOKEN }}) and the direct twine invocation in the step that runs
"uv run --with=twine -- twine upload dist/*" with an OIDC-based publish flow:
stop setting TWINE_PASSWORD from secrets.PYPI_API_TOKEN, enable id-token: write
and packages: write in the workflow permissions, and use an OIDC-capable
publisher (for example, switch to the pypa/gh-action-pypi-publish action with
use_oidc: true or request an OIDC token and feed that token to TWINE_PASSWORD)
so the twine upload step no longer depends on the long-lived
secrets.PYPI_API_TOKEN value.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Switch PyPI publishing to OIDC trusted publishing (stop using PYPI_API_TOKEN for TWINE_PASSWORD).

@curquiza We should really consider switching to OIDC trusted publishing for publishing the project to PyPI in the near future, given the many supply chain and security attacks happening nowadays.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Created #1232

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
.github/workflows/pypi-publish.yml (1)

36-36: ⚡ Quick win

Pin Twine for deterministic CI uploads.

In .github/workflows/pypi-publish.yml line 36, uvx twine upload dist/* can resolve/install the latest Twine when Twine isn’t already cached, which makes release behavior drift over time. Prefer pinning an exact Twine version (e.g., uvx twine@6.2.0 upload dist/*) or installing Twine with a locked/pinned version before upload.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pypi-publish.yml at line 36, Replace the unpinned Twine
invocation "uvx twine upload dist/*" with a pinned Twine version to ensure
deterministic CI uploads; either call the runner tool with an exact Twine
release (e.g., use "uvx twine@6.2.0 upload dist/*") or add a preceding step that
installs Twine with a locked version (e.g., pip install twine==6.2.0) and then
run "uvx twine upload dist/*" so the upload uses the pinned Twine release.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @.github/workflows/pypi-publish.yml:
- Line 36: Replace the unpinned Twine invocation "uvx twine upload dist/*" with
a pinned Twine version to ensure deterministic CI uploads; either call the
runner tool with an exact Twine release (e.g., use "uvx twine@6.2.0 upload
dist/*") or add a preceding step that installs Twine with a locked version
(e.g., pip install twine==6.2.0) and then run "uvx twine upload dist/*" so the
upload uses the pinned Twine release.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f6e12e73-52e2-444b-a298-27607ff59c36

📥 Commits

Reviewing files that changed from the base of the PR and between 07f8086 and 9be0e9f.

📒 Files selected for processing (2)
  • .github/workflows/pypi-publish.yml
  • Dockerfile

@Strift Strift added the maintenance Anything related to maintenance (CI, tests, refactoring...) label May 25, 2026
Copy link
Copy Markdown
Contributor

@Strift Strift left a comment

Choose a reason for hiding this comment

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

Hello @DhavalGojiya and thanks for this PR 🙌

It's a much welcome improvement :)

@Strift Strift added this pull request to the merge queue May 25, 2026
Merged via the queue into meilisearch:main with commit ada25db May 25, 2026
11 checks passed
@DhavalGojiya
Copy link
Copy Markdown
Contributor Author

Hello @DhavalGojiya and thanks for this PR 🙌

It's a much welcome improvement :)

Your welcome, many new improvements coming soon 😉

@DhavalGojiya DhavalGojiya deleted the feat/migrate-to-uv branch May 25, 2026 05:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance Anything related to maintenance (CI, tests, refactoring...)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GitHub CI Actions workflow matrix variable resolves to empty

2 participants