Skip to content

Probe known Maven repos for sources jars - #301

Merged
soimkim merged 5 commits into
mainfrom
mvn
Aug 12, 2026
Merged

Probe known Maven repos for sources jars#301
soimkim merged 5 commits into
mainfrom
mvn

Conversation

@soimkim

@soimkim soimkim commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Maven downloads now search multiple repositories for artifacts, source JARs, versions, and metadata.
    • Maven version detection and latest-version lookup provide more reliable results across repositories.
  • Bug Fixes

    • Improved download result messages by avoiding misleading success text and ensuring an empty message is returned on success.
  • Tests

    • Added coverage for Maven repository discovery, metadata handling, version resolution, source downloads, and CLI download results.

Resolve mvnrepository links by checking common repository hosts in
popularity order instead of hard-falling back to Google Maven only.
Keep the requested GAV when any known host has it, and only fall back to
the highest-priority repository latest when no exact version matches.
Keep leftover git fail text out of success results so callers see a clean message.
@soimkim soimkim self-assigned this Aug 12, 2026
@soimkim soimkim added the bug fix [PR] Fix the bug label Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@soimkim, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9cf4096a-426a-4116-8ada-65b33a98a924

📥 Commits

Reviewing files that changed from the base of the PR and between 0fc74e9 and b4345be.

📒 Files selected for processing (2)
  • src/fosslight_util/_get_downloadable_url.py
  • tests/test_download_maven.py
📝 Walkthrough

Walkthrough

Maven resolution now probes configured repositories for versions, metadata, source JARs, and artifact bases. Download fallback handling now clears stale errors and omits empty wget errors.

Changes

Maven repository resolution

Layer / File(s) Summary
Maven repository contracts and version validation
src/fosslight_util/_get_downloadable_url.py, tests/test_download_maven.py
Adds candidate repository constants and validates exact Maven versions through repository availability checks.
Latest-version metadata resolution
src/fosslight_util/_get_downloadable_url.py, tests/test_download_maven.py
Reads repository metadata for latest versions and tests repository priority and XML parsing.
Maven source and artifact resolution
src/fosslight_util/_get_downloadable_url.py, tests/test_download_maven.py
Probes repositories for source JARs and artifact bases and returns resolved download URLs.

Fallback download error reporting

Layer / File(s) Summary
Fallback download message handling
src/fosslight_util/download.py, tests/test_download_version_hint.py
Clears stale Git errors after successful fallback downloads and omits absent wget errors.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant get_download_location_for_maven
  participant MavenRepository
  CLI->>get_download_location_for_maven: request Maven download
  get_download_location_for_maven->>MavenRepository: probe version, metadata, or source JAR
  MavenRepository-->>get_download_location_for_maven: return repository URL
  get_download_location_for_maven-->>CLI: return resolved download location
Loading

Suggested reviewers: bjk7119

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: probing known Maven repositories to find source JARs.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mvn

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
src/fosslight_util/_get_downloadable_url.py (2)

924-945: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Consider defusedxml for remote XML.

ET.fromstring parses content from remote hosts. defusedxml.ElementTree blocks entity-expansion attacks and is the recommended parser for untrusted input. Ruff flags this as S314.

The risk is limited here, because the hosts are a fixed allowlist. Treat this as hardening.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fosslight_util/_get_downloadable_url.py` around lines 924 - 945, Update
_maven_latest_version_from_repo to parse remote Maven metadata with
defusedxml.ElementTree instead of the standard ET parser. Preserve the existing
metadata extraction and exception handling behavior while replacing the
ET.fromstring call and corresponding import with the hardened parser.

Source: Linters/SAST tools


967-988: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Skip the directory listing when the host does not serve listings.

_probe_maven_sources_jar calls _maven_sources_from_directory for every repository, including hosts that return an HTML error page or no listing. That adds one blocking urlopen per repository on top of the three HEAD probes. Consider running the listing step only after _maven_http_ok(version_dir) confirms the version directory exists.

♻️ Proposed refactor
 def _probe_maven_sources_jar(group_path: str, artifact_id: str, version: str) -> str:
     for repo_base in MAVEN_REPOSITORY_BASES:
         version_dir = f"{repo_base}/{group_path}/{artifact_id}/{version}"
         for classifier in MAVEN_SOURCE_CLASSIFIERS:
             sources_url = f"{version_dir}/{artifact_id}-{version}-{classifier}.jar"
             if _maven_http_ok(sources_url):
                 logger.info(f"Maven sources found: {sources_url}")
                 return sources_url
+        if not _maven_http_ok(f"{version_dir}/"):
+            continue
         listed = _maven_sources_from_directory(version_dir, artifact_id, version)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fosslight_util/_get_downloadable_url.py` around lines 967 - 988, Update
_probe_maven_sources_jar so _maven_sources_from_directory is called only when
_maven_http_ok(version_dir) confirms the Maven version directory exists.
Preserve the existing classifier checks, listing result handling, repository
iteration, and empty-string fallback.
tests/test_download_maven.py (2)

27-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Widen the fake signature to accept any arguments.

fake_get accepts only url and timeout. If version_exists later adds a header or parameter argument, this test fails with a TypeError instead of a clear assertion. The other fakes in this file already use *_args, **_kwargs.

♻️ Proposed refactor
-    def fake_get(url, timeout=5):
+    def fake_get(url, *_args, **_kwargs):
         assert "deps.dev" in url
         return _FakeResponse(200, {"versions": [{"versionKey": {"version": "6.1.14"}}]})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_download_maven.py` around lines 27 - 31, Update the fake_get test
helper to accept arbitrary positional and keyword arguments while preserving its
URL assertion and response behavior, matching the flexible signatures used by
the other fakes in the file.

126-144: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for the no-sources failure path.

This PR changes get_download_location_for_maven to raise an error when no configured repository contains the artifact. The previous code fell back to Google Maven. That behavior change has no test. Add a case where _probe_maven_sources_jar returns "" and assert the function returns (False, '').

💚 Proposed test
def test_get_download_location_for_maven_returns_false_when_no_sources(monkeypatch):
    monkeypatch.setattr(
        downloadable_url,
        "_probe_maven_sources_jar",
        lambda *_args, **_kwargs: "",
    )

    ok, url = downloadable_url.get_download_location_for_maven(
        "mvnrepository.com/artifact/io.confluent/kafka-avro-serializer/8.2.1"
    )
    assert ok is False
    assert url == ""


def test_get_download_location_for_maven_returns_artifact_base_without_version(monkeypatch):
    base = "https://repo1.maven.org/maven2/org/springframework/spring-core"
    monkeypatch.setattr(
        downloadable_url,
        "_probe_maven_artifact_base",
        lambda group_path, artifact_id: base,
    )

    ok, url = downloadable_url.get_download_location_for_maven(
        "mvnrepository.com/artifact/org.springframework/spring-core"
    )
    assert ok is True
    assert url == base
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_download_maven.py` around lines 126 - 144, Add a test alongside
test_get_download_location_for_maven_uses_candidate_sources that stubs
downloadable_url._probe_maven_sources_jar to return an empty string, invokes
get_download_location_for_maven with the same versioned artifact, and asserts
the result is (False, "").
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/fosslight_util/_get_downloadable_url.py`:
- Around line 908-921: The Maven version probe in _maven_version_available
currently makes too many slow requests; reduce each repository check to the .pom
and, optionally, the version directory, and lower the per-probe timeout while
preserving exact-version detection. At
src/fosslight_util/_get_downloadable_url.py:908-921, update
_maven_version_available accordingly; at
src/fosslight_util/_get_downloadable_url.py:314-332, verify version_exists has
acceptable worst-case batch latency after the reduction and add a per-artifact
result cache if needed.
- Around line 590-593: Add an explicit timeout to the deps.dev fallback request
in the find_version branch of _get_downloadable_url, matching the timeout
convention used by other requests.get calls in the module.
- Around line 948-964: Update _maven_sources_from_directory to pass the
established probe timeout to urlopen, and import and use urllib.parse.urljoin
when resolving both preferred and fallback hrefs against the directory URL.
Preserve the existing source-jar selection and empty-string error behavior while
ensuring relative, root-relative, and absolute links produce valid URLs.
- Around line 1015-1020: Update get_download_location_for_maven() so the
artifact_base fallback from _probe_maven_artifact_base is not returned as a
downloadable URL when latest-version resolution fails. Return False for
unresolved versions, or resolve a concrete version and return its sources JAR
URL instead; preserve successful resolved-version behavior.

In `@src/fosslight_util/download.py`:
- Around line 358-363: Update the message-selection logic in the download error
handling so msg_wget is checked before msg. When both are present after a failed
Git clone and wget fallback, set the result exclusively to wget fail:
{wget_message}; preserve the existing git and RubyGems handling for cases
without a wget failure.

---

Nitpick comments:
In `@src/fosslight_util/_get_downloadable_url.py`:
- Around line 924-945: Update _maven_latest_version_from_repo to parse remote
Maven metadata with defusedxml.ElementTree instead of the standard ET parser.
Preserve the existing metadata extraction and exception handling behavior while
replacing the ET.fromstring call and corresponding import with the hardened
parser.
- Around line 967-988: Update _probe_maven_sources_jar so
_maven_sources_from_directory is called only when _maven_http_ok(version_dir)
confirms the Maven version directory exists. Preserve the existing classifier
checks, listing result handling, repository iteration, and empty-string
fallback.

In `@tests/test_download_maven.py`:
- Around line 27-31: Update the fake_get test helper to accept arbitrary
positional and keyword arguments while preserving its URL assertion and response
behavior, matching the flexible signatures used by the other fakes in the file.
- Around line 126-144: Add a test alongside
test_get_download_location_for_maven_uses_candidate_sources that stubs
downloadable_url._probe_maven_sources_jar to return an empty string, invokes
get_download_location_for_maven with the same versioned artifact, and asserts
the result is (False, "").
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 436d2757-3d60-4bf8-9237-4a0356e11da2

📥 Commits

Reviewing files that changed from the base of the PR and between c586cce and 0fc74e9.

📒 Files selected for processing (4)
  • src/fosslight_util/_get_downloadable_url.py
  • src/fosslight_util/download.py
  • tests/test_download_maven.py
  • tests/test_download_version_hint.py

Comment thread src/fosslight_util/_get_downloadable_url.py
Comment thread src/fosslight_util/_get_downloadable_url.py
Comment thread src/fosslight_util/_get_downloadable_url.py
Comment thread src/fosslight_util/_get_downloadable_url.py
Comment thread src/fosslight_util/download.py
Prefer groupId host hints, shorten HTTP timeouts, and cache sources probes so downloads do not stall on dead mirrors.
Prevent hanging when the deps.dev fallback request stalls.
@soimkim
soimkim merged commit f43ce7c into main Aug 12, 2026
6 of 8 checks passed
@soimkim
soimkim deleted the mvn branch August 12, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug fix [PR] Fix the bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant