ci: use uv for test dependency installation (fixes Poetry resolve hang)#2152
Open
RonShakutai wants to merge 15 commits into
Open
ci: use uv for test dependency installation (fixes Poetry resolve hang)#2152RonShakutai wants to merge 15 commits into
RonShakutai wants to merge 15 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the CI workflow against indefinite hangs during Poetry dependency resolution by adding explicit timeouts and ensuring Poetry runs non-interactively, improving reliability of the test matrix runs across Presidio components.
Changes:
- Add a job-level timeout (
timeout-minutes: 60) for the matrixtestjob to prevent unbounded runtime. - Add a step-level timeout (
timeout-minutes: 30) specifically for the “Install dependencies” step to cap Poetry resolution time. - Add
--no-interactiontopoetry installto avoid CI waiting on prompts.
Contributor
Coverage report (presidio-anonymizer)Click to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||
Contributor
Coverage report (presidio-image-redactor)Click to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||
Contributor
Coverage report (presidio-cli)Click to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||
Contributor
The analyzer test job runs `poetry install --all-extras` with no committed lock, so Poetry performs a universal resolve of the full optional-dependencies graph on every run. That resolve backtracks for many minutes — effectively hanging — driven by the langextract extra's deep, loosely-bounded transitive tree. Reproduced locally: Poetry >6 min (never completed); uv ~2s for the same 158-package resolution. Switch the test jobs to uv: - Install uv via astral-sh/setup-uv. - Create a per-component venv with `uv venv --seed` (seed keeps pip for the wheel-build step) and expose it via $GITHUB_PATH / $VIRTUAL_ENV. - `uv pip install -e '.<extras>'` plus the test tooling that previously came from the Poetry dev group (uv does not read that group). - Add a job-level `timeout-minutes: 60` (and 30 on the install step) so a bad resolve fails fast instead of hanging. No package metadata changed — pyproject.toml is untouched; this only swaps the CI install tooling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
a029bf8 to
7340a02
Compare
omri374
reviewed
Jul 12, 2026
Use "uv run --no-sync" for spaCy model downloads, pytest, and diff-cover instead of exposing the venv on $GITHUB_PATH. "uv sync" builds the project's .venv (resolving the analyzer --all-extras graph in seconds where Poetry's lockless universal resolve hangs), and the subsequent steps execute inside it idiomatically. The --all-extras selection stays in the job matrix, unchanged from main. Wheel-build keeps using the system interpreter, matching the previous Poetry behaviour. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The astral-sh/setup-uv action is not on the org's allowed-actions list, so adding it made the CI workflow fail at startup (startup_failure) before any job ran. Install a pinned uv from PyPI with the already present setup-python instead; this needs no new third-party action and keeps the resolver benefits that motivated the Poetry -> uv switch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
spaCy's `download` command shells out to `python -m pip install`, but uv-created virtualenvs ship without pip, so runtime/first-use model downloads (e.g. the presidio-cli conftest fetching en_core_web_lg) failed with SystemExit: 1. Install pip alongside the test tooling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrate each CI-tested package's development tooling from Poetry's [tool.poetry.group.dev.dependencies] to the standard PEP 735 [dependency-groups] table, and commit a uv.lock per package. This makes pyproject.toml the single source of truth for dev tooling and lets CI and Docker install a pinned, reproducible dependency graph instead of resolving on every run. The [project] metadata and the poetry-core build backend are unchanged, so wheels/sdists are byte-for-byte identical. Covers presidio-analyzer, presidio-anonymizer, presidio-cli, presidio-image-redactor, presidio-structured. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CI now runs `uv sync --locked --group dev`, which installs exactly the locked graph and fails if pyproject.toml and uv.lock disagree rather than silently resolving new versions. The dev group provides the test tooling (and pip, which spaCy's model download shells out to), so the manual `uv pip install pytest ...` line is gone. The uv cache is persisted across runs via actions/cache keyed on uv.lock and trimmed with `uv cache prune --ci`. The analyzer/anonymizer/image-redactor images consume the same lockfile with `uv sync --locked --no-default-groups --extra server --no-install-project` into UV_PROJECT_ENVIRONMENT=/usr/local, guaranteeing images use the same dependency graph as CI. Splitting the dependency layer from the source COPY keeps it cached until pyproject/uv.lock change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
Dependency ReviewThe following issues were found:
|
The newly committed uv.lock files pin exact versions, so dependency-review now sees two transformers advisories that already exist on main (capped at transformers <5 by spacy-huggingface-pipelines and tracked as Dependabot alerts). They are unrelated to the Poetry->uv migration and will be addressed in separate security PRs, so allow-list the two GHSAs here to keep this PR's dependency review unblocked. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SharonHart
requested changes
Jul 12, 2026
SharonHart
left a comment
Contributor
There was a problem hiding this comment.
- Add uv lock files to be reviewed by CODWOWNERS (like the tomls)
- Add instructions for copilot for always checking that uv.lock chnges are always committed when toml dependencies change
Address review feedback from @SharonHart: - CODEOWNERS: require presidio-administrators approval for **/uv.lock, the same as **/pyproject.toml, so lockfile changes get dependency review. - copilot-instructions: switch the local dev commands to uv and add an explicit rule that editing pyproject.toml dependencies requires regenerating and committing that package's uv.lock in the same change, since CI installs with `uv sync --locked` and fails on drift. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SharonHart
previously approved these changes
Jul 12, 2026
Address review feedback:
- ci.yml: use ${{ env.UV_CACHE_DIR }} for the cache action path instead of
hardcoding /mnt/uv-cache, so the cache and uv stay in sync if the dir
changes.
- copilot-instructions: update the "Technology Stack" bullet to name uv as
the dependency/install tool (poetry-core retained only as build backend),
matching the uv-based dev commands already documented.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
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.
Change Description
CI installs dependencies with
poetry installand no committed lock, so Poetry does a universal resolve of the fulloptional-dependenciesgraph on every run. That resolve backtracks for many minutes — effectively hanging — driven by thelangextractextra's deep, loosely-bounded transitive tree (google-genai, google-cloud-storage, aiohttp…). The same pathology hit the local-build/E2E job, wheredocker compose buildsat on "Resolving dependencies" for ~40 min until the job was cancelled.Reproduced locally (Python 3.13, warm cache): Poetry >6 min, never completed;
uvresolves the same graph in ~2s.Fix — swap CI dependency installation to uv
Test matrix jobs (
.github/workflows/ci.yml):python -m pip install uv==0.11.6(theastral-sh/setup-uvaction is not on the org's allowed-actions list — adding it made the workflow fail at startup, so uv is installed from PyPI via the existingsetup-python).uv sync <extras> --python <matrix>builds the project.venv; the spaCy-download, pytest and diff-cover steps run inside it viauv run --no-sync.pip+ the test tooling that previously came from the Poetry dev group are installed explicitly (uv doesn't read that group;pipis needed because spaCy's model download shells out topython -m pip install)./mntdisk viaUV_CACHE_DIR(mirroring the oldPOETRY_CACHE_DIR=/mnt/...), withUV_LINK_MODE=copyto avoid cross-filesystem hardlink warnings.tomlion Python < 3.11 (Poetry used to pull it onto the runner incidentally;buildneeds it to readpyproject.tomland it isn't in the hashed requirements file).timeout-minutes: 60(and30on the install step) so a bad resolve fails fast instead of hanging.Service image builds:
Dockerfiles install deps withuv pip install --system -r pyproject.toml --extra server(verified valid; the analyzer install layer resolves in ~9s vs Poetry's ~40 min hang).entrypoint.shscripts rungunicorndirectly instead ofpoetry run gunicorn, since the images no longer install Poetry. Verified locally: containers start healthy and/healthreturns 200.pyproject.toml(package metadata) is untouched — this only changes the install/run tooling. The Python 3.14 matrix job is kept as-is.Verified: all 22 test-matrix jobs (incl. Python 3.14) and the local-build/E2E job pass; the E2E image build dropped from a ~40 min hang to ~2.5 min.
Note
Per @omri374's review: this PR already moves all of CI off Poetry (test jobs + service image builds —
ci.ymlhas no functional Poetry left). A fuller replacement (thepoetry-corebuild backend, theDockerfile.{stanza,transformers,windows}variants,install_dependencies.sh, and contributor docs) is larger and better handled as a follow-up.Issue reference
N/A
Checklist