Skip to content

Conversation

eramongodb
Copy link
Contributor

@eramongodb eramongodb commented Aug 7, 2025

Resolves DRIVERS-3253. Followup to #585 and #676, motivated by this comment in DRIVERS-3249:

We should have repeatable builds in so much as is possible.

Accordingly, this PR proposes creating a uv.lock file for each pyproject.toml in DET.


First, requires-python in .evergreen/orchestration is bumped to 3.9 for consistency with .evergreen/pyproject.toml, as otherwise:

× No solution found when resolving dependencies:
╰─▶ Because the requested Python version (>=3.8) does not satisfy Python>=3.9 and drivers-evergreen-tools==0.1.0 depends on Python>=3.9, we can conclude that drivers-evergreen-tools==0.1.0 cannot be used.
    And because only drivers-evergreen-tools==0.1.0 is available and your project depends on drivers-evergreen-tools, we can conclude that your project's requirements are unsatisfiable.

Second, a uv.lock file is created for each pyproject.toml currently in DET under .evergreen and .evergreen/orchestration using the command uv lock. Quoting uv docs:

uv.lock is a universal or cross-platform lockfile that captures the packages that would be installed across all possible Python markers such as operating system, architecture, and Python version.

Unlike the pyproject.toml, which is used to specify the broad requirements of your project, the lockfile contains the exact resolved versions that are installed in the project environment. This file should be checked into version control, allowing for consistent and reproducible installations across machines.

There is nothing interesting in the lockfile for .evergreen/pyproject.toml, which is only used as a convenient means to install mongodl.py + related scripts as "tool executables". Regardless, this PR includes this file for consistency.

The lockfile for .evergreen/orchestration/pyproject.toml inherits the dependencies of mongo_orchestration (its only direct dependency) and pins the package versions to the latest available (per the default "highest" resolution strategy). Notably, this includes pymongo (currently pinned to 4.14.0) as well as certifi (the --with in install-cli.sh is not necessary and therefore removed; this can be restored if it is required by some other downstream project/script beyond .evergreen/orchestration/pyproject.toml).

Note

uv doesn't yet support uv.lock integration with uv tool install per astral-uv/uv#5815. The uv run --quiet --frozen --isolated uv pip freeze uv export command is used as a workaround. This command runs uv sync --frozen in an isolated virtual environment, which installs packages according to the project lockfile, then outputs a requirements.txt file according to the list of installed packages. The output currently looks like (for $MONGODB_VERSION >= 4.2):

# This file was autogenerated by uv via the following command:
#    uv export --frozen --format requirements.txt -o uv-requirements.txt
-e .
../
    # via drivers-orchestration
bottle==0.13.4 \
    --hash=sha256:045684fbd2764eac9cdeb824861d1551d113e8b683d8d26e296898d3dd99a12e \
    --hash=sha256:787e78327e12b227938de02248333d788cfe45987edca735f8f88e03472c3f47
    # via mongo-orchestration
certifi==2025.8.3 \
    --hash=sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407 \
    --hash=sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5
    # via requests
...
urllib3==2.5.0 \
    --hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \
    --hash=sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc
    # via requests

The requirements file is prefixed with uv- to avoid potentially conflicting with any pre-existing requirements.txt file in the target directory.

Third, to continue supporting backward compatibility with MongoDB Server versions that have been dropped by the latest PyMongo release (e.g. server versions 3.6 and 4.0), the --overrides flag is added to the uv tool install command in install-cli.sh script. The overrides file may be specified by a new DRIVERS_TOOLS_INSTALL_CLI_OVERRIDES environment variable as appropriate for whichever project may be invoking the install-cli.sh script. This env var is used by .evergreen/orchestration/setup.sh to specify the pymongo constraints per $MONGODB_VERSION. The overrides file is named uv-override-dependencies.txt in reference to the [override-dependencies] uv project setting.

Note

The --with flag cannot be used to override direct dependency requirements:

× No solution found when resolving dependencies:
╰─▶ Because you require pymongo<4.14 and pymongo==4.14.0, we can conclude that your requirements are unsatisfiable.

The resulting behavior looks as follows given MONGODB_VERSION=4.2 (from .evergreen/orchestration, with --verbose, focusing on the pymongo dependency, unrelated lines omitted for brevity):

DEBUG Adding direct dependency: pymongo>=4.14.0, <4.14.0+
DEBUG Adding transitive dependency for mongo-orchestration==0.12.0.dev0: pymongo>=4, <5
DEBUG Searching for a compatible version of pymongo (>=4.14.0, <4.14.0+)
DEBUG Selecting: pymongo==4.14.0 [compatible] (pymongo-4.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl)
 + pymongo==4.14.0

and with MONGODB_VERSION=4.0 (which appends pymongo<4.14 to the override dependencies file):

DEBUG Adding direct dependency: pymongo<4.14
DEBUG Adding transitive dependency for mongo-orchestration==0.12.0.dev0: pymongo<4.14
DEBUG Searching for a compatible version of pymongo (<4.14)
DEBUG Selecting: pymongo==4.13.2 [compatible] (pymongo-4.13.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl)
 + pymongo==4.13.2

@eramongodb
Copy link
Contributor Author

Investigating the following error observed on some platforms (but not others):

error: Failed to parse `uv.lock`
  Caused by: TOML parse error at line 170, column 9
    |
170 | sdist = { hash = "sha256:1286103cc4eddd80b485d3dfa83b1a8e748007756b2094b85db89503be825ba4" }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
data did not match any variant of untagged enum SourceDistWire

Possibly a uv version compatibility issue? 🤔

@blink1073
Copy link
Member

Possibly a uv version compatibility issue? 🤔

Yeah this might be stretching the lock file's cross-platform capability.

@blink1073
Copy link
Member

We could instead add pymongo to a requirements-in.txt file

@eramongodb
Copy link
Contributor Author

eramongodb commented Aug 7, 2025

Possibly a uv version compatibility issue? 🤔

Looks like the macos-14-arm64 distro is sometimes (???) selecting a uv binary whose version (0.5.9, Dec 2024) is much older than other distros (0.7.0+, Apr 2025). Concerning the lockfile parsing errors, astral-sh/uv#10654 might be related. Regenerating the uv.lock file with 0.5.9 appears to have resolved the parsing issues while remaining compatible with newer uv versions.

$ command -V uv
uv is /opt/homebrew/bin/uv
$ uv --version
uv 0.5.9 (Homebrew 2024-12-13)
$ cat uv.lock
...
sdist = { url = "https://github.com/mongodb/mongo-orchestration/archive/master.tar.gz", hash = "sha256:1286103cc4eddd80b485d3dfa83b1a8e748007756b2094b85db89503be825ba4" }
...
$ command -V uv
uv is /opt/homebrew/bin/uv
$ uv --version
uv 0.8.4 (Homebrew 2025-07-30)
$ cat uv.lock
...
sdist = { hash = "sha256:1286103cc4eddd80b485d3dfa83b1a8e748007756b2094b85db89503be825ba4" }
...

Future updates to the lockfiles should hopefully not encounter this issue once the uv binary on the problematic EVG distros are updated to a more recent version than 0.5.9 (e.g. at least 0.6.0 or newer).

Filed DEVPROD-20614 to track the investigation and update of system-provided uv on the macos-14-arm64 distro hosts.

@eramongodb
Copy link
Contributor Author

eramongodb commented Aug 7, 2025

Alternatively, the install-cli.sh script could be updated to unconditionally prefer using the Python-Toolchain-provided uv binary (more likely to be up-to-date) over the system-provided uv binary by unconditionally adding the Python Toolchain bin directory to PATH (rather than conditioning it on the absence of a system-provided uv binary).

@blink1073
Copy link
Member

I think if "CI" is set, we should only ever use the toolchain if present, or fall back to installing uv in a venv. That will allow us to control the version better.

@eramongodb
Copy link
Contributor Author

eramongodb commented Aug 7, 2025

I don't think we want to condition it on the $CI environment variable, since that would result in an inconsistency between test vs. downstream environments. Instead, I propose using the uv binary found via existing lookup routines to install a more up-to-date uv binary via uv tool install uv. This will ensure a consistent uv binary version is used across all environments and is also always within our control. For starters, pinned the version to uv~=0.8.0 to allow automatic patch releases updates.

@blink1073
Copy link
Member

Perhaps we should add a Troubleshooting section to the Readme, and say "if you see this error, here is where to apply the fix".

Copy link
Contributor

@matthewdale matthewdale left a comment

Choose a reason for hiding this comment

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

Looks good! 👍

@eramongodb
Copy link
Contributor Author

