Skip to content

Guard poetry-lock-update against silent release-age downgrades - #59

Merged
blink1073 merged 1 commit into
Calysto:mainfrom
blink1073:fix-poetry-lock-update-downgrade
Aug 24, 2026
Merged

Guard poetry-lock-update against silent release-age downgrades#59
blink1073 merged 1 commit into
Calysto:mainfrom
blink1073:fix-poetry-lock-update-downgrade

Conversation

@blink1073

Copy link
Copy Markdown
Contributor

References

Calysto/metakernel#481

Description

poetry-lock-update runs poetry update --no-interaction --lock under POETRY_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 update exits 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: pyzmq had 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 ordinary chore: update poetry.lock with no warnings, merged cleanly, and then broke the Test (Python 3.15t) job — pip had to build the older pyzmq from source (no cp315t wheel 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 successful poetry update --lock, diff the resulting lock file against the pre-run backup. Any package that regressed to an older version gets added to POETRY_SOLVER_MIN_RELEASE_AGE_EXCLUDE and the resolve is retried, the same way an outright resolver failure is already handled.
  • If a regression persists even after its cooldown is waived, the cooldown wasn't the cause (some other constraint moved) — that resolution is accepted rather than blocked or retried to the attempt cap, but it's surfaced as a distinct ::warning:: and a "Unresolved downgrades" section in the job summary so a human notices before merging.
  • action.yml: the resolve step now installs the tomli fallback 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_OUTPUT gains one new line (downgrades=...) alongside the existing waived=... 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

  • Some or all of the content of this PR was generated by AI.
  • The human author has carefully reviewed this PR and run this code.
  • AI tools and models used: Claude (root-cause investigation, patch, and tests)

@blink1073 blink1073 added the bug Something isn't working label Aug 24, 2026
@blink1073
blink1073 marked this pull request as ready for review August 24, 2026 13:42
@blink1073 blink1073 closed this Aug 24, 2026
@blink1073 blink1073 reopened this Aug 24, 2026
@blink1073
blink1073 merged commit 817626c into Calysto:main Aug 24, 2026
24 of 40 checks passed
@blink1073
blink1073 deleted the fix-poetry-lock-update-downgrade branch August 24, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant