Skip to content

Refactor ecosystem checkers to use shared resolver and pins utilities - #3

Merged
algomaster99 merged 2 commits into
mainfrom
claude/prototype-npm-pypi-j4i1pp
Jul 29, 2026
Merged

Refactor ecosystem checkers to use shared resolver and pins utilities#3
algomaster99 merged 2 commits into
mainfrom
claude/prototype-npm-pypi-j4i1pp

Conversation

@algomaster99

Copy link
Copy Markdown
Member

Summary

This PR refactors the npm and pypi ecosystem checkers to use a shared, injected resolver interface and consolidates version pinning logic into a new pkg/util/pins package. This eliminates duplicate code, improves testability by removing hard-coded HTTP calls, and leverages git-pkgs libraries for consistent manifest parsing and version comparison across ecosystems.

Key Changes

  • New pkg/util/pins package: Provides ExactVersion() to identify exactly-pinned dependencies (handling npm's bare semver and pypi's "==" operator requirements) and Diff() to compare pinned versions against latest releases. Uses git-pkgs/vers for ecosystem-aware version comparison.

  • New pkg/util/resolver package: Defines a Resolver interface for looking up latest versions by PURL, with an EnrichmentResolver implementation backed by git-pkgs/enrichment. Enables dependency injection for testing.

  • Refactored npm checker:

    • Replaced custom regex-based exact version detection with pins.ExactVersion()
    • Switched from manual JSON parsing to git-pkgs/manifests for consistent dependency extraction
    • Removed embedded Resolver type; now accepts injected resolver.Resolver
    • Uses pins.Diff() for version comparison logic
  • Refactored pypi checkers (requirements.txt and pyproject.toml):

    • Consolidated parsing into parsePypiPins() using git-pkgs/manifests
    • Replaced custom PEP 508 parsing with pins.ExactVersion() (with requireOperator=true for pypi)
    • Removed embedded Resolver type; now accepts injected resolver.Resolver
    • Uses pins.Diff() for version comparison logic
    • Added support for Poetry's [tool.poetry] tables via manifests
  • Updated main.go: Changed checkers from a global slice to newCheckers(res) function that injects the shared resolver into npm and pypi checkers.

  • Test improvements: Replaced HTTP mocking with simple fakeResolver implementations; tests now verify resolver lookup counts instead of HTTP request counts.

Notable Implementation Details

  • ExactVersion() handles ecosystem-specific syntax: npm accepts bare versions, pypi requires "==" operator; both strip environment markers/comments
  • Diff() only reports pins that were added or changed by the write, ignoring untouched pins even if outdated
  • EnrichmentResolver uses a 10-second timeout per lookup to stay under Claude Code's PreToolUse hook timeout
  • PURL construction uses git-pkgs/purl for consistency across ecosystems

https://claude.ai/code/session_01BwRfS8pJnmHGmWdLt1t6Y6

claude and others added 2 commits July 28, 2026 22:38
Prototype the migration described in #2 for npm and pypi, leaving Maven
on its bespoke parser per the issue's exception:

- Parse package.json, requirements.txt, and pyproject.toml through
  git-pkgs/manifests instead of hand-rolled parsers. pyproject.toml now
  also covers Poetry's [tool.poetry] tables, not just PEP 621.
- Identify exact pins and compare pinned-vs-latest versions with
  git-pkgs/vers ecosystem rules instead of raw string equality.
- Resolve latest versions through git-pkgs/enrichment
  (enrichment.NewEcosystemsClient() explicitly, avoiding GIT_PKGS_DIRECT/
  git-config-dependent behavior), reading PackageInfo.LatestVersion
  instead of maintaining npm/PyPI HTTP clients.
- Add pkg/util/resolver.Resolver as an injectable seam around enrichment
  so tests supply a fake instead of hitting the network, and
  pkg/util/pins for shared exact-pin/diff logic used by both ecosystems.

Binary size grew from ~10.0MB to ~12.0MB (manifests/registries register
every parser and registry), cold-start overhead is a few ms and well
under typical hook timeouts. The enrichment resolver's own timeout
(10s) stays under Claude Code's hook timeout regardless of the
underlying client's default. Note: this sandbox's egress policy blocks
packages.ecosyste.ms, so the live resolver path is exercised by
construction/unit tests with a fake resolver, not a real network call.
@algomaster99
algomaster99 merged commit 559d345 into main Jul 29, 2026
2 checks passed
@algomaster99
algomaster99 deleted the claude/prototype-npm-pypi-j4i1pp branch July 29, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants