ci: Pin transitive dependencies for tests on Python>=3.8#6437
4 issues
Medium
Constraints are not part of the on-disk cache key, causing stale dependency pins after config changes - `scripts/populate_tox/populate_tox.py:266-279`
The file cache in package_dependencies.jsonl is keyed on (name, version, python_version) only; if deps constraints for an integration change in TEST_SUITE_CONFIG, a subsequent run will return the previously-cached (now incorrect) resolved dependencies without re-running the pip dry-run, silently producing wrong transitive dependency pins.
`.split("-")` on sdist filename in `_has_free_threading_dependencies` crashes for multi-hyphen package names - `scripts/populate_tox/populate_tox.py:13`
In _has_free_threading_dependencies (populate_tox.py ~line 730), when a transitive dependency only ships as a source distribution, the code does:
package_release = wheel_filename.rstrip(".tar.gz")
dependency_name, dependency_version = package_release.split("-")The unpack assumes exactly two parts. For any sdist whose package name contains a hyphen (e.g. azure-core-1.29.5.tar.gz, google-auth-2.x.y.tar.gz, typing-extensions-...tar.gz), split("-") yields ≥3 elements and raises ValueError: too many values to unpack (expected 2), aborting tox generation for that combination.
Use package_release.rsplit("-", 1) to split off only the version (PEP 440 versions never contain - in this context once the sdist filename is formed). Note also that rstrip(".tar.gz") is character-based and will over-strip filenames ending in characters from {., t, a, r, g, z} (e.g. foo-1.0.tar.gz → foo-1.0 ok, but foobar-1.0.tar.gz → foobar-1.0 also ok; however foo-1.2.tar.gz is fine while a name like boto3-... is fine — but the pattern is still fragile and should be removesuffix(".tar.gz")).
Constraints passed to `fetch_package_dependencies` are silently ignored when the disk cache has a prior unconstrained entry - `scripts/populate_tox/populate_tox.py:934-939`
When _render_transitive_dependencies calls fetch_package_dependencies with a non-empty constraints tuple, _fetch_package_dependencies_from_cache ignores constraints in its key lookup, so a prior unconstrained disk-cache entry (e.g. one written by _has_free_threading_dependencies for the same (package, version, "3.14t") triple) is returned as-is, silently discarding the constraints and producing incorrect pinned transitive dependencies for that Python version.
Low
DryRunFailed silently skips transitive dependency pins for a Python version without marking the generated tox env - `scripts/populate_tox/populate_tox.py:1215-1219`
When _render_transitive_dependencies raises DryRunFailed for a particular (release, python_version), the loop continues without appending to release.transitive_dependencies, but the release stays in test_releases and gets rendered into tox.ini with pins from whichever Python versions succeeded. The failure is only surfaced via a print() during generation, so the generated tox.ini carries no marker that pinning is partially missing for one Python version. Since this is a developer-run CI tooling script with visible stdout output (not runtime/production code), severity is low — consider either failing the run, or emitting a comment into the generated env so the gap is auditable after the fact.
4 skills analyzed
| Skill | Findings | Duration | Cost |
|---|---|---|---|
| security-review | 0 | 1m 3s | $0.81 |
| code-review | 2 | 7m 34s | $1.80 |
| find-bugs | 2 | 19m 21s | $4.39 |
| skill-scanner | 0 | 13.6s | $0.71 |
⏱ 28m 12s · 3.3M in / 133.1k out · $7.73