Skip to content

fix: correctly resolve npm dist-tags latest using semver - #425

Merged
dkliban merged 2 commits into
pulp:mainfrom
dkliban:version-matching
Aug 24, 2026
Merged

fix: correctly resolve npm dist-tags latest using semver#425
dkliban merged 2 commits into
pulp:mainfrom
dkliban:version-matching

Conversation

@dkliban

@dkliban dkliban commented Aug 24, 2026

Copy link
Copy Markdown
Member

Summary

  • Replace lexicographic max(versions) with semver.Version.parse as sort key so that 10.0.0 correctly ranks above 9.0.0
  • Filter out pre-release versions (e.g. 1.0.0-alpha.1) when selecting the latest dist-tag; fall back to all versions only if no stable versions exist
  • Add semver>=3.0.0 as a declared runtime dependency in pyproject.toml
  • Fix extract_package_info() regex to match full semver strings including pre-release and build-metadata suffixes
  • Fix ruff linting (import sorting, line length)
  • Add functional tests for semver dist-tags resolution

Based on #415 by @BethGriggs with linting fixes and functional tests added.

Test plan

  • ruff check and ruff format --check pass on all changed files
  • test_dist_tags_latest_is_highest_semver — publishes 1.0.0, 9.0.0, 10.0.0; asserts latest=10.0.0
  • test_dist_tags_latest_excludes_prerelease — publishes 1.0.0, 2.0.0, 3.0.0-alpha.1; asserts latest=2.0.0
  • test_dist_tags_latest_falls_back_to_prerelease — publishes only 1.0.0-beta.1; asserts latest=1.0.0-beta.1

🤖 Generated with Claude Code

Previously, latest was selected using Python's built-in max() on raw
version strings, which performs lexicographic comparison (e.g.
"9.0.0" > "10.0.0") and did not exclude pre-release versions.

- Parse all version strings once via semver.Version.parse, skipping
  any malformed values, to avoid redundant parsing and ValueError on
  invalid versions in the fallback path
- Filter out pre-release versions (e.g. 1.0.0-alpha.1) when selecting
  the latest dist-tag; fall back to all valid semver versions if no
  stable versions exist
- Add semver>=3.0.0 as a declared runtime dependency in pyproject.toml
- Fix extract_package_info() regex to match full semver strings
  including pre-release and build-metadata suffixes; make base_name
  non-greedy ([^/]+?) to avoid ambiguity on hyphenated package names
  like my-pkg-1.0.0-rc.1.tgz, where a greedy match would consume into
  the version and cause extract_package_info() to return (None, None)

Assisted By: Bob
- Fix import sorting (ruff I001) and line length in models.py
- Add upper bound to semver dependency (semver>=3.0.0,<4)
- Add functional tests for semver dist-tags resolution:
  - latest uses semver ordering (10.0.0 > 9.0.0)
  - pre-release versions excluded from latest
  - fallback to pre-release when no stable versions exist

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@dkliban
dkliban merged commit f96a2a8 into pulp:main Aug 24, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants