PYTHON-5956 Add python/setup action for shared uv+just CI setup - #117
Merged
Conversation
Python driver repos each repeat the same block of steps to get uv, just, and dependencies in place before a CI job can run. This action does that once so they can share it. Python comes from setup-python and uv is pointed at that interpreter through UV_PYTHON, rather than letting uv download a managed one: the runner images already ship it. `just install` is optional two ways over. A job that needs no project dependencies sets run-install to false, and a project with no justfile or no install recipe skips the step instead of failing, so the same defaults work for consumers that only want the tools on PATH. Recipe detection matches whole names. Substring matching would fire on install-deps, preinstall, and uninstall, and `grep -w` is no help there because it counts `-` as a word boundary. The repo's own Python test job now uses the action to get uv and just, which exercises it end to end on every run.
setup-python fails on a version with no stable release yet, where uv would have downloaded the prerelease itself. mongo-python-driver's build matrix tests against a beta Python, so it needs the fallback available.
The design copied a 7 day cooldown from mongo-python-driver's local set-uv-exclude-newer action, but PYTHON-5980 deleted that action and committed uv.lock instead. A repo with a lock file has already pinned its resolution, and UV_EXCLUDE_NEWER set here would override it. Keep the input for a repo that wants a cooldown and has no lock file, but do not impose one.
Code scanning treats the two GITHUB_ENV writes as new alerts and fails the check. Exporting to the caller's later steps is what the step is for, and a composite action has no other mechanism, so the audit has nothing actionable to report.
uv resolves a prerelease Python on its own when no stable release exists. A repo moving to this action would otherwise lose that and fail instead, so the default should match the behaviour being replaced rather than the stricter setup-python default.
Setting UV_EXCLUDE_NEWER from here fought with the consuming repo. A repo that commits uv.lock records exclude-newer in the lock, so exporting a different value made `uv lock --check` fail: mongo-python-driver's static job would have broken. Resolution policy belongs to the repo, in its pyproject.toml, uv.toml, or lock file, so the action no longer touches it. Python action docs move to python/README.md and python-labs/README.md, with the top-level README linking to them.
Conflict in README.md: mongodb-labs#118 documented the uv-lock-update action's new exclude_newer input in the Python section that this branch moved into python/README.md. Kept the split and ported mongodb-labs#118's wording into the moved section, which now matches main's text exactly.
6 tasks
The install ran by default, which meant the action needed to detect a missing justfile or install recipe and skip gracefully. That detection was the only reason run_install.sh and its tests existed: defensive work for consumers that never wanted an install. Opting in removes the need for it. A caller asking for `run-install: true` has an install recipe, so a missing one should fail rather than be skipped silently, and the step is a plain `just install` again. Of mongo-python-driver's eight converted jobs, four install and four do not, so neither default saves the caller any lines. Putting tools on PATH is what this action promises; installing dependencies is a side effect a job should ask for.
Conflict in ci.yml: Dependabot bumped setup-uv to v10.0.1 on the step this branch replaced with the python/setup action. Kept the replacement and moved the action's own pin to v10.0.1, so the repo carries one pin. v10 disables caching for pull_request_target, workflow_run, and release when enable-cache is 'auto'. The action passes an explicit value, so the default path is unaffected.
A boolean only ran `install`. A comma-separated list lets a job name the recipes it needs, so setup and the recipes that follow it are one step. Entries run in order and stop at the first failure. A blank entry is skipped, so a trailing comma does not invoke the default recipe, and an entry may carry arguments.
Running recipes mixed dependency management into an action whose job is installing tools. A job that needs project dependencies runs its own `just install` step.
There was a problem hiding this comment.
🟡 Changes recommended
Two documented pre-publish action paths do not exist and would make copied workflows fail.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds a shared Python CI setup action and reorganizes Python documentation.
Changes:
- Installs Python, uv, and just through one composite action.
- Exercises the action in CI.
- Moves Python and Python Labs documentation into dedicated READMEs.
File summaries
| File | Description |
|---|---|
README.md |
Links dedicated Python documentation. |
python/setup/action.yml |
Defines the shared setup action. |
python/README.md |
Documents Python actions. |
python-labs/README.md |
Documents Python Labs actions. |
.github/workflows/ci.yml |
Uses the setup action in CI. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The index claimed the Labs README covered the same actions as the driver one. It documents pre-publish and post-publish only. Both pre-publish examples pointed at `pre-publishv2`, a path that does not exist, so a copied workflow failed to resolve the action.
blink1073
marked this pull request as ready for review
September 2, 2026 15:37
aclark4life
requested changes
Sep 2, 2026
| # The tests below need uv, which the python/setup action installs. Using it | ||
| # here also exercises the action itself on every run. | ||
| - name: Install Python tooling | ||
| uses: $/python/setup |
Collaborator
There was a problem hiding this comment.
Typo probably ^, ./python/setup ?
Member
Author
There was a problem hiding this comment.
No, that is the new syntax for relative files
aclark4life
approved these changes
Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PYTHON-5956
Adds a
python/setupaction that puts Python, uv, and just onPATH. mongo-python-driver repeats that block in eight jobs, andnode/setupalready does the same for Node.Most of the diff is from moving the Python-specific parts of the top level README down one level so we don't keep clogging up space.
Python comes from
setup-python, with uv pinned to that interpreter rather than downloading a managed one the runner already ships.The action installs tools and nothing else. It runs no just recipes and sets no resolution policy, so a job that needs project dependencies runs its own
just installstep, and a repo that wants a publication cutoff configuresexclude-neweror commits auv.lock.This repo's
test-pythonjob uses the action, so every run exercises it. The Python docs move out of the top-level README into python/README.md. The first consumer is mongodb/mongo-python-driver#2990, and adoption elsewhere is tracked in PYTHON-5957.Validation
Converted all eight jobs on a fork of mongo-python-driver: 14 jobs green.
setup-pythonresolved every version that matrix needs, read from the job logs rather than inferred from a green tick: free-threaded 3.13.15t, 3.15.0-rc.1, PyPy 7.3.23 on 3.11.15, and 3.9.25.allow-prereleasesdefaults to true so the 3.15 beta resolves, matching what uv did on its own.