Guard poetry-lock-update against silent release-age downgrades - #59
Merged
blink1073 merged 1 commit intoAug 24, 2026
Merged
Conversation
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.
References
Calysto/metakernel#481
Description
poetry-lock-updaterunspoetry update --no-interaction --lockunderPOETRY_SOLVER_MIN_RELEASE_AGE(a cooldown that hides package releases published more recently than N days, to guard against supply-chain attacks). When the cooldown hides the true latest version of a package, Poetry's resolver falls back to an older version instead — and if that older version still satisfies every constraint,poetry updateexits 0 with no error. Poetry only logs which versions the cooldown suppressed at-vv, so at normal verbosity this "successful" resolve can silently downgrade a package already in the lock file, with nothing in the output to flag it.This is exactly what happened in Calysto/metakernel#481:
pyzmqhad been deliberately pinned to 27.2.0 to get Python 3.15 free-threaded wheels. The next scheduled lock-update run quietly relocked it to 27.1.0 (whose newest release fell inside the cooldown window), because 27.1.0 was still resolvable. The resulting PR looked like an ordinarychore: update poetry.lockwith no warnings, merged cleanly, and then broke theTest (Python 3.15t)job — pip had to build the older pyzmq from source (nocp315twheel exists for it), and that source build failed on an unrelated Cython issue, which is what actually showed up in CI.Changes
resolve_lock.py: after every successfulpoetry update --lock, diff the resulting lock file against the pre-run backup. Any package that regressed to an older version gets added toPOETRY_SOLVER_MIN_RELEASE_AGE_EXCLUDEand the resolve is retried, the same way an outright resolver failure is already handled.::warning::and a "Unresolved downgrades" section in the job summary so a human notices before merging.action.yml: the resolve step now installs thetomlifallback on older interpreters, matching what the later diff step already does, since version comparison needs to parse both lock files.test_resolve_lock.sh: updated fixtures to valid lock TOML (now required since the script parses them) and added coverage for both new paths — a silent downgrade that gets waived and fixed, and one that persists and gets reported instead.Backwards-incompatible changes
None.
GITHUB_OUTPUTgains one new line (downgrades=...) alongside the existingwaived=...line; nothing currently reads that output so this is additive.Testing
bash actions/poetry-lock-update/test_resolve_lock.sh— 32/32 checks pass, including 8 new cases covering the downgrade-guard behavior (waived-and-fixed, and persists-and-reported).AI usage