Aside: it looks like the inconsistent uv version problem on MacOS distros might also manifest as the following error on macOS 11 distros due to providing uv version 0.2.9 (?!):

error: unrecognized subcommand 'install'
  tip: a similar subcommand exists: 'uv pip install'
Usage: uv tool [OPTIONS] <COMMAND>
For more information, try '--help'.

It is unclear since when this downgrade occurred (EVG image event log doesn't reveal any recent changes), but it seems to have taken place sometime after August 1 (no task failures prior). The uv binary version consistency issues on MacOS distros are being tracked by DEVPROD-20614, but per DevProd guidelines these fixes will likely not be applied to the "long EOL'd" macOS 11 distros.

@blink1073
Copy link
Member

Perhaps we should add a Troubleshooting section to the Readme, and say "if you see this error, here is where to apply the fix".

I'm concerned about the discoverability of knowing to make this change when PyMongo drops support for a MongoDB version.

@eramongodb
Copy link
Contributor Author

I'm concerned about the discoverability of knowing to make this change when PyMongo drops support for a MongoDB version.

Added a section to the README documenting the PyMongo dependency and update instructions.

Copy link
Member

@blink1073 blink1073 left a comment

Choose a reason for hiding this comment

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

Excellent, thank you!

@blink1073
Copy link
Member

Ah, we're getting failures on macos arm:

[2025/08/20 09:42:02.687] fatal: No names found, cannot describe anything.
[2025/08/20 09:42:02.687] Using Python 3.11.1 environment at: /Library/Frameworks/Python.Framework/Versions/3.11
[2025/08/20 09:42:02.747]   × No solution found when resolving dependencies:
[2025/08/20 09:42:02.747]   ╰─▶ Because you require setuptools==65.5.0 and setuptools==80.9.0, we can
[2025/08/20 09:42:02.747]       conclude that your requirements are unsatisfiable.

@blink1073
Copy link
Member

bash .evergreen/prepare-env-and-resources.sh runs fine on my local machine, adding a trace might help.

@eramongodb
Copy link
Contributor Author

eramongodb commented Aug 20, 2025

Odd. The only explicit mention of setuptools in DET scripts is:

if [ $ver == "39" ]; then
req="setuptools==70.3.0"
fi

I cannot find any (relevant) mention of setuptools in mongo-orchestration either. I wonder where these requirements are coming from. 🤔

@blink1073
Copy link
Member

I echoed the content of uv-requirements.txt in this patch:

[2025/08/20 14:16:11.964] certifi==2025.7.14
[2025/08/20 14:16:11.964] pip==22.3.1
[2025/08/20 14:16:11.964] pip==25.1.1
[2025/08/20 14:16:11.964] rust-just==1.42.4
[2025/08/20 14:16:11.964] setuptools==65.5.0
[2025/08/20 14:16:11.964] setuptools==80.9.0
[2025/08/20 14:16:11.964] uv==0.8.3

@eramongodb
Copy link
Contributor Author

Solved: it's a Python binary compatibility problem due to the uv run uv pip freeze pattern. Successful tasks find Python 3.13, whereas failing tasks find Python 3.11. It seems the uv pip freeze command may be including seed packages required by the isolated virtual environment in its output.

It turns out a more suitable command for this purpose which does not require pip or an isolated virtual environment is uv export. Even when it finds Python 3.11, pip and setuptools are not included in the requirements.

PR description has been updated accordingly.

Copy link
Member

@blink1073 blink1073 left a comment

Choose a reason for hiding this comment

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

Thanks again!

@blink1073
Copy link
Member

I found another issue, make run-server no longer works:

+ declare uv_install_args
+ uv_install_args=(--quiet --force --editable --with-requirements uv-requirements.txt --overrides "${DRIVERS_TOOLS_INSTALL_CLI_OVERRIDES:?}")
+ uv tool install --quiet --force --editable --with-requirements uv-requirements.txt --overrides /Users/steve.silvester/workspace/drivers-evergreen-tools/.evergreen/orchestration/uv-override-dependencies.txt .
  × Failed to build `drivers-tools-auth-aws @
  │ file:///Users/steve.silvester/workspace/drivers-evergreen-tools/.evergreen/auth_aws`
  ╰─▶ /Users/steve.silvester/workspace/drivers-evergreen-tools/.evergreen/auth_aws does not appear to be a Python
      project, as neither `pyproject.toml` nor `setup.py` are present in the directory
make: *** [run-server] Error 1

It is because we have auth_aws as part of the workspace in pyproject.toml.

Adding this file as auth_aws/pyproject.toml fixes it:

[project]
name = "drivers-tools-auth-aws"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.9"
dependencies = []

[tool.setuptools]
packages = []

@eramongodb
Copy link
Contributor Author

eramongodb commented Aug 21, 2025

It is because we have auth_aws as part of the workspace in pyproject.toml.

I don't this is correct. The error suggests uv tool install . is being run in the .evergreen/auth_aws directory (which has no pyproject.toml). install-cli.sh should be installing .evergreen (for mongodl.py+etc.) or .evergreen/orchestration (for drivers-orchestration), not .evergreen/auth_aws. install-cli.sh is invoked from the .evergreen directory in all cases except .evergreen/orchestration/setup.sh, which invokes it twice: once with .evergreen and once more with .evergreen/orchestration (+ .evergreen/tests/test-cli.sh which invokes it three times, one extra as a reinstall test). Where/how is running make run-server resulting in install-cli.sh being invoked with a target directory of .evergreen/auth_aws?

@blink1073
Copy link
Member

No, uv is attempting to build a project in the workspace, and failing to do so, because it has no pyproject.toml file. As to why it occurs when invoking one script and not the other, I'm not sure, but I first noticed this when running our server start script from pymongo, which is also broken in the same way.

@eramongodb
Copy link
Contributor Author

uv is attempting to build a project in the workspace, and failing to do so, because it has no pyproject.toml file

Only because it is attempting to build .evergreen/auth_aws, not .evergreen or .evergreen/orchestration. .evergreen/auth_aws would only be part of either .evergreen or .evergreen/orchestration's workspace if their pyproject.toml defined a workspace to begin with. Neither project does this: there is no [tool.uv.workspace] or [tool.uv.sources]. This can also be verified by running uv build in both .evergreen:

$ uv build
Building source distribution...
Building wheel from source distribution...
Successfully built dist/drivers_evergreen_tools-0.1.0.tar.gz
Successfully built dist/drivers_evergreen_tools-0.1.0-py3-none-any.whl

$ tar -tf dist/drivers_evergreen_tools-0.1.0.tar.gz
drivers_evergreen_tools-0.1.0/mongodl.py
drivers_evergreen_tools-0.1.0/mongosh_dl.py
drivers_evergreen_tools-0.1.0/socks5srv.py
drivers_evergreen_tools-0.1.0/.gitignore
drivers_evergreen_tools-0.1.0/pyproject.toml
drivers_evergreen_tools-0.1.0/PKG-INFO

and in .evergreen/orchestration:

$ uv build
Building source distribution...
Building wheel from source distribution...
Successfully built dist/drivers_orchestration-0.1.0.tar.gz
Successfully built dist/drivers_orchestration-0.1.0-py3-none-any.whl

$ tar -tf dist/drivers_orchestration-0.1.0.tar.gz
drivers_orchestration-0.1.0/drivers_orchestration.py
drivers_orchestration-0.1.0/.gitignore
drivers_orchestration-0.1.0/pyproject.toml
drivers_orchestration-0.1.0/PKG-INFO

However, when run in .evergreen/auth_aws:

$ uv build
Building source distribution...
  × Failed to build `.evergreen/auth_aws`
  ╰─▶ .evergreen/auth_aws does not appear to be a Python project, as neither `pyproject.toml` nor `setup.py` are present in
      the directory

The original error message states: Failed to build drivers-tools-auth-aws @ file:///Users/steve.silvester/workspace/drivers-evergreen-tools/.evergreen/auth_aws. Where is this drivers-tools-auth-aws defined? It's not mentioned anywhere in the DET repository.

@blink1073
Copy link
Member

Apologies for the false alarm, I blew away my local branch and used your latest changes and I no longer see the unexpected behavior.

@ShaneHarvey
Copy link
Contributor

I’ll defer to Steve’s review.

@eramongodb eramongodb removed the request for review from ShaneHarvey August 22, 2025 20:19
@eramongodb eramongodb merged commit 9da8ebc into mongodb-labs:master Aug 22, 2025
77 checks passed
@eramongodb eramongodb deleted the det-uv-lock branch August 22, 2025 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants